import java.io.File;\r
import java.io.FileInputStream;\r
import java.io.IOException;\r
+import java.util.Map;\r
import java.util.Properties;\r
import java.util.StringTokenizer;\r
\r
\r
import org.apache.tools.ant.Project;\r
\r
-/** Load reference to directories from an slcRoot.properties file */\r
+import org.argeo.slc.core.test.WritableTestRun;\r
+\r
+/**\r
+ * <p>\r
+ * Manager and initializer of the properties required by SLC Ant.\r
+ * </p>\r
+ * \r
+ * <p>\r
+ * All properties described here will get a value one way or another (see below\r
+ * for details)/ Each property will be accessible via Ant or Spring properties.\r
+ * </p>\r
+ * \r
+ * <p>\r
+ * The property <i>slc.rootFile</i> is set based on the location of the SLC\r
+ * root property file found in the directory structure of a called Ant file. The\r
+ * default name of this file is <b>slcRoot.properties</b> (can be set by\r
+ * {@link #setSlcRootFileName(String)}). <br>\r
+ * This property provides the absolute path to the unique SLC root property file\r
+ * which marks the root of an Ant SLC tree structure.\r
+ * </p>\r
+ * \r
+ * <p>\r
+ * The property <i>slc.rootDir</i> is inferred from <i>slc.rootFile</i> and\r
+ * provides a convenient shortcut to the root directory of the Ant files\r
+ * directory structure.\r
+ * </p>\r
+ * \r
+ * <p>\r
+ * A few directory and file related properties can be set in the SLC root\r
+ * property file (if they are not explicitly set their default values will be\r
+ * used):\r
+ * \r
+ * <table border="1" cellspacing="0">\r
+ * <tr>\r
+ * <th>Property</th>\r
+ * <th>Description</th>\r
+ * <th>Default</th>\r
+ * </tr>\r
+ * <tr>\r
+ * <td><i>slc.confDir</i></td>\r
+ * <td>Directory where to find the various configuration files of a given SLC\r
+ * Ant deployment</td>\r
+ * <td>${slc.rootDir}/../conf</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td><i>slc.workDir</i></td>\r
+ * <td>Directory where data can be retrieved or generated: build outputs, test\r
+ * inputs/outputs, test results, etc. The underlying directory structure is\r
+ * specified by the specific SLC application.</td>\r
+ * <td>${slc.rootDir}/../work</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td><i>slc.propertyFileNames</i></td>\r
+ * <td>Comma-separated list of the files names of the property files to load\r
+ * from the conf directory. Having various files allows to separate between SLC\r
+ * framework properties and properties specific to a given application built on\r
+ * top of SLC. All will be available across Ant and Spring.</td>\r
+ * <td>slc.properties</td>\r
+ * </tr>\r
+ * </table> <b>Note:</b> Only the properties above can be set in the SLC root\r
+ * properties file. All other properties should be defined in the registered\r
+ * conf files.\r
+ * </p>\r
+ * \r
+ * <p>\r
+ * Any property can be defined in the conf files defined in the SLC root\r
+ * properties file (see above). SLC expects some which will have defaults but\r
+ * can be overriden there. By convention they should be defined in the\r
+ * <b>slc.properties</b> file, while application specific properties should be\r
+ * defined in other conf files. This allows for a clean spearation between SLC\r
+ * and the applications built on top of it:\r
+ * \r
+ * <table border="1" cellspacing="0">\r
+ * <tr>\r
+ * <th>Property</th>\r
+ * <th>Description</th>\r
+ * <th>Default</th>\r
+ * </tr>\r
+ * <tr>\r
+ * <td><i>slc.applicationContext</i></td>\r
+ * <td>Path to the root Spring application context file used by SLC Ant.</td>\r
+ * <td>${slc.confDir}/applicationContext.xml</td>\r
+ * </tr>\r
+ * <tr>\r
+ * <td><i>slc.defaultTestRun</i></td>\r
+ * <td>Name of the {@link WritableTestRun} Spring bean that the\r
+ * <code>slc.test</code> task will use by default. This can be overridden when\r
+ * calling the task from Ant.</td>\r
+ * <td>defaultTestRun</td>\r
+ * </tr>\r
+ * </table>\r
+ * </p>\r
+ */\r
public class SlcAntConfig {\r
// SLC ROOT PROPERTIES\r
public final static String ROOT_FILE_PROPERTY = "slc.rootFile";\r
// SLC LOCAL PROPERTIES\r
public static String DIR_DESCRIPTION_PROPERTY = "slc.dirDescription";\r
\r
+ private String slcRootFileName = "slcRoot.properties";\r
+ private String slcLocalFileName = "slcLocal.properties";\r
+\r
/**\r
- * Retrieve all properties and set them as project user properties. Root\r
- * properties (that is from slcRoot file) are added to System properties\r
- * (e.g. in order to be used by Spring)\r
+ * Retrieves or infers all properties and set them as project user\r
+ * properties. All these properties will be set as project properties <b>if\r
+ * they had not been set as project properties before</b> (like by\r
+ * overriding through the standard Ant mechanisms).\r
+ * \r
+ * @param project\r
+ * the Ant <code>Project</code> being run.\r
*/\r
- public static void initProject(Project project, File slcRootFile) {\r
- System.getProperties().putAll(project.getUserProperties());\r
- System.setProperty(ROOT_FILE_PROPERTY, slcRootFile.getAbsolutePath());\r
- Properties all = prepareAllProperties();\r
+ public void initProject(Project project) {\r
+ File projectBaseDir = project.getBaseDir();\r
+ File slcRootFile = findSlcRootFile(projectBaseDir);\r
+ if (slcRootFile == null) {\r
+ throw new SlcAntException("Cannot find SLC root file");\r
+ }\r
+ // pass the project properties through the System properties\r
+ System.getProperties().putAll((Map<?, ?>) project.getUserProperties());\r
+ Properties all = prepareAllProperties(slcRootFile);\r
for (Object o : all.keySet()) {\r
String key = o.toString();\r
if (project.getUserProperty(key) == null) {// not already set\r
}\r
}\r
\r
- public static Properties prepareAllProperties() {\r
+ /**\r
+ * Retrieves or infers all required properties.\r
+ * \r
+ * @param slcRootFile\r
+ * the location of the SLC root file\r
+ * \r
+ * @return the prepared properties. Note that it also contains the System\r
+ * and Ant properties which had previously been set.\r
+ */\r
+ protected Properties prepareAllProperties(File slcRootFile) {\r
try {\r
Properties all = new Properties();\r
all.putAll(System.getProperties());\r
+ all.put(ROOT_FILE_PROPERTY, slcRootFile.getCanonicalPath());\r
\r
- if (all.getProperty(ROOT_FILE_PROPERTY) == null) {\r
- throw new RuntimeException("System Property "\r
- + ROOT_FILE_PROPERTY + " has to be set.");\r
- }\r
-\r
- File slcRootFile = new File(all.getProperty(ROOT_FILE_PROPERTY))\r
- .getAbsoluteFile();\r
- Properties rootProps = loadFile(slcRootFile.getAbsolutePath());\r
+ Properties rootProps = loadFile(slcRootFile.getCanonicalPath());\r
\r
final File confDir;\r
final File workDir;\r
PROPERTY_FILE_NAMES_PROPERTY, "slc.properties"), ",");\r
while (st.hasMoreTokens()) {\r
String fileName = st.nextToken();\r
- properties.putAll(loadFile(confDir.getAbsolutePath() + File.separator\r
- + fileName));\r
+ properties.putAll(loadFile(confDir.getAbsolutePath()\r
+ + File.separator + fileName));\r
}\r
\r
for (Object o : properties.keySet()) {\r
\r
// Default log4j\r
if (all.getProperty("log4j.configuration") == null) {\r
- System.setProperty("log4j.configuration",confDir\r
+ System.setProperty("log4j.configuration", confDir\r
.getCanonicalPath()\r
- + File.separator + "log4j.properties" );\r
+ + File.separator + "log4j.properties");\r
// TODO: fix dependency to log4j\r
- Log4jConfigurer.initLogging(confDir\r
- .getCanonicalPath()\r
+ Log4jConfigurer.initLogging(confDir.getCanonicalPath()\r
+ File.separator + "log4j.properties");\r
}\r
\r
}\r
}\r
\r
- public static Properties loadFile(String path) {\r
+ /** Loads the content of a file as <code>Properties</code>. */\r
+ private Properties loadFile(String path) {\r
Properties p = new Properties();\r
try {\r
FileInputStream in = new FileInputStream(path);\r
return p;\r
}\r
\r
+ /**\r
+ * Looks for a file named {@link #getSlcLocalFileName()} in the directory,\r
+ * loads it as properties file and return the value of the property\r
+ * {@link #DIR_DESCRIPTION_PROPERTY}.\r
+ */\r
+ public String getDescriptionForDir(File dir) {\r
+ String description = dir.getName();\r
+ File slcLocal = new File(dir.getPath() + File.separator\r
+ + getSlcLocalFileName());\r
+ if (slcLocal.exists()) {\r
+ Properties properties = loadFile(slcLocal.getAbsolutePath());\r
+ description = properties.getProperty(\r
+ SlcAntConfig.DIR_DESCRIPTION_PROPERTY, description);\r
+ }\r
+ return description;\r
+ }\r
+\r
+ /**\r
+ * Recursively scans directories downwards until it find a file names as\r
+ * defined by {@link #getSlcRootFileName()}.\r
+ */\r
+ public File findSlcRootFile(File dir) {\r
+ for (File file : dir.listFiles()) {\r
+ if (!file.isDirectory()\r
+ && file.getName().equals(getSlcRootFileName())) {\r
+ return file;\r
+ }\r
+ }\r
+\r
+ File parentDir = dir.getParentFile();\r
+ if (parentDir == null) {\r
+ return null;// stop condition: not found\r
+ } else {\r
+ return findSlcRootFile(parentDir);\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Gets the file name of the file marking the root directory, default being\r
+ * <i>slcRoot.properties</i>.\r
+ */\r
+ public String getSlcRootFileName() {\r
+ return slcRootFileName;\r
+ }\r
+\r
+ /** Sets the file name of the file marking the root directory. */\r
+ public void setSlcRootFileName(String slcRootFileName) {\r
+ this.slcRootFileName = slcRootFileName;\r
+ }\r
+\r
+ /**\r
+ * Gets the file name of the file containing directory specific properties,\r
+ * default being <i>slcLocal.properties</i>.\r
+ */\r
+ public String getSlcLocalFileName() {\r
+ return slcLocalFileName;\r
+ }\r
+\r
+ /** Sets the file name of the file containing directory specific properties. */\r
+ public void setSlcLocalFileName(String slcLocalFileName) {\r
+ this.slcLocalFileName = slcLocalFileName;\r
+ }\r
+\r
}\r