View Javadoc
1   package org.andromda.maven.plugin.andromdapp.hibernate;
2   
3   import java.io.File;
4   import java.lang.reflect.Method;
5   import java.sql.Connection;
6   import java.util.ArrayList;
7   import java.util.Arrays;
8   import java.util.List;
9   import java.util.Map;
10  import org.andromda.core.common.ClassUtils;
11  import org.andromda.maven.plugin.andromdapp.SchemaManagement;
12  import org.andromda.maven.plugin.andromdapp.SchemaManagementException;
13  import org.apache.commons.lang.ObjectUtils;
14  import org.apache.commons.lang.StringUtils;
15  import org.apache.log4j.Logger;
16  import org.codehaus.plexus.util.DirectoryScanner;
17  
18  /**
19   * A Hibernate management object.
20   *
21   * @author Chad Brandon
22   */
23  public abstract class HibernateSchemaManagement
24      implements SchemaManagement
25  {
26      /**
27       * getLogger(HibernateSchemaManagement.class)
28       */
29      protected static Logger logger = Logger.getLogger(HibernateSchemaManagement.class);
30  
31      /**
32       * The Hibernate 2 schema export class name.
33       */
34      protected static final String HIBERNATE_2_PACKAGE = "net.sf.hibernate.tool.hbm2ddl";
35  
36      /**
37       * The Hibernate 3 schema export class name.
38       */
39      protected static final String HIBERNATE_3_PACKAGE = "org.hibernate.tool.hbm2ddl";
40  
41      /**
42       * The Hibernate version
43       */
44      private String version;
45  
46      /**
47       * Sets the version of Hibernate to target.
48       *
49       * @param version the version of Hibernate to target.
50       */
51      public void setVersion(final String version)
52      {
53          this.version = version;
54      }
55  
56      /**
57       * Retrieves the class that performs the execution work.
58       *
59       * @return the Hibernate class that performs the work.
60       */
61      protected Class getExecutionClass()
62      {
63          Class hibernateClass = null;
64          String hibernate2ClassName = null;
65          String hibernate3ClassName = null;
66          try
67          {
68              hibernate3ClassName = HIBERNATE_3_PACKAGE + '.' + this.getExecutionClassName();
69              hibernateClass = ClassUtils.loadClass(hibernate3ClassName);
70          }
71          catch (Exception exception)
72          {
73              // - ignore, means we can't find the Hibernate 3 class
74          }
75          try
76          {
77              hibernate2ClassName = HIBERNATE_2_PACKAGE + '.' + this.getExecutionClassName();
78              hibernateClass = ClassUtils.loadClass(hibernate2ClassName);
79          }
80          catch (Exception exception)
81          {
82              // - ignore, means we can't find the Hibernate 2 class
83          }
84          if (hibernateClass == null)
85          {
86              throw new RuntimeException(
87                  "There appear to be no Hibernate 2 or 3 jars are your classpath, because neither '" +
88                  hibernate2ClassName + "', nor '" + hibernate3ClassName + "' could be found");
89          }
90          return hibernateClass;
91      }
92  
93      /**
94       * Returns the current Hibernate version this management object
95       * is targetting.
96       *
97       * @return the Hibernate version (2 or 3).
98       */
99      protected String getVersion()
100     {
101         return this.version;
102     }
103 
104     /**
105      * Stores the path to which output should be written.
106      */
107     private String outputPath;
108 
109     /**
110      * Sets the path to which the output should be written.
111      *
112      * @param outputPath
113      */
114     public void setOutputPath(final String outputPath)
115     {
116         this.outputPath = outputPath;
117     }
118 
119     /**
120      * Attempts to retrieve the given property with the given <code>name</code>.
121      *
122      * @param properties the properties from which to retrieve the property.
123      * @param name the name of the property to retrieve.
124      * @return the value of the property.
125      */
126     protected String getProperty(
127         final Map properties,
128         final String name)
129     {
130         final String value = ObjectUtils.toString(properties.get(name));
131         return value;
132     }
133 
134     /**
135      * Attempts to retrieve the given property with the given <code>name</code>.
136      * If the property isn't found an exception is thrown.
137      *
138      * @param properties the properties from which to retrieve the property.
139      * @param name the name of the property to retrieve.
140      * @return the value of the property.
141      */
142     protected String getRequiredProperty(
143         final Map properties,
144         final String name)
145     {
146         final String value = ObjectUtils.toString(properties.get(name));
147         if (StringUtils.isBlank(value))
148         {
149             throw new SchemaManagementException("The '" + name + "' must be specified");
150         }
151         return value;
152     }
153 
154     /**
155      * Gets the path to which output should be written.
156      *
157      * @return the output path.
158      */
159     protected String getOutputPath()
160     {
161         return this.outputPath;
162     }
163 
164     /**
165      * Returns the name of the class that performs the execution.
166      *
167      * @return the execution class.
168      */
169     protected abstract String getExecutionClassName();
170 
171     /**
172      * @see org.andromda.maven.plugin.andromdapp.SchemaManagement#execute(java.sql.Connection, java.util.Map)
173      */
174     public String execute(
175         Connection connection,
176         java.util.Map options)
177         throws Exception
178     {
179         final String hibernateDialect = "hibernate.dialect";
180         System.setProperty(
181             hibernateDialect,
182             this.getRequiredProperty(
183                 options,
184                 hibernateDialect));
185         final List<String> argumentList = this.getArguments(options);
186         final String[] arguments = argumentList.toArray(new String[argumentList.size()]);
187         final Class executionClass = this.getExecutionClass();
188         final Method method = executionClass.getMethod(
189                 "main",
190                 new Class[] {String[].class});
191         method.invoke(
192             executionClass,
193             new Object[] {arguments});
194 
195         return this.getExecutionOuputPath(options);
196     }
197 
198     /**
199      * Returns the path of the execution output file.
200      *
201      * @param options the options from which to retrieve properties.
202      * @return the output path.
203      */
204     protected abstract String getExecutionOuputPath(final Map options);
205 
206     /**
207      * Retrieves the arguments common to all Hibernate schema management
208      * tasks.
209      *
210      * @param options the options from which to retrieve any required properties.
211      * @return the list of common arguments.
212      */
213     private List<String> getArguments(final Map options)
214         throws Exception
215     {
216         final List<String> mappingFiles =
217             this.getMappingFilesList(
218                 this.getRequiredProperty(
219                     options,
220                     "mappingFileExtension"),
221                 this.getRequiredProperty(
222                     options,
223                     "mappingsLocation"));
224         final String[] args = new String[] {"--delimiter=;", "--format"};
225         final List<String> arguments = new ArrayList<String>(Arrays.asList(args));
226         arguments.addAll(mappingFiles);
227         this.addArguments(
228             options,
229             arguments);
230         return arguments;
231     }
232 
233     /**
234      * Adds any arguments required by the specialized class.
235      *
236      * @param options any options from which to retrieve argument values.
237      * @param arguments the list of arguments to add.
238      * @throws Exception
239      */
240     protected abstract void addArguments(
241         final Map options,
242         final List<String> arguments) throws Exception;
243 
244     /**
245      * Retrieves all mapping files having the given <code>extension</code>
246      * existing in the <code>baseDirectory</code> or any of its sub directories.
247      *
248      * @param extension the mapping file extension
249      * @param baseDirectory the directory from which to perform the search.
250      * @return the list of mapping files
251      */
252     protected List<String> getMappingFilesList(
253         final String extension,
254         final String baseDirectory)
255     {
256         final DirectoryScanner scanner = new DirectoryScanner();
257         scanner.setBasedir(baseDirectory);
258         scanner.setIncludes(new String[] {"**/*." + extension});
259         scanner.setExcludes(null);
260         scanner.scan();
261 
262         final List<String> files = new ArrayList<String>();
263         for (String path : Arrays.asList(scanner.getIncludedFiles()))
264         {
265             files.add(new File(
266                     baseDirectory,
267                     path).toString());
268         }
269         return files;
270     }
271 }