]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.agent/src/main/java/org/argeo/slc/ant/SlcProjectHelper.java
New runtime end to end (not yet working)
[gpl/argeo-slc.git] / org.argeo.slc.agent / src / main / java / org / argeo / slc / ant / SlcProjectHelper.java
1 package org.argeo.slc.ant;
2
3 import java.io.File;
4 import java.io.IOException;
5 import java.io.InputStream;
6 import java.net.InetAddress;
7 import java.net.UnknownHostException;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Properties;
11 import java.util.UUID;
12 import java.util.Vector;
13
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;
27
28 /**
29 * Custom implementation of an Ant <code>ProjectHelper</code> binding a Spring
30 * application context and a structure registry with the Ant project.
31 */
32 public class SlcProjectHelper extends ProjectHelper2 {
33 private static Log log;
34
35 protected SlcAntConfig slcAntConfig = null;
36
37 @Override
38 public void parse(Project project, Object source) throws BuildException {
39
40 if (source instanceof File) {
41 File sourceFile = (File) source;
42 // Reset basedir property, in order to avoid base dir override when
43 // running in Maven
44 project.setProperty("basedir", sourceFile.getParentFile()
45 .getAbsolutePath());
46 }
47
48 if (slcAntConfig != null) {
49 // Config already initialized (probably import), only parse
50 super.parse(project, source);
51 return;
52 }
53
54 // Initialize config
55 slcAntConfig = new SlcAntConfig();
56
57 if (!slcAntConfig.initProject(project)) {
58 // not SLC compatible, do normal Ant
59 super.parse(project, source);
60 return;
61 }
62
63 if (log == null) {
64 // log4j is initialized only now
65 log = LogFactory.getLog(SlcProjectHelper.class);
66 }
67
68 if (log.isDebugEnabled())
69 log.debug("SLC properties are set, starting initialization for "
70 + source + " (projectHelper=" + this + ")");
71
72 beforeParsing(project);
73
74 // Calls the underlying implementation to do the actual work
75 super.parse(project, source);
76
77 afterParsing(project);
78 }
79
80 /**
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.
84 */
85 protected void beforeParsing(Project project) {
86 // Init Spring application context
87 initSpringContext(project);
88
89 // Init structure registry
90 DefaultSRegistry registry = new DefaultSRegistry();
91 project.addReference(SlcAntConstants.REF_STRUCTURE_REGISTRY, registry);
92 }
93
94 /**
95 * Performs operations after parsing of the main file. Called only once (not
96 * for imports).
97 */
98 protected void afterParsing(Project project) {
99 // Creates structure root
100 registerProjectAndParents(project, slcAntConfig);
101 addCustomTaskAndTypes(project);
102 }
103
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))
111 .getAbsoluteFile();
112 File baseDir = project.getBaseDir().getAbsoluteFile();
113 List<File> dirs = new Vector<File>();
114 File currentDir = baseDir;
115 do {
116 dirs.add(currentDir);
117 currentDir = currentDir.getParentFile();
118 if (log.isTraceEnabled())
119 log.trace("List " + currentDir);
120 } while (!currentDir.equals(rootDir.getParentFile()));
121
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);
126
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);
134 } else {
135 description = slcAntConfig.getDescriptionForDir(dir);
136 if (log.isTraceEnabled())
137 log.trace("Dir desc " + i + "/" + dirs.size() + ": "
138 + description);
139 }
140 SimpleSElement element = new SimpleSElement(description);
141
142 // creates and register path
143 if (!dir.equals(rootDir)) {// already set
144 currPath = currPath.createChild(dir.getName());
145 }
146 registry.register(currPath, element);
147 }
148 project.addReference(SlcAntConstants.REF_PROJECT_PATH, currPath);
149 }
150
151 /** Gets the path of a project (root). */
152 // private static TreeSPath getProjectPath(Project project) {
153 // return (TreeSPath) project.getReference(REF_PROJECT_PATH);
154 // }
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
163 // use URL instead?
164 AbstractApplicationContext context = new FileSystemXmlApplicationContext(
165 '/' + acPath);
166 context.registerShutdownHook();
167 project.addReference(SlcAntConstants.REF_ROOT_CONTEXT, context);
168
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);
175 // }
176 }
177
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();
183 try {
184 project.addTaskDefinition(name, Class.forName(taskdefs
185 .getProperty(name)));
186 } catch (ClassNotFoundException e) {
187 log.error("Unknown class for task " + name, e);
188 }
189 }
190 Properties typedefs = getDefs(project, SlcAntConstants.SLC_TYPEDEFS_RESOURCE_PATH);
191 for (Object o : typedefs.keySet()) {
192 String name = o.toString();
193 try {
194 project.addDataTypeDefinition(name, Class.forName(typedefs
195 .getProperty(name)));
196 } catch (ClassNotFoundException e) {
197 log.error("Unknown class for type " + name, e);
198 }
199 }
200 }
201
202 private static Properties getDefs(Project project, String path) {
203 Properties defs = new Properties();
204 try {
205 InputStream in = project.getClass().getResourceAsStream(path);
206 defs.load(in);
207 in.close();
208 } catch (IOException e) {
209 throw new SlcAntException("Cannot load task definitions", e);
210 }
211 return defs;
212 }
213
214 protected static void createAndRegisterSlcExecution(Project project) {
215 SlcExecution slcExecution = new SlcExecution();
216 slcExecution.setUuid(UUID.randomUUID().toString());
217 try {
218 slcExecution.setHost(InetAddress.getLocalHost().getHostName());
219 } catch (UnknownHostException e) {
220 slcExecution.setHost(SlcExecution.UNKOWN_HOST);
221 }
222
223 if (project.getReference(SlcAntConstants.REF_ROOT_CONTEXT) != null) {
224 slcExecution.setType(SlcAntConstants.EXECTYPE_SLC_ANT);
225 } else {
226 slcExecution.setType(SlcAntConstants.EXECTYPE_ANT);
227 }
228
229 slcExecution.setUser(System.getProperty("user.name"));
230 slcExecution.setStatus(SlcExecution.STATUS_RUNNING);
231 slcExecution.getAttributes().put("ant.file",
232 project.getProperty("ant.file"));
233
234 project.addReference(SlcAntConstants.REF_SLC_EXECUTION,
235 slcExecution);
236
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);
244 }
245
246 }
247 }