Index: test/java/org/apache/ivy/plugins/resolver/PackagerResolverTest.java =================================================================== --- test/java/org/apache/ivy/plugins/resolver/PackagerResolverTest.java (revision 0) +++ test/java/org/apache/ivy/plugins/resolver/PackagerResolverTest.java (revision 0) @@ -0,0 +1,176 @@ +/* + * 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.ivy.plugins.resolver; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.Date; +import java.util.GregorianCalendar; + +import org.apache.ivy.core.event.EventManager; +import org.apache.ivy.core.module.descriptor.Artifact; +import org.apache.ivy.core.module.descriptor.DefaultArtifact; +import org.apache.ivy.core.module.descriptor.DefaultDependencyDescriptor; +import org.apache.ivy.core.module.id.ModuleRevisionId; +import org.apache.ivy.core.report.ArtifactDownloadReport; +import org.apache.ivy.core.report.DownloadReport; +import org.apache.ivy.core.report.DownloadStatus; +import org.apache.ivy.core.resolve.DownloadOptions; +import org.apache.ivy.core.resolve.ResolveData; +import org.apache.ivy.core.resolve.ResolveEngine; +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.core.sort.SortEngine; +import org.apache.ivy.plugins.resolver.packager.PackagerResolver; +import org.apache.ivy.plugins.resolver.packager.SubProcess; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.taskdefs.Delete; + +/** + * Tests PackagerResolver. + */ +// junit +public class PackagerResolverTest extends AbstractDependencyResolverTest { + + private IvySettings _settings; + + private ResolveEngine _engine; + + private ResolveData _data; + + private File _cache; + + private File _workdir; + private File _builddir; + private File _cachedir; + private File _websitedir; // really a symlink + + protected void setUp() throws Exception { + _settings = new IvySettings(); + _engine = new ResolveEngine(_settings, new EventManager(), new SortEngine(_settings)); + _cache = new File("build/cache"); + _data = new ResolveData(_engine, new ResolveOptions()); + _cache.mkdirs(); + _settings.setDefaultCache(_cache); + + // Create work space with build and resource cache directories + _workdir = new File(new File(System.getProperty("java.io.tmpdir")), "PackagerResolverTest"); + _builddir = new File(_workdir, "build"); + _cachedir = new File(_workdir, "resources"); + _websitedir = new File(_workdir, "website"); + cleanupTempDirs(); + if (!_builddir.mkdirs() || !_cachedir.mkdirs()) { + throw new Exception("can't create directories under " + _workdir); + } + + // Add symlink to create "website" + String linkFrom = new File("test/repositories/packager/website").getAbsolutePath(); + String linkTo = _websitedir.getAbsolutePath(); + SubProcess proc = new SubProcess( + new String[] { "ln", "-sf", linkFrom, linkTo }, null, null); + if (proc.run() != 0) + throw new RuntimeException("can't symlink " + linkFrom + " -> " + linkTo); + } + + protected void tearDown() throws Exception { + Delete del = new Delete(); + del.setProject(new Project()); + del.setDir(_cache); + del.execute(); + cleanupTempDirs(); + } + + protected void cleanupTempDirs() throws Exception { + PackagerResolver.deleteRecursive(_builddir); + PackagerResolver.deleteRecursive(_cachedir); + _websitedir.delete(); + } + + public void testFile() throws Exception { + + // Create and configure resolver + PackagerResolver resolver = new PackagerResolver(); + resolver.setSettings(_settings); + File repoRoot = new File("test/repositories/packager/repo"); + resolver.addIvyPattern( + "" + new File(repoRoot, "[organisation]/[module]/[revision]/ivy.xml").toURL()); + resolver.setPackagerPattern( + "" + new File(repoRoot, "[organisation]/[module]/[revision]/packager.xml").toURL()); + resolver.setBuildRoot(_builddir.getAbsolutePath()); + resolver.setResourceCache(_cachedir.getAbsolutePath()); + resolver.setPreserveBuildDirectories(true); + + resolver.setName("packager"); + assertEquals("packager", resolver.getName()); + + // Get module descriptor + ModuleRevisionId mrid = ModuleRevisionId.newInstance("org", "mod", "1.0"); + ResolvedModuleRevision rmr = resolver.getDependency( + new DefaultDependencyDescriptor(mrid, false), _data); + assertNotNull(rmr); + + assertEquals(mrid, rmr.getId()); + Date pubdate = new GregorianCalendar(2004, 10, 1, 11, 0, 0).getTime(); + assertEquals(pubdate, rmr.getPublicationDate()); + + // Download artifact + Artifact artifact = new DefaultArtifact(mrid, pubdate, "mod", "jar", "jar"); + DownloadReport report = resolver.download(new Artifact[] {artifact}, downloadOptions()); + assertNotNull(report); + + assertEquals(1, report.getArtifactsReports().length); + + ArtifactDownloadReport ar = report.getArtifactReport(artifact); + assertNotNull(ar); + + assertEquals(artifact, ar.getArtifact()); + assertEquals(DownloadStatus.SUCCESSFUL, ar.getDownloadStatus()); + + // Verify resource cache now contains the distribution archive + assertTrue(new File(_cachedir, "mod-1.0.tar.gz").exists()); + + // Download again, should use Ivy cache this time + report = resolver.download(new Artifact[] {artifact}, downloadOptions()); + assertNotNull(report); + + assertEquals(1, report.getArtifactsReports().length); + + ar = report.getArtifactReport(artifact); + assertNotNull(ar); + + assertEquals(artifact, ar.getArtifact()); + assertEquals(DownloadStatus.NO, ar.getDownloadStatus()); + + // Now download the maven2 artifact + artifact = DefaultArtifact.cloneWithAnotherName(artifact, "foobar-janfu"); + report = resolver.download(new Artifact[] {artifact}, downloadOptions()); + assertNotNull(report); + + assertEquals(1, report.getArtifactsReports().length); + + ar = report.getArtifactReport(artifact); + assertNotNull(ar); + + assertEquals(artifact, ar.getArtifact()); + assertEquals(DownloadStatus.SUCCESSFUL, ar.getDownloadStatus()); + } +} Property changes on: test/java/org/apache/ivy/plugins/resolver/PackagerResolverTest.java ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Index: test/repositories/packager/website/dist/mod-1.0.tar.gz =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/gzip Property changes on: test/repositories/packager/website/dist/mod-1.0.tar.gz ___________________________________________________________________ Name: svn:mime-type + application/gzip Index: test/repositories/packager/website/m2repo/org/apache/ivy/foobar/1.0/foobar-1.0-janfu.jar =================================================================== Index: test/repositories/packager/repo/org/mod/1.0/ivy.xml =================================================================== --- test/repositories/packager/repo/org/mod/1.0/ivy.xml (revision 0) +++ test/repositories/packager/repo/org/mod/1.0/ivy.xml (revision 0) @@ -0,0 +1,30 @@ + + + + + + + + Property changes on: test/repositories/packager/repo/org/mod/1.0/ivy.xml ___________________________________________________________________ Name: svn:mime-type + text/xml Name: svn:keywords + Id Name: svn:eol-style + native Index: test/repositories/packager/repo/org/mod/1.0/packager.xml =================================================================== --- test/repositories/packager/repo/org/mod/1.0/packager.xml (revision 0) +++ test/repositories/packager/repo/org/mod/1.0/packager.xml (revision 0) @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + Property changes on: test/repositories/packager/repo/org/mod/1.0/packager.xml ___________________________________________________________________ Name: svn:mime-type + text/xml Name: svn:keywords + Id Name: svn:eol-style + native Index: CHANGES.txt =================================================================== --- CHANGES.txt (revision 665706) +++ CHANGES.txt (working copy) @@ -64,12 +64,14 @@ John Williams Patrick Woodworth Jaroslaw Wypychowski + Archie Cobbs trunk version ===================================== - NEW: Retain original dependency constraint rules in resolved ivy file (IVY-739) - NEW: Add a new resolve mode (optionally per module) to utilize dynamic constraint rule metadata (IVY-740) - NEW: Add transitive dependency version and branch override mechanism (IVY-784) +- NEW: Add new packager resolver (IVY-829) - IMPROVEMENT: declare source and javadoc artifacts in maven2 modules (IVY-325) - IMPROVEMENT: Set the last modified attribute of files downloaded from repositories (IVY-823) Index: src/java/org/apache/ivy/plugins/resolver/packager/PackagerResolver.java =================================================================== --- src/java/org/apache/ivy/plugins/resolver/packager/PackagerResolver.java (revision 0) +++ src/java/org/apache/ivy/plugins/resolver/packager/PackagerResolver.java (revision 0) @@ -0,0 +1,222 @@ +/* + * 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.ivy.plugins.resolver.packager; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.Iterator; + +import org.apache.ivy.core.module.descriptor.Artifact; +import org.apache.ivy.core.module.descriptor.DefaultArtifact; +import org.apache.ivy.core.module.id.ModuleRevisionId; +import org.apache.ivy.plugins.resolver.URLResolver; +import org.apache.ivy.plugins.resolver.util.ResolvedResource; +import org.apache.ivy.util.Message; + +/** + * Resolver that performs a "build" operation to resolve artifacts. + * + *

+ * The resolver is configured with a base URL, from which the "ivy.xml" + * and "packager.xml" files are resolved. The latter file contains + * instructions describing how to build the actual artifacts. + */ +public class PackagerResolver extends URLResolver { + + private static final String PACKAGER_ARTIFACT_NAME = "packager"; + private static final String PACKAGER_ARTIFACT_TYPE = "packager"; + private static final String PACKAGER_ARTIFACT_EXT = "xml"; + + private final HashMap/**/ packagerCache = new HashMap(); + + private File buildRoot; + private File resourceCache; + private String resourceURL; + private boolean validate = true; + private boolean preserve; + private boolean verbose; + private boolean quiet; + + public PackagerResolver() { + Runtime.getRuntime().addShutdownHook(new Thread() { + public void run() { + clearCache(); + } + }); + } + + protected synchronized void clearCache() { + if (this.preserve) { + return; + } + for (Iterator i = packagerCache.values().iterator(); i.hasNext();) { + PackagerCacheEntry entry = (PackagerCacheEntry) i.next(); + entry.cleanup(); + } + packagerCache.clear(); + if (this.buildRoot != null) { + deleteRecursive(this.buildRoot); + } + } + + /** + * Set root directory under which builds take place. + */ + public void setBuildRoot(String buildRoot) { + this.buildRoot = new File(buildRoot); + } + + /** + * Set resource cache directory. + */ + public void setResourceCache(String resourceCache) { + this.resourceCache = resourceCache != null ? new File(resourceCache) : null; + } + + /** + * Set base resource override URL pattern. + */ + public void setResourceURL(String resourceURL) { + this.resourceURL = resourceURL; + } + + /** + * Set pattern for locating "packager.xml" files. + */ + public void setPackagerPattern(String pattern) { + ArrayList list = new ArrayList(); + list.add(pattern); + setArtifactPatterns(list); + } + + /** + * Set whether to preserve build directories. Default is false. + */ + public void setPreserveBuildDirectories(boolean preserve) { + this.preserve = preserve; + } + + /** + * Set whether to run ant with the -verbose flag. Default is false. + */ + public void setVerbose(boolean verbose) { + this.verbose = verbose; + } + + /** + * Set whether to run ant with the -quiet flag. Default is false. + */ + public void setQuiet(boolean quiet) { + this.quiet = quiet; + } + + /** + * Set whether to validate downloaded packager.xml files. Default is true. + */ + public void setValidate(boolean validate) { + this.validate = validate; + } + + public void setAllownomd(boolean b) { + Message.error("allownomd not supported by resolver " + this); + } + public void setDescriptor(String rule) { + if (DESCRIPTOR_OPTIONAL.equals(rule)) { + Message.error("descriptor=\"" + DESCRIPTOR_OPTIONAL + + "\" not supported by resolver " + this); + return; + } + super.setDescriptor(rule); + } + + // @Override + public void validate() { + super.validate(); + if (this.buildRoot == null) { + throw new IllegalStateException("no buildRoot specified"); + } + if (getArtifactPatterns().size() == 0) { + throw new IllegalStateException("no packager pattern specified"); + } + } + + // @Override + protected synchronized ResolvedResource findArtifactRef(Artifact artifact, Date date) { + + // For our special packager.xml file, defer to superclass + if (PACKAGER_ARTIFACT_NAME.equals(artifact.getName()) + && PACKAGER_ARTIFACT_TYPE.equals(artifact.getType()) + && PACKAGER_ARTIFACT_EXT.equals(artifact.getExt())) { + return super.findArtifactRef(artifact, date); + } + + // Check the cache + ModuleRevisionId mr = artifact.getModuleRevisionId(); + PackagerCacheEntry entry = (PackagerCacheEntry) packagerCache.get(mr); + + // Ignore invalid entries + if (entry != null && !entry.isBuilt()) { + packagerCache.remove(mr); + entry.cleanup(); + entry = null; + } + + // Build the artifacts (if not done already) + if (entry == null) { + ResolvedResource packager = findArtifactRef(new DefaultArtifact(mr, null, + PACKAGER_ARTIFACT_NAME, PACKAGER_ARTIFACT_TYPE, PACKAGER_ARTIFACT_EXT), date); + if (packager == null) { + return null; + } + entry = new PackagerCacheEntry(mr, this.buildRoot, this.resourceCache, + this.resourceURL, this.validate, this.preserve, this.verbose, this.quiet); + try { + entry.build(packager.getResource().openStream()); + } catch (IOException e) { + throw new RuntimeException("can't build artifact " + artifact, e); + } + packagerCache.put(mr, entry); + } + + // Return reference to desired artifact + return entry.getBuiltArtifact(artifact); + } + + public String getTypeName() { + return "packager"; + } + + public static boolean deleteRecursive(File file) { + if (!file.exists()) { + return true; + } + if (file.isDirectory()) { + File[] files = file.listFiles(); + for (int i = 0; i < files.length; i++) { + if (!deleteRecursive(files[i])) { + return false; + } + } + } + return file.delete(); + } +} + Property changes on: src/java/org/apache/ivy/plugins/resolver/packager/PackagerResolver.java ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/ivy/plugins/resolver/packager/packager.xsl =================================================================== --- src/java/org/apache/ivy/plugins/resolver/packager/packager.xsl (revision 0) +++ src/java/org/apache/ivy/plugins/resolver/packager/packager.xsl (revision 0) @@ -0,0 +1,485 @@ + + + + + + + + + + + + + + + GENERATED FILE - DO NOT EDIT + Generated by $Id$ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ${ivy.packager.resourceCache} + + + using resource cache: ${ivy.packager.resourceCache} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + archive + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + gzip + + + bzip2 + + + + + + + + + + + + + + + + + + + + + + + jar + war + zip + tar + tar.gz + tar.gz + tar.bz2 + + + + + + + + + + + + + + + + + + + + + + + + + + + + ignoring unexpected XML node <> + + + + Property changes on: src/java/org/apache/ivy/plugins/resolver/packager/packager.xsl ___________________________________________________________________ Name: svn:mime-type + text/xml Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/ivy/plugins/resolver/packager/PackagerCacheEntry.java =================================================================== --- src/java/org/apache/ivy/plugins/resolver/packager/PackagerCacheEntry.java (revision 0) +++ src/java/org/apache/ivy/plugins/resolver/packager/PackagerCacheEntry.java (revision 0) @@ -0,0 +1,212 @@ +/* + * 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.ivy.plugins.resolver.packager; + +import java.io.BufferedOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.util.ArrayList; + +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.resolver.util.ResolvedResource; + +/** + * 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 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 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.verbose = verbose; + this.quiet = quiet; + } + // CheckStyle:ParameterNumber ON + + /** + * Attempt to build this entry. + * + * @param packagerXML packager XML input stream + * @throws IllegalStateException if this entry has already been built + */ + public synchronized void build(InputStream packagerXML) 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 + 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"); + + // Create new process argument list + ArrayList paramList = new ArrayList(); + paramList.add("ant"); + if (this.verbose) { + paramList.add("-verbose"); + } + if (this.quiet) { + paramList.add("-quiet"); + } + paramList.add("-Divy.packager.organisation=" + this.mr.getModuleId().getOrganisation()); + paramList.add("-Divy.packager.module=" + this.mr.getModuleId().getName()); + paramList.add("-Divy.packager.revision=" + this.mr.getRevision()); + paramList.add("-Divy.packager.branch=" + this.mr.getBranch()); + if (this.resourceCache != null) { + paramList.add("-Divy.packager.resourceCache=" + this.resourceCache.getCanonicalPath()); + } + if (this.resourceURL != null) { + paramList.add("-Divy.packager.resourceURL=" + getResourceURL()); + } + if (this.validate) { + paramList.add("-Divy.packager.validate=true"); + } + String[] params = (String[]) paramList.toArray(new String[paramList.size()]); + + // Run ant + SubProcess proc = new SubProcess(params, null, this.dir); + int result; + try { + result = proc.run(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + if (result != 0) { + throw new IOException("build in directory `" + this.dir + "' failed"); + } + this.built = true; + } + + /** + * Has this entry been successfully built? + */ + public synchronized boolean isBuilt() { + return this.built; + } + + /** + * Get a built artifact. + * + * @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 PackagerResolver.deleteRecursive(this.dir); + } + + protected void saveFile(String name, InputStream input) throws IOException { + OutputStream out = new BufferedOutputStream( + new FileOutputStream(new File(this.dir, name))); + SubProcess.relayStream(input, out); + input.close(); + out.close(); + } + + 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(this.resourceURL, this.mr.getOrganisation(), + this.mr.getName(), this.mr.getRevision(), null, null, null, null, + this.mr.getAttributes()); + 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()); + } +} + Property changes on: src/java/org/apache/ivy/plugins/resolver/packager/PackagerCacheEntry.java ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/ivy/plugins/resolver/packager/packager-1.0.xsd =================================================================== --- src/java/org/apache/ivy/plugins/resolver/packager/packager-1.0.xsd (revision 0) +++ src/java/org/apache/ivy/plugins/resolver/packager/packager-1.0.xsd (revision 0) @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property changes on: src/java/org/apache/ivy/plugins/resolver/packager/packager-1.0.xsd ___________________________________________________________________ Name: svn:mime-type + text/xml Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/ivy/plugins/resolver/packager/BuiltFileResource.java =================================================================== --- src/java/org/apache/ivy/plugins/resolver/packager/BuiltFileResource.java (revision 0) +++ src/java/org/apache/ivy/plugins/resolver/packager/BuiltFileResource.java (revision 0) @@ -0,0 +1,85 @@ +/* + * 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.ivy.plugins.resolver.packager; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.ivy.core.IvyPatternHelper; +import org.apache.ivy.core.module.descriptor.Artifact; +import org.apache.ivy.plugins.repository.Resource; + +/** + * Represents an artifact built by a {@link PackagerResolver}. + */ +public class BuiltFileResource implements Resource { + + /** + * Where the build file should put built artifacts (relative + * to the build directory). Value is: {@value} + */ + public static final String BUILT_ARTIFACT_PATTERN = "artifacts/[type]s/[artifact].[ext]"; + + private final File file; + + public BuiltFileResource(File file) { + this.file = file; + } + + public BuiltFileResource(File dir, Artifact artifact) { + this(new File(dir, IvyPatternHelper.substitute(BUILT_ARTIFACT_PATTERN, artifact))); + } + + public String getName() { + return file.toURI().toString(); + } + + public Resource clone(String name) { + return new BuiltFileResource(new File(name)); + } + + public long getLastModified() { + return file.lastModified(); + } + + public long getContentLength() { + return file.length(); + } + + public boolean exists() { + return file.exists(); + } + + public String toString() { + return getName(); + } + + public File getFile() { + return file; + } + + public boolean isLocal() { + return false; + } + + public InputStream openStream() throws IOException { + return new FileInputStream(file); + } +} Property changes on: src/java/org/apache/ivy/plugins/resolver/packager/BuiltFileResource.java ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/ivy/plugins/resolver/packager/SubProcess.java =================================================================== --- src/java/org/apache/ivy/plugins/resolver/packager/SubProcess.java (revision 0) +++ src/java/org/apache/ivy/plugins/resolver/packager/SubProcess.java (revision 0) @@ -0,0 +1,106 @@ +/* + * 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.ivy.plugins.resolver.packager; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; + +/** + * Simple utility class for executing subprocesses. Handles I/O streams + * by closing standard input and relaying standard output and error. + */ +public class SubProcess { + + private static final int BUFSIZE = 1024; + + private final String[] cmd; + private final String[] env; + private final File dir; + + /** + * Constructor. + * + * @param cmd command parameters + * @param env command environment + * @param dir command working directory + * @see Runtime.exec(String[], String[], File) + */ + public SubProcess(String[] cmd, String[] env, File dir) { + this.cmd = cmd; + this.env = env; + this.dir = dir; + } + + /** + * Execute the process and wait for it to complete. + * + * @return exit value from process + */ + public int run() throws IOException, InterruptedException { + Process proc = Runtime.getRuntime().exec(this.cmd, this.env, this.dir); + proc.getOutputStream().close(); + Thread relay1 = startRelay(proc.getInputStream(), System.out); + Thread relay2 = startRelay(proc.getErrorStream(), System.err); + int result; + relay1.join(); + relay2.join(); + return proc.waitFor(); + } + + /** + * Create and start a separate thread that copies input to output and closes + * the input when done. + * + * @param in input stream to read from + * @param out output stream to copy to + * @return thread doing the work + */ + public static Thread startRelay(final InputStream in, final OutputStream out) { + Thread thread = new Thread() { + public void run() { + try { + relayStream(in, out); + in.close(); + } catch (IOException e) { + return; + } + } + }; + thread.setDaemon(true); + thread.start(); + return thread; + } + + /** + * Copy from input to output. Does not close either stream when finished. + * + * @param in input stream to read from + * @param out output stream to copy to + */ + public static void relayStream(InputStream in, OutputStream out) throws IOException { + byte[] buf = new byte[BUFSIZE]; + int r; + while ((r = in.read(buf)) != -1) { + out.write(buf, 0, r); + } + out.flush(); + } +} + Property changes on: src/java/org/apache/ivy/plugins/resolver/packager/SubProcess.java ___________________________________________________________________ Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/ivy/plugins/resolver/packager/build.xml =================================================================== --- src/java/org/apache/ivy/plugins/resolver/packager/build.xml (revision 0) +++ src/java/org/apache/ivy/plugins/resolver/packager/build.xml (revision 0) @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Property changes on: src/java/org/apache/ivy/plugins/resolver/packager/build.xml ___________________________________________________________________ Name: svn:mime-type + text/xml Name: svn:keywords + Id Name: svn:eol-style + native Index: src/java/org/apache/ivy/core/settings/typedef.properties =================================================================== --- src/java/org/apache/ivy/core/settings/typedef.properties (revision 665706) +++ src/java/org/apache/ivy/core/settings/typedef.properties (working copy) @@ -27,6 +27,7 @@ vsftp = org.apache.ivy.plugins.resolver.VsftpResolver vfs = org.apache.ivy.plugins.resolver.VfsResolver cache = org.apache.ivy.plugins.resolver.CacheResolver +packager = org.apache.ivy.plugins.resolver.packager.PackagerResolver latest-revision = org.apache.ivy.plugins.latest.LatestRevisionStrategy latest-lexico = org.apache.ivy.plugins.latest.LatestLexicographicStrategy Index: src/example/packager-resolver/ivysettings.xml =================================================================== --- src/example/packager-resolver/ivysettings.xml (revision 0) +++ src/example/packager-resolver/ivysettings.xml (revision 0) @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + Property changes on: src/example/packager-resolver/ivysettings.xml ___________________________________________________________________ Name: svn:mime-type + text/xml Name: svn:keywords + Id Name: svn:eol-style + native Index: doc/configuration/resolvers.html =================================================================== --- doc/configuration/resolvers.html (revision 665706) +++ doc/configuration/resolvers.html (working copy) @@ -63,6 +63,7 @@ IvyRepStandardFinds ivy files on ivyrep and artifacts on ibiblio. IBiblioStandardFinds artifacts on ibiblio. +PackagerStandardFinds ivy files and packaging instructions via URLs, then creates artifacts by following the instructions. FileSystemStandardThis very performant resolver finds ivy files and artifacts in your file system. UrlStandardFinds ivy files and artifacts in any repository accessible with urls. VfsStandardFinds ivy files and artifacts in any repository accessible with apache commons vfs. Index: doc/toc.json =================================================================== --- doc/toc.json (revision 665706) +++ doc/toc.json (working copy) @@ -295,6 +295,13 @@ ] }, { + "id":"resolver/packager", + "title":"Packager resolver", + "children": [ + + ] + }, + { "id":"resolver/filesystem", "title":"File System resolver", "children": [ Index: doc/resolver/packager.html =================================================================== --- doc/resolver/packager.html (revision 0) +++ doc/resolver/packager.html (revision 0) @@ -0,0 +1,396 @@ + + + + + + + + + + + + + Property changes on: doc/resolver/packager.html ___________________________________________________________________ Name: svn:mime-type + text/html Name: svn:keywords + Id Name: svn:eol-style + native