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