]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - org.argeo.slc/src/main/java/org/argeo/slc/ant/SlcAntConfig.java
Improve reporting
[gpl/argeo-slc.git] / org.argeo.slc / src / main / java / org / argeo / slc / ant / SlcAntConfig.java
index 61c74524c52db399458248eb6ea50d205008ca40..6085c663531082223c70947cc2c11852170e44e1 100644 (file)
@@ -3,88 +3,262 @@ package org.argeo.slc.ant;
 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
+import org.springframework.util.Log4jConfigurer;\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_DIR_PROPERTY = "org.argeo.slc.ant.rootDir";\r
-       public final static String CONF_DIR_PROPERTY = "org.argeo.slc.ant.confDir";\r
-       public final static String WORK_DIR_PROPERTY = "org.argeo.slc.ant.workDir";\r
+       /** Property for the root file (SLC root property file). */\r
+       public final static String ROOT_FILE_PROPERTY = "slc.rootFile";\r
+       /** Property for the root dir (SLC root property file). */\r
+       public final static String ROOT_DIR_PROPERTY = "slc.rootDir";\r
+       /** Property for the conf dir (SLC root property file). */\r
+       public final static String CONF_DIR_PROPERTY = "slc.confDir";\r
+       /** Property for the work dir (SLC root property file). */\r
+       public final static String WORK_DIR_PROPERTY = "slc.workDir";\r
        /**\r
         * Comma-separated list of property file names to load from the conf dir and\r
         * add to project user properties\r
         */\r
-       public final static String PROPERTY_FILE_NAMES_PROPERTY = "org.argeo.slc.ant.propertyFileNames";\r
-       \r
+       public final static String PROPERTY_FILE_NAMES_PROPERTY = "slc.propertyFileNames";\r
+\r
        // SLC CONF PROPERTIES\r
        /** Path to the root Spring application context */\r
-       public static String APPLICATION_CONTEXT_PROPERTY = "org.argeo.slc.ant.applicationContext";\r
-\r
-       private final File confDir;\r
-       private final File rootDir;\r
-       private final File workDir;\r
-\r
-       /** Retrieve all properties and set them as project user properties */\r
-       public SlcAntConfig(Project project, File slcRootFile) {\r
-               Properties p = loadFile(slcRootFile.getAbsolutePath());\r
-\r
-               // Root dir\r
-               rootDir = slcRootFile.getParentFile();\r
-               project.setUserProperty(ROOT_DIR_PROPERTY, rootDir.getAbsolutePath());\r
-\r
-               // Conf dir\r
-               if (project.getUserProperty(CONF_DIR_PROPERTY) == null) {\r
-                       confDir = new File(p.getProperty(CONF_DIR_PROPERTY, rootDir\r
-                                       .getAbsolutePath()\r
-                                       + "/../conf")).getAbsoluteFile();\r
-                       project.setUserProperty(CONF_DIR_PROPERTY, confDir\r
-                                       .getAbsolutePath());\r
-               } else {\r
-                       confDir = new File(project.getUserProperty(CONF_DIR_PROPERTY))\r
-                                       .getAbsoluteFile();\r
-               }\r
+       public static String APPLICATION_CONTEXT_PROPERTY = "slc.applicationContext";\r
+       /** Name of the Spring bean used by default */\r
+       public static String DEFAULT_TEST_RUN_PROPERTY = "slc.defaultTestRun";\r
 \r
-               // Work dir\r
-               if (project.getUserProperty(WORK_DIR_PROPERTY) == null) {\r
-                       workDir = new File(p.getProperty(WORK_DIR_PROPERTY, rootDir\r
-                                       .getAbsolutePath()\r
-                                       + "/../work")).getAbsoluteFile();\r
-                       project.setUserProperty(WORK_DIR_PROPERTY, workDir\r
-                                       .getAbsolutePath());\r
-               } else {\r
-                       workDir = new File(project.getUserProperty(WORK_DIR_PROPERTY))\r
-                                       .getAbsoluteFile();\r
-               }\r
+       // SLC LOCAL PROPERTIES\r
+       /** Property for the dir description (SLC local property file). */\r
+       public static String DIR_DESCRIPTION_PROPERTY = "slc.dirDescription";\r
 \r
-               // Properties from the conf dir files\r
-               Properties properties = new Properties();\r
-               StringTokenizer st = new StringTokenizer(p.getProperty(\r
-                               PROPERTY_FILE_NAMES_PROPERTY, "slc.properties"), ",");\r
-               while (st.hasMoreTokens()) {\r
-                       String fileName = st.nextToken();\r
-                       properties.putAll(loadFile(confDir.getAbsolutePath() + "/"\r
-                                       + fileName));\r
+       private String slcRootFileName = "slcRoot.properties";\r
+       private String slcLocalFileName = "slcLocal.properties";\r
+\r
+       /**\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
+        * @return whether the project could be initialized for SLC usage (e.g.\r
+        *         presence of an SLC root file)\r
+        */\r
+       public boolean initProject(Project project) {\r
+               File projectBaseDir = project.getBaseDir();\r
+               File slcRootFile = findSlcRootFile(projectBaseDir);\r
+               if (slcRootFile == null) {\r
+                       return false;\r
                }\r
 \r
-               for (Object o : properties.keySet()) {\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
-                               project.setUserProperty(key, properties.getProperty(key));\r
+                               project.setUserProperty(key, all.getProperty(key));\r
                        }\r
                }\r
+               return true;\r
+       }\r
+\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
+                       final String fileUrlPrefix = "";\r
+\r
+                       Properties all = new Properties();\r
+                       all.putAll(System.getProperties());\r
+                       all.put(ROOT_FILE_PROPERTY, slcRootFile.getCanonicalPath());\r
+\r
+                       Properties rootProps = loadFile(slcRootFile.getCanonicalPath());\r
+\r
+                       final File confDir;\r
+                       final File workDir;\r
+                       // Root dir\r
+                       final File rootDir = slcRootFile.getParentFile();\r
+                       all.setProperty(ROOT_DIR_PROPERTY, fileUrlPrefix\r
+                                       + rootDir.getCanonicalPath());\r
+\r
+                       // Conf dir\r
+                       if (all.getProperty(CONF_DIR_PROPERTY) == null) {\r
+                               confDir = new File(rootProps.getProperty(CONF_DIR_PROPERTY,\r
+                                               rootDir.getAbsolutePath() + "/../conf"))\r
+                                               .getCanonicalFile();\r
+                               all.setProperty(CONF_DIR_PROPERTY, fileUrlPrefix\r
+                                               + confDir.getAbsolutePath());\r
+                       } else {\r
+                               confDir = new File(all.getProperty(CONF_DIR_PROPERTY))\r
+                                               .getCanonicalFile();\r
+                       }\r
+\r
+                       // Work dir\r
+                       if (all.getProperty(WORK_DIR_PROPERTY) == null) {\r
+                               workDir = new File(rootProps.getProperty(WORK_DIR_PROPERTY,\r
+                                               rootDir.getAbsolutePath() + "/../work"))\r
+                                               .getCanonicalFile();\r
+                               all.setProperty(WORK_DIR_PROPERTY, fileUrlPrefix\r
+                                               + workDir.getAbsolutePath());\r
+                       } else {\r
+                               workDir = new File(all.getProperty(WORK_DIR_PROPERTY))\r
+                                               .getCanonicalFile();\r
+                       }\r
+\r
+                       // Properties from the conf dir files\r
+                       Properties properties = new Properties();\r
+                       StringTokenizer st = new StringTokenizer(rootProps.getProperty(\r
+                                       PROPERTY_FILE_NAMES_PROPERTY, "slc.properties"), ",");\r
+                       while (st.hasMoreTokens()) {\r
+                               String fileName = st.nextToken();\r
+                               properties.putAll(loadFile(confDir.getAbsolutePath()\r
+                                               + File.separator + fileName));\r
+                       }\r
+\r
+                       for (Object o : properties.keySet()) {\r
+                               String key = o.toString();\r
+                               if (all.getProperty(key) == null) {// not already set\r
+                                       all.setProperty(key, properties.getProperty(key));\r
+                               }\r
+                       }\r
 \r
-               // Default application context\r
-               if (project.getUserProperty(APPLICATION_CONTEXT_PROPERTY) == null) {\r
-                       project.setUserProperty(APPLICATION_CONTEXT_PROPERTY, confDir\r
-                                       .getAbsolutePath()\r
-                                       + "/applicationContext.xml");\r
+                       // Default application context\r
+                       if (all.getProperty(APPLICATION_CONTEXT_PROPERTY) == null) {\r
+                               all.setProperty(APPLICATION_CONTEXT_PROPERTY, confDir\r
+                                               .getAbsolutePath()\r
+                                               + "/applicationContext.xml");\r
+                       }\r
+                       // Default test run\r
+                       if (all.getProperty(DEFAULT_TEST_RUN_PROPERTY) == null) {\r
+                               all.setProperty(DEFAULT_TEST_RUN_PROPERTY, "defaultTestRun");\r
+                       }\r
+\r
+                       // Default log4j\r
+                       if (all.getProperty("log4j.configuration") == null) {\r
+                               System.setProperty("log4j.configuration", confDir\r
+                                               .getCanonicalPath()\r
+                                               + File.separator + "log4j.properties");\r
+                               // TODO: fix dependency to log4j\r
+                               Log4jConfigurer.initLogging(confDir.getCanonicalPath()\r
+                                               + File.separator + "log4j.properties");\r
+                       }\r
+\r
+                       return all;\r
+               } catch (Exception e) {\r
+                       throw new SlcAntException("Unexpected exception while configuring",\r
+                                       e);\r
                }\r
        }\r
 \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
@@ -97,16 +271,67 @@ public class SlcAntConfig {
                return p;\r
        }\r
 \r
-       public File getConfDir() {\r
-               return confDir;\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
-       public File getRootDir() {\r
-               return rootDir;\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
-       public File getWorkDir() {\r
-               return workDir;\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