001: package org.andromda.ant.task;
002:
003: import java.io.FileNotFoundException;
004: import java.net.URL;
005: import java.util.Iterator;
006: import java.util.Map;
007:
008: import org.andromda.core.AndroMDA;
009: import org.andromda.core.common.ResourceUtils;
010: import org.apache.commons.lang.StringUtils;
011: import org.apache.commons.lang.exception.ExceptionUtils;
012: import org.apache.tools.ant.BuildException;
013: import org.apache.tools.ant.taskdefs.MatchingTask;
014:
015: /**
016: * <p/> This class wraps the AndroMDA model processor so that AndroMDA can be
017: * used as an Ant task. Represents the <code><andromda></code> custom
018: * task which can be called from an Ant build script.
019: * </p>
020: *
021: * @author <a href="http://www.mbohlen.de">Matthias Bohlen </a>
022: * @author <a href="http://www.amowers.com">Anthony Mowers </a>
023: * @author Chad Brandon
024: * @see org.andromda.core.AndroMDA
025: */
026: public class AndroMDAGenTask extends MatchingTask {
027: /**
028: * Initialize the context class loader.
029: */
030: static {
031: initializeContextClassLoader();
032: }
033:
034: /**
035: * Stores the configuration URI.
036: */
037: private URL configurationUri;
038:
039: /**
040: * Sets the URI to the configuration file.
041: *
042: * @param configurationUri
043: */
044: public void setConfigurationUri(final URL configurationUri) {
045: this .configurationUri = configurationUri;
046: }
047:
048: /**
049: * <p/>
050: * Starts the generation of source code from an object model. </p>
051: * <p/>
052: * This is the main entry point of the application when running Ant. It is called by ant whenever the surrounding
053: * task is executed (which could be multiple times). </p>
054: *
055: * @throws BuildException if something goes wrong
056: */
057: public void execute() throws BuildException {
058: // initialize before the execute as well in case we
059: // want to execute more than once
060: initializeContextClassLoader();
061: try {
062: if (this .configurationUri == null) {
063: throw new BuildException(
064: "Configuration is not a valid URI --> '"
065: + this .configurationUri + "'");
066: }
067: final AndroMDA andromda = AndroMDA.newInstance();
068: if (andromda != null) {
069: andromda.run(this .replaceProperties(ResourceUtils
070: .getContents(configurationUri)));
071: andromda.shutdown();
072: }
073: } catch (Throwable throwable) {
074: final Throwable cause = ExceptionUtils.getCause(throwable);
075: if (cause != null) {
076: throwable = cause;
077: }
078: if (throwable instanceof FileNotFoundException) {
079: throw new BuildException(
080: "No configuration could be loaded from --> '"
081: + configurationUri + "'");
082: }
083: throw new BuildException(throwable);
084: } finally {
085: // Set the context class loader back ot its system class loaders
086: // so that any processes running after won't be trying to use
087: // the ContextClassLoader for this class.
088: Thread.currentThread().setContextClassLoader(
089: ClassLoader.getSystemClassLoader());
090: }
091: }
092:
093: /**
094: * Replaces all properties having the style
095: * <code>${some.property}</code> with the value
096: * of the specified property if there is one.
097: *
098: * @param fileContents the fileContents to perform replacement on.
099: */
100: protected String replaceProperties(String string) {
101: final Map properties = this .getProject().getProperties();
102: if (properties != null && !properties.isEmpty()) {
103: for (final Iterator iterator = properties.keySet()
104: .iterator(); iterator.hasNext();) {
105: final String name = (String) iterator.next();
106: final String property = "${" + name + "}";
107: final String value = (String) properties.get(name);
108: string = StringUtils.replace(string, property, value);
109: }
110: }
111:
112: // remove any left over property references
113: string = this .removePropertyReferences(string);
114: return string;
115: }
116:
117: /**
118: * The property reference pattern.
119: */
120: private static final String PROPERTY_REFERENCE = "\\$\\{.*\\}";
121:
122: /**
123: * Removes any ${some.property} type references from the string
124: * and returns the modifed string.
125: * @param string the string from which to remove the property
126: * references
127: *
128: * @return the modified string.
129: */
130: public String removePropertyReferences(String string) {
131: if (string != null) {
132: string = string.replaceAll(PROPERTY_REFERENCE, "");
133: }
134: return string;
135: }
136:
137: /**
138: * Set the context class loader so that any classes using it (the contextContextClassLoader) have access to the
139: * correct loader.
140: */
141: private final static void initializeContextClassLoader() {
142: Thread.currentThread().setContextClassLoader(
143: AndroMDAGenTask.class.getClassLoader());
144: }
145: }
|