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 15:12:51 UTC
svn commit: r1496021 - in /ace/sandbox/bramk/org.apache.ace.cli: ./
src/org/apache/ace/cli/deployment/ src/org/apache/ace/cli/repository/
test/org/ test/org/apache/ test/org/apache/ace/ test/org/apache/ace/cli/
test/org/apache/ace/cli/deployment/
Author: bramk
Date: Mon Jun 24 13:12:50 2013
New Revision: 1496021
URL: http://svn.apache.org/r1496021
Log:
[sandbox] Added initial code for continuous deployment
Added:
ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/
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/
ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/
ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/
ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/
ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/
ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/ContinuousDeployerTest.java
ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/DeployerUtilTest.java
Modified:
ace/sandbox/bramk/org.apache.ace.cli/bnd.bnd
ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/AceObrRepository.java
Modified: ace/sandbox/bramk/org.apache.ace.cli/bnd.bnd
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/bnd.bnd?rev=1496021&r1=1496020&r2=1496021&view=diff
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/bnd.bnd (original)
+++ ace/sandbox/bramk/org.apache.ace.cli/bnd.bnd Mon Jun 24 13:12:50 2013
@@ -1,15 +1,19 @@
--buildpath: biz.aQute.bnd;version=2.1.0,\
- biz.aQute.repository;version=2.1.0,\
+-buildpath: biz.aQute.repository;version=2.1.0,\
+ biz.aQute.bnd;version=2.1.0,\
com.google.gson,\
org.amdatu.ace.client,\
org.apache.commons.cli,\
- org.osgi.impl.bundle.repoindex.lib
+ org.osgi.impl.bundle.repoindex.lib,\
+ junit.osgi
+
+-removeheaders: Bnd-LastModified
Private-Package: \
org.apache.commons.cli,\
org.apache.ace.cli,\
org.apache.ace.cli.command,\
org.apache.ace.cli.repository,\
+ org.apache.ace.cli.deployment,\
org.amdatu.ace.client,\
org.amdatu.ace.client.model,\
com.google.gson.*,\
Added: 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=1496021&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/ContinuousDeployer.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/ContinuousDeployer.java Mon Jun 24 13:12:50 2013
@@ -0,0 +1,169 @@
+package org.apache.ace.cli.deployment;
+
+import static org.apache.ace.cli.deployment.DeployerUtil.copyResources;
+import static org.apache.ace.cli.deployment.DeployerUtil.findResources;
+import static org.apache.ace.cli.deployment.DeployerUtil.getIdentity;
+import static org.apache.ace.cli.deployment.DeployerUtil.getIdentityVersionRequirement;
+import static org.apache.ace.cli.deployment.DeployerUtil.getJarWithNewVersion;
+import static org.apache.ace.cli.deployment.DeployerUtil.getNextSnapshotVersion;
+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.jarsDiffer;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.List;
+
+import org.osgi.framework.Version;
+import org.osgi.resource.Resource;
+
+import aQute.bnd.deployer.repository.FixedIndexedRepo;
+import aQute.bnd.service.Strategy;
+
+public class ContinuousDeployer {
+
+ FixedIndexedRepo m_deploymentRepo;
+ FixedIndexedRepo m_developmentRepo;
+ FixedIndexedRepo m_releaseRepo;
+
+ public ContinuousDeployer(FixedIndexedRepo deploymentRepo, FixedIndexedRepo developmentRepo, FixedIndexedRepo releaseRepo) {
+ m_deploymentRepo = deploymentRepo;
+ m_developmentRepo = developmentRepo;
+ m_releaseRepo = releaseRepo;
+ }
+
+ /**
+ * Deploys all resources from the development respsitory into the deployment repository.
+ *
+ * @return
+ * @throws Exception
+ */
+ 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;
+ }
+
+ /**
+ * Deploys a resource to the deployment repository.
+ *
+ * @param resource
+ * The resource
+ * @throws Exception
+ * On failure
+ */
+ private void deployResource(Resource resource) throws Exception {
+ 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);
+ }
+ }
+
+ /**
+ * Deploys a released resource from the release repository to the deployment repository if it has not been deployed
+ * yet.
+ *
+ * @param resource
+ * The resource
+ * @throws Exception
+ * On failure
+ */
+ private void deployReleasedResource(Resource resource) throws Exception {
+ List<Resource> deployedResources = findResources(m_deploymentRepo, getIdentity(resource), getVersion(resource).toString());
+ boolean isDeployed = deployedResources.size() > 0;
+ if (!isDeployed) {
+ System.out.println("Uploading release: " + getString(resource));
+ copyResources(m_releaseRepo, m_deploymentRepo, getIdentityVersionRequirement(resource));
+ }
+ else {
+ System.out.println("Ignoring release: " + getString(resource));
+ }
+ }
+
+ /**
+ * Deploys a snapshot resource to the deployment repository if it differs from the highest existing snapshot
+ * resource of the same base version in the deployment repository.
+ *
+ * @param resource
+ * The resource
+ * @throws Exception
+ * On failure
+ */
+ private void deploySnapshotResource(Resource resource) throws Exception {
+
+ Version releasedBaseVersion = getReleasedBaseVersion(resource);
+ Resource snapshotResource = getHighestSnapshotResource(resource, releasedBaseVersion);
+ if (snapshotResource == null) {
+ System.out.println("Uploading initial snapshot: " + getNextSnapshotVersion(releasedBaseVersion));
+ deploySnapshotResource(resource, getNextSnapshotVersion(releasedBaseVersion));
+ }
+ else {
+ System.out.println("Found existing snapshot: " + getString(snapshotResource));
+
+ File developmentResource = m_developmentRepo.get(getIdentity(resource), getVersion(resource).toString(), Strategy.EXACT, null);
+ File deployedResource = m_deploymentRepo.get(getIdentity(snapshotResource), getVersion(snapshotResource).toString(), Strategy.EXACT, null);
+ File comparableDeployedResource = getJarWithNewVersion(deployedResource, getVersion(resource).toString());
+
+ if (jarsDiffer(comparableDeployedResource, developmentResource)) {
+ System.out.println("Uploading new snapshot: " + getNextSnapshotVersion(getVersion(snapshotResource)));
+ deploySnapshotResource(resource, getNextSnapshotVersion(getVersion(snapshotResource)));
+ }
+ else {
+ System.out.println("Ignoring new snapshot: " + getString(resource));
+ }
+ }
+ }
+
+ private void deploySnapshotResource(Resource resource, Version snapshotVersion) throws Exception {
+
+ File file = m_developmentRepo.get(getIdentity(resource), getVersion(resource).toString(), Strategy.EXACT, null);
+ File snapshotVersionedJar = getJarWithNewVersion(file, snapshotVersion.toString());
+ InputStream input = null;
+ try {
+ input = new FileInputStream(snapshotVersionedJar);
+ m_deploymentRepo.put(input, null);
+ }
+ finally {
+ if (input != null)
+ input.close();
+ }
+ }
+
+ private Resource getHighestSnapshotResource(Resource resource, Version base) throws Exception {
+ List<Resource> resources = findResources(m_deploymentRepo, getIdentity(resource));
+ Resource matchedResource = null;
+ for (Resource candidateResource : resources) {
+ if (isSameBaseVersion(getVersion(candidateResource), base)
+ && (matchedResource == null || getVersion(matchedResource).compareTo(getVersion(candidateResource)) < 0)) {
+ matchedResource = candidateResource;
+ }
+ }
+ return matchedResource;
+ }
+
+ private Version getReleasedBaseVersion(Resource resource) throws Exception {
+ List<Resource> resources = findResources(m_releaseRepo, getIdentity(resource));
+ Version resourceVersion = getVersion(resource);
+ Version baseVersion = Version.emptyVersion;
+ for (Resource candidate : resources) {
+ Version candidateVersion = getVersion(candidate);
+ if (candidateVersion.compareTo(resourceVersion) < 0) {
+ if (candidateVersion.compareTo(baseVersion) > 0) {
+ baseVersion = candidateVersion;
+ }
+ }
+ }
+ return baseVersion;
+ }
+}
Added: 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=1496021&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/DeployerUtil.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/deployment/DeployerUtil.java Mon Jun 24 13:12:50 2013
@@ -0,0 +1,327 @@
+package org.apache.ace.cli.deployment;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.StringReader;
+import java.net.URI;
+import java.nio.ByteBuffer;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import java.util.zip.ZipOutputStream;
+
+import org.osgi.framework.Version;
+import org.osgi.resource.Capability;
+import org.osgi.resource.Requirement;
+import org.osgi.resource.Resource;
+import org.osgi.service.repository.Repository;
+
+import aQute.bnd.deployer.repository.AbstractIndexedRepo;
+import aQute.bnd.differ.DiffPluginImpl;
+import aQute.bnd.osgi.Jar;
+import aQute.bnd.osgi.resource.CapReqBuilder;
+import aQute.bnd.service.Strategy;
+import aQute.bnd.service.diff.Delta;
+import aQute.bnd.service.diff.Diff;
+import aQute.bnd.service.diff.Differ;
+import aQute.bnd.service.diff.Tree;
+
+public final class DeployerUtil {
+
+ public static final String QUALIFIER_PREFIX = "CDS";
+
+ private static final Pattern QUALIFIER_PATTERN = Pattern.compile(QUALIFIER_PREFIX + "([\\d]{3})$|(.*)(_" + QUALIFIER_PREFIX + "([\\d]{3})?$)");
+
+ /**
+ * Given ad version, creates the 'next' snapshot version. If the version has no snapshot qualifier a new one will be
+ * added. If it does, it will be incremented.
+ *
+ * @param version
+ * The version
+ * @return The next snapshot Version
+ * @throws Exception
+ * On Failure
+ */
+ public static Version getNextSnapshotVersion(Version version) throws Exception {
+
+ if (version.getQualifier() == null || version.getQualifier().equals("")) {
+ return new Version(version.getMajor(), version.getMinor(), version.getMicro(), getSnapshotQualifier("", 0));
+ }
+ Matcher qualifierMatcher = QUALIFIER_PATTERN.matcher(version.getQualifier());
+ if (!qualifierMatcher.matches()) {
+ return new Version(version.getMajor(), version.getMinor(), version.getMicro(), getSnapshotQualifier(version.getQualifier(), 0));
+ }
+
+ String qualifierMatch = qualifierMatcher.group(1);
+ if (qualifierMatch != null) {
+ int sequence = Integer.parseInt(qualifierMatch);
+ return new Version(version.getMajor(), version.getMinor(), version.getMicro(), getSnapshotQualifier("", ++sequence));
+ }
+
+ String qualifierPrefix = qualifierMatcher.group(2);
+ qualifierMatch = qualifierMatcher.group(4);
+ int sequence = Integer.parseInt(qualifierMatch);
+ return new Version(version.getMajor(), version.getMinor(), version.getMicro(), getSnapshotQualifier(qualifierPrefix, ++sequence));
+ }
+
+ /**
+ * Check if there is a diff between two jar files.
+ *
+ * @param first
+ * The first Jar file
+ * @param second
+ * The second Jar file
+ * @return <code>true</code> if there is a difference, otherwise <code>false</code>
+ * @throws Exception
+ * On failure
+ */
+ public static boolean jarsDiffer(File first, File second) throws Exception {
+
+ Differ di = new DiffPluginImpl();
+ Tree n = di.tree(new Jar(second));
+ Tree o = di.tree(new Jar(first));
+
+ Diff diff = n.diff(o);
+ for (Diff child : diff.getChildren()) {
+ for (Diff childc : child.getChildren()) {
+ if (childc.getDelta() == Delta.UNCHANGED || childc.getDelta() == Delta.IGNORED) {
+ continue;
+ }
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Clones a jar file while replacing the Bundle-Version in the manifest with the specified value.
+ *
+ * @param sourceJar
+ * The existing jar
+ * @param version
+ * The new version
+ * @return The new Jar
+ * @throws IOException
+ * On failure
+ */
+ public static File getJarWithNewVersion(File sourceJar, String version) throws IOException {
+
+ File targetFile = File.createTempFile("bundle", ".jar");
+ byte[] buf = new byte[1024];
+
+ ZipInputStream zin = new ZipInputStream(new FileInputStream(sourceJar));
+ ZipOutputStream out = new ZipOutputStream(new FileOutputStream(targetFile));
+ ZipEntry entry = zin.getNextEntry();
+ while (entry != null) {
+ String name = entry.getName();
+ out.putNextEntry(new ZipEntry(name));
+
+ if (name.equals("META-INF/MANIFEST.MF")) {
+ ByteBuffer bb = ByteBuffer.allocate(10 * 1024);
+ int len;
+ while ((len = zin.read(buf)) > 0) {
+ bb.put(buf, 0, len);
+ }
+
+ BufferedReader r = new BufferedReader(new StringReader(new String(bb.array(), 0, bb.position())));
+ String line;
+ while ((line = r.readLine()) != null) {
+ if (line.startsWith("Bundle-Version:")) {
+ out.write(("Bundle-Version: " + version + "\r\n").getBytes());
+ }
+ else {
+ out.write((line + "\r\n").getBytes());
+ }
+ }
+ }
+ else {
+ int len;
+ while ((len = zin.read(buf)) > 0) {
+ out.write(buf, 0, len);
+ }
+ }
+ entry = zin.getNextEntry();
+ }
+ zin.close();
+ out.close();
+ return targetFile;
+ }
+
+ public static String getString(Resource resource) {
+ return getIdentity(resource) + "/" + getVersion(resource) + "/" + getType(resource);
+ }
+
+ public static String getIdentity(Resource resource) {
+ Map<String, Object> attrs = getNamespaceAttributes(resource, "osgi.identity");
+ if (attrs == null)
+ return null;
+ return (String) attrs.get("osgi.identity");
+
+ }
+
+ public static Requirement getIdentityVersionRequirement(Resource resource) {
+ Requirement requirement = new CapReqBuilder("osgi.identity")
+ .addDirective("filter", String.format("(&(osgi.identity=%s)(version=%s)(type=*))", getIdentity(resource), getVersion(resource)))
+ .buildSyntheticRequirement();
+ return requirement;
+ }
+
+ public static List<Resource> copyResources(AbstractIndexedRepo fromRepo, AbstractIndexedRepo toRepo, String bsn) throws Exception {
+ return copyResources(fromRepo, toRepo, bsn, "*");
+ }
+
+ public static List<Resource> copyResources(AbstractIndexedRepo fromRepo, AbstractIndexedRepo toRepo, String bsn, String version) throws Exception {
+ return copyResources(fromRepo, toRepo, bsn, version, "*");
+ }
+
+ public static List<Resource> copyResources(AbstractIndexedRepo fromRepo, AbstractIndexedRepo toRepo, String bsn, String version, String type) throws Exception {
+ Requirement requirement = new CapReqBuilder("osgi.identity")
+ .addDirective("filter", String.format("(&(osgi.identity=%s)(version=%s)(type=%s))", bsn, version, type))
+ .buildSyntheticRequirement();
+ return copyResources(fromRepo, toRepo, requirement);
+ }
+
+ public static List<Resource> copyResources(AbstractIndexedRepo fromRepo, AbstractIndexedRepo toRepo, Requirement requirement) throws Exception {
+ List<Resource> resources = findResources(fromRepo, requirement);
+ for (Resource resource : resources) {
+ File file = fromRepo.get(getIdentity(resource), getVersion(resource).toString(), Strategy.EXACT, null);
+ InputStream input = null;
+ try {
+ input = new FileInputStream(file);
+ toRepo.put(input, null);
+ }
+ finally {
+ if (input != null)
+ input.close();
+ }
+ }
+ return resources;
+ }
+
+ public static List<Resource> findResources(Repository repository, String bsn) {
+ return findResources(repository, bsn, "*");
+ }
+
+ public static List<Resource> findResources(Repository repository, String bsn, String version) {
+ return findResources(repository, bsn, version, "*");
+ }
+
+ public static List<Resource> findResources(Repository repository, String bsn, String version, String type) {
+ Requirement requirement = new CapReqBuilder("osgi.identity")
+ .addDirective("filter", String.format("(&(osgi.identity=%s)(version=%s)(type=%s))", bsn, version, type))
+ .buildSyntheticRequirement();
+ return findResources(repository, requirement);
+ }
+
+ public static List<Resource> findResources(Repository repository, Requirement requirement) {
+ Map<Requirement, Collection<Capability>> sourceResources = repository.findProviders(Collections.singleton(requirement));
+ if (sourceResources.isEmpty() || sourceResources.get(requirement).isEmpty()) {
+ return Collections.emptyList();
+ }
+ List<Resource> resources = new ArrayList<Resource>();
+ Iterator<Capability> capabilities = sourceResources.get(requirement).iterator();
+ while (capabilities.hasNext()) {
+ Capability capability = capabilities.next();
+ resources.add(capability.getResource());
+ }
+ return resources;
+ }
+
+ public static Version getVersion(Resource resource) {
+ Map<String, Object> attrs = getNamespaceAttributes(resource, "osgi.identity");
+ if (attrs == null)
+ return Version.emptyVersion;
+ Version version = (Version) attrs.get("version");
+ return version == null ? Version.emptyVersion : version;
+ }
+
+ public static List<Version> getVersions(List<Resource> resources) {
+ List<Version> versions = new ArrayList<Version>();
+ for (Resource resource : resources) {
+ versions.add(getVersion(resource));
+ }
+ return versions;
+ }
+
+ public static String getType(Resource resource) {
+ Map<String, Object> attrs = getNamespaceAttributes(resource, "osgi.identity");
+ if (attrs == null)
+ return null;
+ return (String) attrs.get("type");
+ }
+
+ public static String getUrl(Resource resource) {
+ Map<String, Object> attrs = getNamespaceAttributes(resource, "osgi.content");
+ if (attrs == null)
+ return null;
+ URI url = (URI) attrs.get("url");
+ return url == null ? null : url.toString();
+ }
+
+ public static String getMimetype(Resource resource) {
+ Map<String, Object> attrs = getNamespaceAttributes(resource, "osgi.content");
+ if (attrs == null)
+ return null;
+ return (String) attrs.get("mime");
+ }
+
+ public static String getSHA(Resource resource) {
+ Map<String, Object> attrs = getNamespaceAttributes(resource, "osgi.content");
+ if (attrs == null)
+ return null;
+ return (String) attrs.get("osgi.content");
+ }
+
+ public static boolean isSameBaseVersion(Version left, Version right) {
+ return left.getMajor() == right.getMajor() && left.getMinor() == right.getMinor() && left.getMicro() == right.getMicro();
+ }
+
+ private static Map<String, Object> getNamespaceAttributes(Resource resource, String namespace) {
+ List<Capability> caps = resource.getCapabilities(namespace);
+ if (caps.isEmpty())
+ return null;
+ Map<String, Object> attrs = caps.get(0).getAttributes();
+ if (attrs == null)
+ return null;
+ return attrs;
+ }
+
+ private static String getSnapshotQualifier(String prefix, int i) {
+ if (!isEmpty(prefix)) {
+ prefix = prefix + "_";
+ }
+ else {
+ prefix = "";
+ }
+ if (i < 10) {
+ return prefix + QUALIFIER_PREFIX + "00" + i;
+ }
+ else if (i < 100) {
+ return prefix + QUALIFIER_PREFIX + "0" + i;
+ }
+ else if (i < 1000) {
+ return prefix + QUALIFIER_PREFIX + i;
+ }
+ else {
+ throw new IllegalArgumentException("Can not qualifiers above 999");
+ }
+ }
+
+ private static boolean isEmpty(String s) {
+ return s == null || s.equals("");
+ }
+
+ private DeployerUtil() {
+ }
+}
Modified: ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/AceObrRepository.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/AceObrRepository.java?rev=1496021&r1=1496020&r2=1496021&view=diff
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/AceObrRepository.java (original)
+++ ace/sandbox/bramk/org.apache.ace.cli/src/org/apache/ace/cli/repository/AceObrRepository.java Mon Jun 24 13:12:50 2013
@@ -98,6 +98,7 @@ public class AceObrRepository extends Fi
}
else {
// We need a mimetype or Jetty will throw a 500 Form too large
+
connection.setRequestProperty("Content-Type", "application/octet-stream");
}
@@ -133,7 +134,7 @@ public class AceObrRepository extends Fi
}
}
catch (IOException e) {
- throw new IOException("Error importing resource: " + e.getMessage());
+ throw new IOException("Error importing resource: " + e.getMessage(), e);
}
finally {
if (output != null) {
Added: 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=1496021&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/ContinuousDeployerTest.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/ContinuousDeployerTest.java Mon Jun 24 13:12:50 2013
@@ -0,0 +1,189 @@
+package org.apache.ace.cli.deployment;
+
+import static org.apache.ace.cli.deployment.DeployerUtil.copyResources;
+import static org.apache.ace.cli.deployment.DeployerUtil.findResources;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.InputStream;
+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;
+
+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;
+ ContinuousDeployer m_deployer;
+
+ public void setUp() throws Exception {
+ m_workDir = new File("generated/cdtest-" + System.currentTimeMillis());
+ m_workDir.mkdir();
+ m_developmentRepo = createRepo(new File(m_workDir, "development"), "development");
+ m_deploymentRepo = createRepo(new File(m_workDir, "deployment"), "deployment");
+ m_releaseRepo = createRepo(new File(m_workDir, "release"), "release");
+ m_deployer = new ContinuousDeployer(m_deploymentRepo, m_developmentRepo, m_releaseRepo);
+ }
+
+ public void testInitialReleaseDeployment() throws Exception {
+
+ // an initial released bundle from development
+ m_developmentRepo.put(generateBundle("foo.bar", "1.0.0"), null);
+ copyResources(m_developmentRepo, m_releaseRepo, "foo.bar", "1.0.0");
+
+ // should have receive the correct release version
+ m_deployer.deployResources();
+ assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "1.0.0").size());
+
+ // re-deploy of unchanged bundle should not affect the state
+ m_deployer.deployResources();
+ assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "1.0.0").size());
+ }
+
+ public void testInitialSnapshotDeployment() throws Exception {
+
+ // an initial unreleased bundle from development
+ deployBundle(m_developmentRepo, createBundle("foo.bar", "1.0.0"));
+ Thread.sleep(100);
+
+ // should have receive the correct snapshot version
+ m_deployer.deployResources();
+ assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "0.0.0.CDS000").size());
+
+ // re-deploy of unchanged bundle should not affect the state
+ m_deployer.deployResources();
+ assertEquals(1, findResources(m_deploymentRepo, "foo.bar", "0.0.0.CDS000").size());
+
+ // re-deploy of changed bundle should increment snapshot
+
+ // 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);
+
+ // Why do these manifest differ??? Unless in debug... there is a race condition in the BND IO?
+
+ // FIXME bug end
+
+ 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.CDS001").size());
+ }
+
+ private LocalIndexedRepo 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();
+ repo.setProperties(props);
+ return repo;
+ }
+
+ private void deployBundle(LocalIndexedRepo repo, InputStream stream) throws Exception {
+ try {
+ repo.put(stream, null);
+ stream.close();
+ }
+ finally {
+ stream.close();
+ }
+ }
+
+ private void deployBundle(LocalIndexedRepo 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 InputStream generateBundle(final String bsn, final String version, final String... headers) throws Exception {
+ final PipedInputStream in = new PipedInputStream();
+ final PipedOutputStream out = new PipedOutputStream(in);
+ new Thread(
+ new Runnable() {
+ public void run() {
+ Builder b = new Builder();
+ try {
+ b.setBundleSymbolicName(bsn);
+ b.setBundleVersion(version);
+ for (int i = 0; i < headers.length; i += 2) {
+ b.setProperty(headers[i], headers[i + 1]);
+ }
+ b.setProperty("-noextraheaders", "true");
+ Jar jar = b.build();
+ jar.getManifest(); // Not sure whether this is needed...
+ jar.write(out);
+ out.flush();
+ out.close();
+ jar.close();
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ }
+ finally {
+ b.close();
+ }
+ }
+ }).start();
+ return in;
+ }
+
+ private File createBundle(final String bsn, final String version, final String... headers) throws Exception {
+ Builder b = new Builder();
+ try {
+ b.setBundleSymbolicName(bsn);
+ b.setBundleVersion(version);
+ for (int i = 0; i < headers.length; i += 2) {
+ b.setProperty(headers[i], headers[i + 1]);
+ }
+ b.setProperty("-noextraheaders", "true");
+ Jar jar = b.build();
+ jar.getManifest(); // Not sure whether this is needed...
+ File tmp = File.createTempFile("tmpbundle", ".jar");
+ jar.write(tmp);
+ jar.close();
+ return tmp;
+ }
+ catch (Exception e) {
+ e.printStackTrace();
+ throw e;
+ }
+ finally {
+ b.close();
+ }
+ }
+}
Added: ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/DeployerUtilTest.java
URL: http://svn.apache.org/viewvc/ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/DeployerUtilTest.java?rev=1496021&view=auto
==============================================================================
--- ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/DeployerUtilTest.java (added)
+++ ace/sandbox/bramk/org.apache.ace.cli/test/org/apache/ace/cli/deployment/DeployerUtilTest.java Mon Jun 24 13:12:50 2013
@@ -0,0 +1,25 @@
+package org.apache.ace.cli.deployment;
+
+import static org.apache.ace.cli.deployment.DeployerUtil.QUALIFIER_PREFIX;
+import static org.apache.ace.cli.deployment.DeployerUtil.getNextSnapshotVersion;
+import static org.osgi.framework.Version.parseVersion;
+import junit.framework.TestCase;
+
+public class DeployerUtilTest extends TestCase {
+
+ public void testFirstSnapshotNoQualifier() throws Exception {
+ assertEquals(parseVersion("1.0.0." + QUALIFIER_PREFIX + "000"), getNextSnapshotVersion(parseVersion("1.0.0")));
+ }
+
+ public void testFirstSnapshotQualifier() throws Exception {
+ assertEquals(parseVersion("1.0.0.RC_" + QUALIFIER_PREFIX + "000"), getNextSnapshotVersion(parseVersion("1.0.0.RC")));
+ }
+
+ public void testSecondSnapshotNoQualifier() throws Exception {
+ assertEquals(parseVersion("1.0.0." + QUALIFIER_PREFIX + "001"), getNextSnapshotVersion(parseVersion("1.0.0." + QUALIFIER_PREFIX + "000")));
+ }
+
+ public void testSecondSnapshotQualifier() throws Exception {
+ assertEquals(parseVersion("1.0.0.RC_" + QUALIFIER_PREFIX + "001"), getNextSnapshotVersion(parseVersion("1.0.0.RC_" + QUALIFIER_PREFIX + "000")));
+ }
+}