--- a/buildframework/helium/sf/java/core/src/com/nokia/helium/core/ant/HeliumExecutor.java Wed Jun 16 16:51:40 2010 +0300
+++ b/buildframework/helium/sf/java/core/src/com/nokia/helium/core/ant/HeliumExecutor.java Fri Aug 13 14:59:05 2010 +0300
@@ -14,262 +14,283 @@
* Description:
*
*/
-
package com.nokia.helium.core.ant;
-import java.util.StringTokenizer;
-import java.util.Vector;
-import java.util.Enumeration;
-import java.util.List;
-import java.io.BufferedReader;
-import java.io.FileWriter;
-import java.io.InputStream;
import java.io.File;
import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.JarURLConnection;
+import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
-
-import org.apache.tools.ant.taskdefs.ImportTask;
-import org.apache.tools.ant.helper.DefaultExecutor;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Target;
-import org.apache.tools.ant.Location;
-import com.nokia.helium.core.ant.types.*;
-
-import java.util.HashMap;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
-import org.apache.log4j.Logger;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.BuildListener;
+import org.apache.tools.ant.BuildLogger;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.ProjectHelper;
+import org.apache.tools.ant.helper.DefaultExecutor;
+
+import com.nokia.helium.core.MultiCauseBuildException;
+import com.nokia.helium.core.ant.types.HlmDefList;
/**
* This class implements a flexible Ant Executor which allows dynamic discovery
* and automatic loading of new features. It also supports pre/post actions to
* be executed.
+ *
*/
public class HeliumExecutor extends DefaultExecutor {
- private HashMap<String, Vector<HlmDefinition>> preOperations = new HashMap<String, Vector<HlmDefinition>>();
- private HashMap<String, Vector<HlmDefinition>> postOperations = new HashMap<String, Vector<HlmDefinition>>();
- private HashMap<String, Vector<HlmExceptionHandler>> exceptionHandlers = new HashMap<String, Vector<HlmExceptionHandler>>();
- private Project project;
- private Logger log = Logger.getLogger(HeliumExecutor.class);
+
+ private static final String HELP_TARGET = "help";
+
+ private List<HlmDefList> hlmDefCache = new ArrayList<HlmDefList>();
+ private MultiCauseBuildException failure;
/**
- * Override the default Ant executor.
+ * Execute the specified Targets for the specified Project.
*
* @param project
- * Object of the project
+ * the Ant Project.
* @param targetNames
- * Array of target names to execute
- *
+ * String[] of Target names.
+ * @throws BuildException
+ * on error
*/
public void executeTargets(Project project, String[] targetNames) {
- this.project = project;
- log.debug("Running executeTargets");
- BuildException failure = null;
- try {
- loadModules(project);
- doOperations(preOperations, project, targetNames);
- super.executeTargets(project, targetNames);
- } catch (BuildException e) {
- // Saving current issue
- // We are Ignoring the errors as no need to fail the build.
- failure = e;
+ if (targetNames.length > 1 && targetNames[0].equals(HELP_TARGET)) {
+ displayHelp(project, targetNames);
+ } else {
+ executeRegularTargets(project, targetNames);
}
+ }
+ /**
+ * Execute the given targets.
+ *
+ * @param project
+ * is the ant project
+ * @param targetNames
+ * array of target names to be executed.
+ */
+ public void executeRegularTargets(Project project, String[] targetNames) {
+ project.log("Running executeTargets", Project.MSG_DEBUG);
+ loadModules(project);
+ handlePreBuildActions(project, targetNames);
try {
- doOperations(postOperations, project, targetNames);
- } catch (BuildException e) {
- // Treating possible new issues...
- if (failure != null) {
- failure = new BuildException(e.toString() + failure.toString());
- } else {
- failure = e;
- }
- }
- // Propagating any raised issues.
- if (failure != null) {
- handleExceptions(project, failure);
- throw failure;
+ super.executeTargets(project, targetNames);
+ } catch (BuildException be) {
+ recordFailure(be);
+ } finally {
+ handlePostBuildActions(project, targetNames);
+ // Propagating any raised issues.
+ handleException(project);
}
}
/**
- * Loading all the discovered modules.
+ * Method loads all the available helium modules from the system classpath.
*
- * @param module
- * @param prj
+ * @param project
+ * is the ant project.
*/
- private void loadModules(Project prj) {
- List<File> moduleList = loadAvailableModules();
- for (File moduleName : moduleList) {
- loadModule(moduleName, prj);
+ @SuppressWarnings("unchecked")
+ private void loadModules(Project project) {
+ try {
+ List<URL> modules = getAvailableModules();
+ project.log("Total no of modules available : " + modules.size(), Project.MSG_DEBUG);
+ for (URL module : modules) {
+ loadModule(project, module);
+ }
+ Map<String, Object> references = (Hashtable<String, Object>)project.getReferences();
+ for (String key : references.keySet()) {
+ Object refObj = references.get(key);
+ if (refObj instanceof HlmDefList) {
+ hlmDefCache.add((HlmDefList)refObj);
+ project.log("Total pre build actions : "
+ + ((HlmDefList)refObj).getPreBuildActions().size(), Project.MSG_DEBUG);
+ project.log("Total post build actions : "
+ + ((HlmDefList)refObj).getPostBuildActions().size(), Project.MSG_DEBUG);
+ project.log("Total exception handlers : "
+ + ((HlmDefList)refObj).getExceptionHandlers().size(), Project.MSG_DEBUG);
+ }
+ }
+ } catch (BuildException be) {
+ recordFailure(be);
}
}
/**
- * Load a specific module.
+ * Returns a list of available helium modules from the system classpath.
*
- * @param moduleLib
- * @param prj
+ * @return a list of helium module files.
*/
- private void loadModule(File moduleLib, Project prj) {
- String file = getHlmAntLibFile(moduleLib);
- if (file == null) {
- return;
- }
- log.debug("Loading " + moduleLib.getName());
- ImportTask task = new ImportTask();
- Target target = new Target();
- target.setName("");
- target.setProject(prj);
- task.setOwningTarget(target);
- task.setLocation(new Location(file));
- task.setFile(file);
- task.setProject(prj);
- task.execute();
- String moduleName = getModuleName(moduleLib);
- Object refObject = prj.getReference(moduleName + ".list");
-
- if (refObject == null) {
- log.debug(moduleName + ".list not found");
+ private List<URL> getAvailableModules() {
+ List<URL> moduleList = new ArrayList<URL>();
+ String classpathString = System.getProperty("java.class.path");
+ String[] modules = classpathString.split(File.pathSeparator);
+ File module = null;
+ URL url = null;
+ for (String moduleName : modules) {
+ module = new File(moduleName);
+ if (module != null && module.isFile()
+ && module.getName().endsWith(".jar")) {
+ try {
+ String hlmAntlibXmlFile = findHeliumAntlibXml(new JarFile(
+ module));
+ if (hlmAntlibXmlFile != null) {
+ url = new URL("jar:" + module.toURI().toString() + "!/"
+ + hlmAntlibXmlFile);
+ moduleList.add(url);
+ }
+ } catch (MalformedURLException me) {
+ throw new BuildException(
+ "Error occured while getting helium module "
+ + module + " : ", me);
+ } catch (IOException ioe) {
+ throw new BuildException("Error reading file " + module
+ + ": " + ioe.getMessage(), ioe);
+ }
+ }
}
- if (refObject != null && refObject instanceof HlmDefList) {
- HlmDefList defList = (HlmDefList) refObject;
- Vector<HlmDefinition> tempDefList = new Vector<HlmDefinition>(
- defList.getPreDefList());
- if (tempDefList != null) {
- preOperations.put(moduleName, tempDefList);
- }
- Vector<HlmDefinition> tempPostDefList = new Vector<HlmDefinition>(
- defList.getPostDefList());
- if (tempPostDefList != null) {
- postOperations.put(moduleName, tempPostDefList);
- }
- Vector<HlmExceptionHandler> tempExceptionDefList = defList
- .getExceptionHandlerList();
- if (tempExceptionDefList != null) {
- exceptionHandlers.put(moduleName, tempExceptionDefList);
- }
- log.debug("loadModule:pre-opsize: "
- + preOperations.size());
- log.debug("loadModule:post-opsize: "
- + postOperations.size());
- log.debug("loadModule:exception-opsize: "
- + exceptionHandlers.size());
- log.debug("Checking " + moduleLib);
- }
+ return moduleList;
}
/**
* Search for helium.antlib.xml under the module Jar.
*
- * @param moduleLib
- * @return
- * @throws IOException
+ * @param jarFile
+ * is the jar to be searched in.
+ * @return the helium.antlib.xml
*/
- protected URL findHeliumAntlibXml(File moduleLib) throws IOException {
- JarFile jarFile = new JarFile(moduleLib);
- Enumeration<JarEntry> jee = jarFile.entries();
- while (jee.hasMoreElements()) {
- JarEntry je = jee.nextElement();
+ private String findHeliumAntlibXml(JarFile jarFile) {
+ String hlmAntlibXmlFile = null;
+ for (Enumeration<JarEntry> jarEntries = jarFile.entries(); jarEntries
+ .hasMoreElements();) {
+ JarEntry je = jarEntries.nextElement();
if (je.getName().endsWith("/helium.antlib.xml")) {
- return new URL("jar:" + moduleLib.toURI().toString() + "!/"
- + je.getName());
+ hlmAntlibXmlFile = je.getName();
+ break;
}
}
- return null;
+ return hlmAntlibXmlFile;
}
/**
- * Retrieve the found helium.antlib.xml. TODO improve if possible without
- * extracting the file.
+ * Method loads the specified module .
*
- * @param moduleLib
- * @return
+ * @param project
+ * is the ant project.
+ * @param module
+ * the helium module to be loaded.
*/
- private String getHlmAntLibFile(File moduleLib) {
- log.debug("[HeliumExecutor] Checking " + moduleLib);
- try {
- URL url = findHeliumAntlibXml(moduleLib);
- if (url == null)
- return null;
- log.debug("Getting " + url);
-
- JarURLConnection jarConnection = (JarURLConnection) url
- .openConnection();
- JarEntry jarEntry = jarConnection.getJarEntry();
- JarFile jarFile = new JarFile(moduleLib);
- InputStream is = jarFile.getInputStream(jarEntry);
- InputStreamReader isr = new InputStreamReader(is);
- BufferedReader reader = new BufferedReader(isr);
- File file = File.createTempFile("helium", "antlib.xml");
- file.deleteOnExit();
- FileWriter writer = new FileWriter(file);
- String line;
- while ((line = reader.readLine()) != null) {
- writer.write(line + "\n");
- }
- writer.close();
- reader.close();
- log.debug("Temp file " + file.getAbsolutePath());
- return file.getAbsolutePath();
- } catch (IOException ex) {
- log.error("Error: " + ex.getMessage(), ex);
- return null;
- }
+ private void loadModule(Project project, URL module) {
+ project.log("Loading module : " + module.toString(), Project.MSG_DEBUG);
+ ProjectHelper helper = (ProjectHelper) project
+ .getReference(ProjectHelper.PROJECTHELPER_REFERENCE);
+ helper.parse(project, module);
}
- private void doOperations(
- HashMap<String, Vector<HlmDefinition>> operations, Project prj,
- String[] targetNames) {
- log.debug("doOperations: start");
- for (String moduleName : operations.keySet()) {
- log.debug("doOperations: module: " + moduleName);
- for (HlmDefinition definition : operations.get(moduleName)) {
- definition.execute(prj, moduleName, targetNames);
+ /**
+ * Method handles all the pre build events.
+ *
+ * @param project
+ * is the ant project.
+ * @param targets
+ * an array of target names.
+ */
+ private void handlePreBuildActions(Project project, String[] targets) {
+ for (HlmDefList hlmDefList : hlmDefCache) {
+ for (PreBuildAction event : hlmDefList.getPreBuildActions()) {
+ try {
+ event.executeOnPreBuild(project, targets);
+ } catch (BuildException be) {
+ // Saving current issue
+ // We are Ignoring the errors as no need to fail the build.
+ recordFailure(be);
+ }
}
}
}
- private void handleExceptions(Project prj, Exception e) {
- for (String moduleName : this.exceptionHandlers.keySet()) {
- log.debug("handleExceptions: module: " + moduleName);
- for (HlmExceptionHandler exceptionHandler : this.exceptionHandlers
- .get(moduleName)) {
- exceptionHandler.handleException(prj, moduleName, e);
+ /**
+ * Method handles all the post build events.
+ *
+ * @param project
+ * is the ant project.
+ * @param targets
+ * an array of target names.
+ */
+ private void handlePostBuildActions(Project project, String[] targets) {
+ for (HlmDefList hlmDefList : hlmDefCache) {
+ for (PostBuildAction event : hlmDefList.getPostBuildActions()) {
+ try {
+ event.executeOnPostBuild(project, targets);
+ } catch (BuildException be) {
+ // Treating possible new issues...
+ recordFailure(be);
+ }
}
}
}
- private String getModuleName(File moduleLib) {
- String name = moduleLib.getName();
- name = name.substring(0, name.lastIndexOf('.'));
- // The module name can ends with a version
- if (name.matches("(\\w|-)+-\\d+(\\.\\d+)+")) {
- name = name.substring(0, name.lastIndexOf('-'));
+ /**
+ * Records a build failure.
+ *
+ * @param be
+ * a build failure.
+ */
+ private void recordFailure(BuildException be) {
+ if (failure == null) {
+ failure = new MultiCauseBuildException();
}
- return name;
+ failure.add(be);
}
- private List<File> loadAvailableModules() {
- List<File> moduleList = new ArrayList<File>();
- String classpathString = System.getProperty("java.class.path");
- StringTokenizer tokenizier = new StringTokenizer(classpathString,
- File.pathSeparator);
- String token;
- while (tokenizier.hasMoreTokens()) {
- token = (String) tokenizier.nextToken();
- if (new File(token).isFile() && token.endsWith(".jar")) {
- moduleList.add(new File(token));
+ /**
+ * Method handles the recored build failures if any.
+ *
+ * @param project
+ * is the ant project.
+ */
+ private void handleException(Project project) {
+ if (failure != null) {
+ for (HlmDefList hlmDefList : hlmDefCache) {
+ for (HlmExceptionHandler handler : hlmDefList
+ .getExceptionHandlers()) {
+ try {
+ handler.handleException(project, failure);
+ } catch (BuildException be) {
+ // Treating possible new issues...
+ recordFailure(be);
+ }
+ }
+ }
+ throw failure;
+ }
+ }
+
+ @SuppressWarnings("unchecked")
+ private void displayHelp(Project project, String[] targetNames) {
+ if (targetNames.length > 1) {
+ project.setProperty("help.item", targetNames[1]);
+ }
+ // Set Emacs mode to true for all listeners, so that help text does
+ // not have [echo] at the start of each line
+ Iterator<BuildListener> iter = project.getBuildListeners().iterator();
+ while (iter.hasNext()) {
+ BuildListener listener = iter.next();
+ if (listener instanceof BuildLogger) {
+ BuildLogger logger = (BuildLogger) listener;
+ logger.setEmacsMode(true);
}
}
- return moduleList;
+ // Run the 'help' target
+ project.executeTarget(HELP_TARGET);
}
-
- protected Project getProject() {
- return project;
- }
-}
\ No newline at end of file
+}