]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.core/src/main/java/org/argeo/slc/ant/SlcProjectHelper.java
9dcd2e83523d86a309cb779c688e280d6987f207
[gpl/argeo-slc.git] / org.argeo.slc.core / 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.util.List;
7 import java.util.Map;
8 import java.util.Properties;
9 import java.util.Vector;
10
11 import org.springframework.context.support.AbstractApplicationContext;
12 import org.springframework.context.support.FileSystemXmlApplicationContext;
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
20 import org.argeo.slc.core.UnsupportedException;
21 import org.argeo.slc.core.structure.DefaultSRegistry;
22 import org.argeo.slc.core.structure.SimpleSElement;
23 import org.argeo.slc.core.structure.StructureRegistry;
24 import org.argeo.slc.core.structure.tree.TreeSPath;
25
26 /**
27 * Custom implementation of an Ant <code>ProjectHelper</code> binding a Spring
28 * application context and a structure registry with the Ant project.
29 */
30 public class SlcProjectHelper extends ProjectHelper2 {
31 private static Log log;
32
33 /** The Ant reference to the Spring application context used. */
34 public static String REF_ROOT_CONTEXT = "slcApplicationContext";
35 /** The Ant reference to the SLC structure registry used. */
36 public static String REF_STRUCTURE_REGISTRY = "slcStructureRegistry";
37 /** The Ant reference to the <code>TreePath</code> of the current project */
38 private static String REF_PROJECT_PATH = "slcProjectPath";
39 /**
40 * Resource path to the property file listing the SLC specific Ant tasks:
41 * /org/argeo/slc/ant/taskdefs.properties
42 */
43 private static String SLC_TASKDEFS_RESOURCE_PATH = "/org/argeo/slc/ant/taskdefs.properties";
44 private static String SLC_TYPEDEFS_RESOURCE_PATH = "/org/argeo/slc/ant/typedefs.properties";
45
46 @Override
47 public void parse(Project project, Object source) throws BuildException {
48 if (!(source instanceof File)) {
49 throw new UnsupportedException("Ant file", source);
50 }
51 File sourceFile = (File) source;
52
53 // initialize config
54 SlcAntConfig slcAntConfig = new SlcAntConfig();
55
56 // Reset basedir property, in order to avoid base dir override when
57 // running in Maven
58 project.setProperty("basedir", sourceFile.getParentFile()
59 .getAbsolutePath());
60 if (!slcAntConfig.initProject(project)) {
61 // not SLC compatible, do normal Ant
62 super.parse(project, source);
63 return;
64 }
65
66 if (log == null) {
67 // log4j is initialized only now
68 log = LogFactory.getLog(SlcProjectHelper.class);
69 }
70 log.debug("SLC properties are set, starting initialization for "+sourceFile);
71
72 // init Spring application context
73 initSpringContext(project);
74
75 // init structure registry
76 DefaultSRegistry registry = new DefaultSRegistry();
77 project.addReference(REF_STRUCTURE_REGISTRY, registry);
78
79 // call the underlying implementation to do the actual work
80 super.parse(project, source);
81
82 // create structure root
83 registerProjectAndParents(project, slcAntConfig);
84
85 addCustomTaskAndTypes(project);
86
87 }
88
89 /** Creates the tree-based structure for this project. */
90 private void registerProjectAndParents(Project project,
91 SlcAntConfig slcAntConfig) {
92 StructureRegistry registry = (StructureRegistry) project
93 .getReference(REF_STRUCTURE_REGISTRY);
94 File rootDir = new File(project
95 .getUserProperty(SlcAntConfig.ROOT_DIR_PROPERTY))
96 .getAbsoluteFile();
97 File baseDir = project.getBaseDir().getAbsoluteFile();
98 List<File> dirs = new Vector<File>();
99 File currentDir = baseDir;
100 do {
101 dirs.add(currentDir);
102 currentDir = currentDir.getParentFile();
103 if (log.isTraceEnabled())
104 log.trace("List " + currentDir);
105 } while (!currentDir.equals(rootDir.getParentFile()));
106
107 // first path is root dir (because of previous algorithm)
108 TreeSPath currPath = TreeSPath.createRootPath(rootDir.getName());
109 for (int i = dirs.size() - 1; i >= 0; i--) {
110 File dir = dirs.get(i);
111
112 // retrieves description for this path
113 final String description;
114 if (i == 0) {// project itself
115 description = project.getDescription() != null
116 && !project.getDescription().equals("") ? project
117 .getDescription() : slcAntConfig
118 .getDescriptionForDir(dir);
119 } else {
120 description = slcAntConfig.getDescriptionForDir(dir);
121 if (log.isTraceEnabled())
122 log.trace("Dir desc " + i + "/" + dirs.size() + ": "
123 + description);
124 }
125 SimpleSElement element = new SimpleSElement(description);
126
127 // creates and register path
128 if (!dir.equals(rootDir)) {// already set
129 currPath = currPath.createChild(dir.getName());
130 }
131 registry.register(currPath, element);
132 }
133 project.addReference(REF_PROJECT_PATH, currPath);
134 }
135
136 /** Gets the path of a project (root). */
137 public static TreeSPath getProjectPath(Project project) {
138 return (TreeSPath) project.getReference(REF_PROJECT_PATH);
139 }
140
141 /** Initializes the Spring application context. */
142 private void initSpringContext(Project project) {
143 System.getProperties().putAll((Map<?, ?>) project.getProperties());
144 String acPath = project
145 .getUserProperty(SlcAntConfig.APPLICATION_CONTEXT_PROPERTY);
146 if (log.isDebugEnabled())
147 log.debug("Loading Spring application context from " + acPath);
148 // FIXME: workaround to the removal of leading '/' by Spring
149 // use URL instead?
150 AbstractApplicationContext context = new FileSystemXmlApplicationContext(
151 '/' + acPath);
152 context.registerShutdownHook();
153 project.addReference(REF_ROOT_CONTEXT, context);
154 }
155
156 /** Loads the SLC specific Ant tasks. */
157 private void addCustomTaskAndTypes(Project project) {
158 Properties taskdefs = getDefs(project, SLC_TASKDEFS_RESOURCE_PATH);
159 for (Object o : taskdefs.keySet()) {
160 String name = o.toString();
161 try {
162 project.addTaskDefinition(name, Class.forName(taskdefs
163 .getProperty(name)));
164 } catch (ClassNotFoundException e) {
165 log.error("Unknown class for task " + name, e);
166 }
167 }
168 Properties typedefs = getDefs(project, SLC_TYPEDEFS_RESOURCE_PATH);
169 for (Object o : typedefs.keySet()) {
170 String name = o.toString();
171 try {
172 project.addDataTypeDefinition(name, Class.forName(typedefs
173 .getProperty(name)));
174 } catch (ClassNotFoundException e) {
175 log.error("Unknown class for type " + name, e);
176 }
177 }
178 }
179
180 private Properties getDefs(Project project, String path) {
181 Properties defs = new Properties();
182 try {
183 InputStream in = project.getClass().getResourceAsStream(path);
184 defs.load(in);
185 in.close();
186 } catch (IOException e) {
187 throw new SlcAntException("Cannot load task definitions", e);
188 }
189 return defs;
190 }
191 }