View Javadoc

1   package org.appfuse.mojo.exporter;
2   
3   /*
4    * Copyright 2005 Johann Reyes.
5    *
6    * Licensed under the Apache License, Version 2.0 (the "License");
7    * you may not use this file except in compliance with the License.
8    * You may obtain a copy of the License at
9    *
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  import org.apache.maven.plugin.MojoExecutionException;
20  import org.apache.maven.plugin.MojoFailureException;
21  import org.apache.commons.io.FileUtils;
22  import org.appfuse.mojo.HibernateExporterMojo;
23  import org.hibernate.tool.hbm2x.Exporter;
24  import org.hibernate.tool.hbm2x.POJOExporter;
25  
26  import java.io.File;
27  import java.io.IOException;
28  import java.io.InputStream;
29  import java.io.InputStreamReader;
30  import java.io.BufferedReader;
31  import java.util.Iterator;
32  
33  /**
34   * Generates Java classes from existing database tables. If you want to customize the
35   * reverse engineering strategy, you can modify the default <a href="http://tinyurl.com/3qqgcl">hibernate.reveng.xml</a>
36   * and put it in src/test/resources. You can also override the location by specifying the "revengfile"
37   * property in the &lt;configuration&gt;. For example:
38   *
39   * <pre>
40     &lt;configuration&gt;
41     &nbsp;&nbsp;&lt;componentProperties&gt;
42     &nbsp;&nbsp;&nbsp;&nbsp;&lt;revengfile&gt;path/to/hibernate.reveng.xml&lt;/revengfile&gt;
43     &nbsp;&nbsp;&lt;/componentProperties&gt;
44     &nbsp;&nbsp;&lt;genericCore&gt;${amp.genericCore}&lt;/genericCore&gt;
45     &nbsp;&nbsp;&lt;fullSource&gt;${amp.fullSource}&lt;/fullSource&gt;
46     &lt;/configuration&gt;
47   * </pre>
48   *
49   * <p><b>Oracle Users</b>: If you create a custom hibernate.reveng.xml, make sure to capitalize the table names
50   * in &lt;schema-selection match-schema="MY_SCHEMA_NAME"/&gt;. You'll also need to add the following line to your
51   * jdbc.properties file:</p>
52   * <pre>
53     hibernatetool.metadatadialect=org.hibernate.cfg.reveng.dialect.OracleMetaDataDialect
54     </pre>
55   *
56   * @author <a href="mailto:jreyes@hiberforum.org">Johann Reyes</a>
57   * @version $Id: ModelGeneratorMojo.java 3535 2007-03-07 21:02:07Z jreyes $
58   * @goal gen-model
59   * @phase generate-sources
60   * @execute phase="process-resources"
61   */
62  public class ModelGeneratorMojo extends HibernateExporterMojo {
63      /**
64       * The path where the generated artifacts will be placed. This is intentionally not set to the
65       * default location for maven generated sources. This is to keep these files out of the
66       * eclipse/idea generated sources directory as the intention is that these files will be copied
67       * to a source directory to be edited and modified and not re generated each time the plugin is
68       * run. If you want to regenerate the files each time you build the project just set this value
69       * to ${basedir}/target/generated-sources or set the flag on eclipse/idea plugin to include this
70       * file in your project file as a source directory.
71       *
72       * @parameter expression="${appfuse.destinationDirectory}" default-value="${basedir}"
73       * @noinspection UnusedDeclaration
74       */
75      private String destinationDirectory;
76  
77      /**
78       * The directory containing the source code.
79       *
80       * @parameter expression="${appfuse.sourceDirectory}" default-value="${basedir}/target/appfuse/generated-sources"
81       * @noinspection UnusedDeclaration
82       */
83      private String sourceDirectory;
84  
85      /**
86       * Allows disabling installation - for tests and end users that don't want to do a full installation
87       *
88       * @parameter expression="${appfuse.disableInstallation}" default-value="false"
89       */
90      private boolean disableInstallation;
91  
92      /**
93       * @parameter expression="${appfuse.templateDirectory}" default-value="${basedir}/src/test/resources"
94       * @noinspection UnusedDeclaration
95       */
96      private String templateDirectory;
97  
98      /**
99       * Default constructor.
100      */
101     public ModelGeneratorMojo() {
102         addDefaultComponent("target/appfuse/generated-sources", "configuration", false);
103         addDefaultComponent("target/appfuse/generated-sources", "jdbcconfiguration", true);
104         addDefaultComponent("target/appfuse/generated-sources", "annotationconfiguration", true);
105     }
106 
107 // --------------------- Interface ExporterMojo ---------------------
108 
109     /**
110      * Returns <b>gen-model</b>.
111      *
112      * @return String goal's name
113      */
114     public String getName() {
115         return "gen-model";
116     }
117 
118     @Override
119     public void execute() throws MojoExecutionException, MojoFailureException {
120         getComponentProperties().put("implementation", "jdbcconfiguration");
121         getComponentProperties().put("outputDirectory",
122                 (sourceDirectory != null) ? sourceDirectory : "${basedir}/target/appfuse/generated-sources");
123 
124         // default location for reveng file is src/test/resources
125         File revengFile = new File("src/test/resources/hibernate.reveng.xml");
126         if (revengFile.exists() && getComponentProperty("revengfile") == null) {
127            getComponentProperties().put("revengfile", "src/test/resources/hibernate.reveng.xml");
128         }
129         
130         // Check for existence of hibernate.reveng.xml and if there isn't one, create it
131         // Specifying the file explicitly in pom.xml overrides default location
132         if (getComponentProperty("revengfile") == null) {
133             getComponentProperties().put("revengfile", "target/test-classes/hibernate.reveng.xml");
134         }
135 
136         File existingConfig = new File(getComponentProperty("revengfile"));
137         if (!existingConfig.exists()) {
138             InputStream in = this.getClass().getResourceAsStream("/appfuse/model/hibernate.reveng.ftl");
139             StringBuffer configFile = new StringBuffer();
140             try {
141                 InputStreamReader isr = new InputStreamReader(in);
142                 BufferedReader reader = new BufferedReader(isr);
143                 String line;
144                 while ((line = reader.readLine()) != null) {
145                     configFile.append(line).append("\n");
146                 }
147                 reader.close();
148 
149                 getLog().info("Writing 'hibernate.reveng.xml' to " + existingConfig.getPath());
150                 FileUtils.writeStringToFile(existingConfig, configFile.toString());
151             } catch (IOException io) {
152                 throw new MojoFailureException(io.getMessage());
153             }
154         }
155 
156         // if package name is not configured, default to project's groupId
157         if (getComponentProperty("packagename") == null) {
158             getComponentProperties().put("packagename", getProject().getGroupId() + ".model");
159         }
160         
161         if (getComponentProperty("configurationfile") == null) {
162             // look for jdbc.properties and set "propertyfile" to its path
163             File jdbcProperties = new File("target/classes/jdbc.properties");
164             if (!jdbcProperties.exists()) {
165                 jdbcProperties = new File("target/test-classes/jdbc.properties");
166             }
167             if (jdbcProperties.exists()) {
168                 if (getComponentProperty("propertyfile") == null) {
169                     getComponentProperties().put("propertyfile", jdbcProperties.getPath());
170                     getLog().debug("Set propertyfile to '" + jdbcProperties.getPath() + "'");
171                 }
172             } else {
173                 throw new MojoFailureException("Failed to find jdbc.properties in classpath.");
174             }
175         }
176 
177         // For some reason, the classloader created in HibernateExporterMojo does not work
178         // when using jdbcconfiguration - it can't find the JDBC Driver (no suitable driver).
179         // Skipping the resetting of the classloader and manually adding the dependency (with XML) works.
180         // It's ugly, but it works. I wish there was a way to get get this plugin to recognize the jdbc driver
181         // from the project.
182 
183         super.doExecute();
184 
185         if (System.getProperty("disableInstallation") != null) {
186             disableInstallation = Boolean.valueOf(System.getProperty("disableInstallation"));
187         }
188 
189         // allow installation to be supressed when testing
190         if (!disableInstallation) {
191             // copy the generated file to the model directory of the project
192             try {
193                 String packageName = getComponentProperties().get("packagename");
194                 String packageAsDir = packageName.replaceAll("\\.", "/");
195                 File dir = new File(sourceDirectory + "/" + packageAsDir);
196                 if (dir.exists()) {
197                     Iterator filesIterator = FileUtils.iterateFiles(dir, new String[] {"java"}, false);
198                     while (filesIterator.hasNext()) {
199                         File f = (File) filesIterator.next();
200                         getLog().info("Copying generated '" + f.getName() + "' to project...");
201                         FileUtils.copyFileToDirectory(f, new File(destinationDirectory + "/src/main/java/" + packageAsDir));
202                     }
203                 } else {
204                     throw new MojoFailureException("No tables found in database to generate code from.");
205                 }
206                 FileUtils.forceDelete(dir);
207             } catch (IOException io) {
208                 throw new MojoFailureException(io.getMessage());
209             }
210         }
211     }
212 
213     /**
214      * @see HibernateExporterMojo#configureExporter(org.hibernate.tool.hbm2x.Exporter)
215      */
216     protected Exporter configureExporter(Exporter exp) throws MojoExecutionException {
217         // add output directory to compile roots
218         getProject().addCompileSourceRoot(new File(getComponent().getOutputDirectory()).getPath());
219 
220         // now set the extra properties for the POJO Exporter
221         POJOExporter exporter = (POJOExporter) super.configureExporter(exp);
222 
223         // Add custom template path if specified
224         String[] templatePaths;
225         if (templateDirectory != null) {
226             templatePaths = new String[exporter.getTemplatePaths().length + 1];
227             templatePaths[0] = templateDirectory;
228             if (exporter.getTemplatePaths().length > 1) {
229                 for (int i = 1; i < exporter.getTemplatePaths().length; i++) {
230                     templatePaths[i] = exporter.getTemplatePaths()[i-1];
231                 }
232             }
233         } else {
234             templatePaths = exporter.getTemplatePaths();
235         }
236 
237         exporter.setTemplatePath(templatePaths);
238         exporter.setTemplateName("appfuse/model/Pojo.ftl");
239         exporter.getProperties().setProperty("basepackage", getProject().getGroupId());
240         exporter.getProperties().setProperty("ejb3", getComponentProperty("ejb3", "true"));
241         exporter.getProperties().setProperty("jdk5", getComponentProperty("jdk5", "true"));
242 
243         if (isFullSource()) {
244             exporter.getProperties().setProperty("appfusepackage", getProject().getGroupId());
245         } else {
246             exporter.getProperties().setProperty("appfusepackage", "org.appfuse");
247         }
248 
249         
250         return exporter;
251     }
252 
253     /**
254      * Instantiates a org.hibernate.tool.hbm2x.POJOExporter object.
255      *
256      * @return POJOExporter
257      */
258     protected Exporter createExporter() {
259         return new POJOExporter();
260     }
261 }