1 package org
.argeo
.slc
.ant
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
8 import java
.util
.Properties
;
9 import java
.util
.StringTokenizer
;
10 import java
.util
.Vector
;
12 import org
.apache
.commons
.io
.IOUtils
;
13 import org
.apache
.commons
.logging
.Log
;
14 import org
.apache
.commons
.logging
.LogFactory
;
15 import org
.apache
.log4j
.Appender
;
16 import org
.apache
.log4j
.LogManager
;
17 import org
.apache
.log4j
.MDC
;
18 import org
.apache
.tools
.ant
.BuildListener
;
19 import org
.apache
.tools
.ant
.Project
;
20 import org
.apache
.tools
.ant
.ProjectHelper
;
21 import org
.apache
.tools
.ant
.helper
.ProjectHelper2
;
22 import org
.argeo
.slc
.SlcException
;
23 import org
.argeo
.slc
.core
.structure
.SimpleSElement
;
24 import org
.argeo
.slc
.core
.structure
.tree
.TreeSPath
;
25 import org
.argeo
.slc
.core
.structure
.tree
.TreeSRegistry
;
26 import org
.argeo
.slc
.logging
.Log4jUtils
;
27 import org
.argeo
.slc
.process
.SlcExecution
;
28 import org
.argeo
.slc
.runtime
.SlcApplication
;
29 import org
.argeo
.slc
.runtime
.SlcExecutionOutput
;
30 import org
.argeo
.slc
.spring
.SpringUtils
;
31 import org
.argeo
.slc
.structure
.StructureRegistry
;
32 import org
.springframework
.beans
.factory
.BeanFactoryUtils
;
33 import org
.springframework
.beans
.factory
.ListableBeanFactory
;
34 import org
.springframework
.beans
.factory
.config
.PropertyPlaceholderConfigurer
;
35 import org
.springframework
.beans
.factory
.xml
.XmlBeanDefinitionReader
;
36 import org
.springframework
.context
.ConfigurableApplicationContext
;
37 import org
.springframework
.context
.support
.GenericApplicationContext
;
38 import org
.springframework
.core
.io
.DefaultResourceLoader
;
39 import org
.springframework
.core
.io
.Resource
;
40 import org
.springframework
.core
.io
.ResourceLoader
;
41 import org
.springframework
.util
.SystemPropertyUtils
;
43 public class AntSlcApplication
implements SlcApplication
<AntExecutionContext
> {
44 private final static String DEFAULT_APP_LOG4J_PROPERTIES
= "org/argeo/slc/ant/defaultAppLog4j.properties";
46 private final static Log log
= LogFactory
.getLog(AntSlcApplication
.class);
48 private Resource contextLocation
;
49 private ConfigurableApplicationContext parentContext
;
51 private Resource rootDir
;
52 private Resource confDir
;
55 private Resource slcRootFile
;
57 public void execute(SlcExecution slcExecution
, Properties properties
,
58 Map
<String
, Object
> references
,
59 SlcExecutionOutput
<AntExecutionContext
> executionOutput
) {
61 // Properties and application logging initialization
62 initSystemProperties(properties
);
63 Log4jUtils
.initLog4j("classpath:" + DEFAULT_APP_LOG4J_PROPERTIES
);
65 log
.info("\n###\n### Start SLC execution " + slcExecution
.getUuid()
67 if (log
.isDebugEnabled()) {
68 log
.debug("rootDir=" + rootDir
);
69 log
.debug("confDir=" + confDir
);
70 log
.debug("workDir=" + workDir
);
74 String scriptRelativePath
= findAntScript(slcExecution
);
75 List
<String
> targets
= findAntTargets(slcExecution
);
77 // Spring initialization
78 ConfigurableApplicationContext ctx
= createExecutionContext(slcExecution
);
80 // Ant project initialization
81 Project project
= new Project();
82 AntExecutionContext executionContext
= new AntExecutionContext(project
);
83 project
.addReference(AntConstants
.REF_ROOT_CONTEXT
, ctx
);
84 project
.addReference(AntConstants
.REF_SLC_EXECUTION
, slcExecution
);
87 initProject(project
, properties
, references
);
88 parseProject(project
, scriptRelativePath
);
91 initStructure(project
, scriptRelativePath
);
92 runProject(project
, targets
);
94 if (executionOutput
!= null)
95 executionOutput
.postExecution(executionContext
);
101 protected void initSystemProperties(Properties userProperties
) {
102 // Set user properties as system properties so that Spring can access
104 if (userProperties
!= null) {
105 for (Object key
: userProperties
.keySet()) {
106 System
.setProperty(key
.toString(), userProperties
107 .getProperty(key
.toString()));
111 if (System
.getProperty(AntConstants
.DEFAULT_TEST_RUN_PROPERTY
) == null) {
112 System
.setProperty(AntConstants
.DEFAULT_TEST_RUN_PROPERTY
,
118 setSystemPropertyForRes(AntConstants
.ROOT_DIR_PROPERTY
, rootDir
);
120 setSystemPropertyForRes(AntConstants
.CONF_DIR_PROPERTY
, confDir
);
122 System
.setProperty(AntConstants
.WORK_DIR_PROPERTY
, workDir
123 .getCanonicalPath());
125 // Additional properties in slc.properties file. Already set sytem
126 // properties (such as the various directories) can be resolved in
128 if (confDir
!= null) {
129 Resource slcPropertiesRes
= confDir
130 .createRelative("slc.properties");
131 if (slcPropertiesRes
.exists()) {
132 Properties slcProperties
= new Properties();
133 InputStream in
= slcPropertiesRes
.getInputStream();
135 slcProperties
.load(in
);
137 IOUtils
.closeQuietly(in
);
140 for (Object obj
: slcProperties
.keySet()) {
141 String key
= obj
.toString();
142 if (!System
.getProperties().containsKey(key
)) {
143 String value
= SystemPropertyUtils
144 .resolvePlaceholders(slcProperties
146 System
.setProperty(key
, value
);
151 } catch (Exception e
) {
152 throw new SlcException("Cannot init system properties.", e
);
157 * Set property as an absolute file path if the resource can be located on
158 * the file system, or as an url.
160 private void setSystemPropertyForRes(String key
, Resource res
)
164 value
= res
.getFile().getCanonicalPath();
165 } catch (IOException e
) {
166 value
= res
.getURL().toString();
168 System
.setProperty(key
, value
);
171 protected ConfigurableApplicationContext
createExecutionContext(
172 SlcExecution slcExecution
) {
175 // Find runtime definition
176 Resource runtimeRes
= null;
177 String runtimeStr
= slcExecution
.getAttributes().get(
178 AntConstants
.EXECATTR_RUNTIME
);
179 if (runtimeStr
== null)
180 runtimeStr
= System
.getProperty(AntConstants
.RUNTIME_PROPERTY
,
183 ResourceLoader rl
= new DefaultResourceLoader(getClass()
185 try {// tries absolute reference
186 runtimeRes
= rl
.getResource(runtimeStr
);
187 } catch (Exception e
) {
190 if (runtimeRes
== null || !runtimeRes
.exists()) {
192 runtimeRes
= confDir
.createRelative("runtime/" + runtimeStr
196 // Find runtime independent application context definition
197 if (confDir
!= null && contextLocation
== null) {
198 contextLocation
= confDir
199 .createRelative("applicationContext.xml");
202 GenericApplicationContext ctx
= new GenericApplicationContext(
204 ctx
.setDisplayName("SLC Execution #" + slcExecution
.getUuid());
206 XmlBeanDefinitionReader xmlReader
= new XmlBeanDefinitionReader(ctx
);
207 if (runtimeRes
!= null && runtimeRes
.exists())
208 xmlReader
.loadBeanDefinitions(runtimeRes
);
210 log
.warn("No runtime context defined");
212 if (contextLocation
!= null && contextLocation
.exists())
213 xmlReader
.loadBeanDefinitions(contextLocation
);
215 log
.warn("No runtime independent application context defined");
217 // Add property place holder
218 PropertyPlaceholderConfigurer ppc
= new PropertyPlaceholderConfigurer();
219 ppc
.setIgnoreUnresolvablePlaceholders(true);
220 ctx
.addBeanFactoryPostProcessor(ppc
);
224 } catch (Exception e
) {
225 throw new SlcException(
226 "Cannot create SLC execution application context.", e
);
230 protected String
findAntScript(SlcExecution slcExecution
) {
231 String scriptStr
= slcExecution
.getAttributes().get(
232 AntConstants
.EXECATTR_ANT_FILE
);
233 if (scriptStr
== null)
234 throw new SlcException("No Ant script provided");
239 protected List
<String
> findAntTargets(SlcExecution slcExecution
) {
240 String targetList
= slcExecution
.getAttributes().get(
241 AntConstants
.EXECATTR_ANT_TARGETS
);
242 List
<String
> targets
= new Vector
<String
>();
243 if (targetList
!= null) {
244 StringTokenizer stTargets
= new StringTokenizer(targetList
, ",");
245 while (stTargets
.hasMoreTokens()) {
246 targets
.add(stTargets
.nextToken());
252 protected void initProject(Project project
, Properties properties
,
253 Map
<String
, Object
> references
) {
254 if (properties
!= null) {
255 for (Map
.Entry
<Object
, Object
> entry
: properties
.entrySet()) {
256 project
.setUserProperty(entry
.getKey().toString(), entry
257 .getValue().toString());
261 if (references
!= null) {
262 for (Map
.Entry
<String
, Object
> entry
: references
.entrySet()) {
263 project
.addReference(entry
.getKey(), entry
.getValue());
267 // project.addBuildListener(new CommonsLoggingListener());
269 ListableBeanFactory context
= (ListableBeanFactory
) project
270 .getReference(AntConstants
.REF_ROOT_CONTEXT
);
271 // Register build listeners
272 Map
<String
, BuildListener
> listeners
= BeanFactoryUtils
273 .beansOfTypeIncludingAncestors(context
, BuildListener
.class,
275 for (BuildListener listener
: listeners
.values()) {
276 project
.addBuildListener(listener
);
279 // Register log4j appenders from context
280 MDC
.put(AntConstants
.MDC_ANT_PROJECT
, project
);
281 Map
<String
, Appender
> appenders
= context
.getBeansOfType(
282 Appender
.class, false, true);
283 for (Appender appender
: appenders
.values()) {
284 LogManager
.getRootLogger().addAppender(appender
);
288 addCustomTaskAndTypes(project
);
291 /** Loads the SLC specific Ant tasks. */
292 protected void addCustomTaskAndTypes(Project project
) {
293 Properties taskdefs
= getDefs(project
,
294 AntConstants
.SLC_TASKDEFS_RESOURCE_PATH
);
295 for (Object o
: taskdefs
.keySet()) {
296 String name
= o
.toString();
297 String className
= taskdefs
.getProperty(name
);
299 project
.addTaskDefinition(name
, Class
.forName(className
));
300 } catch (ClassNotFoundException e
) {
301 log
.warn("Unknown class " + className
+ " for task " + name
);
304 Properties typedefs
= getDefs(project
,
305 AntConstants
.SLC_TYPEDEFS_RESOURCE_PATH
);
306 for (Object o
: typedefs
.keySet()) {
307 String name
= o
.toString();
309 project
.addDataTypeDefinition(name
, Class
.forName(typedefs
310 .getProperty(name
)));
311 } catch (ClassNotFoundException e
) {
312 log
.error("Unknown class for type " + name
, e
);
317 private Properties
getDefs(Project project
, String path
) {
318 Properties defs
= new Properties();
320 InputStream in
= project
.getClass().getResourceAsStream(path
);
323 } catch (IOException e
) {
324 throw new SlcException("Cannot load task definitions", e
);
329 protected void initStructure(Project project
, String scriptRelativePath
) {
330 // Init structure registry
331 StructureRegistry
<TreeSPath
> registry
= new TreeSRegistry();
332 project
.addReference(AntConstants
.REF_STRUCTURE_REGISTRY
, registry
);
335 StringTokenizer st
= new StringTokenizer(scriptRelativePath
, "/");
336 TreeSPath currPath
= null;
337 while (st
.hasMoreTokens()) {
338 String name
= st
.nextToken();
339 if (currPath
== null) {
340 currPath
= TreeSPath
.createRootPath(name
);
342 if (st
.hasMoreTokens())// don't register project file
343 currPath
= currPath
.createChild(name
);
345 registry
.register(currPath
, new SimpleSElement(name
));
349 String projectName
= project
.getName() != null
350 && !project
.getName().equals("") ? project
.getName()
352 TreeSPath projectPath
= currPath
.createChild(projectName
);
354 String projectDesc
= project
.getDescription() != null
355 && !project
.getDescription().equals("") ? project
356 .getDescription() : projectPath
.getName();
358 registry
.register(projectPath
, new SimpleSElement(projectDesc
));
359 project
.addReference(AntConstants
.REF_PROJECT_PATH
, projectPath
);
361 if (log
.isDebugEnabled())
362 log
.debug("Project path: " + projectPath
);
365 protected void parseProject(Project project
, String scriptRelativePath
) {
367 Resource script
= rootDir
.createRelative(scriptRelativePath
);
370 File scriptFile
= script
.getFile();
371 baseDir
= scriptFile
.getParentFile();
372 } catch (IOException e
) {// resource is not a file
373 baseDir
= new File(System
.getProperty("user.dir"));
375 project
.setBaseDir(baseDir
);
376 // Reset basedir property, in order to avoid base dir override when
378 project
.setProperty("basedir", baseDir
.getAbsolutePath());
380 ProjectHelper2 projectHelper
= new ProjectHelper2();
381 project
.addReference(ProjectHelper
.PROJECTHELPER_REFERENCE
,
383 projectHelper
.parse(project
, script
.getURL());
384 } catch (Exception e
) {
385 throw new SlcException("Could not parse project for script "
386 + scriptRelativePath
, e
);
391 protected void runProject(Project p
, List
<String
> targets
) {
392 p
.fireBuildStarted();
393 Throwable exception
= null;
395 if (targets
.size() == 0) {// no target defined
396 p
.executeTarget(p
.getDefaultTarget());
398 p
.executeTargets(new Vector
<String
>(targets
));
400 } catch (Throwable e
) {
402 throw new SlcException("SLC Ant execution failed", exception
);
404 p
.fireBuildFinished(exception
);
408 public void setContextLocation(Resource contextLocation
) {
409 this.contextLocation
= contextLocation
;
412 public void setRootDir(Resource rootDir
) {
413 this.rootDir
= rootDir
;
416 public void setConfDir(Resource confDir
) {
417 this.confDir
= confDir
;
420 public void setWorkDir(File workDir
) {
421 this.workDir
= workDir
;
424 public void setParentContext(ConfigurableApplicationContext runtimeContext
) {
425 this.parentContext
= runtimeContext
;
428 public void setSlcRootFile(Resource slcRootFile
) {
429 this.slcRootFile
= slcRootFile
;
433 * Init all directories based on the SLC root file. TODO: don't override
434 * already specified dirs.
436 public void initFromSlcRootFile() {
437 // AntSlcApplication application = new AntSlcApplication();
438 InputStream inRootFile
= null;
440 // Remove basedir property in order to avoid conflict with Maven
441 // if (all.containsKey("basedir"))
442 // all.remove("basedir");
444 inRootFile
= slcRootFile
.getInputStream();
445 Properties rootProps
= loadFile(inRootFile
);
447 Resource confDir
= null;
450 final Resource rootDir
= SpringUtils
.getParent(slcRootFile
);
453 String confDirStr
= rootProps
454 .getProperty(AntConstants
.CONF_DIR_PROPERTY
);
455 if (confDirStr
!= null)
456 confDir
= new DefaultResourceLoader(getClass().getClassLoader())
457 .getResource(confDirStr
);
459 if (confDir
== null || !confDir
.exists()) {
460 // confDir = rootDir.createRelative("../conf");
461 confDir
= SpringUtils
.getParent(rootDir
)
462 .createRelative("conf/");
466 String workDirStr
= rootProps
467 .getProperty(AntConstants
.WORK_DIR_PROPERTY
);
468 if (workDirStr
!= null) {
469 workDir
= new File(workDirStr
);
472 if (workDir
== null || !workDir
.exists()) {
474 File rootDirAsFile
= rootDir
.getFile();
475 workDir
= new File(rootDirAsFile
.getParent()
476 + File
.separator
+ "work").getCanonicalFile();
477 } catch (IOException e
) {
478 workDir
= new File(System
.getProperty("java.io.tmpdir")
479 + File
.separator
+ "slcExecutions" + File
.separator
480 + slcRootFile
.getURL().getPath());
481 log
.debug("Root dir is not a file: " + e
.getMessage()
482 + ", creating work dir in temp: " + workDir
);
491 if (log
.isDebugEnabled())
492 log
.debug("Ant SLC application initialized based on root file "
494 } catch (IOException e
) {
495 throw new SlcException(
496 "Could not prepare SLC application for root file "
499 IOUtils
.closeQuietly(inRootFile
);
503 /** Loads the content of a file as <code>Properties</code>. */
504 private Properties
loadFile(InputStream in
) {
505 Properties p
= new Properties();
508 } catch (IOException e
) {
509 throw new SlcException("Cannot read SLC root file", e
);