View Javadoc

1   package org.apache.maven.continuum.management;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *   http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import com.sampullara.cli.Args;
23  import com.sampullara.cli.Argument;
24  import org.apache.log4j.BasicConfigurator;
25  import org.apache.log4j.Level;
26  import org.apache.log4j.Logger;
27  import org.apache.maven.artifact.Artifact;
28  import org.apache.maven.artifact.factory.ArtifactFactory;
29  import org.apache.maven.artifact.manager.WagonManager;
30  import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
31  import org.apache.maven.artifact.repository.ArtifactRepository;
32  import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
33  import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout;
34  import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout;
35  import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
36  import org.apache.maven.artifact.resolver.ArtifactResolutionException;
37  import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
38  import org.apache.maven.artifact.resolver.ArtifactResolver;
39  import org.apache.maven.artifact.resolver.DebugResolutionListener;
40  import org.apache.maven.artifact.resolver.ResolutionListener;
41  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
42  import org.apache.maven.artifact.resolver.filter.ExcludesArtifactFilter;
43  import org.apache.maven.continuum.management.util.PlexusFileSystemXmlApplicationContext;
44  import org.apache.maven.settings.MavenSettingsBuilder;
45  import org.apache.maven.settings.Mirror;
46  import org.apache.maven.settings.Profile;
47  import org.apache.maven.settings.Proxy;
48  import org.apache.maven.settings.Repository;
49  import org.apache.maven.settings.Server;
50  import org.apache.maven.settings.Settings;
51  import org.apache.maven.wagon.repository.RepositoryPermissions;
52  import org.codehaus.plexus.PlexusContainer;
53  import org.codehaus.plexus.PlexusContainerException;
54  import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
55  import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
56  import org.codehaus.plexus.spring.PlexusClassPathXmlApplicationContext;
57  import org.codehaus.plexus.spring.PlexusContainerAdapter;
58  import org.codehaus.plexus.util.xml.Xpp3Dom;
59  import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
60  
61  import java.io.File;
62  import java.io.IOException;
63  import java.net.URL;
64  import java.net.URLClassLoader;
65  import java.util.ArrayList;
66  import java.util.Collection;
67  import java.util.Collections;
68  import java.util.Iterator;
69  import java.util.List;
70  import java.util.Map;
71  import java.util.Properties;
72  
73  /**
74   * An application for performing database upgrades from old Continuum and Redback versions. A suitable tool until it
75   * is natively incorporated into Continuum itself.
76   *
77   * @version $Id: DataManagementCli.java 1372260 2012-08-13 04:29:09Z brett $
78   */
79  public class DataManagementCli
80  {
81      private static final Logger LOGGER = Logger.getLogger( DataManagementCli.class );
82  
83      private static final String JAR_FILE_PREFIX = "jar:file:";
84  
85      private static final String FILE_PREFIX = "file:";
86  
87      private static final String SPRING_CONTEXT_LOC = "!/**/META-INF/spring-context.xml";
88  
89      private static final String PLEXUS_XML_LOC = "!/**/META-INF/plexus/components.xml";
90  
91      public static void main( String[] args )
92          throws Exception
93      {
94          Commands command = new Commands();
95  
96          DatabaseFormat databaseFormat;
97          OperationMode mode;
98          SupportedDatabase databaseType;
99  
100         try
101         {
102             Args.parse( command, args );
103             if ( command.help )
104             {
105                 Args.usage( command );
106                 return;
107             }
108             if ( command.version )
109             {
110                 System.out.print( "continuum-data-management version " + getVersion() );
111                 return;
112             }
113             databaseFormat = DatabaseFormat.valueOf( command.databaseFormat );
114             mode = OperationMode.valueOf( command.mode );
115             databaseType = SupportedDatabase.valueOf( command.databaseType );
116         }
117         catch ( IllegalArgumentException e )
118         {
119             System.err.println( e.getMessage() );
120             Args.usage( command );
121             return;
122         }
123 
124         if ( command.directory.exists() && !command.directory.isDirectory() )
125         {
126             System.err.println( command.directory + " already exists and is not a directory." );
127             Args.usage( command );
128             return;
129         }
130 
131         if ( !command.overwrite && mode == OperationMode.EXPORT && command.directory.exists() )
132         {
133             System.err.println(
134                 command.directory + " already exists and will not be overwritten unless the -overwrite flag is used." );
135             Args.usage( command );
136             return;
137         }
138 
139         if ( command.buildsJdbcUrl == null && command.usersJdbcUrl == null )
140         {
141             System.err.println( "You must specify one of -buildsJdbcUrl and -usersJdbcUrl" );
142             Args.usage( command );
143             return;
144         }
145 
146         if ( command.usersJdbcUrl != null && databaseFormat == DatabaseFormat.CONTINUUM_103 )
147         {
148             System.err.println( "The -usersJdbcUrl option can not be used with Continuum 1.0.3 databases" );
149             Args.usage( command );
150             return;
151         }
152 
153         if ( SupportedDatabase.OTHER.equals( databaseType ) )
154         {
155             if ( command.driverClass == null || command.artifactId == null || command.groupId == null ||
156                 command.artifactVersion == null || command.password == null || command.username == null )
157             {
158                 System.err.println(
159                     "If OTHER databaseType is selected, -driverClass, -artifactId, -groupId, -artifactVersion, -username and -password must be provided together" );
160                 Args.usage( command );
161                 return;
162             }
163             databaseType.defaultParams = new DatabaseParams( command.driverClass, command.groupId, command.artifactId,
164                                                              command.artifactVersion, command.username,
165                                                              command.password );
166         }
167 
168         BasicConfigurator.configure();
169         if ( command.debug )
170         {
171             Logger.getRootLogger().setLevel( Level.DEBUG );
172             Logger.getLogger( "JPOX" ).setLevel( Level.DEBUG );
173         }
174         else
175         {
176             Logger.getRootLogger().setLevel( Level.INFO );
177             Logger.getLogger( "JPOX" ).setLevel( Level.WARN );
178         }
179 
180         if ( command.settings != null && !command.settings.isFile() )
181         {
182             System.err.println( command.settings + " not exists or is not a file." );
183             Args.usage( command );
184             return;
185         }
186 
187         if ( command.buildsJdbcUrl != null )
188         {
189             LOGGER.info( "Processing Continuum database..." );
190             processDatabase( databaseType, databaseFormat, mode, command.buildsJdbcUrl, command.directory,
191                              command.settings, databaseFormat.getContinuumToolRoleHint(), "data-management-jdo",
192                              "continuum", command.strict );
193         }
194 
195         if ( command.usersJdbcUrl != null )
196         {
197             LOGGER.info( "Processing Redback database..." );
198             processDatabase( databaseType, databaseFormat, mode, command.usersJdbcUrl, command.directory,
199                              command.settings, databaseFormat.getRedbackToolRoleHint(), "data-management-redback-jdo",
200                              "redback", command.strict );
201         }
202     }
203 
204     private static void processDatabase( SupportedDatabase databaseType, DatabaseFormat databaseFormat,
205                                          OperationMode mode, String jdbcUrl, File directory, File setting,
206                                          String toolRoleHint, String managementArtifactId, String configRoleHint,
207                                          boolean strict )
208         throws PlexusContainerException, ComponentLookupException, ComponentLifecycleException,
209         ArtifactNotFoundException, ArtifactResolutionException, IOException
210     {
211         String applicationVersion = getVersion();
212 
213         DatabaseParams params = new DatabaseParams( databaseType.defaultParams );
214         params.setUrl( jdbcUrl );
215 
216         PlexusClassPathXmlApplicationContext classPathApplicationContext = new PlexusClassPathXmlApplicationContext(
217             new String[]{"classpath*:/META-INF/spring-context.xml", "classpath*:/META-INF/plexus/components.xml",
218                 "classpath*:/META-INF/plexus/plexus.xml"} );
219 
220         PlexusContainerAdapter container = new PlexusContainerAdapter();
221         container.setApplicationContext( classPathApplicationContext );
222 
223         initializeWagon( container, setting );
224 
225         List<Artifact> artifacts = new ArrayList<Artifact>();
226         artifacts.addAll( downloadArtifact( container, params.getGroupId(), params.getArtifactId(), params.getVersion(),
227                                             setting ) );
228         artifacts.addAll( downloadArtifact( container, "org.apache.continuum", managementArtifactId, applicationVersion,
229                                             setting ) );
230         artifacts.addAll( downloadArtifact( container, "jpox", "jpox", databaseFormat.getJpoxVersion(), setting ) );
231 
232         List<String> jars = new ArrayList<String>();
233 
234         // Little hack to make it work more nicely in the IDE
235         List<String> exclusions = new ArrayList<String>();
236         URLClassLoader cp = (URLClassLoader) DataManagementCli.class.getClassLoader();
237         List<URL> jarUrls = new ArrayList<URL>();
238 
239         for ( URL url : cp.getURLs() )
240         {
241             String urlEF = url.toExternalForm();
242             if ( urlEF.endsWith( "target/classes/" ) )
243             {
244                 int idEndIdx = urlEF.length() - 16;
245                 String id = urlEF.substring( urlEF.lastIndexOf( '/', idEndIdx - 1 ) + 1, idEndIdx );
246                 // continuum-legacy included because the IDE doesn't do the proper assembly of enhanced classes and JDO metadata
247                 if ( !"data-management-api".equals( id ) && !"data-management-cli".equals( id ) &&
248                     !"continuum-legacy".equals( id ) && !"continuum-model".equals( id ) &&
249                     !"redback-legacy".equals( id ) )
250                 {
251                     LOGGER.debug( "[IDE Help] Adding '" + id + "' as an exclusion and using one from classpath" );
252                     exclusions.add( "org.apache.continuum:" + id );
253                     jars.add( url.getPath() );
254                     jarUrls.add( url );
255                 }
256             }
257 
258             // Sometimes finds its way into the IDE. Make sure it is loaded in the extra classloader too
259             if ( urlEF.contains( "jpox-enhancer" ) )
260             {
261                 LOGGER.debug( "[IDE Help] Adding 'jpox-enhancer' as an exclusion and using one from classpath" );
262                 jars.add( url.getPath() );
263                 jarUrls.add( url );
264             }
265         }
266 
267         ArtifactFilter filter = new ExcludesArtifactFilter( exclusions );
268 
269         for ( Artifact a : artifacts )
270         {
271             if ( "jpox".equals( a.getGroupId() ) && "jpox".equals( a.getArtifactId() ) )
272             {
273                 if ( a.getVersion().equals( databaseFormat.getJpoxVersion() ) )
274                 {
275                     LOGGER.debug( "Adding artifact: " + a.getFile() );
276                     jars.add( JAR_FILE_PREFIX + a.getFile().getAbsolutePath() + SPRING_CONTEXT_LOC );
277                     jars.add( JAR_FILE_PREFIX + a.getFile().getAbsolutePath() + PLEXUS_XML_LOC );
278                     jarUrls.add( new URL( FILE_PREFIX + a.getFile().getAbsolutePath() ) );
279                 }
280             }
281             else if ( filter.include( a ) )
282             {
283                 LOGGER.debug( "Adding artifact: " + a.getFile() );
284                 jars.add( JAR_FILE_PREFIX + a.getFile().getAbsolutePath() + SPRING_CONTEXT_LOC );
285                 jars.add( JAR_FILE_PREFIX + a.getFile().getAbsolutePath() + PLEXUS_XML_LOC );
286                 jarUrls.add( new URL( FILE_PREFIX + a.getFile().getAbsolutePath() ) );
287             }
288         }
289 
290         URLClassLoader newClassLoader = new URLClassLoader( (URL[]) jarUrls.toArray( new URL[jarUrls.size()] ), cp );
291         Thread.currentThread().setContextClassLoader( newClassLoader );
292         classPathApplicationContext.setClassLoader( newClassLoader );
293 
294         PlexusFileSystemXmlApplicationContext fileSystemApplicationContext = new PlexusFileSystemXmlApplicationContext(
295             (String[]) jars.toArray( new String[jars.size()] ), classPathApplicationContext );
296         fileSystemApplicationContext.setClassLoader( newClassLoader );
297         container.setApplicationContext( fileSystemApplicationContext );
298 
299         DatabaseFactoryConfigurator configurator = (DatabaseFactoryConfigurator) container.lookup(
300             DatabaseFactoryConfigurator.class.getName(), configRoleHint );
301         configurator.configure( params );
302 
303         DataManagementTool manager = (DataManagementTool) container.lookup( DataManagementTool.class.getName(),
304                                                                             toolRoleHint );
305 
306         if ( mode == OperationMode.EXPORT )
307         {
308             manager.backupDatabase( directory );
309         }
310         else if ( mode == OperationMode.IMPORT )
311         {
312             manager.eraseDatabase();
313             manager.restoreDatabase( directory, strict );
314         }
315     }
316 
317     private static void initializeWagon( PlexusContainerAdapter container, File setting )
318         throws ComponentLookupException, ComponentLifecycleException, IOException
319     {
320         WagonManager wagonManager = (WagonManager) container.lookup( WagonManager.ROLE );
321 
322         Settings settings = getSettings( container, setting );
323 
324         try
325         {
326             Proxy proxy = settings.getActiveProxy();
327 
328             if ( proxy != null )
329             {
330                 if ( proxy.getHost() == null )
331                 {
332                     throw new IOException( "Proxy in settings.xml has no host" );
333                 }
334 
335                 wagonManager.addProxy( proxy.getProtocol(), proxy.getHost(), proxy.getPort(), proxy.getUsername(),
336                                        proxy.getPassword(), proxy.getNonProxyHosts() );
337             }
338 
339             for ( Iterator i = settings.getServers().iterator(); i.hasNext(); )
340             {
341                 Server server = (Server) i.next();
342 
343                 wagonManager.addAuthenticationInfo( server.getId(), server.getUsername(), server.getPassword(),
344                                                     server.getPrivateKey(), server.getPassphrase() );
345 
346                 wagonManager.addPermissionInfo( server.getId(), server.getFilePermissions(),
347                                                 server.getDirectoryPermissions() );
348 
349                 if ( server.getConfiguration() != null )
350                 {
351                     wagonManager.addConfiguration( server.getId(), (Xpp3Dom) server.getConfiguration() );
352                 }
353             }
354 
355             RepositoryPermissions defaultPermissions = new RepositoryPermissions();
356 
357             defaultPermissions.setDirectoryMode( "775" );
358 
359             defaultPermissions.setFileMode( "664" );
360 
361             wagonManager.setDefaultRepositoryPermissions( defaultPermissions );
362 
363             for ( Iterator i = settings.getMirrors().iterator(); i.hasNext(); )
364             {
365                 Mirror mirror = (Mirror) i.next();
366 
367                 wagonManager.addMirror( mirror.getId(), mirror.getMirrorOf(), mirror.getUrl() );
368             }
369         }
370         finally
371         {
372             container.release( wagonManager );
373         }
374 
375     }
376 
377     private static Collection<Artifact> downloadArtifact( PlexusContainer container, String groupId, String artifactId,
378                                                           String version, File setting )
379         throws ComponentLookupException, ArtifactNotFoundException, ArtifactResolutionException, IOException
380     {
381         ArtifactRepositoryFactory factory = (ArtifactRepositoryFactory) container.lookup(
382             ArtifactRepositoryFactory.ROLE );
383 
384         DefaultRepositoryLayout layout = (DefaultRepositoryLayout) container.lookup( ArtifactRepositoryLayout.ROLE,
385                                                                                      "default" );
386 
387         ArtifactRepository localRepository = factory.createArtifactRepository( "local", getLocalRepositoryURL(
388             container, setting ), layout, null, null );
389 
390         List<ArtifactRepository> remoteRepositories = new ArrayList<ArtifactRepository>();
391         remoteRepositories.add( factory.createArtifactRepository( "central", "http://repo1.maven.org/maven2", layout,
392                                                                   null, null ) );
393         //Load extra repositories from active profile
394 
395         Settings settings = getSettings( container, setting );
396         List<String> profileIds = settings.getActiveProfiles();
397         Map<String, Profile> profilesAsMap = settings.getProfilesAsMap();
398         if ( profileIds != null && !profileIds.isEmpty() )
399         {
400             for ( String profileId : profileIds )
401             {
402                 Profile profile = profilesAsMap.get( profileId );
403                 if ( profile != null )
404                 {
405                     List<Repository> repos = profile.getRepositories();
406                     if ( repos != null && !repos.isEmpty() )
407                     {
408                         for ( Repository repo : repos )
409                         {
410                             remoteRepositories.add( factory.createArtifactRepository( repo.getId(), repo.getUrl(),
411                                                                                       layout, null, null ) );
412                         }
413                     }
414                 }
415             }
416         }
417 
418         ArtifactFactory artifactFactory = (ArtifactFactory) container.lookup( ArtifactFactory.ROLE );
419         Artifact artifact = artifactFactory.createArtifact( groupId, artifactId, version, Artifact.SCOPE_RUNTIME,
420                                                             "jar" );
421         Artifact dummyArtifact = artifactFactory.createProjectArtifact( "dummy", "dummy", "1.0" );
422 
423         if ( artifact.isSnapshot() )
424         {
425             remoteRepositories.add( factory.createArtifactRepository( "apache.snapshots",
426                                                                       "http://people.apache.org/repo/m2-snapshot-repository",
427                                                                       layout, null, null ) );
428         }
429 
430         ArtifactResolver resolver = (ArtifactResolver) container.lookup( ArtifactResolver.ROLE );
431 
432         List<String> exclusions = new ArrayList<String>();
433         exclusions.add( "org.apache.continuum:data-management-api" );
434         exclusions.add( "org.codehaus.plexus:plexus-component-api" );
435         exclusions.add( "org.codehaus.plexus:plexus-container-default" );
436         exclusions.add( "org.slf4j:slf4j-api" );
437         exclusions.add( "log4j:log4j" );
438 
439         ArtifactFilter filter = new ExcludesArtifactFilter( exclusions );
440 
441         List<? extends ResolutionListener> listeners;
442         if ( LOGGER.isDebugEnabled() )
443         {
444             listeners = Collections.singletonList( new DebugResolutionListener( container.getLogger() ) );
445         }
446         else
447         {
448             listeners = Collections.emptyList();
449         }
450 
451         ArtifactMetadataSource source = (ArtifactMetadataSource) container.lookup( ArtifactMetadataSource.ROLE,
452                                                                                    "maven" );
453         ArtifactResolutionResult result = resolver.resolveTransitively( Collections.singleton( artifact ),
454                                                                         dummyArtifact, Collections.emptyMap(),
455                                                                         localRepository, remoteRepositories, source,
456                                                                         filter, listeners );
457 
458         return result.getArtifacts();
459     }
460 
461     private static String getLocalRepositoryURL( PlexusContainer container, File setting )
462         throws ComponentLookupException, IOException
463     {
464         String repositoryPath;
465         File settingsFile = new File( System.getProperty( "user.home" ), ".m2/settings.xml" );
466         if ( setting != null )
467         {
468             Settings settings = getSettings( container, setting );
469             repositoryPath = new File( settings.getLocalRepository() ).toURL().toString();
470         }
471         else if ( !settingsFile.exists() )
472         {
473             repositoryPath = new File( System.getProperty( "user.home" ), ".m2/repository" ).toURL().toString();
474         }
475         else
476         {
477             Settings settings = getSettings( container, null );
478             repositoryPath = new File( settings.getLocalRepository() ).toURL().toString();
479         }
480         return repositoryPath;
481     }
482 
483     private static Settings getSettings( PlexusContainer container, File setting )
484         throws ComponentLookupException, IOException
485     {
486         MavenSettingsBuilder mavenSettingsBuilder = (MavenSettingsBuilder) container.lookup(
487             MavenSettingsBuilder.class.getName() );
488         try
489         {
490             if ( setting != null )
491             {
492                 return mavenSettingsBuilder.buildSettings( setting, false );
493             }
494             else
495             {
496                 return mavenSettingsBuilder.buildSettings( false );
497             }
498         }
499         catch ( XmlPullParserException e )
500         {
501             e.printStackTrace();
502             throw new IOException( "Can't read settings.xml. " + e.getMessage() );
503         }
504     }
505 
506     private static String getVersion()
507         throws IOException
508     {
509         Properties properties = new Properties();
510         properties.load( DataManagementCli.class.getResourceAsStream(
511             "/META-INF/maven/org.apache.continuum/data-management-api/pom.properties" ) );
512         return properties.getProperty( "version" );
513     }
514 
515     private static class Commands
516     {
517 
518         @Argument( description = "Display help information", value = "help", alias = "h" )
519         private boolean help;
520 
521         @Argument( description = "Display version information", value = "version", alias = "v" )
522         private boolean version;
523 
524         @Argument(
525             description = "The JDBC URL for the Continuum database that contains the data to convert, or to import the data into",
526             value = "buildsJdbcUrl" )
527         private String buildsJdbcUrl;
528 
529         @Argument(
530             description = "The JDBC URL for the Redback database that contains the data to convert, or to import the data into",
531             value = "usersJdbcUrl" )
532         private String usersJdbcUrl;
533 
534         // TODO: ability to use the enum directly would be nice
535         @Argument(
536             description = "Format of the database. Valid values are CONTINUUM_103, CONTINUUM_109, CONTINUUM_11. Default is CONTINUUM_11." )
537         private String databaseFormat = DatabaseFormat.CONTINUUM_11.toString();
538 
539 /* TODO: not yet supported
540         @Argument(
541             description = "Format of the backup directory. Valid values are CONTINUUM_103, CONTINUUM_109, CONTINUUM_11. Default is CONTINUUM_11.")
542         private String dataFileFormat = DatabaseFormat.CONTINUUM_11.toString();
543 */
544 
545         @Argument(
546             description = "The directory to export the data to, or import the data from. Default is 'backups' in the current working directory.",
547             value = "directory" )
548         private File directory = new File( "backups" );
549 
550         @Argument(
551             description = "Mode of operation. Valid values are IMPORT and EXPORT. Default is EXPORT.",
552             value = "mode" )
553         private String mode = OperationMode.EXPORT.toString();
554 
555         @Argument(
556             description = "Whether to overwrite the designated directory if it already exists in export mode. Default is false.",
557             value = "overwrite" )
558         private boolean overwrite;
559 
560         @Argument(
561             description = "The type of database to use. Currently supported values are DERBY_10_1. The default value is DERBY_10_1.",
562             value = "databaseType" )
563         private String databaseType = SupportedDatabase.DERBY_10_1.toString();
564 
565         @Argument( description = "JDBC driver class", value = "driverClass", required = false )
566         private String driverClass;
567 
568         @Argument( description = "JDBC driver groupId", value = "groupId", required = false )
569         private String groupId;
570 
571         @Argument( description = "JDBC driver artifactId", value = "artifactId", required = false )
572         private String artifactId;
573 
574         @Argument( description = "Artifact version of the JDBC driver class",
575                    value = "artifactVersion",
576                    required = false )
577         private String artifactVersion;
578 
579         @Argument( description = "Username", value = "username", required = false )
580         private String username;
581 
582         @Argument( description = "Password", value = "password", required = false )
583         private String password;
584 
585         @Argument(
586             description = "Turn on debugging information. Default is off.",
587             value = "debug" )
588         private boolean debug;
589 
590         @Argument( description = "Alternate path for the user settings file", value = "settings", required = false,
591                    alias = "s" )
592         private File settings;
593 
594         @Argument( description = "Run on strict mode. Default is false.", value = "strict" )
595         private boolean strict;
596     }
597 
598     private enum OperationMode
599     {
600         IMPORT, EXPORT
601     }
602 
603     private enum SupportedDatabase
604     {
605         DERBY_10_1( new DatabaseParams( "org.apache.derby.jdbc.EmbeddedDriver", "org.apache.derby", "derby", "10.1.3.1",
606                                         "sa", "" ) ),
607 
608         OTHER( new DatabaseParams( null, null, null, null, null, null ) );
609 
610         private DatabaseParams defaultParams;
611 
612         SupportedDatabase( DatabaseParams defaultParams )
613         {
614             this.defaultParams = defaultParams;
615         }
616     }
617 }