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
.springframework
.beans
.factory
.ListableBeanFactory
;
15 import org
.springframework
.context
.ApplicationContext
;
16 import org
.springframework
.context
.support
.AbstractApplicationContext
;
17 import org
.springframework
.context
.support
.FileSystemXmlApplicationContext
;
19 import org
.apache
.commons
.logging
.Log
;
20 import org
.apache
.commons
.logging
.LogFactory
;
21 import org
.apache
.log4j
.LogManager
;
22 import org
.apache
.tools
.ant
.BuildException
;
23 import org
.apache
.tools
.ant
.BuildListener
;
24 import org
.apache
.tools
.ant
.Project
;
25 import org
.apache
.tools
.ant
.helper
.ProjectHelper2
;
27 import org
.argeo
.slc
.core
.process
.SlcExecution
;
28 import org
.argeo
.slc
.core
.process
.SlcExecutionNotifier
;
29 import org
.argeo
.slc
.core
.structure
.DefaultSRegistry
;
30 import org
.argeo
.slc
.core
.structure
.SimpleSElement
;
31 import org
.argeo
.slc
.core
.structure
.StructureRegistry
;
32 import org
.argeo
.slc
.core
.structure
.tree
.TreeSPath
;
35 * Custom implementation of an Ant <code>ProjectHelper</code> binding a Spring
36 * application context and a structure registry with the Ant project.
38 public class SlcProjectHelper
extends ProjectHelper2
{
39 private static Log log
;
41 /** The Ant reference to the Spring application context used. */
42 public static String REF_ROOT_CONTEXT
= "slcApplicationContext";
43 /** The Ant reference to the SLC structure registry used. */
44 public static String REF_STRUCTURE_REGISTRY
= "slcStructureRegistry";
45 /** The Ant reference to the <code>TreePath</code> of the current project */
46 public static String REF_PROJECT_PATH
= "slcProjectPath";
48 * Resource path to the property file listing the SLC specific Ant tasks:
49 * /org/argeo/slc/ant/taskdefs.properties
51 private static String SLC_TASKDEFS_RESOURCE_PATH
= "/org/argeo/slc/ant/taskdefs.properties";
52 private static String SLC_TYPEDEFS_RESOURCE_PATH
= "/org/argeo/slc/ant/typedefs.properties";
54 protected SlcAntConfig slcAntConfig
= null;
57 public void parse(Project project
, Object source
) throws BuildException
{
59 if (source
instanceof File
) {
60 File sourceFile
= (File
) source
;
61 // Reset basedir property, in order to avoid base dir override when
63 project
.setProperty("basedir", sourceFile
.getParentFile()
67 if (slcAntConfig
!= null) {
68 // Config already initialized (probably import), only parse
69 super.parse(project
, source
);
74 slcAntConfig
= new SlcAntConfig();
76 if (!slcAntConfig
.initProject(project
)) {
77 // not SLC compatible, do normal Ant
78 super.parse(project
, source
);
83 // log4j is initialized only now
84 log
= LogFactory
.getLog(SlcProjectHelper
.class);
87 if (log
.isDebugEnabled())
88 log
.debug("SLC properties are set, starting initialization for "
89 + source
+ " (projectHelper=" + this + ")");
91 beforeParsing(project
);
93 // Calls the underlying implementation to do the actual work
94 super.parse(project
, source
);
96 afterParsing(project
);
100 * Performs operations after config initialization and before Ant file
101 * parsing. Performed only once when the main project file is parsed. Should
102 * be called by overriding methods.
104 protected void beforeParsing(Project project
) {
105 // Init Spring application context
106 initSpringContext(project
);
108 // Init structure registry
109 DefaultSRegistry registry
= new DefaultSRegistry();
110 project
.addReference(REF_STRUCTURE_REGISTRY
, registry
);
114 * Performs operations after parsing of the main file. Called only once (not
117 protected void afterParsing(Project project
) {
118 // Creates structure root
119 registerProjectAndParents(project
, slcAntConfig
);
120 addCustomTaskAndTypes(project
);
123 /** Creates the tree-based structure for this project. */
124 private void registerProjectAndParents(Project project
,
125 SlcAntConfig slcAntConfig
) {
126 StructureRegistry
<TreeSPath
> registry
= (StructureRegistry
<TreeSPath
>) project
127 .getReference(REF_STRUCTURE_REGISTRY
);
128 File rootDir
= new File(project
129 .getUserProperty(SlcAntConfig
.ROOT_DIR_PROPERTY
))
131 File baseDir
= project
.getBaseDir().getAbsoluteFile();
132 List
<File
> dirs
= new Vector
<File
>();
133 File currentDir
= baseDir
;
135 dirs
.add(currentDir
);
136 currentDir
= currentDir
.getParentFile();
137 if (log
.isTraceEnabled())
138 log
.trace("List " + currentDir
);
139 } while (!currentDir
.equals(rootDir
.getParentFile()));
141 // first path is root dir (because of previous algorithm)
142 TreeSPath currPath
= TreeSPath
.createRootPath(rootDir
.getName());
143 for (int i
= dirs
.size() - 1; i
>= 0; i
--) {
144 File dir
= dirs
.get(i
);
146 // retrieves description for this path
147 final String description
;
148 if (i
== 0) {// project itself
149 description
= project
.getDescription() != null
150 && !project
.getDescription().equals("") ? project
151 .getDescription() : project
.getName() != null ? project
152 .getName() : slcAntConfig
.getDescriptionForDir(dir
);
154 description
= slcAntConfig
.getDescriptionForDir(dir
);
155 if (log
.isTraceEnabled())
156 log
.trace("Dir desc " + i
+ "/" + dirs
.size() + ": "
159 SimpleSElement element
= new SimpleSElement(description
);
161 // creates and register path
162 if (!dir
.equals(rootDir
)) {// already set
163 currPath
= currPath
.createChild(dir
.getName());
165 registry
.register(currPath
, element
);
167 project
.addReference(REF_PROJECT_PATH
, currPath
);
170 /** Gets the path of a project (root). */
171 // private static TreeSPath getProjectPath(Project project) {
172 // return (TreeSPath) project.getReference(REF_PROJECT_PATH);
174 /** Initializes the Spring application context. */
175 private void initSpringContext(Project project
) {
176 System
.getProperties().putAll((Map
<?
, ?
>) project
.getProperties());
177 String acPath
= project
178 .getUserProperty(SlcAntConfig
.APPLICATION_CONTEXT_PROPERTY
);
179 if (log
.isDebugEnabled())
180 log
.debug("Loading Spring application context from " + acPath
);
181 // FIXME: workaround to the removal of leading '/' by Spring
183 AbstractApplicationContext context
= new FileSystemXmlApplicationContext(
185 context
.registerShutdownHook();
186 project
.addReference(REF_ROOT_CONTEXT
, context
);
188 createAndRegisterSlcExecution(project
);
189 // Add build listeners declared in Spring context
190 // Map<String, BuildListener> listeners = context.getBeansOfType(
191 // BuildListener.class, false, true);
192 // for (BuildListener listener : listeners.values()) {
193 // project.addBuildListener(listener);
197 /** Loads the SLC specific Ant tasks. */
198 protected static void addCustomTaskAndTypes(Project project
) {
199 Properties taskdefs
= getDefs(project
, SLC_TASKDEFS_RESOURCE_PATH
);
200 for (Object o
: taskdefs
.keySet()) {
201 String name
= o
.toString();
203 project
.addTaskDefinition(name
, Class
.forName(taskdefs
204 .getProperty(name
)));
205 } catch (ClassNotFoundException e
) {
206 log
.error("Unknown class for task " + name
, e
);
209 Properties typedefs
= getDefs(project
, SLC_TYPEDEFS_RESOURCE_PATH
);
210 for (Object o
: typedefs
.keySet()) {
211 String name
= o
.toString();
213 project
.addDataTypeDefinition(name
, Class
.forName(typedefs
214 .getProperty(name
)));
215 } catch (ClassNotFoundException e
) {
216 log
.error("Unknown class for type " + name
, e
);
221 private static Properties
getDefs(Project project
, String path
) {
222 Properties defs
= new Properties();
224 InputStream in
= project
.getClass().getResourceAsStream(path
);
227 } catch (IOException e
) {
228 throw new SlcAntException("Cannot load task definitions", e
);
233 protected static void createAndRegisterSlcExecution(Project project
) {
234 SlcExecution slcExecution
= new SlcExecution();
235 slcExecution
.setUuid(UUID
.randomUUID().toString());
237 slcExecution
.setHost(InetAddress
.getLocalHost().getHostName());
238 } catch (UnknownHostException e
) {
239 slcExecution
.setHost(SlcExecution
.UNKOWN_HOST
);
242 if (project
.getReference(SlcProjectHelper
.REF_ROOT_CONTEXT
) != null) {
243 slcExecution
.setType(SlcExecutionBuildListener
.SLC_ANT_TYPE
);
245 slcExecution
.setType(SlcExecutionBuildListener
.ANT_TYPE
);
248 slcExecution
.setUser(System
.getProperty("user.name"));
249 slcExecution
.setStatus(SlcExecution
.STATUS_RUNNING
);
250 slcExecution
.getAttributes().put("ant.file",
251 project
.getProperty("ant.file"));
253 project
.addReference(SlcExecutionBuildListener
.REF_SLC_EXECUTION
,
256 // Add build listeners declared in Spring context
257 Map
<String
, ProjectRelatedBuildListener
> listeners
= ((ListableBeanFactory
) project
258 .getReference(REF_ROOT_CONTEXT
)).getBeansOfType(
259 ProjectRelatedBuildListener
.class, false, true);
260 for (ProjectRelatedBuildListener listener
: listeners
.values()) {
261 listener
.init(project
);
262 project
.addBuildListener(listener
);