You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ace.apache.org by br...@apache.org on 2013/06/24 17:49:57 UTC
svn commit: r1496102 - in /ace/sandbox/bramk/org.apache.ace.cli:
src/org/apache/ace/cli/deployment/ test/org/apache/ace/cli/deployment/
Author: bramk
Date: Mon Jun 24 15:49:56 2013
New Revision: 1496102
URL: http://svn.apache.org/r1496102
Log:
[sandbox] Added custom repo to work around IO issues
Added:
ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/CustomLocalIndexRepo.java
Modified:
ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/ContinuousDeployer.java
ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/DeployerUtil.java
ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/ContinuousDeployerTest.java
Modified: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/ContinuousDeployer.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/ContinuousDeployer.java?rev=1496102&r1=1496101&r2=1496102&view=diff
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/ContinuousDeployer.java (original)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/ContinuousDeployer.java Mon Jun 24 15:49:56 2013
@@ -9,6 +9,7 @@ import static org.apache.ace.cli.deploym
import static org.apache.ace.cli.deployment.DeployerUtil.getString;
import static org.apache.ace.cli.deployment.DeployerUtil.getVersion;
import static org.apache.ace.cli.deployment.DeployerUtil.isSameBaseVersion;
+import static org.apache.ace.cli.deployment.DeployerUtil.isSnapshotVersion;
import static org.apache.ace.cli.deployment.DeployerUtil.jarsDiffer;
import java.io.File;
@@ -35,7 +36,7 @@ public class ContinuousDeployer {
}
/**
- * Deploys all resources from the development respsitory into the deployment repository.
+ * Deploys all resources from the development repository into the deployment repository.
*
* @return
* @throws Exception
@@ -43,7 +44,6 @@ public class ContinuousDeployer {
public List<Resource> deployResources() throws Exception {
List<Resource> resources = findResources(m_developmentRepo, "*", "*");
for (Resource resource : resources) {
- System.out.println("Deploying resource: " + getString(resource));
deployResource(resource);
}
return resources;
@@ -61,11 +61,9 @@ public class ContinuousDeployer {
List<Resource> releaseResources = findResources(m_releaseRepo, getIdentity(resource), getVersion(resource).toString());
boolean isReleased = releaseResources.size() > 0;
if (isReleased) {
- System.out.println("Deploying release: " + getString(resource));
deployReleasedResource(resource);
}
else {
- System.out.println("Deploying snapshot: " + getString(resource));
deploySnapshotResource(resource);
}
}
@@ -144,7 +142,9 @@ public class ContinuousDeployer {
List<Resource> resources = findResources(m_deploymentRepo, getIdentity(resource));
Resource matchedResource = null;
for (Resource candidateResource : resources) {
- if (isSameBaseVersion(getVersion(candidateResource), base)
+ Version candidateVersion = getVersion(candidateResource);
+
+ if (isSnapshotVersion(candidateVersion) && isSameBaseVersion(getVersion(candidateResource), base)
&& (matchedResource == null || getVersion(matchedResource).compareTo(getVersion(candidateResource)) < 0)) {
matchedResource = candidateResource;
}
Modified: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/DeployerUtil.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/DeployerUtil.java?rev=1496102&r1=1496101&r2=1496102&view=diff
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/DeployerUtil.java (original)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/DeployerUtil.java Mon Jun 24 15:49:56 2013
@@ -287,6 +287,14 @@ public final class DeployerUtil {
return left.getMajor() == right.getMajor() && left.getMinor() == right.getMinor() && left.getMicro() == right.getMicro();
}
+ public static boolean isSnapshotVersion(Version version) {
+ if (version.getQualifier() == null || version.getQualifier().equals("")) {
+ return false;
+ }
+ Matcher qualifierMatcher = QUALIFIER_PATTERN.matcher(version.getQualifier());
+ return qualifierMatcher.matches();
+ }
+
private static Map<String, Object> getNamespaceAttributes(Resource resource, String namespace) {
List<Capability> caps = resource.getCapabilities(namespace);
if (caps.isEmpty())
Modified: ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/ContinuousDeployerTest.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/ContinuousDeployerTest.java?rev=1496102&r1=1496101&r2=1496102&view=diff
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/ContinuousDeployerTest.java (original)
+++ ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/ContinuousDeployerTest.java Mon Jun 24 15:49:56 2013
@@ -10,8 +10,6 @@ import java.io.PipedInputStream;
import java.io.PipedOutputStream;
import java.util.HashMap;
import java.util.Map;
-import java.util.Map.Entry;
-import java.util.jar.JarFile;
import junit.framework.TestCase;
@@ -20,14 +18,13 @@ import org.osgi.framework.Constants;
import aQute.bnd.deployer.repository.LocalIndexedRepo;
import aQute.bnd.osgi.Builder;
import aQute.bnd.osgi.Jar;
-import aQute.bnd.service.Strategy;
public class ContinuousDeployerTest extends TestCase {
File m_workDir;
- LocalIndexedRepo m_developmentRepo;
- LocalIndexedRepo m_releaseRepo;
- LocalIndexedRepo m_deploymentRepo;
+ CustomLocalIndexRepo m_developmentRepo;
+ CustomLocalIndexRepo m_releaseRepo;
+ CustomLocalIndexRepo m_deploymentRepo;
ContinuousDeployer m_deployer;
public void setUp() throws Exception {
@@ -57,8 +54,7 @@ public class ContinuousDeployerTest exte
public void testInitialSnapshotDeployment() throws Exception {
// an initial unreleased bundle from development
- deployBundle(m_developmentRepo, createBundle("foo.bar", "1.0.0"));
- Thread.sleep(100);
+ deployBundle(m_developmentRepo, createBundle("foo.bar", "1.0.0", Constants.BUNDLE_COPYRIGHT, "Bundle 0"));
// should have receive the correct snapshot version
m_deployer.deployResources();
@@ -69,41 +65,63 @@ public class ContinuousDeployerTest exte
assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "0.0.0.CDS000").size());
// re-deploy of changed bundle should increment snapshot
+ deployBundle(m_developmentRepo, createBundle("foo.bar", "1.0.0", Constants.BUNDLE_COPYRIGHT, "Bundle 1"));
+ m_deployer.deployResources();
+ assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "0.0.0.CDS001").size());
+ }
- // FIXME bug start
-
- // create a new bundle and list manifest
- File update = createBundle("foo.bar", "1.0.0", Constants.BUNDLE_COPYRIGHT, "Bundle 1", "bla", "bla");
- listManifest(update);
-
- // deploy, retrieve and list manifest
- deployBundle(m_developmentRepo, update);
- File check = m_developmentRepo.get("foo.bar", "1.0.0", Strategy.EXACT, null);
- listManifest(check);
+// FIXME fails
+//
+// public void testSnapshotTakesCorrectBaseVersion() throws Exception {
+//
+// // an initial unreleased bundle from development
+// deployBundle(m_developmentRepo, createBundle("foo.bar", "1.0.0", Constants.BUNDLE_COPYRIGHT, "Bundle 1.0"));
+// deployBundle(m_developmentRepo, createBundle("foo.bar", "2.0.0", Constants.BUNDLE_COPYRIGHT, "Bundle 2.0"));
+// copyResources(m_developmentRepo, m_releaseRepo, "foo.bar");
+// m_deployer.deployResources();
+//
+// deployBundle(m_developmentRepo, createBundle("foo.bar", "1.0.1", Constants.BUNDLE_COPYRIGHT, "Bundle 1.0.1"));
+// m_deployer.deployResources();
+//
+// // should have receive the correct snapshot version
+// assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "1.0.0.CDS000").size());
+//
+// deployBundle(m_developmentRepo, createBundle("foo.bar", "2.1.0", Constants.BUNDLE_COPYRIGHT, "Bundle 2.1.0"));
+// m_deployer.deployResources();
+//
+// // should have receive the correct snapshot version
+// assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "2.0.0.CDS000").size());
+// }
- // Why do these manifest differ??? Unless in debug... there is a race condition in the BND IO?
+ public void testInitialSnapshotThenReleaseDeployment() throws Exception {
- // FIXME bug end
+ // an initial unreleased bundle from development
+ deployBundle(m_developmentRepo, createBundle("foo.bar", "1.0.0", Constants.BUNDLE_NAME, "Snapshot bundle"));
+ // should have receive the correct snapshot version
m_deployer.deployResources();
+ assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "0.0.0.CDS000").size());
- // assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "0.0.0.CDS000").size());
- assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "0.0.0.CDS001").size());
+ // release of changed bundle
+ deployBundle(m_developmentRepo, createBundle("foo.bar", "1.0.0", Constants.BUNDLE_NAME, "Release 1"));
+ copyResources(m_developmentRepo, m_releaseRepo, "foo.bar", "1.0.0");
+ m_deployer.deployResources();
+ assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "1.0.0").size());
}
- private LocalIndexedRepo createRepo(File root, String name) throws Exception {
+ private CustomLocalIndexRepo createRepo(File root, String name) throws Exception {
if (!(root.exists() || root.mkdir()) || !root.isDirectory())
throw new Exception("Can not access root: " + root.getAbsolutePath());
Map<String, String> props = new HashMap<String, String>();
props.put(LocalIndexedRepo.PROP_LOCAL_DIR, root.getAbsolutePath());
props.put(LocalIndexedRepo.PROP_PRETTY, "true");
props.put(LocalIndexedRepo.PROP_OVERWRITE, "true");
- LocalIndexedRepo repo = new LocalIndexedRepo();
+ CustomLocalIndexRepo repo = new CustomLocalIndexRepo();
repo.setProperties(props);
return repo;
}
- private void deployBundle(LocalIndexedRepo repo, InputStream stream) throws Exception {
+ private void deployBundle(CustomLocalIndexRepo repo, InputStream stream) throws Exception {
try {
repo.put(stream, null);
stream.close();
@@ -113,22 +131,22 @@ public class ContinuousDeployerTest exte
}
}
- private void deployBundle(LocalIndexedRepo repo, File file) throws Exception {
+ private void deployBundle(CustomLocalIndexRepo repo, File file) throws Exception {
deployBundle(repo, new FileInputStream(file));
}
- private void listManifest(File file) throws Exception {
- JarFile j = new JarFile(file);
- System.out.println("--------------------------");
- System.out.println("Manifest for " + file.getAbsolutePath());
- System.out.println("--------------------------");
- for (Entry<Object, Object> entry : j.getManifest().getMainAttributes().entrySet()) {
- System.out.println(" " + entry.getKey() + ": " + entry.getValue());
- }
- j.close();
- System.out.println("--------------------------");
-
- }
+ // private void listManifest(File file) throws Exception {
+ // JarFile j = new JarFile(file);
+ // System.out.println("--------------------------");
+ // System.out.println("Manifest for " + file.getAbsolutePath());
+ // System.out.println("--------------------------");
+ // for (Entry<Object, Object> entry : j.getManifest().getMainAttributes().entrySet()) {
+ // System.out.println(" " + entry.getKey() + ": " + entry.getValue());
+ // }
+ // j.close();
+ // System.out.println("--------------------------");
+ //
+ // }
private InputStream generateBundle(final String bsn, final String version, final String... headers) throws Exception {
final PipedInputStream in = new PipedInputStream();
Added: ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/CustomLocalIndexRepo.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/CustomLocalIndexRepo.java?rev=1496102&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/CustomLocalIndexRepo.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/CustomLocalIndexRepo.java Mon Jun 24 15:49:56 2013
@@ -0,0 +1,435 @@
+package org.apache.ace.cli.deployment;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URI;
+import java.security.DigestInputStream;
+import java.security.MessageDigest;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.Coordinator;
+import org.osgi.service.coordinator.Participant;
+import org.osgi.service.log.LogService;
+
+import aQute.bnd.deployer.repository.FixedIndexedRepo;
+import aQute.bnd.deployer.repository.api.IRepositoryContentProvider;
+import aQute.bnd.filerepo.FileRepo;
+import aQute.bnd.osgi.Jar;
+import aQute.bnd.osgi.Verifier;
+import aQute.bnd.service.Refreshable;
+import aQute.bnd.service.RepositoryListenerPlugin;
+import aQute.bnd.version.Version;
+import aQute.bnd.version.VersionRange;
+import aQute.lib.io.IO;
+
+/**
+ * Copy from bnd LocalIndexedRepo to work around some IO issues. Also note that it does not keep qualifier versions. A
+ * version 1.0.0.X will overwrite version 1.0.0 :(
+ *
+ */
+public class CustomLocalIndexRepo extends FixedIndexedRepo implements Refreshable, Participant {
+
+ private static final String CACHE_PATH = ".cache";
+ public static final String PROP_LOCAL_DIR = "local";
+ public static final String PROP_READONLY = "readonly";
+ public static final String PROP_PRETTY = "pretty";
+ public static final String PROP_OVERWRITE = "overwrite";
+
+ private static final VersionRange RANGE_ANY = new VersionRange(Version.LOWEST.toString());
+
+ private FileRepo storageRepo;
+ private boolean readOnly;
+ private boolean pretty = false;
+ private boolean overwrite = true;
+ private File storageDir;
+
+ // @GuardedBy("newFilesInCoordination")
+ private final List<URI> newFilesInCoordination = new LinkedList<URI>();
+
+ @Override
+ public synchronized void setProperties(Map<String, String> map) {
+ super.setProperties(map);
+
+ // Load essential properties
+ String localDirPath = map.get(PROP_LOCAL_DIR);
+ if (localDirPath == null)
+ throw new IllegalArgumentException(String.format("Attribute '%s' must be set on %s plugin.",
+ PROP_LOCAL_DIR, getClass().getName()));
+
+ storageDir = new File(localDirPath);
+ if (storageDir.exists() && !storageDir.isDirectory())
+ throw new IllegalArgumentException(String.format("Local path '%s' exists and is not a directory.",
+ localDirPath));
+
+ readOnly = Boolean.parseBoolean(map.get(PROP_READONLY));
+ pretty = Boolean.parseBoolean(map.get(PROP_PRETTY));
+ overwrite = map.get(PROP_OVERWRITE) == null ? true : Boolean.parseBoolean(map.get(PROP_OVERWRITE));
+
+ // Configure the storage repository
+ storageRepo = new FileRepo(storageDir);
+
+ // Set the local index and cache directory locations
+ cacheDir = new File(storageDir, CACHE_PATH);
+ if (cacheDir.exists() && !cacheDir.isDirectory())
+ throw new IllegalArgumentException(String.format(
+ "Cannot create repository cache: '%s' already exists but is not directory.",
+ cacheDir.getAbsolutePath()));
+ }
+
+ @Override
+ protected synchronized List<URI> loadIndexes() throws Exception {
+ Collection<URI> remotes = super.loadIndexes();
+ List<URI> indexes = new ArrayList<URI>(remotes.size() + generatingProviders.size());
+
+ for (IRepositoryContentProvider contentProvider : generatingProviders) {
+ File indexFile = getIndexFile(contentProvider);
+ try {
+ if (indexFile.exists()) {
+ indexes.add(indexFile.toURI());
+ }
+ else {
+ if (contentProvider.supportsGeneration()) {
+ generateIndex(indexFile, contentProvider);
+ indexes.add(indexFile.toURI());
+ }
+ }
+ }
+ catch (Exception e) {
+ logService.log(LogService.LOG_ERROR, String.format(
+ "Unable to load/generate index file '%s' for repository type %s", indexFile,
+ contentProvider.getName()), e);
+ }
+ }
+
+ indexes.addAll(remotes);
+ return indexes;
+ }
+
+ private File getIndexFile(IRepositoryContentProvider contentProvider) {
+ String indexFileName = contentProvider.getDefaultIndexName(pretty);
+ File indexFile = new File(storageDir, indexFileName);
+ return indexFile;
+ }
+
+ private synchronized void regenerateAllIndexes() {
+ for (IRepositoryContentProvider provider : generatingProviders) {
+ if (!provider.supportsGeneration()) {
+ logService.log(LogService.LOG_WARNING,
+ String.format("Repository type '%s' does not support index generation.", provider.getName()));
+ continue;
+ }
+ File indexFile = getIndexFile(provider);
+ try {
+ generateIndex(indexFile, provider);
+ }
+ catch (Exception e) {
+ logService.log(LogService.LOG_ERROR, String.format(
+ "Unable to regenerate index file '%s' for repository type %s", indexFile, provider.getName()),
+ e);
+ }
+ }
+ }
+
+ private synchronized void generateIndex(File indexFile, IRepositoryContentProvider provider) throws Exception {
+ if (indexFile.exists() && !indexFile.isFile())
+ throw new IllegalArgumentException(String.format(
+ "Cannot create file: '%s' already exists but is not a plain file.", indexFile.getAbsoluteFile()));
+
+ Set<File> allFiles = new HashSet<File>();
+ gatherFiles(allFiles);
+
+ FileOutputStream out = null;
+ try {
+ if (!storageDir.exists() && !storageDir.mkdirs()) {
+ throw new IOException("Could not create directory " + storageDir);
+ }
+ out = new FileOutputStream(indexFile);
+
+ URI rootUri = storageDir.getCanonicalFile().toURI();
+ provider.generateIndex(allFiles, out, this.getName(), rootUri, pretty, registry, logService);
+ }
+ finally {
+ IO.close(out);
+ }
+ }
+
+ private void gatherFiles(Set<File> allFiles) throws Exception {
+ if (!storageDir.isDirectory())
+ return;
+
+ List<String> bsns = storageRepo.list(null);
+ if (bsns != null)
+ for (String bsn : bsns) {
+ File[] files = storageRepo.get(bsn, RANGE_ANY);
+ if (files != null)
+ for (File file : files) {
+ allFiles.add(file.getCanonicalFile());
+ }
+ }
+ }
+
+ @Override
+ public boolean canWrite() {
+ return !readOnly;
+ }
+
+ private synchronized void finishPut() throws Exception {
+ reset();
+ regenerateAllIndexes();
+
+ List<URI> clone = new ArrayList<URI>(newFilesInCoordination);
+ synchronized (newFilesInCoordination) {
+ newFilesInCoordination.clear();
+ }
+ for (URI entry : clone) {
+ File file = new File(entry);
+ fireBundleAdded(file);
+ }
+ }
+
+ public synchronized void ended(Coordination coordination) throws Exception {
+ finishPut();
+ }
+
+ public void failed(Coordination coordination) throws Exception {
+ ArrayList<URI> clone;
+ synchronized (newFilesInCoordination) {
+ clone = new ArrayList<URI>(newFilesInCoordination);
+ newFilesInCoordination.clear();
+ }
+ for (URI entry : clone) {
+ try {
+ new File(entry).delete();
+ }
+ catch (Exception e) {
+ reporter.warning("Failed to remove repository entry %s on coordination rollback: %s", entry, e);
+ }
+ }
+ }
+
+ protected File putArtifact(File tmpFile) throws Exception {
+ assert (tmpFile != null);
+ assert (tmpFile.isFile());
+
+ init();
+
+ Jar jar = new Jar(tmpFile);
+ try {
+ String bsn = jar.getBsn();
+ if (bsn == null || !Verifier.isBsn(bsn))
+ throw new IllegalArgumentException("Jar does not have a Bundle-SymbolicName manifest header");
+
+ File dir = new File(storageDir, bsn);
+ if (dir.exists() && !dir.isDirectory())
+ throw new IllegalArgumentException("Path already exists but is not a directory: "
+ + dir.getAbsolutePath());
+ if (!dir.exists() && !dir.mkdirs()) {
+ throw new IOException("Could not create directory " + dir);
+ }
+
+ String versionString = jar.getVersion();
+ if (versionString == null)
+ versionString = "0";
+ else if (!Verifier.isVersion(versionString))
+ throw new IllegalArgumentException("Invalid version " + versionString + " in file " + tmpFile);
+
+ Version version = Version.parseVersion(versionString);
+ String fName = bsn + "-" + version.getWithoutQualifier() + ".jar";
+ File file = new File(dir, fName);
+
+ // check overwrite policy
+ if (!overwrite && file.exists())
+ return null;
+
+ // An open jar on file will fail rename on windows
+ jar.close();
+
+ // listManifest(tmpFile);
+ // IO.rename(tmpFile, file);
+ IO.copy(tmpFile, file);
+ Thread.sleep(1000);
+ // IO.copy(tmpFile, file);
+ // listManifest(file);
+
+ synchronized (newFilesInCoordination) {
+ newFilesInCoordination.add(file.toURI());
+ }
+
+ Coordinator coordinator = (registry != null) ? registry.getPlugin(Coordinator.class) : null;
+ if (!(coordinator != null && coordinator.addParticipant(this))) {
+ finishPut();
+ }
+ return file;
+ }
+ finally {
+ jar.close();
+ }
+ }
+
+ // public static final long ONE_KB = 1024;
+ // public static final long ONE_MB = ONE_KB * ONE_KB;
+ // private static final long FILE_COPY_BUFFER_SIZE = ONE_MB * 30;
+ //
+ // private void copyFile(final File srcFile, final File destFile) throws IOException {
+ //
+ // FileInputStream fis = null;
+ // FileOutputStream fos = null;
+ // FileChannel input = null;
+ // FileChannel output = null;
+ // try {
+ // fis = new FileInputStream(srcFile);
+ // fos = new FileOutputStream(destFile);
+ // input = fis.getChannel();
+ // output = fos.getChannel();
+ // final long size = input.size(); // TODO See IO-386
+ // long pos = 0;
+ // long count = 0;
+ // while (pos < size) {
+ // final long remain = size - pos;
+ // count = remain > FILE_COPY_BUFFER_SIZE ? FILE_COPY_BUFFER_SIZE : remain;
+ // final long bytesCopied = output.transferFrom(input, pos, count);
+ // if (bytesCopied == 0) { // IO-385 - can happen if file is truncated after caching the size
+ // break; // ensure we don't loop forever
+ // }
+ // pos += bytesCopied;
+ // }
+ // } finally {
+ // output.close();
+ // fos.close();
+ // input.close();
+ // fis.close();
+ // }
+ //
+ // final long srcLen = srcFile.length(); // TODO See IO-386
+ // final long dstLen = destFile.length(); // TODO See IO-386
+ // if (srcLen != dstLen) {
+ // throw new IOException("Failed to copy full contents from '" +
+ // srcFile + "' to '" + destFile + "' Expected length: " + srcLen +" Actual: " + dstLen);
+ // }
+ // }
+ //
+ // private void listManifest(File file) throws Exception {
+ // JarFile j = new JarFile(file);
+ // System.out.println("--------------------------");
+ // System.out.println("Manifest for " + file.getAbsolutePath());
+ // System.out.println("--------------------------");
+ // for (Entry<Object, Object> entry : j.getManifest().getMainAttributes().entrySet()) {
+ // System.out.println(" " + entry.getKey() + ": " + entry.getValue());
+ // }
+ // j.close();
+ // System.out.println("--------------------------");
+ //
+ // }
+
+ /* NOTE: this is a straight copy of FileRepo.put */
+ @Override
+ public synchronized PutResult put(InputStream stream, PutOptions options) throws Exception {
+ /* determine if the put is allowed */
+ if (readOnly) {
+ throw new IOException("Repository is read-only");
+ }
+
+ if (options == null)
+ options = DEFAULTOPTIONS;
+
+ /* both parameters are required */
+ if (stream == null)
+ throw new IllegalArgumentException("No stream and/or options specified");
+
+ /* the root directory of the repository has to be a directory */
+ if (!storageDir.isDirectory()) {
+ throw new IOException("Repository directory " + storageDir + " is not a directory");
+ }
+
+ /*
+ * setup a new stream that encapsulates the stream and calculates (when needed) the digest
+ */
+ DigestInputStream dis = new DigestInputStream(stream, MessageDigest.getInstance("SHA-1"));
+
+ File tmpFile = null;
+ try {
+ /*
+ * copy the artifact from the (new/digest) stream into a temporary file in the root directory of the
+ * repository
+ */
+ tmpFile = IO.createTempFile(storageDir, "put", ".bnd");
+ IO.copy(dis, tmpFile);
+
+ /* beforeGet the digest if available */
+ byte[] disDigest = dis.getMessageDigest().digest();
+
+ if (options.digest != null && !Arrays.equals(options.digest, disDigest))
+ throw new IOException("Retrieved artifact digest doesn't match specified digest");
+
+ /* put the artifact into the repository (from the temporary file) */
+ File file = putArtifact(tmpFile);
+
+ PutResult result = new PutResult();
+ if (file != null) {
+ result.digest = disDigest;
+ result.artifact = file.toURI();
+ }
+
+ return result;
+ }
+ finally {
+ if (tmpFile != null && tmpFile.exists()) {
+ IO.delete(tmpFile);
+ }
+ }
+ }
+
+ public boolean refresh() {
+ reset();
+ return true;
+ }
+
+ public synchronized File getRoot() {
+ return storageDir;
+ }
+
+ protected void fireBundleAdded(File file) {
+ if (registry == null)
+ return;
+ List<RepositoryListenerPlugin> listeners = registry.getPlugins(RepositoryListenerPlugin.class);
+ Jar jar = null;
+ for (RepositoryListenerPlugin listener : listeners) {
+ try {
+ if (jar == null)
+ jar = new Jar(file);
+ listener.bundleAdded(this, jar, file);
+ }
+ catch (Exception e) {
+ if (reporter != null)
+ reporter.warning("Repository listener threw an unexpected exception: %s", e);
+ }
+ finally {
+ if (jar != null)
+ jar.close();
+ }
+ }
+ }
+
+ @Override
+ public synchronized String getLocation() {
+ StringBuilder builder = new StringBuilder();
+ builder.append(storageDir.getAbsolutePath());
+
+ String otherPaths = super.getLocation();
+ if (otherPaths != null && otherPaths.length() > 0)
+ builder.append(", ").append(otherPaths);
+
+ return builder.toString();
+ }
+
+}