package org.argeo.slc.ant; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Vector; import org.springframework.context.support.AbstractApplicationContext; import org.springframework.context.support.FileSystemXmlApplicationContext; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.Project; import org.apache.tools.ant.helper.ProjectHelperImpl; import org.argeo.slc.core.structure.DefaultSRegistry; import org.argeo.slc.core.structure.SimpleSElement; import org.argeo.slc.core.structure.StructureRegistry; import org.argeo.slc.core.structure.tree.TreeSPath; /** * Custom implementation of an Ant ProjectHelper binding a Spring * application context and a structure registry with the Ant project. */ public class SlcProjectHelper extends ProjectHelperImpl { private static Log log; /** The Ant reference to the Spring application context used. */ public static String REF_ROOT_CONTEXT = "slcApplicationContext"; /** The Ant reference to the SLC structure registry used. */ public static String REF_STRUCTURE_REGISTRY = "slcStructureRegistry"; /** The Ant reference to the TreePath of the current project */ private static String REF_PROJECT_PATH = "slcProjectPath"; /** * Resource path to the property file listing the SLC specific Ant tasks: * /org/argeo/slc/ant/taskdefs.properties */ private static String SLC_TASKDEFS_RESOURCE_PATH = "/org/argeo/slc/ant/taskdefs.properties"; @Override public void parse(Project project, Object source) throws BuildException { // initialize config SlcAntConfig slcAntConfig = new SlcAntConfig(); if (!slcAntConfig.initProject(project)) { // not SLC compatible, do normal Ant super.parse(project, source); return; } if (log == null) { // log4j is initialized only now log = LogFactory.getLog(SlcProjectHelper.class); } log.debug("SLC properties are set, starting initialization.."); // init Spring application context initSpringContext(project); // init structure registry DefaultSRegistry registry = new DefaultSRegistry(); project.addReference(REF_STRUCTURE_REGISTRY, registry); // call the underlying implementation to do the actual work super.parse(project, source); // create structure root registerProjectAndParents(project, slcAntConfig); addSlcTasks(project); } /** Creates the tree-based structure for this project. */ private void registerProjectAndParents(Project project, SlcAntConfig slcAntConfig) { StructureRegistry registry = (StructureRegistry) project .getReference(REF_STRUCTURE_REGISTRY); File rootDir = new File(project .getUserProperty(SlcAntConfig.ROOT_DIR_PROPERTY)) .getAbsoluteFile(); File baseDir = project.getBaseDir().getAbsoluteFile(); List dirs = new Vector(); File currentDir = baseDir; do { dirs.add(currentDir); currentDir = currentDir.getParentFile(); if (log.isTraceEnabled()) log.trace("List " + currentDir); } while (!currentDir.equals(rootDir.getParentFile())); // first path is root dir (because of previous algorithm) TreeSPath currPath = TreeSPath.createRootPath(rootDir.getName()); for (int i = dirs.size() - 1; i >= 0; i--) { File dir = dirs.get(i); // retrieves description for this path final String description; if (i == 0) {// project itself description = project.getDescription() != null ? project .getDescription() : ""; } else { description = slcAntConfig.getDescriptionForDir(dir); } SimpleSElement element = new SimpleSElement(description); // creates and register path if (!dir.equals(rootDir)) {// already set currPath = currPath.createChild(dir.getName()); } registry.register(currPath, element); } project.addReference(REF_PROJECT_PATH, currPath); } /** Gets the path of a project (root). */ public static TreeSPath getProjectPath(Project project) { return (TreeSPath) project.getReference(REF_PROJECT_PATH); } /** Initializes the Spring application context. */ private void initSpringContext(Project project) { System.getProperties().putAll((Map) project.getProperties()); String acPath = project .getUserProperty(SlcAntConfig.APPLICATION_CONTEXT_PROPERTY); AbstractApplicationContext context = new FileSystemXmlApplicationContext( acPath); context.registerShutdownHook(); project.addReference(REF_ROOT_CONTEXT, context); } /** Loads the SLC specific Ant tasks. */ private void addSlcTasks(Project project) { Properties taskdefs = new Properties(); try { InputStream in = project.getClass().getResourceAsStream( SLC_TASKDEFS_RESOURCE_PATH); taskdefs.load(in); in.close(); } catch (IOException e) { throw new SlcAntException("Cannot load task definitions", e); } for (Object o : taskdefs.keySet()) { String name = o.toString(); try { project.addTaskDefinition(name, Class.forName(taskdefs .getProperty(name))); } catch (ClassNotFoundException e) { log.error("Unknown class for task " + name, e); } } } }