001: package org.andromda.maven.plugin.andromdapp.hibernate;
002:
003: import java.io.File;
004: import java.lang.reflect.Method;
005: import java.sql.Connection;
006: import java.util.ArrayList;
007: import java.util.Arrays;
008: import java.util.Iterator;
009: import java.util.List;
010: import java.util.Map;
011:
012: import org.andromda.core.common.ClassUtils;
013: import org.andromda.maven.plugin.andromdapp.SchemaManagement;
014: import org.andromda.maven.plugin.andromdapp.SchemaManagementException;
015: import org.apache.commons.lang.ObjectUtils;
016: import org.apache.log4j.Logger;
017: import org.codehaus.plexus.util.DirectoryScanner;
018:
019: /**
020: * A Hibernate management object.
021: *
022: * @author Chad Brandon
023: */
024: public abstract class HibernateSchemaManagement implements
025: SchemaManagement {
026: protected static Logger logger = Logger
027: .getLogger(HibernateSchemaManagement.class);
028:
029: /**
030: * The Hibernate 2 schema export class name.
031: */
032: protected static final String HIBERNATE_2_PACKAGE = "net.sf.hibernate.tool.hbm2ddl";
033:
034: /**
035: * The Hibernate 3 schema export class name.
036: */
037: protected static final String HIBERNATE_3_PACKAGE = "org.hibernate.tool.hbm2ddl";
038:
039: /**
040: * The Hibernate version
041: */
042: private String version;
043:
044: /**
045: * Sets the version of Hibernate to target.
046: *
047: * @param version the version of Hibernate to target.
048: */
049: public void setVersion(final String version) {
050: this .version = version;
051: }
052:
053: /**
054: * Retrieves the class that performs the execution work.
055: *
056: * @return the Hibernate class that performs the work.
057: */
058: protected Class getExecutionClass() {
059: Class hibernateClass = null;
060: String hibernate2ClassName = null;
061: String hibernate3ClassName = null;
062: try {
063: hibernate3ClassName = HIBERNATE_3_PACKAGE + "."
064: + this .getExecutionClassName();
065: hibernateClass = ClassUtils.loadClass(hibernate3ClassName);
066: } catch (Exception exception) {
067: // - ignore, means we can't find the Hibernate 3 class
068: }
069: try {
070: hibernate2ClassName = HIBERNATE_2_PACKAGE + "."
071: + this .getExecutionClassName();
072: hibernateClass = ClassUtils.loadClass(hibernate2ClassName);
073: } catch (Exception exception) {
074: // - ignore, means we can't find the Hibernate 2 class
075: }
076: if (hibernateClass == null) {
077: throw new RuntimeException(
078: "There appear to be no Hibernate 2 or 3 jars are your classpath, because neither '"
079: + hibernate2ClassName
080: + "', nor '"
081: + hibernate3ClassName + "' could be found");
082: }
083: return hibernateClass;
084: }
085:
086: /**
087: * Returns the current Hibernate version this management object
088: * is targetting.
089: *
090: * @return the Hibernate version (2 or 3).
091: */
092: protected String getVersion() {
093: return this .version;
094: }
095:
096: /**
097: * Stores the path to which output should be written.
098: */
099: private String outputPath;
100:
101: /**
102: * Sets the path to which the output should be written.
103: *
104: * @param outputPath
105: */
106: public void setOutputPath(final String outputPath) {
107: this .outputPath = outputPath;
108: }
109:
110: /**
111: * Attempts to retrieve the given property with the given <code>name</code>.
112: * If the property isn't found an exception is thrown.
113: *
114: * @param properties the properties from which to retrieve the property.
115: * @param name the name of the property to retrieve.
116: * @return the value of the property.
117: */
118: protected String getRequiredProperty(final Map properties,
119: final String name) {
120: final String value = ObjectUtils.toString(properties.get(name));
121: if (value == null || value.trim().length() == 0) {
122: throw new SchemaManagementException("The '" + name
123: + "' must be specified");
124: }
125: return value;
126: }
127:
128: /**
129: * Gets the path to which output should be written.
130: *
131: * @return the output path.
132: */
133: protected String getOutputPath() {
134: return this .outputPath;
135: }
136:
137: /**
138: * Returns the name of the class that performs the execution.
139: *
140: * @return the execution class.
141: */
142: protected abstract String getExecutionClassName();
143:
144: /**
145: * @see org.andromda.maven.plugin.andromdapp.SchemaManagement#execute(java.sql.Connection, java.util.Map)
146: */
147: public String execute(Connection connection, java.util.Map options)
148: throws Exception {
149: final String hibernateDialect = "hibernate.dialect";
150: System.setProperty(hibernateDialect, this .getRequiredProperty(
151: options, hibernateDialect));
152: final String[] arguments = (String[]) this
153: .getArguments(options).toArray(new String[0]);
154: final Class executionClass = this .getExecutionClass();
155: final Method method = executionClass.getMethod("main",
156: new Class[] { String[].class });
157: method.invoke(executionClass, new Object[] { arguments });
158:
159: return this .getExecutionOuputPath(options);
160: }
161:
162: /**
163: * Returns the path of the execution output file.
164: *
165: * @param options the options from which to retrieve properties.
166: * @return the output path.
167: */
168: protected abstract String getExecutionOuputPath(final Map options);
169:
170: /**
171: * Retrieves the arguments common to all Hibernate schema management
172: * tasks.
173: *
174: * @param options the options from which to retrieve any required properties.
175: * @return the list of common arguments.
176: */
177: private List getArguments(final Map options) throws Exception {
178: final List mappingFiles = this .getMappingFilesList(this
179: .getRequiredProperty(options, "mappingFileExtension"),
180: this .getRequiredProperty(options, "mappingsLocation"));
181: final String[] args = new String[] { "--delimiter=;",
182: "--format" };
183: final List arguments = new ArrayList(Arrays.asList(args));
184: arguments.addAll(mappingFiles);
185: this .addArguments(options, arguments);
186: return arguments;
187: }
188:
189: /**
190: * Adds any arguments required by the specialized class.
191: *
192: * @param options any options from which to retrieve argument values.
193: * @param arguments the list of arguments to add.
194: */
195: protected abstract void addArguments(final Map options,
196: final List arguments) throws Exception;
197:
198: /**
199: * Retrieves all mapping files having the given <code>extension</code>
200: * existing in the <code>baseDirectory</code> or any of its sub directories.
201: *
202: * @param extension the mapping file extension
203: * @param baseDirectory the directory from which to perform the search.
204: * @return the list of mapping files
205: */
206: protected List getMappingFilesList(final String extension,
207: final String baseDirectory) {
208: final DirectoryScanner scanner = new DirectoryScanner();
209: scanner.setBasedir(baseDirectory);
210: scanner.setIncludes(new String[] { "**/*." + extension });
211: scanner.setExcludes(null);
212: scanner.scan();
213:
214: final List files = new ArrayList();
215: for (final Iterator iterator = Arrays.asList(
216: scanner.getIncludedFiles()).iterator(); iterator
217: .hasNext();) {
218: final String path = (String) iterator.next();
219: files.add(new File(baseDirectory, path).toString());
220: }
221: return files;
222: }
223: }
|