1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package nl.toolforge.karma.core.cmd.impl;
20
21 import nl.toolforge.core.util.file.MyFileUtils;
22 import nl.toolforge.karma.core.KarmaRuntimeException;
23 import nl.toolforge.karma.core.cmd.CommandDescriptor;
24 import nl.toolforge.karma.core.cmd.CommandException;
25 import nl.toolforge.karma.core.cmd.DefaultCommand;
26 import nl.toolforge.karma.core.cmd.util.AntLogger;
27 import nl.toolforge.karma.core.cmd.util.BuildEnvironment;
28 import nl.toolforge.karma.core.manifest.Manifest;
29 import nl.toolforge.karma.core.manifest.ManifestException;
30 import nl.toolforge.karma.core.module.Module;
31 import nl.toolforge.karma.core.module.ModuleTypeException;
32 import org.apache.commons.io.FileUtils;
33 import org.apache.commons.logging.Log;
34 import org.apache.commons.logging.LogFactory;
35 import org.apache.tools.ant.Project;
36 import org.apache.tools.ant.ProjectHelper;
37 import org.apache.tools.ant.helper.ProjectHelperImpl;
38 import org.apache.tools.ant.taskdefs.Delete;
39 import org.apache.tools.ant.taskdefs.Mkdir;
40 import org.apache.tools.ant.types.FileSet;
41
42 import java.io.BufferedReader;
43 import java.io.BufferedWriter;
44 import java.io.File;
45 import java.io.FileWriter;
46 import java.io.IOException;
47 import java.io.InputStreamReader;
48
49 /***
50 * Superclass for all commands dealing with building modules. This class provides all basic property mappers and methods
51 * that are required to use the <code>build-module.xml</code> properly.
52 *
53 * @author D.A. Smedes
54 * @author W.H. Schraal
55 * @version $Id: AbstractBuildCommand.java,v 1.38 2004/11/10 23:53:08 asmedes Exp $
56 */
57 public abstract class AbstractBuildCommand extends DefaultCommand {
58
59 private static final Log logger = LogFactory.getLog(AbstractBuildCommand.class);
60
61 protected Module module = null;
62
63 private File tempBuildFileLocation = null;
64 private Project project = null;
65 private BuildEnvironment env = null;
66
67 /***
68 * Creates a command by initializing the command through its <code>CommandDescriptor</code>.
69 *
70 * @param descriptor The command descriptor instance containing the basic information for this command
71 */
72 public AbstractBuildCommand(CommandDescriptor descriptor) {
73 super(descriptor);
74 }
75
76 public void execute() throws CommandException {
77
78 if (!getContext().isManifestLoaded()) {
79 throw new CommandException(ManifestException.NO_ACTIVE_MANIFEST);
80 }
81
82 if (getCommandLine().hasOption("m")) {
83 String moduleName = getCommandLine().getOptionValue("m");
84
85 try {
86
87
88 module = getCurrentManifest().getModule(moduleName);
89
90 if (module == null) {
91 throw new CommandException(ManifestException.MODULE_NOT_FOUND, new Object[]{module});
92 }
93
94 if (!getCurrentManifest().isLocal(module)) {
95 throw new CommandException(ManifestException.MODULE_NOT_LOCAL, new Object[]{module});
96 }
97
98
99 } catch (ManifestException m) {
100 throw new CommandException(m.getErrorCode(), m.getMessageArguments());
101 }
102 }
103
104
105
106 env = new BuildEnvironment(getCurrentManifest(), module);
107 }
108
109 /***
110 * Helper method to retrieve the current manifest.
111 *
112 * @return The current manifest.
113 */
114 protected final Manifest getCurrentManifest() {
115 return getContext().getCurrentManifest();
116 }
117
118 /***
119 * Helper method to get to the current module.
120 *
121 * @return
122 */
123 protected Module getCurrentModule() {
124
125 if (module == null) {
126 throw new KarmaRuntimeException("Module is null. Execute method has not been called by subclass.");
127 }
128 return module;
129 }
130
131 /***
132 * Retrieve the build environment, which is initialized with the current manifest and module.
133 */
134 protected BuildEnvironment getBuildEnvironment() {
135 return env;
136 }
137
138 /***
139 * Returns the compile directory for a module, relative to the manifests' <code>build</code> directory.
140 *
141 * @return
142 */
143 protected final File getCompileDirectory() throws ModuleTypeException {
144
145 if (module == null) {
146 throw new IllegalArgumentException("Module cannot be null.");
147 }
148
149 File base = env.getModuleBuildRootDirectory();
150
151 if (module.getType().equals(Module.JAVA_WEB_APPLICATION)) {
152 return new File(base, "build/WEB-INF/classes");
153 } else {
154 return new File(base, "build");
155 }
156 }
157
158 /***
159 * Gets an Ant project initializing the project with <code>buildFile</code> which should be located on the
160 * classpath in the <code>ant</code> subdirectory.
161 *
162 * @param buildFile The build file that should be loaded.
163 * @return An Ant project initialized with <code>buildFile</code>.
164 */
165 protected Project getAntProject(String buildFile) throws CommandException {
166
167 ProjectHelper helper = new ProjectHelperImpl();
168 try {
169 File tmp = getBuildFile(buildFile);
170 helper.parse(getProjectInstance(), tmp);
171 setBuildFileLocation(tmp);
172 } catch (IOException e) {
173 throw new CommandException(e, CommandException.BUILD_FAILED, new Object[] {getCurrentModule().getName()});
174 }
175
176 return project;
177 }
178
179
180 /***
181 * Gets an Ant <code>Project</code> for a module.
182 *
183 * @return
184 * @throws CommandException
185 */
186 protected Project getProjectInstance() throws CommandException {
187
188 if (project == null) {
189
190
191 AntLogger logger = new AntLogger(this);
192
193
194
195 logger.setOutputPrintStream(System.out);
196
197
198 String logLevel = System.getProperty("antloglevel");
199 int antLogLevel = Project.MSG_WARN;
200 if (logLevel.equalsIgnoreCase("debug")) {
201 antLogLevel = Project.MSG_DEBUG;
202 } else if (logLevel.equalsIgnoreCase("info")) {
203 antLogLevel = Project.MSG_INFO;
204 }
205 logger.setMessageOutputLevel(antLogLevel);
206
207
208
209 project = new Project();
210 project.addBuildListener(logger);
211 project.init();
212 }
213
214 return project;
215 }
216
217 /***
218 * Performs an <mkdir>-task on this commands' Ant project.
219 */
220 public void executeMkdir(File dir) throws CommandException {
221
222 if (project == null) {
223 project = getProjectInstance();
224 }
225
226 Mkdir mkdir = new Mkdir();
227 mkdir.setProject(project);
228 mkdir.setDir(dir);
229 mkdir.execute();
230 }
231
232 /***
233 * Performs a <delete>-task on this commands' Ant project.
234 */
235 public void executeDelete(File dir, String includes) throws CommandException {
236
237 if (project == null) {
238 project = getProjectInstance();
239 }
240
241 if (dir != null && dir.exists()) {
242
243
244
245 Delete delete = new Delete();
246 delete.setProject(project);
247
248 FileSet fileset = new FileSet();
249 fileset.setDir(dir);
250 fileset.setIncludes(includes);
251
252 delete.addFileset(fileset);
253 delete.execute();
254 }
255 }
256
257 public void executeDelete(File dir) throws CommandException {
258
259 if (project == null) {
260 project = getProjectInstance();
261 }
262
263 try {
264
265
266
267 Delete delete = new Delete();
268 delete.setProject(project);
269
270 if (dir.equals(new File("."))) {
271 throw new KarmaRuntimeException("We don't do that stuff here ...");
272 }
273
274 delete.setDir(dir);
275 delete.execute();
276 } catch (RuntimeException r) {
277 throw new CommandException(CommandException.BUILD_FAILED, new Object[]{r.getMessage()});
278 }
279 }
280
281 private final File getBuildFile(String buildFile) throws IOException {
282
283 File tmp = null;
284
285 tmp = MyFileUtils.createTempDirectory();
286
287 ClassLoader loader = this.getClass().getClassLoader();
288
289 BufferedReader in =
290 new BufferedReader(new InputStreamReader(loader.getResourceAsStream("ant/" + buildFile)));
291 BufferedWriter out =
292 new BufferedWriter(new FileWriter(new File(tmp, buildFile)));
293
294 String str;
295 while ((str = in.readLine()) != null) {
296 out.write(str);
297 }
298 out.close();
299 in.close();
300
301
302
303 return new File(tmp, buildFile);
304 }
305
306 private void setBuildFileLocation(File tmpBuildFileLocation) {
307 this.tempBuildFileLocation = tmpBuildFileLocation;
308 }
309
310 /***
311 * Called by {@link nl.toolforge.karma.core.cmd.CommandContext} after executing a command.
312 */
313 public final void cleanUp() {
314
315 try {
316 if (tempBuildFileLocation != null) {
317 FileUtils.deleteDirectory(tempBuildFileLocation.getParentFile());
318 }
319 } catch (IOException e) {
320 logger.warn("Could not remove temporary directory for Ant build file.");
321 }
322 }
323
324 }