| /* |
| * 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 |
| * |
| * https://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.ivy.plugins.resolver.packager; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Map; |
| |
| import org.apache.ivy.core.IvyPatternHelper; |
| import org.apache.ivy.core.module.descriptor.Artifact; |
| import org.apache.ivy.core.module.id.ModuleRevisionId; |
| import org.apache.ivy.plugins.repository.Resource; |
| import org.apache.ivy.plugins.resolver.util.ResolvedResource; |
| import org.apache.ivy.util.FileUtil; |
| import org.apache.ivy.util.Message; |
| import org.apache.tools.ant.BuildException; |
| import org.apache.tools.ant.BuildLogger; |
| import org.apache.tools.ant.DefaultLogger; |
| import org.apache.tools.ant.Project; |
| import org.apache.tools.ant.ProjectHelper; |
| |
| /** |
| * Represents one entry in the cache of a {@link PackagerResolver}. |
| */ |
| public class PackagerCacheEntry { |
| |
| private final ModuleRevisionId mr; |
| |
| private final File dir; |
| |
| private final File resourceCache; |
| |
| private final String resourceURL; |
| |
| private final boolean validate; |
| |
| private final boolean preserve; |
| |
| private final boolean restricted; |
| |
| private final boolean verbose; |
| |
| private final boolean quiet; |
| |
| private boolean built; |
| |
| // CheckStyle:ParameterNumber OFF |
| public PackagerCacheEntry(ModuleRevisionId mr, File rootDir, File resourceCache, |
| String resourceURL, boolean validate, boolean preserve, boolean restricted, |
| boolean verbose, boolean quiet) { |
| this.mr = mr; |
| this.dir = getSubdir(rootDir, this.mr); |
| this.resourceCache = resourceCache; |
| this.resourceURL = resourceURL; |
| this.validate = validate; |
| this.preserve = preserve; |
| this.restricted = restricted; |
| this.verbose = verbose; |
| this.quiet = quiet; |
| } |
| |
| // CheckStyle:ParameterNumber ON |
| |
| /** |
| * Attempt to build this entry. |
| * |
| * @param packagerResource |
| * packager metadata resource |
| * @param properties |
| * a map of properties to pass to the child Ant build responsible for dependency |
| * packaging |
| * |
| * @throws IOException |
| * if this entry has already been built |
| */ |
| public synchronized void build(Resource packagerResource, Map<String, String> properties) throws IOException { |
| // Sanity check |
| if (this.built) { |
| throw new IllegalStateException("build in directory `" + this.dir |
| + "' already completed"); |
| } |
| |
| // Remove work directory if it exists (e.g. left over from last time) |
| if (this.dir.exists()) { |
| if (!cleanup()) { |
| throw new IOException("can't remove directory `" + this.dir + "'"); |
| } |
| } |
| |
| // Create work directory |
| if (!this.dir.mkdirs()) { |
| throw new IOException("can't create directory `" + this.dir + "'"); |
| } |
| |
| // Write out packager XML |
| InputStream packagerXML = packagerResource.openStream(); |
| saveFile("packager.xml", packagerXML); |
| |
| // Write packager XSLT |
| saveFile("packager.xsl"); |
| |
| // Write packager XSD |
| saveFile("packager-1.0.xsd"); |
| |
| // Write master Ant build file |
| saveFile("build.xml"); |
| |
| // Execute the Ant build file |
| Project project = new Project(); |
| project.init(); |
| project.setUserProperty("ant.file", new File(dir, "build.xml").getAbsolutePath()); |
| ProjectHelper.configureProject(project, new File(dir, "build.xml")); |
| project.setBaseDir(dir); |
| |
| // Configure logging verbosity |
| BuildLogger logger = new DefaultLogger(); |
| logger.setMessageOutputLevel(this.verbose ? Project.MSG_VERBOSE |
| : this.quiet ? Project.MSG_WARN : Project.MSG_INFO); |
| logger.setOutputPrintStream(System.out); |
| logger.setErrorPrintStream(System.err); |
| project.addBuildListener(logger); |
| |
| // Set properties |
| project.setUserProperty("ivy.packager.organisation", "" |
| + this.mr.getModuleId().getOrganisation()); |
| project.setUserProperty("ivy.packager.module", "" + this.mr.getModuleId().getName()); |
| project.setUserProperty("ivy.packager.revision", "" + this.mr.getRevision()); |
| project.setUserProperty("ivy.packager.branch", "" + this.mr.getBranch()); |
| if (this.resourceCache != null) { |
| project.setUserProperty("ivy.packager.resourceCache", |
| "" + this.resourceCache.getCanonicalPath()); |
| } |
| if (this.resourceURL != null) { |
| project.setUserProperty("ivy.packager.resourceURL", "" + getResourceURL()); |
| } |
| if (this.validate) { |
| project.setUserProperty("ivy.packager.validate", "true"); |
| } |
| project.setUserProperty("ivy.packager.restricted", "" + this.restricted); |
| project.setUserProperty("ivy.packager.quiet", String.valueOf(quiet)); |
| if (properties != null) { |
| for (Map.Entry<String, String> entry : properties.entrySet()) { |
| project.setUserProperty(entry.getKey(), entry.getValue()); |
| } |
| } |
| |
| // Execute task |
| Message.verbose("performing packager resolver build in " + this.dir); |
| try { |
| project.executeTarget("build"); |
| this.built = true; |
| } catch (BuildException e) { |
| Message.verbose("packager resolver build failed: " + e); |
| throw e; |
| } |
| } |
| |
| /** |
| * Has this entry been successfully built? |
| * |
| * @return boolean |
| */ |
| public synchronized boolean isBuilt() { |
| return this.built; |
| } |
| |
| /** |
| * Get a built artifact. |
| * |
| * @param artifact ditto |
| * @return ResolvedResource |
| * @throws IllegalStateException |
| * if this entry's built has not (yet) completed successfully |
| */ |
| public ResolvedResource getBuiltArtifact(Artifact artifact) { |
| if (!this.built) { |
| throw new IllegalStateException("build in directory `" + this.dir |
| + "' has not yet successfully completed"); |
| } |
| return new ResolvedResource(new BuiltFileResource(this.dir, artifact), |
| this.mr.getRevision()); |
| } |
| |
| public synchronized boolean cleanup() { |
| this.built = false; |
| return FileUtil.forceDelete(this.dir); |
| } |
| |
| protected void saveFile(String name, InputStream input) throws IOException { |
| FileUtil.copy(input, new File(this.dir, name), null); |
| } |
| |
| protected void saveFile(String name) throws IOException { |
| InputStream input = getClass().getResourceAsStream(name); |
| if (input == null) { |
| throw new IOException("can't find resource `" + name + "'"); |
| } |
| saveFile(name, input); |
| } |
| |
| // @Override |
| protected void finalize() throws Throwable { |
| try { |
| if (!this.preserve) { |
| cleanup(); |
| } |
| } finally { |
| super.finalize(); |
| } |
| } |
| |
| private String getResourceURL() { |
| String baseURL = IvyPatternHelper.substitute(resourceURL, mr.getOrganisation(), |
| mr.getName(), mr.getRevision(), null, null, null, null, |
| mr.getQualifiedExtraAttributes(), null); |
| int slash = baseURL.lastIndexOf('/'); |
| if (slash != -1) { |
| baseURL = baseURL.substring(0, slash + 1); |
| } |
| return baseURL; |
| } |
| |
| private static File getSubdir(File rootDir, ModuleRevisionId mr) { |
| return new File(rootDir, mr.getOrganisation() + File.separatorChar + mr.getName() |
| + File.separatorChar + mr.getRevision()); |
| } |
| } |