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 @@
| IvyRep | Standard | Finds ivy files on ivyrep and artifacts on ibiblio. |
| IBiblio | Standard | Finds artifacts on ibiblio. |
+| Packager | Standard | Finds ivy files and packaging instructions via URLs, then creates artifacts by following the instructions. |
| FileSystem | Standard | This very performant resolver finds ivy files and artifacts in your file system. |
| Url | Standard | Finds ivy files and artifacts in any repository accessible with urls. |
| Vfs | Standard | Finds 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