public ResolvedPath getResolvedPluginPath( Plugin plugin, String pathId, boolean mergeWithCore, boolean overrideCore, boolean flatten) { String key = "pluginPath#" + plugin.toShortString() + "#" + pathId + "#" + mergeWithCore + "#" + overrideCore + "#" + flatten; ResolvedPath path = (ResolvedPath) pathCache.get(key); if (path == null) { path = _getResolvedPluginPath(plugin, pathId, mergeWithCore, overrideCore, flatten); pathCache.put(key, path); } else { log.debug("Cache hit for: " + key); } return path; }
public ResolvedPath _getResolvedPluginPath( Plugin plugin, String pathId, boolean mergeWithCore, boolean overrideCore, boolean flatten) { // Create a mock artifact for the resolver as a way to add user specified path specs and // overrides RepoArtifact artifact = new RepoArtifact(); RepoDependency dependency = new RepoDependency(); RepoArtifactId pluginId = plugin.getArtifact().getId(); dependency.setId(pluginId); artifact.addDependency(dependency); String id = "plugin"; artifact.addPath(new RepoPath(id, "Plugin path", true, true)); // Add dependencies if (plugin.getDependency() != null) { for (Iterator j = plugin.getDependency().getPathSpecs().iterator(); j.hasNext(); ) { RepoPathSpec pluginPathSpec = (RepoPathSpec) j.next(); if (pluginPathSpec.getFrom().equals(pathId)) { // Add user specifications. Ignore the mandatory flag and to paths as they // are not relevant. However, allow descend to be false in case the writer of the // plugin added bogus dependencies. dependency.addPathSpec( new RepoPathSpec( pathId, id, pluginPathSpec.getOptions(), (pluginPathSpec.isDescend() == null) ? Boolean.TRUE : pluginPathSpec.isDescend(), Boolean.TRUE)); } } } if (dependency.getPathSpecs().size() == 0) { // Add default ... user hasn't specified anything dependency.addPathSpec(new RepoPathSpec(pathId, id, null, Boolean.TRUE, Boolean.TRUE)); } // Add core overrides if applicable if (overrideCore) { for (Iterator j = coreOverrides.iterator(); j.hasNext(); ) { RepoOverride override = (RepoOverride) j.next(); artifact.addOverride(override); } } // Add overrides for (Iterator i = overrides.iterator(); i.hasNext(); ) { ws.quokka.core.model.Override override = (ws.quokka.core.model.Override) i.next(); Set paths = override.matchingPluginPaths(plugin.getArtifact().getId()); if (paths.contains(pathId) || ((paths.size() == 1) && paths.contains("*"))) { // Create a copy of the override, moving matching plugin paths to be standard paths RepoOverride copy = new RepoOverride( Collections.singleton("*"), override.getGroup(), override.getName(), override.getType(), override.getVersion(), override.getWithVersion(), override.getWithPathSpecs()); artifact.addOverride(copy); } } // Remove the plugin itself from the path // TODO: Look into a better way of doing this, perhaps modifying Resolver so it has the option // of not adding the root in first place. ResolvedPath path = pathResolver.resolvePath(id, artifact); path.setId("Plugin path '" + pathId + "' from " + pluginId.toShortString()); List artifacts = new ArrayList(); for (Iterator i = path.getArtifacts().iterator(); i.hasNext(); ) { artifact = (RepoArtifact) i.next(); if (!artifact.getId().equals(pluginId)) { artifacts.add(artifact); } if (pluginId.equals(artifact.getId().getAnnotations().get("declaredBy"))) { artifact.getId().getAnnotations().remove("declaredBy"); } } path = new ResolvedPath(path.getId(), artifacts); path = handleMergeAndFlatten(mergeWithCore, flatten, path); return path; }
public List _resolvePathGroup(Target target, String pathGroupId) { Plugin plugin = target.getPlugin(); PathGroup pathGroup = target.getPathGroup(pathGroupId); if (pathGroup == null) { if (plugin.getDeclaringPlugin() != null) { String declaringTargetName = plugin.getDeclaringPlugin().getNameSpace() + ":" + parseImplements(target)[2]; pathGroup = plugin.getDeclaringPlugin().getTarget(declaringTargetName).getPathGroup(pathGroupId); // TODO: Check the path group only refers to project paths? } Assert.isTrue( pathGroup != null, "Target '" + target.getName() + "' has requested path group '" + pathGroupId + "' that does not exist"); } if (log.isDebugEnabled()) { log.debug( "Resolving path: target=" + target.getName() + ", pathGroup=" + pathGroupId + ", pathGroupElements=" + pathGroup.getPaths()); } List paths = new ArrayList(); // Note: merging with core is turned off here so that the proper path tree is maintained // However, core overrides are still applied by separating that into a different flag resolvePath( pathGroup.getPaths(), paths, false, pathGroup.getMergeWithCore().booleanValue(), target, false); if (log.isDebugEnabled()) { log.debug("Resolved the following paths for path group '" + pathGroup + "'"); for (Iterator i = paths.iterator(); i.hasNext(); ) { ResolvedPath path = (ResolvedPath) i.next(); log.debug(pathResolver.formatPath(path, false)); } } ResolvedPath path = pathResolver.merge(paths); if (pathGroup.getMergeWithCore().booleanValue()) { path = mergeWithCore(path); } // System.out.println(pathResolver.formatPath(path, false)); StringBuffer sb = new StringBuffer(); for (Iterator i = path.getArtifacts().iterator(); i.hasNext(); ) { RepoArtifact artifact = (RepoArtifact) i.next(); sb.append(artifact.getId().toShortString()).append(";"); } if (log.isDebugEnabled()) { log.debug( "Resolved path: target=" + target.getName() + ", pathGroup=" + pathGroupId + ", path=" + sb.toString()); } return path.getArtifacts(); }
private void addTarget(Map resolved, Target target) { // System.out.println("Adding " + target.getName() + " from " + parents); if (target.getPrefix() != null) { target.setDefaultProperties(expandPrefix(target.getPrefix(), target.getDefaultProperties())); } Target existing = (Target) resolved.get(target.getName()); if (existing != null) { RepoArtifactId targetId = target.getPlugin().getArtifact().getId(); RepoArtifactId existingId = existing.getPlugin().getArtifact().getId(); Assert.isTrue( targetId.equals(existingId), target.getLocator(), "Multiple targets are defined with the name '" + target.getName() + "'. Declared in " + targetId + " and " + existingId); return; } resolved.put(target.getName(), target); registerTypes(target); registerProjectPaths(target); buildResources.putAll(target.getPlugin().getBuildResources()); // PluginDependency declares the target addDependentTargets(resolved, target); if (target.getImplementsPlugin() != null) { // PluginDependency implements the target declared in another plugin String[] implementsPlugin = parseImplements(target); RepoArtifactId declaringPluginId = fastFindMatchingDependency( target, new RepoArtifactId( implementsPlugin[0], implementsPlugin[1], "plugin", (Version) null)); Plugin declaringPlugin = getPluginInstance(declaringPluginId); String declaringTargetName = declaringPlugin.getNameSpace() + ":" + implementsPlugin[2]; // Get the declaring plugin and find the matching target Target declaringTarget = (Target) resolved.get(declaringTargetName); if (declaringTarget == null) { declaringTarget = declaringPlugin.getTarget(declaringTargetName); Assert.isTrue( declaringTarget != null, target.getLocator(), "'" + declaringTargetName + "' is not defined in '" + declaringPluginId.toShortString() + "'"); addTarget(resolved, declaringTarget); } Assert.isTrue( declaringTarget.isAbstract(), target.getLocator(), "Target is attempting to implement a non-abstract target: target=" + target.getName() + ", implements=" + declaringTarget.getName()); target.getPlugin().setDeclaringPlugin(declaringTarget.getPlugin()); if (!declaringTarget.isImplemented()) { declaringTarget.setImplemented(true); declaringTarget.clearDependencies(); } declaringTarget.addDependency(target.getName()); // Add the declaring targets dependencies to ensure the implementation is executed before them for (Iterator i = declaringTarget.getOriginalDependencies().iterator(); i.hasNext(); ) { String dependency = (String) i.next(); target.addDependency(dependency); } } }
private void resolveTargets(Map resolved, PluginDependency pluginDependency) { List dependencyTargets = new ArrayList(pluginDependency.getTargets()); Plugin plugin = getPluginInstance(pluginDependency.getId()); plugin.setDependency(pluginDependency); for (Iterator i = plugin.getTargets().iterator(); i.hasNext(); ) { Target target = (Target) i.next(); // If the target is based on a template internally, merge with the template if (target.getTemplateName() != null) { String template = target.getTemplateName(); template = (template.indexOf(":") != -1) ? template : (target.getPlugin().getNameSpace() + ":" + template); target.merge(plugin.getTarget(template)); } // Process explicit target definitions boolean added = false; for (Iterator j = dependencyTargets.iterator(); j.hasNext(); ) { PluginDependencyTarget dependencyTarget = (PluginDependencyTarget) j.next(); Target targetInstance = null; if (dependencyTarget.getTemplate() == null) { // Enabling a target String name = dependencyTarget.getName(); name = (name.indexOf(":") != -1) ? name : (target.getPlugin().getNameSpace() + ":" + name); if (target.getName().equals(name)) { Assert.isTrue( !target.isTemplate(), dependencyTarget.getLocator(), "The named target '" + name + "' is a template"); String prefix = dependencyTarget.getPrefix(); Assert.isTrue( (prefix == null) || prefix.equals(target.getPrefix()), dependencyTarget.getLocator(), "The prefix '" + prefix + "' should match the target prefix '" + target.getPrefix() + "' if specified"); if (dependencyTarget.getAlias() != null) { target.setAlias(dependencyTarget.getAlias()); } targetInstance = target; } } else { // Instantiation of a template String template = dependencyTarget.getTemplate(); template = (template.indexOf(":") != -1) ? template : (target.getPlugin().getNameSpace() + ":" + template); if (target.getName().equals(template)) { Assert.isTrue( target.isTemplate(), dependencyTarget.getLocator(), "The named target '" + template + "' is not a template"); targetInstance = (Target) target.clone(); targetInstance.setPrefix(dependencyTarget.getPrefix()); targetInstance.setTemplateName(target.getName()); targetInstance.setName(dependencyTarget.getName()); } } if (targetInstance != null) { added = true; for (Iterator k = dependencyTarget.getDependencies().iterator(); k.hasNext(); ) { String dependency = (String) k.next(); targetInstance.addDependency(dependency); } // Record the plugin dependency target that introduced the target // This will be used later for dependency-of processing targetInstance.setPluginDependencyTarget(dependencyTarget); addTarget(resolved, targetInstance); j.remove(); } } // Use defaults if (!added && pluginDependency.isUseDefaults() && target.isEnabledByDefault()) { addTarget(resolved, target); } } if (dependencyTargets.size() != 0) { List names = new ArrayList(); for (Iterator i = dependencyTargets.iterator(); i.hasNext(); ) { PluginDependencyTarget target = (PluginDependencyTarget) i.next(); names.add(target.getName()); } Assert.isTrue( false, pluginDependency.getLocator(), "The following targets are not defined in plugin '" + plugin.getArtifact().getId().toShortString() + "': " + Strings.join(names.iterator(), ",")); } }
public Runnable createTargetInstance(Target target, Properties localProperties, Logger logger) { // System.out.println("DefaultProjectModel.createTargetInstance"); AntClassLoader loader = null; DefaultResources resources; try { org.apache.tools.ant.types.Path classPath = toAntPath(resolvePathGroup(target, "classpath")); // Allow additional classes to added to the plugin classpath. This is primarily designed to // allow the additional of instrumented testing classes and libraries for code coverage of // integration // tests with Cobertura String key = "quokka.classpath." + target.getPlugin().getArtifact().getId().getGroup(); if (log.isDebugEnabled()) { log.debug("Searching for additional classpath with key: " + key); } String additionalPath = System.getProperty(key); if ((additionalPath != null) && !additionalPath.trim().equals("")) { org.apache.tools.ant.types.Path existing = classPath; classPath = new org.apache.tools.ant.types.Path(antProject, additionalPath); log.verbose("Prefixing classpath with: " + classPath); classPath.append(existing); // Make sure additions override existing } if ("true".equals(antProject.getProperty("quokka.project.debugclassloaders"))) { loader = new QuokkaLoader(target, antProject.getClass().getClassLoader(), antProject, classPath); } else { loader = antProject.createClassLoader(classPath); } loader.setParent(antProject.getCoreLoader()); loader.setParentFirst(true); loader.setIsolated(false); loader.setThreadContextLoader(); // Initialise this plugin Plugin plugin = target.getPlugin(); loader.forceLoadClass(plugin.getClassName()); Class pluginClass = Class.forName(plugin.getClassName(), true, loader); ws.quokka.core.plugin_spi.Plugin actualPlugin = (ws.quokka.core.plugin_spi.Plugin) pluginClass.newInstance(); if (actualPlugin instanceof MetadataAware) { ((MetadataAware) actualPlugin).setMetadata(getMetadata()); } if (actualPlugin instanceof ResourcesAware) { resources = new DefaultResources(this, target, antProject, logger); ((ResourcesAware) actualPlugin).setResources(resources); } if (actualPlugin instanceof RepositoryAware) { ((RepositoryAware) actualPlugin).setRepository(getRepository()); } if (actualPlugin instanceof RepositoryFactoryAware) { ((RepositoryFactoryAware) actualPlugin) .setRepositoryFactory( (RepositoryFactory) antProject.getReference(ProjectHelper.REPOSITORY_FACTORY)); } if (actualPlugin instanceof ResolverAware) { ((ResolverAware) actualPlugin).setResolver(pathResolver); } if (actualPlugin instanceof ModelFactoryAware) { ((ModelFactoryAware) actualPlugin).setModelFactory(getModelFactory()); } actualPlugin.initialise(); return actualPlugin.getTarget( (target.getTemplateName() != null) ? target.getTemplateName() : target.getName()); } catch (Exception e) { throw new BuildException(e); } finally { if (loader != null) { loader.resetThreadContextLoader(); loader.cleanup(); } } }