| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| package org.apache.easyant.core.ant; |
| |
| import java.io.File; |
| import java.io.PrintStream; |
| import java.lang.reflect.Field; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.Map; |
| |
| import org.apache.easyant.core.EasyAntMagicNames; |
| import org.apache.easyant.core.ant.listerners.MultiModuleLogger; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.BuildListener; |
| import org.apache.tools.ant.BuildLogger; |
| import org.apache.tools.ant.DefaultLogger; |
| import org.apache.tools.ant.Location; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.ProjectHelper; |
| import org.apache.tools.ant.Target; |
| import org.apache.tools.ant.util.ClasspathUtils; |
| |
| /** |
| * Utilitary class to manipulate ant's project (such as creating toplevel target) |
| * |
| */ |
| public class ProjectUtils { |
| |
| private ProjectUtils() { |
| } |
| |
| private static final long MEGABYTE = 1024 * 1024; |
| |
| /** |
| * emulates a top level target |
| * |
| * @return a top level target |
| */ |
| public static Target createTopLevelTarget() { |
| Target topLevel = new Target(); |
| topLevel.setName(""); |
| return topLevel; |
| } |
| |
| /** |
| * Emulate an empty project import task check that projectHelper is at toplevel by checking the size of |
| * projectHelper.getImportTask() |
| * |
| * @return a temporary file acting as a mainscript |
| */ |
| public static File emulateMainScript(Project project) { |
| return project.getBaseDir(); |
| } |
| |
| /** |
| * Replace main logger implementation |
| * |
| * @param project |
| * a given project |
| * @param logger |
| * {@link BuildLogger} implementation to use |
| */ |
| public static void replaceMainLogger(Project project, BuildLogger logger) { |
| // Change the default output logger |
| PrintStream out = System.out; |
| PrintStream err = System.err; |
| int currentLogLevel = Project.MSG_INFO; |
| project.log("removing current logger", Project.MSG_DEBUG); |
| // since DefaultLogger doesn't offer any way to get the out / err print |
| // streams we should use reflection |
| // TODO: we should find a better way to do this |
| for (BuildListener l : project.getBuildListeners()) { |
| if (l instanceof DefaultLogger) { |
| try { |
| Field fieldOut = DefaultLogger.class.getDeclaredField("out"); |
| fieldOut.setAccessible(true); |
| out = (PrintStream) fieldOut.get(l); |
| Field fieldErr = DefaultLogger.class.getDeclaredField("err"); |
| fieldErr.setAccessible(true); |
| err = (PrintStream) fieldErr.get(l); |
| Field fieldMsgLevel = DefaultLogger.class.getDeclaredField("msgOutputLevel"); |
| fieldMsgLevel.setAccessible(true); |
| currentLogLevel = (Integer) fieldMsgLevel.get(l); |
| } catch (IllegalAccessException ex) { |
| throw new BuildException(ex); |
| } catch (SecurityException e) { |
| throw new BuildException(e); |
| } catch (NoSuchFieldException e) { |
| throw new BuildException(e); |
| } |
| project.removeBuildListener(l); |
| } |
| } |
| project.log("Initializing new logger " + logger.getClass().getName(), Project.MSG_DEBUG); |
| logger.setOutputPrintStream(out); |
| logger.setErrorPrintStream(err); |
| logger.setMessageOutputLevel(currentLogLevel); |
| project.setProjectReference(logger); |
| project.addBuildListener(logger); |
| |
| } |
| |
| /** |
| * Install multi module logger Multi module logger specified through {@link EasyAntMagicNames}.MULTIMODULE_LOGGER |
| * property. If this property is not set use default implementation |
| * |
| * @param project |
| * a given project where multi module logger should be installed |
| */ |
| public static void installMultiModuleLogger(Project project) { |
| String multiModuleLoggerClassName = project.getProperty(EasyAntMagicNames.MULTIMODULE_LOGGER); |
| if (multiModuleLoggerClassName == null) { |
| multiModuleLoggerClassName = MultiModuleLogger.class.getCanonicalName(); |
| } |
| BuildLogger buildLogger = (BuildLogger) ClasspathUtils.newInstance(multiModuleLoggerClassName, |
| ProjectUtils.class.getClassLoader(), BuildLogger.class); |
| replaceMainLogger(project, buildLogger); |
| } |
| |
| /** |
| * Print memory details |
| * |
| * @param project |
| * a given project |
| */ |
| public static void printMemoryDetails(Project project) { |
| project.log("---- Memory Details ----"); |
| project.log(" Used Memory = " |
| + (Runtime.getRuntime().totalMemory() / MEGABYTE - Runtime.getRuntime().freeMemory() / MEGABYTE) + "MB"); |
| project.log(" Free Memory = " + (Runtime.getRuntime().freeMemory() / MEGABYTE) + "MB"); |
| project.log(" Total Memory = " + (Runtime.getRuntime().totalMemory() / MEGABYTE) + "MB"); |
| project.log("-----------------------"); |
| } |
| |
| /** |
| * Targets in imported files with a project name and not overloaded by the main build file will be in the target map |
| * twice. This method removes the duplicate target. |
| * |
| * @param targets |
| * the targets to filter. |
| * @return the filtered targets. |
| */ |
| public static Map<String, Target> removeDuplicateTargets(Map<?, ?> targets) { |
| Map<Location, Target> locationMap = new HashMap<Location, Target>(); |
| for (Map.Entry<?, ?> entry1 : targets.entrySet()) { |
| Map.Entry<?, ?> entry = (Map.Entry<?, ?>) entry1; |
| String name = (String) entry.getKey(); |
| Target target = (Target) entry.getValue(); |
| Target otherTarget = locationMap.get(target.getLocation()); |
| // Place this entry in the location map if |
| // a) location is not in the map |
| // b) location is in map, but it's name is longer |
| // (an imported target will have a name. prefix) |
| if (otherTarget == null || otherTarget.getName().length() > name.length()) { |
| locationMap.put(target.getLocation(), target); // Smallest name |
| // wins |
| } |
| } |
| Map<String, Target> ret = new HashMap<String, Target>(); |
| for (Target target : locationMap.values()) { |
| ret.put(target.getName(), target); |
| } |
| return ret; |
| } |
| |
| public static ProjectHelper configureProjectHelper(Project project) { |
| ProjectHelper helper = ProjectHelper.getProjectHelper(); |
| helper.getImportStack().addElement(ProjectUtils.emulateMainScript(project)); |
| project.addReference(ProjectHelper.PROJECTHELPER_REFERENCE, helper); |
| return helper; |
| } |
| |
| public static ProjectHelper getConfiguredProjectHelper(Project project) { |
| return (ProjectHelper) project.getReference(ProjectHelper.PROJECTHELPER_REFERENCE); |
| } |
| } |