/* * 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.services; import org.apache.easyant.core.EasyAntConstants; import org.apache.easyant.core.EasyAntMagicNames; import org.apache.easyant.core.ant.ProjectUtils; import org.apache.easyant.core.ant.listerners.TaskCollectorFromImplicitTargetListener; import org.apache.easyant.core.descriptor.EasyAntModuleDescriptor; import org.apache.easyant.core.descriptor.PluginType; import org.apache.easyant.core.descriptor.PropertyDescriptor; import org.apache.easyant.core.parser.DefaultEasyAntXmlModuleDescriptorParser; import org.apache.easyant.core.parser.EasyAntModuleDescriptorParser; import org.apache.easyant.core.report.*; import org.apache.easyant.tasks.*; import org.apache.ivy.Ivy; import org.apache.ivy.ant.IvyAntSettings; import org.apache.ivy.core.IvyContext; import org.apache.ivy.core.module.id.ModuleId; import org.apache.ivy.core.module.id.ModuleRevisionId; import org.apache.ivy.core.report.ArtifactDownloadReport; import org.apache.ivy.core.report.ResolveReport; import org.apache.ivy.core.resolve.IvyNode; import org.apache.ivy.core.resolve.ResolveOptions; import org.apache.ivy.core.resolve.ResolvedModuleRevision; import org.apache.ivy.core.settings.IvySettings; import org.apache.ivy.plugins.matcher.PatternMatcher; import org.apache.ivy.plugins.parser.ModuleDescriptorParserRegistry; import org.apache.ivy.plugins.repository.url.URLResource; import org.apache.ivy.plugins.resolver.DependencyResolver; import org.apache.ivy.util.Message; import org.apache.tools.ant.*; import org.apache.tools.ant.property.ParseNextProperty; import org.apache.tools.ant.property.PropertyExpander; import org.apache.tools.ant.taskdefs.Property; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.Path; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.text.ParsePosition; import java.util.Enumeration; import java.util.Map; import java.util.Properties; public class DefaultPluginService implements PluginService { private final EasyAntModuleDescriptorParser parser; private final Ivy ivyInstance; private final IvyAntSettings easyantIvySettings; private boolean offlineMode; /** * This is the default constructor, the IvyContext should be the IvyContext configured to the easyant ivy instance * * @param easyantIvySettings the easyant ivy instance */ public DefaultPluginService(final IvyAntSettings easyantIvySettings) { this(easyantIvySettings, new DefaultEasyAntXmlModuleDescriptorParser()); } /** * A custom constructor if you want to specify your own parser / configuration service, you should use this * constructor the IvyContext should be the IvyContext configured to the easyant ivy instance * * @param easyantIvySetings the easyant ivy instance * @param parser a valid easyantModuleDescriptor */ public DefaultPluginService(final IvyAntSettings easyantIvySetings, EasyAntModuleDescriptorParser parser) { this.easyantIvySettings = easyantIvySetings; this.ivyInstance = easyantIvySetings.getConfiguredIvyInstance(easyantIvySetings); if (parser == null) { throw new IllegalArgumentException("You must set a valid easyant module descriptor parser"); } this.parser = parser; ModuleDescriptorParserRegistry.getInstance().addParser(parser); } public EasyAntReport getPluginInfo(File pluginIvyFile, File sourceDirectory, String conf) throws Exception { IvyContext.pushNewContext().setIvy(ivyInstance); EasyAntReport eaReport = null; try { ResolveOptions resolveOptions = buildResolveOptions(conf); ResolveReport report = IvyContext.getContext().getIvy().getResolveEngine() .resolve(pluginIvyFile.toURI().toURL(), resolveOptions); eaReport = new EasyAntReport(); eaReport.setResolveReport(report); eaReport.setModuleDescriptor(report.getModuleDescriptor()); Project project = buildProject(); // expose resolve report for import deferred project.addReference(EasyAntMagicNames.IMPORTED_MODULES_RESOLVE_REPORT_REF, report); // emulate top level project ImportTestModule importTestModule = new ImportTestModule(); importTestModule.setModuleIvy(pluginIvyFile); importTestModule.setSourceDirectory(sourceDirectory); importTestModule.setOwningTarget(ProjectUtils.createTopLevelTarget()); importTestModule.setLocation(new Location(ProjectUtils.emulateMainScript(project).getAbsolutePath())); importTestModule.setProject(project); importTestModule.execute(); analyseProject(project, eaReport, conf); } catch (Exception e) { throw new Exception("An error occured while fetching plugin informations : " + e.getMessage(), e); } finally { IvyContext.popContext(); } return eaReport; } private ResolveOptions buildResolveOptions(String conf) { ResolveOptions resolveOptions = new ResolveOptions(); resolveOptions.setLog(ResolveOptions.LOG_QUIET); resolveOptions.setConfs(conf.split(",")); resolveOptions.setUseCacheOnly(offlineMode); return resolveOptions; } public EasyAntReport getPluginInfo(final ModuleRevisionId moduleRevisionId, String conf) throws Exception { IvyContext.pushNewContext().setIvy(ivyInstance); EasyAntReport eaReport = null; try { ResolveOptions resolveOptions = buildResolveOptions(conf); final ResolveReport report = IvyContext.getContext().getIvy().getResolveEngine() .resolve(moduleRevisionId, resolveOptions, false); eaReport = new EasyAntReport(); eaReport.setResolveReport(report); eaReport.setModuleDescriptor(report.getModuleDescriptor()); Project project = buildProject(); // expose resolve report for import deferred project.addReference(EasyAntMagicNames.IMPORTED_MODULES_RESOLVE_REPORT_REF, report); AbstractImport abstractImport = new AbstractImport() { @Override public void execute() throws BuildException { Path path = createModulePath(moduleRevisionId.getModuleId()); File antFile = null; for (ArtifactDownloadReport artifact : report.getConfigurationReport(getMainConf()).getAllArtifactsReports()) { if ("ant".equals(artifact.getType())) { antFile = artifact.getLocalFile(); } else if (shouldBeAddedToClasspath(artifact)) { path.createPathElement().setLocation(artifact.getLocalFile()); } else { handleOtherResourceFile(moduleRevisionId, artifact.getName(), artifact.getExt(), artifact.getLocalFile()); } } if (antFile != null && antFile.exists()) { ProjectHelper.configureProject(getProject(), antFile); } } }; abstractImport.setProject(project); // location ? abstractImport.execute(); analyseProject(project, eaReport, conf); } catch (Exception e) { throw new Exception("An error occured while fetching plugin informations : " + e.getMessage(), e); } finally { IvyContext.popContext(); } return eaReport; } private Project buildProject() { Project project = new Project(); project.setNewProperty(EasyAntMagicNames.AUDIT_MODE, "true"); project.setNewProperty(EasyAntMagicNames.SKIP_CORE_REVISION_CHECKER, "true"); project.addReference(EasyAntMagicNames.EASYANT_IVY_INSTANCE, easyantIvySettings); TaskCollectorFromImplicitTargetListener listener = new TaskCollectorFromImplicitTargetListener(); listener.addClassToCollect(ParameterTask.class); listener.addClassToCollect(Property.class); listener.addClassToCollect(Import.class); listener.addClassToCollect(ImportDeferred.class); listener.addClassToCollect(Path.class); listener.addClassToCollect(PathTask.class); listener.addClassToCollect(FileSet.class); project.addBuildListener(listener); // add a property helper to ignore basedir property on reports PropertyHelper propertyHelper = PropertyHelper.getPropertyHelper(project); propertyHelper.add(new BypassDefaultPropertyExpander()); project.init(); ProjectUtils.configureProjectHelper(project); return project; } private void analyseProject(Project project, EasyAntReport eaReport, String conf) throws Exception { // handle tasks from implicit target // When using import/include, ant create a "implicit target" to process root tasks. When tasks are declared // outside of a target in root project we are able to parse them "normally" as this implicit target is added to // the project. However this is not the case for tasks declared outside any target in imported build script. // So we use a listener to collect required informations for (BuildListener buildListener : project.getBuildListeners()) { if (buildListener instanceof TaskCollectorFromImplicitTargetListener) { TaskCollectorFromImplicitTargetListener taskCollectorFromImplicitTargetListener = (TaskCollectorFromImplicitTargetListener) buildListener; for (Task task : taskCollectorFromImplicitTargetListener.getTasksCollected()) { handleTask(project, eaReport, conf, task); } } } // handle tasks declared in targets Map<String, Target> targets = ProjectUtils.removeDuplicateTargets(project.getTargets()); for (Target target : targets.values()) { if (!"".equals(target.getName())) { // gather root module location from target if no task at root level was defined TaskCollectorFromImplicitTargetListener.gatherRootModuleLocation(target.getProject(), target.getLocation()); handleTarget(target, eaReport); for (int i = 0; i < target.getTasks().length; i++) { Task task = target.getTasks()[i]; handleTask(project, eaReport, conf, task); } } } } private Object maybeConfigureTask(Task task) { if (task.getRuntimeConfigurableWrapper().getProxy() instanceof UnknownElement) { UnknownElement ue = (UnknownElement) task.getRuntimeConfigurableWrapper().getProxy(); ue.maybeConfigure(); return ue.getRealThing(); } else if (task instanceof UnknownElement) { UnknownElement ue = (UnknownElement) task; ue.maybeConfigure(); return ue.getRealThing(); } else { return task; } } private void handleTask(Project project, EasyAntReport eaReport, String conf, Task task) throws Exception { Class<?> taskClass = ComponentHelper.getComponentHelper(project).getComponentClass(task.getTaskType()); if (taskClass != null) { if (ParameterTask.class.isAssignableFrom(taskClass)) { ParameterTask parameterTask = (ParameterTask) maybeConfigureTask(task); handleParameterTask(parameterTask, eaReport); } if (Property.class.isAssignableFrom(taskClass)) { Property propertyTask = (Property) maybeConfigureTask(task); handleProperty(propertyTask, eaReport); } if (Import.class.isAssignableFrom(taskClass)) { Import importTask = (Import) maybeConfigureTask(task); handleImport(importTask, eaReport, conf); } if (ImportDeferred.class.isAssignableFrom(taskClass)) { ImportDeferred importTask = (ImportDeferred) maybeConfigureTask(task); handleImportDeferred(importTask, eaReport, conf); } if (Path.class.isAssignableFrom(taskClass)) { Path path = (Path) maybeConfigureTask(task); handlePathParameter(task.getRuntimeConfigurableWrapper().getId(), path, task.getOwningTarget(), eaReport); } if (PathTask.class.isAssignableFrom(taskClass)) { PathTask pathTask = (PathTask) maybeConfigureTask(task); handlePathParameter(pathTask, eaReport); } if (FileSet.class.isAssignableFrom(taskClass)) { FileSet fileSet = (FileSet) maybeConfigureTask(task); handleFilesetParameter(task.getRuntimeConfigurableWrapper().getId(), fileSet, task.getOwningTarget(), eaReport); } } } private boolean isCurrentModule(Project project, Location location) { String rootModuleLocation = project.getProperty(TaskCollectorFromImplicitTargetListener.ROOT_MODULE_LOCATION); if (rootModuleLocation == null) { throw new IllegalStateException( "rootModuleLocation not found, looks like TaskCollectorFromImplicitTargetListener is not properly configured"); } return location != null && location.getFileName().equals(rootModuleLocation); } private void handleImport(Import importTask, EasyAntReport eaReport, String conf) throws Exception { ImportedModuleReport importedModuleReport = new ImportedModuleReport(); importedModuleReport.setModuleMrid(importTask.getMrid()); importedModuleReport.setOrganisation(importTask.getOrganisation()); importedModuleReport.setModule(importTask.getModule()); importedModuleReport.setRevision(importTask.getRevision()); importedModuleReport.setMandatory(importTask.isMandatory()); importedModuleReport.setMode(importTask.getMode()); importedModuleReport.setAs(importTask.getAs()); EasyAntReport pluginInfo = getPluginInfo(ModuleRevisionId.parse(importedModuleReport.getModuleMrid()), conf); importedModuleReport.setEasyantReport(pluginInfo); eaReport.addImportedModuleReport(importedModuleReport, isCurrentModule(importTask.getProject(), importTask.getLocation())); Message.debug("Ant file import another module called : " + importedModuleReport.getModuleMrid() + " with mode " + importedModuleReport.getMode()); } private void handleImportDeferred(ImportDeferred importTask, EasyAntReport eaReport, String conf) throws Exception { ImportedModuleReport importedModuleReport = new ImportedModuleReport(); importedModuleReport.setOrganisation(importTask.getOrganisation()); importedModuleReport.setModule(importTask.getModule()); ResolveReport resolveReport = importTask.getProject().getReference( EasyAntMagicNames.IMPORTED_MODULES_RESOLVE_REPORT_REF); if (resolveReport != null) { for (Object o : resolveReport.getDependencies()) { IvyNode dependency = (IvyNode) o; if (dependency.getResolvedId().getOrganisation().equals(importTask.getOrganisation()) // && dependency.getResolvedId().getName().equals(importTask.getModule())) { importedModuleReport.setRevision(dependency.getResolvedId().getRevision()); } } } importedModuleReport.setMandatory(importTask.isMandatory()); importedModuleReport.setMode(importTask.getMode()); importedModuleReport.setAs(importTask.getAs()); EasyAntReport pluginInfo = getPluginInfo(ModuleRevisionId.parse(importedModuleReport.getModuleMrid()), conf); importedModuleReport.setEasyantReport(pluginInfo); eaReport.addImportedModuleReport(importedModuleReport, isCurrentModule(importTask.getProject(), importTask.getLocation())); Message.debug("Ant file import another module called : " + importedModuleReport.getModuleMrid() + " with mode " + importedModuleReport.getMode()); } private void handleProperty(Property property, EasyAntReport eaReport) throws IOException { boolean isCurrentModule = isCurrentModule(property.getProject(), property.getLocation()); if (property.getFile() != null) { Properties propToLoad = new Properties(); File f = property.getFile(); if (f.exists()) { FileInputStream fis = null; try { fis = new FileInputStream(f); propToLoad.load(fis); for (Object o : propToLoad.keySet()) { String key = (String) o; PropertyDescriptor propertyDescriptor = new PropertyDescriptor(key); propertyDescriptor.setValue(propToLoad.getProperty(key)); if (property.getOwningTarget() != null) { propertyDescriptor.setOwningTarget(property.getOwningTarget().getName()); } eaReport.addPropertyDescriptor(propertyDescriptor.getName(), propertyDescriptor, isCurrentModule); } } catch (IOException e) { IOException ioe = new IOException("Unable to parse the property file :" + property.getFile()); ioe.initCause(e); throw ioe; } finally { if (fis != null) { fis.close(); } } } } if (property.getName() != null) { PropertyDescriptor propertyDescriptor = new PropertyDescriptor(property.getName()); propertyDescriptor.setValue(property.getValue()); if (property.getOwningTarget() != null) { propertyDescriptor.setOwningTarget(property.getOwningTarget().getName()); } eaReport.addPropertyDescriptor(property.getName(), propertyDescriptor, isCurrentModule); } } private void handleParameterTask(ParameterTask parameterTask, EasyAntReport eaReport) { boolean isCurrentModule = isCurrentModule(parameterTask.getProject(), parameterTask.getLocation()); if (parameterTask.getProperty() != null) { PropertyDescriptor propertyDescriptor = new PropertyDescriptor(parameterTask.getProperty()); propertyDescriptor.setDefaultValue(parameterTask.getDefault()); // Use unsafe version since we are in audit mode and we want the real value of the required field // (#isRequired method will always return false in audit mode) propertyDescriptor.setRequired(parameterTask.isRequiredUnsafe()); propertyDescriptor.setDescription(parameterTask.getDescription()); if (parameterTask.getOwningTarget() != null) { propertyDescriptor.setOwningTarget(parameterTask.getOwningTarget().getName()); } Message.debug("Ant file has a property called : " + propertyDescriptor.getName()); eaReport.addPropertyDescriptor(propertyDescriptor.getName(), propertyDescriptor, isCurrentModule); } else if (parameterTask.getPath() != null) { ParameterReport parameterReport = new ParameterReport(ParameterType.PATH); parameterReport.setName(parameterTask.getPath()); // Use unsafe version since we are in audit mode and we want the real value of the required field // (#isRequired method will always return false in audit mode) parameterReport.setRequired(parameterTask.isRequiredUnsafe()); parameterReport.setDescription(parameterTask.getDescription()); if (parameterTask.getOwningTarget() != null) { parameterReport.setOwningTarget(parameterTask.getOwningTarget().getName()); } eaReport.addParameterReport(parameterReport, isCurrentModule); Message.debug("Ant file has a path called : " + parameterReport.getName()); } } private void handleFilesetParameter(String id, FileSet fileSet, Target target, EasyAntReport eaReport) { ParameterReport parameterReport = new ParameterReport(ParameterType.FILESET); if (id != null) { parameterReport.setName(id); parameterReport.setRequired(false); parameterReport.setDescription(fileSet.getDescription()); if (target != null) { parameterReport.setOwningTarget(target.getName()); } eaReport.addParameterReport(parameterReport, isCurrentModule(fileSet.getProject(), fileSet.getLocation())); Message.debug("Ant file has a fileset called : " + parameterReport.getName()); } } private void handlePathParameter(String pathid, Path path, Target target, EasyAntReport eaReport) { ParameterReport parameterReport = new ParameterReport(ParameterType.PATH); if (pathid != null) { parameterReport.setName(pathid); parameterReport.setRequired(false); parameterReport.setDescription(path.getDescription()); if (target != null) { parameterReport.setOwningTarget(target.getName()); } eaReport.addParameterReport(parameterReport, isCurrentModule(path.getProject(), path.getLocation())); Message.debug("Ant file has a path called : " + parameterReport.getName()); } } private void handlePathParameter(PathTask pathTask, EasyAntReport eaReport) { ParameterReport parameterReport = new ParameterReport(ParameterType.PATH); if (pathTask.getPathid() != null) { parameterReport.setName(pathTask.getPathid()); parameterReport.setRequired(false); parameterReport.setDescription(pathTask.getDescription()); if (pathTask.getOwningTarget() != null) { parameterReport.setOwningTarget(pathTask.getOwningTarget().getName()); } eaReport.addParameterReport(parameterReport, isCurrentModule(pathTask.getProject(), pathTask.getLocation())); Message.debug("Ant file has a path called : " + parameterReport.getName()); } } private void handleTarget(Target target, EasyAntReport eaReport) { boolean isCurrentModule = isCurrentModule(target.getProject(), target.getLocation()); boolean isExtensionPoint = target instanceof ExtensionPoint; if (!isExtensionPoint) { TargetReport targetReport = new TargetReport(); targetReport.setName(target.getName()); StringBuilder sb = new StringBuilder(); Enumeration<?> targetDeps = target.getDependencies(); while (targetDeps.hasMoreElements()) { String t = (String) targetDeps.nextElement(); sb.append(t); if (targetDeps.hasMoreElements()) { sb.append(","); } } targetReport.setDepends(sb.toString()); targetReport.setDescription(target.getDescription()); targetReport.setIfCase(target.getIf()); targetReport.setUnlessCase(target.getUnless()); for (Target currentTarget : target.getProject().getTargets().values()) { if (currentTarget instanceof ExtensionPoint) { Enumeration<?> dependencies = currentTarget.getDependencies(); while (dependencies.hasMoreElements()) { String dep = (String) dependencies.nextElement(); if (dep.equals(target.getName())) { targetReport.setExtensionPoint(currentTarget.getName()); } } } } eaReport.addTargetReport(targetReport, isCurrentModule); Message.debug("Ant file has a target called : " + targetReport.getName()); } else { ExtensionPointReport extensionPoint = new ExtensionPointReport(target.getName()); StringBuilder sb = new StringBuilder(); Enumeration<?> targetDeps = target.getDependencies(); while (targetDeps.hasMoreElements()) { String t = (String) targetDeps.nextElement(); sb.append(t); if (targetDeps.hasMoreElements()) { sb.append(","); } } extensionPoint.setDepends(sb.toString()); extensionPoint.setDescription(target.getDescription()); eaReport.addExtensionPointReport(extensionPoint, isCurrentModule); Message.debug("Ant file has an extensionPoint called : " + extensionPoint.getName()); } } public EasyAntReport getPluginInfo(ModuleRevisionId moduleRevisionId) throws Exception { return getPluginInfo(moduleRevisionId, "default"); } public EasyAntReport getPluginInfo(String moduleRevisionId) throws Exception { ModuleRevisionId module = buildModuleRevisionId(moduleRevisionId, PluginType.PLUGIN); return getPluginInfo(module); } public EasyAntReport getBuildTypeInfo(String moduleRevisionId) throws Exception { ModuleRevisionId module = buildModuleRevisionId(moduleRevisionId, PluginType.BUILDTYPE); return getPluginInfo(module); } public EasyAntModuleDescriptor getEasyAntModuleDescriptor(File moduleDescriptor) throws Exception { if (moduleDescriptor == null) { throw new Exception("moduleDescriptor cannot be null"); } if (!moduleDescriptor.exists()) { throw new Exception("imposible to find the specified module descriptor" + moduleDescriptor.getAbsolutePath()); } IvyContext.pushNewContext().setIvy(ivyInstance); // First we need to parse the specified file to retrieve all the easyant // stuff parser.parseDescriptor(ivyInstance.getSettings(), moduleDescriptor.toURI().toURL(), new URLResource( moduleDescriptor.toURI().toURL()), true); EasyAntModuleDescriptor md = parser.getEasyAntModuleDescriptor(); IvyContext.popContext(); return md; } public EasyAntReport generateEasyAntReport(File moduleDescriptor, File optionalAntModule, File overrideAntModule) throws Exception { EasyAntReport eaReport = new EasyAntReport(); EasyAntModuleDescriptor md = getEasyAntModuleDescriptor(moduleDescriptor); eaReport.setModuleDescriptor(md.getIvyModuleDescriptor()); Project p = buildProject(); Target implicitTarget = ProjectUtils.createTopLevelTarget(); p.addTarget(implicitTarget); // calculate basedir if (moduleDescriptor != null) { p.setBaseDir(moduleDescriptor.getParentFile()); } else if (optionalAntModule != null) { p.setBaseDir(optionalAntModule.getParentFile()); } else if (overrideAntModule != null) { p.setBaseDir(overrideAntModule.getParentFile()); } LoadModule loadModule = new LoadModule(); loadModule.setBuildModule(moduleDescriptor); loadModule.setBuildFile(optionalAntModule); loadModule.setOwningTarget(implicitTarget); loadModule.setLocation(new Location(ProjectUtils.emulateMainScript(p).getAbsolutePath())); loadModule.setProject(p); loadModule.setTaskName("load-module"); loadModule.execute(); ProjectHelper projectHelper = ProjectUtils.getConfiguredProjectHelper(p); projectHelper.resolveExtensionOfAttributes(p); analyseProject(p, eaReport, "default"); return eaReport; } public ModuleRevisionId[] search(String organisation, String moduleName, String revision, String branch, String matcher, String resolver) throws Exception { IvySettings settings = ivyInstance.getSettings(); if (moduleName == null && PatternMatcher.EXACT.equals(matcher)) { throw new Exception("no module name provided for ivy repository graph task: " + "It can either be set explicitely via the attribute 'module' or " + "via 'ivy.module' property or a prior call to <resolve/>"); } else if (moduleName == null && !PatternMatcher.EXACT.equals(matcher)) { moduleName = PatternMatcher.ANY_EXPRESSION; } ModuleRevisionId mrid = ModuleRevisionId.newInstance(organisation, moduleName, revision); ModuleRevisionId criteria; if ((revision == null) || settings.getVersionMatcher().isDynamic(mrid)) { criteria = new ModuleRevisionId(new ModuleId(organisation, moduleName), branch, "*"); } else { criteria = new ModuleRevisionId(new ModuleId(organisation, moduleName), branch, revision); } PatternMatcher patternMatcher = settings.getMatcher(matcher); if (PatternMatcher.ANY_EXPRESSION.equals(resolver)) { // search in all resolvers. this can be quite slow for complex // repository configurations // with ChainResolvers, since resolvers in chains will be searched // multiple times. return ivyInstance.listModules(criteria, patternMatcher); } else { // limit search to the specified resolver. DependencyResolver dependencyResolver = resolver == null ? settings.getDefaultResolver() : settings .getResolver(resolver); if (dependencyResolver == null) { throw new IllegalArgumentException("Unknown dependency resolver for search: " + resolver); } ivyInstance.pushContext(); try { return ivyInstance.getSearchEngine().listModules(dependencyResolver, criteria, patternMatcher); } finally { ivyInstance.popContext(); } } } public ModuleRevisionId[] search(String organisation, String moduleName) throws Exception { return search(organisation, moduleName, null, null, PatternMatcher.EXACT_OR_REGEXP, null); } public String[] searchModule(String organisation, String moduleName) throws Exception { ModuleRevisionId[] mrids = search(organisation, moduleName); String[] result = new String[mrids.length]; for (int i = 0; i < mrids.length; i++) { result[i] = mrids[i].toString(); } return result; } public String getDescription(ModuleRevisionId mrid) { ResolvedModuleRevision rmr = ivyInstance.findModule(mrid); return rmr.getDescriptor().getDescription(); } public String getPluginDescription(String moduleRevisionId) { ModuleRevisionId module = buildModuleRevisionId(moduleRevisionId, PluginType.PLUGIN); return getDescription(module); } public String getBuildTypeDescription(String moduleRevisionId) { ModuleRevisionId module = buildModuleRevisionId(moduleRevisionId, PluginType.BUILDTYPE); return getDescription(module); } private ModuleRevisionId buildModuleRevisionId(String moduleRevisionId, PluginType pluginType) { String mrid = moduleRevisionId; if (!mrid.matches(".*#.*")) { if (pluginType.equals(PluginType.BUILDTYPE)) { Message.debug("No organisation specified for buildtype " + mrid + " using the default one"); mrid = EasyAntConstants.EASYANT_BUILDTYPES_ORGANISATION + "#" + mrid; } else { Message.debug("No organisation specified for plugin " + mrid + " using the default one"); mrid = EasyAntConstants.EASYANT_PLUGIN_ORGANISATION + "#" + mrid; } } return ModuleRevisionId.parse(mrid); } public EasyAntReport generateEasyAntReport(File moduleDescriptor) throws Exception { return generateEasyAntReport(moduleDescriptor, null, null); } /** * Don't try to expand property on reports. Bypassing default property expander allow us to show real static value * of properties on reports. */ private class BypassDefaultPropertyExpander implements PropertyExpander { public String parsePropertyName(String s, ParsePosition pos, ParseNextProperty notUsed) { int index = pos.getIndex(); // directly check near, triggering characters: if (s.length() - index >= 3 && '$' == s.charAt(index) && '{' == s.charAt(index + 1)) { int start = index; // defer to String.indexOf() for protracted check: int end = s.indexOf('}', start); if (end < 0) { throw new BuildException("Syntax error in property: " + s.substring(index)); } // set marker after "}" pos.setIndex(end + 1); // allow to resolve path to property files // this is mandatory if we want report to contains properties loaded by // property file like done on buildtypes // in that case property needs to be really expanded so we need to strips "${" and "}" characters String strippedPropertyName = s.substring(start + 2, end); if (strippedPropertyName.endsWith("properties.file")) { return strippedPropertyName; } // in other cases return the whole property with "${" and "}" return start == end ? "" : s.substring(start, end + 1); } return null; } } public void setOfflineMode(boolean offlineMode) { this.offlineMode = offlineMode; } }