1 package org
.argeo
.slc
.ant
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
6 import java
.net
.InetAddress
;
7 import java
.net
.UnknownHostException
;
10 import java
.util
.Properties
;
11 import java
.util
.UUID
;
12 import java
.util
.Vector
;
14 import org
.apache
.commons
.logging
.Log
;
15 import org
.apache
.commons
.logging
.LogFactory
;
16 import org
.apache
.tools
.ant
.BuildException
;
17 import org
.apache
.tools
.ant
.Project
;
18 import org
.apache
.tools
.ant
.helper
.ProjectHelper2
;
19 import org
.argeo
.slc
.core
.process
.SlcExecution
;
20 import org
.argeo
.slc
.core
.structure
.DefaultSRegistry
;
21 import org
.argeo
.slc
.core
.structure
.SimpleSElement
;
22 import org
.argeo
.slc
.core
.structure
.StructureRegistry
;
23 import org
.argeo
.slc
.core
.structure
.tree
.TreeSPath
;
24 import org
.springframework
.beans
.factory
.ListableBeanFactory
;
25 import org
.springframework
.context
.support
.AbstractApplicationContext
;
26 import org
.springframework
.context
.support
.FileSystemXmlApplicationContext
;
29 * Custom implementation of an Ant <code>ProjectHelper</code> binding a Spring
30 * application context and a structure registry with the Ant project.
32 public class SlcProjectHelper
extends ProjectHelper2
{
33 private static Log log
;
35 protected SlcAntConfig slcAntConfig
= null;
38 public void parse(Project project
, Object source
) throws BuildException
{
40 if (source
instanceof File
) {
41 File sourceFile
= (File
) source
;
42 // Reset basedir property, in order to avoid base dir override when
44 project
.setProperty("basedir", sourceFile
.getParentFile()
48 if (slcAntConfig
!= null) {
49 // Config already initialized (probably import), only parse
50 super.parse(project
, source
);
55 slcAntConfig
= new SlcAntConfig();
57 if (!slcAntConfig
.initProject(project
)) {
58 // not SLC compatible, do normal Ant
59 super.parse(project
, source
);
64 // log4j is initialized only now
65 log
= LogFactory
.getLog(SlcProjectHelper
.class);
68 if (log
.isDebugEnabled())
69 log
.debug("SLC properties are set, starting initialization for "
70 + source
+ " (projectHelper=" + this + ")");
72 beforeParsing(project
);
74 // Calls the underlying implementation to do the actual work
75 super.parse(project
, source
);
77 afterParsing(project
);
81 * Performs operations after config initialization and before Ant file
82 * parsing. Performed only once when the main project file is parsed. Should
83 * be called by overriding methods.
85 protected void beforeParsing(Project project
) {
86 // Init Spring application context
87 initSpringContext(project
);
89 // Init structure registry
90 DefaultSRegistry registry
= new DefaultSRegistry();
91 project
.addReference(SlcAntConstants
.REF_STRUCTURE_REGISTRY
, registry
);
95 * Performs operations after parsing of the main file. Called only once (not
98 protected void afterParsing(Project project
) {
99 // Creates structure root
100 registerProjectAndParents(project
, slcAntConfig
);
101 addCustomTaskAndTypes(project
);
104 /** Creates the tree-based structure for this project. */
105 private void registerProjectAndParents(Project project
,
106 SlcAntConfig slcAntConfig
) {
107 StructureRegistry
<TreeSPath
> registry
= (StructureRegistry
<TreeSPath
>) project
108 .getReference(SlcAntConstants
.REF_STRUCTURE_REGISTRY
);
109 File rootDir
= new File(project
110 .getUserProperty(SlcAntConstants
.ROOT_DIR_PROPERTY
))
112 File baseDir
= project
.getBaseDir().getAbsoluteFile();
113 List
<File
> dirs
= new Vector
<File
>();
114 File currentDir
= baseDir
;
116 dirs
.add(currentDir
);
117 currentDir
= currentDir
.getParentFile();
118 if (log
.isTraceEnabled())
119 log
.trace("List " + currentDir
);
120 } while (!currentDir
.equals(rootDir
.getParentFile()));
122 // first path is root dir (because of previous algorithm)
123 TreeSPath currPath
= TreeSPath
.createRootPath(rootDir
.getName());
124 for (int i
= dirs
.size() - 1; i
>= 0; i
--) {
125 File dir
= dirs
.get(i
);
127 // retrieves description for this path
128 final String description
;
129 if (i
== 0) {// project itself
130 description
= project
.getDescription() != null
131 && !project
.getDescription().equals("") ? project
132 .getDescription() : project
.getName() != null ? project
133 .getName() : slcAntConfig
.getDescriptionForDir(dir
);
135 description
= slcAntConfig
.getDescriptionForDir(dir
);
136 if (log
.isTraceEnabled())
137 log
.trace("Dir desc " + i
+ "/" + dirs
.size() + ": "
140 SimpleSElement element
= new SimpleSElement(description
);
142 // creates and register path
143 if (!dir
.equals(rootDir
)) {// already set
144 currPath
= currPath
.createChild(dir
.getName());
146 registry
.register(currPath
, element
);
148 project
.addReference(SlcAntConstants
.REF_PROJECT_PATH
, currPath
);
151 /** Gets the path of a project (root). */
152 // private static TreeSPath getProjectPath(Project project) {
153 // return (TreeSPath) project.getReference(REF_PROJECT_PATH);
155 /** Initializes the Spring application context. */
156 private void initSpringContext(Project project
) {
157 System
.getProperties().putAll((Map
<?
, ?
>) project
.getProperties());
158 String acPath
= project
159 .getUserProperty(SlcAntConfig
.APPLICATION_CONTEXT_PROPERTY
);
160 if (log
.isDebugEnabled())
161 log
.debug("Loading Spring application context from " + acPath
);
162 // FIXME: workaround to the removal of leading '/' by Spring
164 AbstractApplicationContext context
= new FileSystemXmlApplicationContext(
166 context
.registerShutdownHook();
167 project
.addReference(SlcAntConstants
.REF_ROOT_CONTEXT
, context
);
169 createAndRegisterSlcExecution(project
);
170 // Add build listeners declared in Spring context
171 // Map<String, BuildListener> listeners = context.getBeansOfType(
172 // BuildListener.class, false, true);
173 // for (BuildListener listener : listeners.values()) {
174 // project.addBuildListener(listener);
178 /** Loads the SLC specific Ant tasks. */
179 protected static void addCustomTaskAndTypes(Project project
) {
180 Properties taskdefs
= getDefs(project
, SlcAntConstants
.SLC_TASKDEFS_RESOURCE_PATH
);
181 for (Object o
: taskdefs
.keySet()) {
182 String name
= o
.toString();
184 project
.addTaskDefinition(name
, Class
.forName(taskdefs
185 .getProperty(name
)));
186 } catch (ClassNotFoundException e
) {
187 log
.error("Unknown class for task " + name
, e
);
190 Properties typedefs
= getDefs(project
, SlcAntConstants
.SLC_TYPEDEFS_RESOURCE_PATH
);
191 for (Object o
: typedefs
.keySet()) {
192 String name
= o
.toString();
194 project
.addDataTypeDefinition(name
, Class
.forName(typedefs
195 .getProperty(name
)));
196 } catch (ClassNotFoundException e
) {
197 log
.error("Unknown class for type " + name
, e
);
202 private static Properties
getDefs(Project project
, String path
) {
203 Properties defs
= new Properties();
205 InputStream in
= project
.getClass().getResourceAsStream(path
);
208 } catch (IOException e
) {
209 throw new SlcAntException("Cannot load task definitions", e
);
214 protected static void createAndRegisterSlcExecution(Project project
) {
215 SlcExecution slcExecution
= new SlcExecution();
216 slcExecution
.setUuid(UUID
.randomUUID().toString());
218 slcExecution
.setHost(InetAddress
.getLocalHost().getHostName());
219 } catch (UnknownHostException e
) {
220 slcExecution
.setHost(SlcExecution
.UNKOWN_HOST
);
223 if (project
.getReference(SlcAntConstants
.REF_ROOT_CONTEXT
) != null) {
224 slcExecution
.setType(SlcAntConstants
.EXECTYPE_SLC_ANT
);
226 slcExecution
.setType(SlcAntConstants
.EXECTYPE_ANT
);
229 slcExecution
.setUser(System
.getProperty("user.name"));
230 slcExecution
.setStatus(SlcExecution
.STATUS_RUNNING
);
231 slcExecution
.getAttributes().put("ant.file",
232 project
.getProperty("ant.file"));
234 project
.addReference(SlcAntConstants
.REF_SLC_EXECUTION
,
237 // Add build listeners declared in Spring context
238 Map
<String
, ProjectRelatedBuildListener
> listeners
= ((ListableBeanFactory
) project
239 .getReference(SlcAntConstants
.REF_ROOT_CONTEXT
)).getBeansOfType(
240 ProjectRelatedBuildListener
.class, false, true);
241 for (ProjectRelatedBuildListener listener
: listeners
.values()) {
242 listener
.init(project
);
243 project
.addBuildListener(listener
);