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
.apache
.tools
.ant
.listener
.CommonsLoggingListener
;
23 import org
.argeo
.slc
.core
.SlcException
;
24 import org
.argeo
.slc
.core
.process
.SlcExecution
;
25 import org
.argeo
.slc
.core
.structure
.SimpleSElement
;
26 import org
.argeo
.slc
.core
.structure
.StructureRegistry
;
27 import org
.argeo
.slc
.core
.structure
.tree
.TreeSPath
;
28 import org
.argeo
.slc
.core
.structure
.tree
.TreeSRegistry
;
29 import org
.argeo
.slc
.logging
.Log4jUtils
;
30 import org
.argeo
.slc
.runtime
.SlcExecutionOutput
;
31 import org
.springframework
.beans
.factory
.BeanFactoryUtils
;
32 import org
.springframework
.beans
.factory
.ListableBeanFactory
;
33 import org
.springframework
.beans
.factory
.config
.PropertyPlaceholderConfigurer
;
34 import org
.springframework
.beans
.factory
.xml
.XmlBeanDefinitionReader
;
35 import org
.springframework
.context
.ConfigurableApplicationContext
;
36 import org
.springframework
.context
.support
.GenericApplicationContext
;
37 import org
.springframework
.core
.io
.DefaultResourceLoader
;
38 import org
.springframework
.core
.io
.Resource
;
39 import org
.springframework
.core
.io
.ResourceLoader
;
40 import org
.springframework
.util
.SystemPropertyUtils
;
42 public class AntSlcApplication
{
43 private final static String DEFAULT_APP_LOG4J_PROPERTIES
= "org/argeo/slc/ant/defaultAppLog4j.properties";
45 private final static Log log
= LogFactory
.getLog(AntSlcApplication
.class);
47 private Resource contextLocation
;
48 private ConfigurableApplicationContext parentContext
;
50 private Resource rootDir
;
51 private Resource confDir
;
54 public void execute(SlcExecution slcExecution
, Properties properties
,
55 Map
<String
, Object
> references
,
56 SlcExecutionOutput
<AntExecutionContext
> executionOutput
) {
58 // Properties and application logging initialization
59 initSystemProperties(properties
);
60 Log4jUtils
.initLog4j("classpath:" + DEFAULT_APP_LOG4J_PROPERTIES
);
62 log
.info("\n###\n### Start SLC execution " + slcExecution
.getUuid()
64 if (log
.isDebugEnabled()) {
65 log
.debug("rootDir=" + rootDir
);
66 log
.debug("confDir=" + confDir
);
67 log
.debug("workDir=" + workDir
);
71 String scriptRelativePath
= findAntScript(slcExecution
);
72 List
<String
> targets
= findAntTargets(slcExecution
);
74 // Spring initialization
75 ConfigurableApplicationContext ctx
= createExecutionContext(slcExecution
);
77 // Ant project initialization
78 Project project
= new Project();
79 AntExecutionContext executionContext
= new AntExecutionContext(project
);
80 project
.addReference(AntConstants
.REF_ROOT_CONTEXT
, ctx
);
81 project
.addReference(AntConstants
.REF_SLC_EXECUTION
, slcExecution
);
84 initProject(project
, properties
, references
);
85 parseProject(project
, scriptRelativePath
);
88 initStructure(project
, scriptRelativePath
);
89 runProject(project
, targets
);
91 if (executionOutput
!= null)
92 executionOutput
.postExecution(executionContext
);
98 protected void initSystemProperties(Properties userProperties
) {
99 // Set user properties as system properties so that Spring can access
101 if (userProperties
!= null) {
102 for (Object key
: userProperties
.keySet()) {
103 System
.setProperty(key
.toString(), userProperties
104 .getProperty(key
.toString()));
108 if (System
.getProperty(AntConstants
.DEFAULT_TEST_RUN_PROPERTY
) == null) {
109 System
.setProperty(AntConstants
.DEFAULT_TEST_RUN_PROPERTY
,
115 System
.setProperty(AntConstants
.ROOT_DIR_PROPERTY
, rootDir
116 .getURL().toString());
118 System
.setProperty(AntConstants
.CONF_DIR_PROPERTY
, confDir
119 .getURL().toString());
121 System
.setProperty(AntConstants
.WORK_DIR_PROPERTY
, workDir
122 .getCanonicalPath());
124 // Additional properties in slc.properties file. Already set sytem
125 // properties (such as the various directories) can be resolved in
127 if (confDir
!= null) {
128 Resource slcPropertiesRes
= confDir
129 .createRelative("slc.properties");
130 if (slcPropertiesRes
.exists()) {
131 Properties slcProperties
= new Properties();
132 InputStream in
= slcPropertiesRes
.getInputStream();
134 slcProperties
.load(in
);
136 IOUtils
.closeQuietly(in
);
139 for (String key
: slcProperties
.stringPropertyNames()) {
140 if (!System
.getProperties().containsKey(key
)) {
141 String value
= SystemPropertyUtils
142 .resolvePlaceholders(slcProperties
144 System
.setProperty(key
, value
);
149 } catch (Exception e
) {
150 throw new SlcException("Cannot init system properties.", e
);
154 protected ConfigurableApplicationContext
createExecutionContext(
155 SlcExecution slcExecution
) {
158 // Find runtime definition
159 Resource runtimeRes
= null;
160 String runtimeStr
= slcExecution
.getAttributes().get(
161 AntConstants
.EXECATTR_RUNTIME
);
162 if (runtimeStr
== null)
163 runtimeStr
= "default";
165 ResourceLoader rl
= new DefaultResourceLoader(getClass()
167 try {// tries absolute reference
168 runtimeRes
= rl
.getResource(runtimeStr
);
169 } catch (Exception e
) {
172 if (runtimeRes
== null || !runtimeRes
.exists()) {
174 runtimeRes
= confDir
.createRelative("runtime/" + runtimeStr
178 // Find runtime independent application context definition
179 if (confDir
!= null && contextLocation
== null) {
180 contextLocation
= confDir
181 .createRelative("applicationContext.xml");
184 GenericApplicationContext ctx
= new GenericApplicationContext(
186 ctx
.setDisplayName("SLC Execution #" + slcExecution
.getUuid());
188 XmlBeanDefinitionReader xmlReader
= new XmlBeanDefinitionReader(ctx
);
189 if (runtimeRes
!= null && runtimeRes
.exists())
190 xmlReader
.loadBeanDefinitions(runtimeRes
);
192 log
.warn("No runtime context defined");
194 if (contextLocation
!= null && contextLocation
.exists())
195 xmlReader
.loadBeanDefinitions(contextLocation
);
197 log
.warn("No runtime independent application context defined");
199 // Add property place holder
200 PropertyPlaceholderConfigurer ppc
= new PropertyPlaceholderConfigurer();
201 ppc
.setIgnoreUnresolvablePlaceholders(true);
202 ctx
.addBeanFactoryPostProcessor(ppc
);
206 } catch (Exception e
) {
207 throw new SlcException(
208 "Cannot create SLC execution application context.", e
);
212 protected String
findAntScript(SlcExecution slcExecution
) {
213 String scriptStr
= slcExecution
.getAttributes().get(
214 AntConstants
.EXECATTR_ANT_FILE
);
215 if (scriptStr
== null)
216 throw new SlcException("No Ant script provided");
221 protected List
<String
> findAntTargets(SlcExecution slcExecution
) {
222 String targetList
= slcExecution
.getAttributes().get(
223 AntConstants
.EXECATTR_ANT_TARGETS
);
224 List
<String
> targets
= new Vector
<String
>();
225 if (targetList
!= null) {
226 StringTokenizer stTargets
= new StringTokenizer(targetList
, ",");
227 while (stTargets
.hasMoreTokens()) {
228 targets
.add(stTargets
.nextToken());
234 protected void initProject(Project project
, Properties properties
,
235 Map
<String
, Object
> references
) {
236 if (properties
!= null) {
237 for (Map
.Entry
<Object
, Object
> entry
: properties
.entrySet()) {
238 project
.setUserProperty(entry
.getKey().toString(), entry
239 .getValue().toString());
243 if (references
!= null) {
244 for (Map
.Entry
<String
, Object
> entry
: references
.entrySet()) {
245 project
.addReference(entry
.getKey(), entry
.getValue());
249 project
.addBuildListener(new CommonsLoggingListener());
251 ListableBeanFactory context
= (ListableBeanFactory
) project
252 .getReference(AntConstants
.REF_ROOT_CONTEXT
);
253 // Register build listeners
254 Map
<String
, BuildListener
> listeners
= BeanFactoryUtils
255 .beansOfTypeIncludingAncestors(context
, BuildListener
.class,
257 for (BuildListener listener
: listeners
.values()) {
258 project
.addBuildListener(listener
);
261 // Register log4j appenders from context
262 MDC
.put(AntConstants
.MDC_ANT_PROJECT
, project
);
263 Map
<String
, Appender
> appenders
= context
.getBeansOfType(
264 Appender
.class, false, true);
265 for (Appender appender
: appenders
.values()) {
266 LogManager
.getRootLogger().addAppender(appender
);
270 addCustomTaskAndTypes(project
);
273 /** Loads the SLC specific Ant tasks. */
274 protected void addCustomTaskAndTypes(Project project
) {
275 Properties taskdefs
= getDefs(project
,
276 AntConstants
.SLC_TASKDEFS_RESOURCE_PATH
);
277 for (Object o
: taskdefs
.keySet()) {
278 String name
= o
.toString();
280 project
.addTaskDefinition(name
, Class
.forName(taskdefs
281 .getProperty(name
)));
282 } catch (ClassNotFoundException e
) {
283 log
.error("Unknown class for task " + name
, e
);
286 Properties typedefs
= getDefs(project
,
287 AntConstants
.SLC_TYPEDEFS_RESOURCE_PATH
);
288 for (Object o
: typedefs
.keySet()) {
289 String name
= o
.toString();
291 project
.addDataTypeDefinition(name
, Class
.forName(typedefs
292 .getProperty(name
)));
293 } catch (ClassNotFoundException e
) {
294 log
.error("Unknown class for type " + name
, e
);
299 private Properties
getDefs(Project project
, String path
) {
300 Properties defs
= new Properties();
302 InputStream in
= project
.getClass().getResourceAsStream(path
);
305 } catch (IOException e
) {
306 throw new SlcException("Cannot load task definitions", e
);
311 protected void initStructure(Project project
, String scriptRelativePath
) {
312 // Init structure registry
313 StructureRegistry
<TreeSPath
> registry
= new TreeSRegistry();
314 project
.addReference(AntConstants
.REF_STRUCTURE_REGISTRY
, registry
);
317 StringTokenizer st
= new StringTokenizer(scriptRelativePath
, "/");
318 TreeSPath currPath
= null;
319 while (st
.hasMoreTokens()) {
320 String name
= st
.nextToken();
321 if (currPath
== null) {
322 currPath
= TreeSPath
.createRootPath(name
);
324 if (st
.hasMoreTokens())// don't register project file
325 currPath
= currPath
.createChild(name
);
327 registry
.register(currPath
, new SimpleSElement(name
));
331 String projectName
= project
.getName() != null
332 && !project
.getName().equals("") ? project
.getName()
334 TreeSPath projectPath
= currPath
.createChild(projectName
);
336 String projectDesc
= project
.getDescription() != null
337 && !project
.getDescription().equals("") ? project
338 .getDescription() : projectPath
.getName();
340 registry
.register(projectPath
, new SimpleSElement(projectDesc
));
341 project
.addReference(AntConstants
.REF_PROJECT_PATH
, projectPath
);
343 if (log
.isDebugEnabled())
344 log
.debug("Project path: " + projectPath
);
347 protected void parseProject(Project project
, String scriptRelativePath
) {
349 Resource script
= rootDir
.createRelative(scriptRelativePath
);
352 File scriptFile
= script
.getFile();
353 baseDir
= scriptFile
.getParentFile();
354 } catch (IOException e
) {// resource is not a file
355 baseDir
= new File(System
.getProperty("user.dir"));
357 project
.setBaseDir(baseDir
);
358 // Reset basedir property, in order to avoid base dir override when
360 project
.setProperty("basedir", baseDir
.getAbsolutePath());
362 ProjectHelper2 projectHelper
= new ProjectHelper2();
363 project
.addReference(ProjectHelper
.PROJECTHELPER_REFERENCE
,
365 projectHelper
.parse(project
, script
.getURL());
366 } catch (Exception e
) {
367 throw new SlcException("Could not parse project for script "
368 + scriptRelativePath
, e
);
373 protected void runProject(Project p
, List
<String
> targets
) {
374 p
.fireBuildStarted();
375 Throwable exception
= null;
377 if (targets
.size() == 0) {// no target defined
378 p
.executeTarget(p
.getDefaultTarget());
380 p
.executeTargets(new Vector
<String
>(targets
));
382 } catch (Throwable e
) {
384 throw new SlcException("SLC Ant execution failed", exception
);
386 p
.fireBuildFinished(exception
);
390 public void setContextLocation(Resource contextLocation
) {
391 this.contextLocation
= contextLocation
;
394 public void setRootDir(Resource rootDir
) {
395 this.rootDir
= rootDir
;
398 public void setConfDir(Resource confDir
) {
399 this.confDir
= confDir
;
402 public void setWorkDir(File workDir
) {
403 this.workDir
= workDir
;
406 public void setParentContext(ConfigurableApplicationContext runtimeContext
) {
407 this.parentContext
= runtimeContext
;