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