]> git.argeo.org Git - gpl/argeo-slc.git/blob - org.argeo.slc.core/src/main/java/org/argeo/slc/ant/SlcAntConfig.java
Rename into Core
[gpl/argeo-slc.git] / org.argeo.slc.core / src / main / java / org / argeo / slc / ant / SlcAntConfig.java
1 package org.argeo.slc.ant;
2
3 import java.io.File;
4 import java.io.FileInputStream;
5 import java.io.IOException;
6 import java.util.Map;
7 import java.util.Properties;
8 import java.util.StringTokenizer;
9
10 import org.springframework.util.Log4jConfigurer;
11
12 import org.apache.tools.ant.Project;
13
14 /**
15 * <p>
16 * Manager and initializer of the properties required by SLC Ant.
17 * </p>
18 *
19 * <p>
20 * All properties described here will get a value one way or another (see below
21 * for details)/ Each property will be accessible via Ant or Spring properties.
22 * </p>
23 *
24 * <p>
25 * The property <i>slc.rootFile</i> is set based on the location of the SLC
26 * root property file found in the directory structure of a called Ant file. The
27 * default name of this file is <b>slcRoot.properties</b> (can be set by
28 * {@link #setSlcRootFileName(String)}). <br>
29 * This property provides the absolute path to the unique SLC root property file
30 * which marks the root of an Ant SLC tree structure.
31 * </p>
32 *
33 * <p>
34 * The property <i>slc.rootDir</i> is inferred from <i>slc.rootFile</i> and
35 * provides a convenient shortcut to the root directory of the Ant files
36 * directory structure.
37 * </p>
38 *
39 * <p>
40 * A few directory and file related properties can be set in the SLC root
41 * property file (if they are not explicitly set their default values will be
42 * used):
43 *
44 * <table border="1" cellspacing="0">
45 * <tr>
46 * <th>Property</th>
47 * <th>Description</th>
48 * <th>Default</th>
49 * </tr>
50 * <tr>
51 * <td><i>slc.confDir</i></td>
52 * <td>Directory where to find the various configuration files of a given SLC
53 * Ant deployment</td>
54 * <td>${slc.rootDir}/../conf</td>
55 * </tr>
56 * <tr>
57 * <td><i>slc.workDir</i></td>
58 * <td>Directory where data can be retrieved or generated: build outputs, test
59 * inputs/outputs, test results, etc. The underlying directory structure is
60 * specified by the specific SLC application.</td>
61 * <td>${slc.rootDir}/../work</td>
62 * </tr>
63 * <tr>
64 * <td><i>slc.propertyFileNames</i></td>
65 * <td>Comma-separated list of the files names of the property files to load
66 * from the conf directory. Having various files allows to separate between SLC
67 * framework properties and properties specific to a given application built on
68 * top of SLC. All will be available across Ant and Spring.</td>
69 * <td>slc.properties</td>
70 * </tr>
71 * </table> <b>Note:</b> Only the properties above can be set in the SLC root
72 * properties file. All other properties should be defined in the registered
73 * conf files.
74 * </p>
75 *
76 * <p>
77 * Any property can be defined in the conf files defined in the SLC root
78 * properties file (see above). SLC expects some which will have defaults but
79 * can be overriden there. By convention they should be defined in the
80 * <b>slc.properties</b> file, while application specific properties should be
81 * defined in other conf files. This allows for a clean spearation between SLC
82 * and the applications built on top of it:
83 *
84 * <table border="1" cellspacing="0">
85 * <tr>
86 * <th>Property</th>
87 * <th>Description</th>
88 * <th>Default</th>
89 * </tr>
90 * <tr>
91 * <td><i>slc.applicationContext</i></td>
92 * <td>Path to the root Spring application context file used by SLC Ant.</td>
93 * <td>${slc.confDir}/applicationContext.xml</td>
94 * </tr>
95 * <tr>
96 * <td><i>slc.defaultTestRun</i></td>
97 * <td>Name of the {@link WritableTestRun} Spring bean that the
98 * <code>slc.test</code> task will use by default. This can be overridden when
99 * calling the task from Ant.</td>
100 * <td>defaultTestRun</td>
101 * </tr>
102 * </table>
103 * </p>
104 */
105 public class SlcAntConfig {
106 // SLC ROOT PROPERTIES
107 /** Property for the root file (SLC root property file). */
108 public final static String ROOT_FILE_PROPERTY = "slc.rootFile";
109 /** Property for the root dir (SLC root property file). */
110 public final static String ROOT_DIR_PROPERTY = "slc.rootDir";
111 /** Property for the conf dir (SLC root property file). */
112 public final static String CONF_DIR_PROPERTY = "slc.confDir";
113 /** Property for the work dir (SLC root property file). */
114 public final static String WORK_DIR_PROPERTY = "slc.workDir";
115 /**
116 * Comma-separated list of property file names to load from the conf dir and
117 * add to project user properties
118 */
119 public final static String PROPERTY_FILE_NAMES_PROPERTY = "slc.propertyFileNames";
120
121 // SLC CONF PROPERTIES
122 /** Path to the root Spring application context */
123 public static String APPLICATION_CONTEXT_PROPERTY = "slc.applicationContext";
124 /** Name of the Spring bean used by default */
125 public static String DEFAULT_TEST_RUN_PROPERTY = "slc.defaultTestRun";
126
127 // SLC LOCAL PROPERTIES
128 /** Property for the dir description (SLC local property file). */
129 public static String DIR_DESCRIPTION_PROPERTY = "slc.dirDescription";
130
131 private String slcRootFileName = "slcRoot.properties";
132 private String slcLocalFileName = "slcLocal.properties";
133
134 /**
135 * Retrieves or infers all properties and set them as project user
136 * properties. All these properties will be set as project properties <b>if
137 * they had not been set as project properties before</b> (like by
138 * overriding through the standard Ant mechanisms).
139 *
140 * @param project
141 * the Ant <code>Project</code> being run.
142 * @return whether the project could be initialized for SLC usage (e.g.
143 * presence of an SLC root file)
144 */
145 public boolean initProject(Project project) {
146 File projectBaseDir = project.getBaseDir();
147 File slcRootFile = findSlcRootFile(projectBaseDir);
148 if (slcRootFile == null) {
149 return false;
150 }
151
152 // pass the project properties through the System properties
153 System.getProperties().putAll((Map<?, ?>) project.getUserProperties());
154 Properties all = prepareAllProperties(slcRootFile);
155 for (Object o : all.keySet()) {
156 String key = o.toString();
157 //System.out.println(key+"="+all.getProperty(key));
158 if (project.getUserProperty(key) == null) {// not already set
159 project.setUserProperty(key, all.getProperty(key));
160 }
161 }
162 return true;
163 }
164
165 /**
166 * Retrieves or infers all required properties.
167 *
168 * @param slcRootFile
169 * the location of the SLC root file
170 *
171 * @return the prepared properties. Note that it also contains the System
172 * and Ant properties which had previously been set.
173 */
174 protected Properties prepareAllProperties(File slcRootFile) {
175 try {
176 final String fileUrlPrefix = "";
177
178 Properties all = new Properties();
179 all.putAll(System.getProperties());
180 all.put(ROOT_FILE_PROPERTY, slcRootFile.getCanonicalPath());
181 // Remove basedir property in order to avoid conflict with Maven
182 if (all.containsKey("basedir"))
183 all.remove("basedir");
184
185 Properties rootProps = loadFile(slcRootFile.getCanonicalPath());
186
187 final File confDir;
188 final File workDir;
189 // Root dir
190 final File rootDir = slcRootFile.getParentFile();
191 all.setProperty(ROOT_DIR_PROPERTY, fileUrlPrefix
192 + rootDir.getCanonicalPath());
193
194 // Conf dir
195 if (all.getProperty(CONF_DIR_PROPERTY) == null) {
196 confDir = new File(rootProps.getProperty(CONF_DIR_PROPERTY,
197 rootDir.getAbsolutePath() + "/../conf"))
198 .getCanonicalFile();
199 all.setProperty(CONF_DIR_PROPERTY, fileUrlPrefix
200 + confDir.getAbsolutePath());
201 } else {
202 confDir = new File(all.getProperty(CONF_DIR_PROPERTY))
203 .getCanonicalFile();
204 }
205
206 // Work dir
207 if (all.getProperty(WORK_DIR_PROPERTY) == null) {
208 workDir = new File(rootProps.getProperty(WORK_DIR_PROPERTY,
209 rootDir.getAbsolutePath() + "/../work"))
210 .getCanonicalFile();
211 all.setProperty(WORK_DIR_PROPERTY, fileUrlPrefix
212 + workDir.getAbsolutePath());
213 } else {
214 workDir = new File(all.getProperty(WORK_DIR_PROPERTY))
215 .getCanonicalFile();
216 }
217
218 // Properties from the conf dir files
219 Properties properties = new Properties();
220 StringTokenizer st = new StringTokenizer(rootProps.getProperty(
221 PROPERTY_FILE_NAMES_PROPERTY, "slc.properties"), ",");
222 while (st.hasMoreTokens()) {
223 String fileName = st.nextToken();
224 properties.putAll(loadFile(confDir.getAbsolutePath()
225 + File.separator + fileName));
226 }
227
228 for (Object o : properties.keySet()) {
229 String key = o.toString();
230 if (all.getProperty(key) == null) {// not already set
231 all.setProperty(key, properties.getProperty(key));
232 }
233 }
234
235 // Default application context
236 if (all.getProperty(APPLICATION_CONTEXT_PROPERTY) == null) {
237 all.setProperty(APPLICATION_CONTEXT_PROPERTY, confDir
238 .getAbsolutePath()
239 + "/applicationContext.xml");
240 }
241 // Default test run
242 if (all.getProperty(DEFAULT_TEST_RUN_PROPERTY) == null) {
243 all.setProperty(DEFAULT_TEST_RUN_PROPERTY, "defaultTestRun");
244 }
245
246 // Default log4j
247 if (all.getProperty("log4j.configuration") == null) {
248 System.setProperty("log4j.configuration", confDir
249 .getCanonicalPath()
250 + File.separator + "log4j.properties");
251 // TODO: fix dependency to log4j
252 Log4jConfigurer.initLogging(confDir.getCanonicalPath()
253 + File.separator + "log4j.properties");
254 }
255
256 return all;
257 } catch (Exception e) {
258 throw new SlcAntException("Unexpected exception while configuring",
259 e);
260 }
261 }
262
263 /** Loads the content of a file as <code>Properties</code>. */
264 private Properties loadFile(String path) {
265 Properties p = new Properties();
266 try {
267 FileInputStream in = new FileInputStream(path);
268 p.load(in);
269 in.close();
270 } catch (IOException e) {
271 throw new SlcAntException("Cannot read SLC root file", e);
272 }
273 return p;
274 }
275
276 /**
277 * Looks for a file named {@link #getSlcLocalFileName()} in the directory,
278 * loads it as properties file and return the value of the property
279 * {@link #DIR_DESCRIPTION_PROPERTY}.
280 */
281 public String getDescriptionForDir(File dir) {
282 String description = dir.getName();
283 File slcLocal = new File(dir.getPath() + File.separator
284 + getSlcLocalFileName());
285 if (slcLocal.exists()) {
286 Properties properties = loadFile(slcLocal.getAbsolutePath());
287 description = properties.getProperty(
288 SlcAntConfig.DIR_DESCRIPTION_PROPERTY, description);
289 }
290 return description;
291 }
292
293 /**
294 * Recursively scans directories downwards until it find a file names as
295 * defined by {@link #getSlcRootFileName()}.
296 */
297 public File findSlcRootFile(File dir) {
298 for (File file : dir.listFiles()) {
299 if (!file.isDirectory()
300 && file.getName().equals(getSlcRootFileName())) {
301 return file;
302 }
303 }
304
305 File parentDir = dir.getParentFile();
306 if (parentDir == null) {
307 return null;// stop condition: not found
308 } else {
309 return findSlcRootFile(parentDir);
310 }
311 }
312
313 /**
314 * Gets the file name of the file marking the root directory, default being
315 * <i>slcRoot.properties</i>.
316 */
317 public String getSlcRootFileName() {
318 return slcRootFileName;
319 }
320
321 /** Sets the file name of the file marking the root directory. */
322 public void setSlcRootFileName(String slcRootFileName) {
323 this.slcRootFileName = slcRootFileName;
324 }
325
326 /**
327 * Gets the file name of the file containing directory specific properties,
328 * default being <i>slcLocal.properties</i>.
329 */
330 public String getSlcLocalFileName() {
331 return slcLocalFileName;
332 }
333
334 /** Sets the file name of the file containing directory specific properties. */
335 public void setSlcLocalFileName(String slcLocalFileName) {
336 this.slcLocalFileName = slcLocalFileName;
337 }
338
339 }