1 package org.andromda.ant.task;
2
3 import java.io.FileNotFoundException;
4 import java.net.URL;
5 import java.util.Iterator;
6 import java.util.Map;
7
8 import org.andromda.core.AndroMDA;
9 import org.andromda.core.common.ResourceUtils;
10 import org.apache.commons.lang.StringUtils;
11 import org.apache.commons.lang.exception.ExceptionUtils;
12 import org.apache.tools.ant.BuildException;
13 import org.apache.tools.ant.taskdefs.MatchingTask;
14
15
16 /***
17 * <p/> This class wraps the AndroMDA model processor so that AndroMDA can be
18 * used as an Ant task. Represents the <code><andromda></code> custom
19 * task which can be called from an Ant build script.
20 * </p>
21 *
22 * @author <a href="http://www.mbohlen.de">Matthias Bohlen </a>
23 * @author <a href="http://www.amowers.com">Anthony Mowers </a>
24 * @author Chad Brandon
25 * @see org.andromda.core.AndroMDA
26 */
27 public class AndroMDAGenTask
28 extends MatchingTask
29 {
30 /***
31 * Initialize the context class loader.
32 */
33 static
34 {
35 initializeContextClassLoader();
36 }
37
38 /***
39 * Stores the configuration URI.
40 */
41 private URL configurationUri;
42
43 /***
44 * Sets the URI to the configuration file.
45 *
46 * @param configurationUri
47 */
48 public void setConfigurationUri(final URL configurationUri)
49 {
50 this.configurationUri = configurationUri;
51 }
52
53 /***
54 * <p/>
55 * Starts the generation of source code from an object model. </p>
56 * <p/>
57 * This is the main entry point of the application when running Ant. It is called by ant whenever the surrounding
58 * task is executed (which could be multiple times). </p>
59 *
60 * @throws BuildException if something goes wrong
61 */
62 public void execute()
63 throws BuildException
64 {
65
66
67 initializeContextClassLoader();
68 try
69 {
70 if (this.configurationUri == null)
71 {
72 throw new BuildException("Configuration is not a valid URI --> '" + this.configurationUri + "'");
73 }
74 final AndroMDA andromda = AndroMDA.newInstance();
75 if (andromda != null)
76 {
77 andromda.run(
78 this.replaceProperties(ResourceUtils.getContents(configurationUri)));
79 andromda.shutdown();
80 }
81 }
82 catch (Throwable throwable)
83 {
84 final Throwable cause = ExceptionUtils.getCause(throwable);
85 if (cause != null)
86 {
87 throwable = cause;
88 }
89 if (throwable instanceof FileNotFoundException)
90 {
91 throw new BuildException("No configuration could be loaded from --> '" + configurationUri + "'");
92 }
93 throw new BuildException(throwable);
94 }
95 finally
96 {
97
98
99
100 Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
101 }
102 }
103
104 /***
105 * Replaces all properties having the style
106 * <code>${some.property}</code> with the value
107 * of the specified property if there is one.
108 *
109 * @param fileContents the fileContents to perform replacement on.
110 */
111 protected String replaceProperties(String string)
112 {
113 final Map properties = this.getProject().getProperties();
114 if (properties != null && !properties.isEmpty())
115 {
116 for (final Iterator iterator = properties.keySet().iterator(); iterator.hasNext();)
117 {
118 final String name = (String)iterator.next();
119 final String property = "${" + name + "}";
120 final String value = (String)properties.get(name);
121 string = StringUtils.replace(string, property, value);
122 }
123 }
124
125
126 string = this.removePropertyReferences(string);
127 return string;
128 }
129
130 /***
131 * The property reference pattern.
132 */
133 private static final String PROPERTY_REFERENCE = "//$//{.*//}";
134
135 /***
136 * Removes any ${some.property} type references from the string
137 * and returns the modifed string.
138 * @param string the string from which to remove the property
139 * references
140 *
141 * @return the modified string.
142 */
143 public String removePropertyReferences(String string)
144 {
145 if (string != null)
146 {
147 string = string.replaceAll(PROPERTY_REFERENCE, "");
148 }
149 return string;
150 }
151
152 /***
153 * Set the context class loader so that any classes using it (the contextContextClassLoader) have access to the
154 * correct loader.
155 */
156 private final static void initializeContextClassLoader()
157 {
158 Thread.currentThread().setContextClassLoader(AndroMDAGenTask.class.getClassLoader());
159 }
160 }