+/*
+ * Copyright (C) 2007-2012 Argeo GmbH
+ *
+ * Licensed 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.argeo.slc.repo;
import java.io.ByteArrayOutputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Iterator;
+import java.util.Set;
import java.util.StringTokenizer;
+import java.util.TreeSet;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
+import java.util.zip.ZipInputStream;
import javax.jcr.Credentials;
import javax.jcr.GuestCredentials;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.RepositoryFactory;
+import javax.jcr.Session;
import javax.jcr.SimpleCredentials;
import javax.jcr.nodetype.NodeType;
import org.apache.commons.io.IOUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import org.argeo.ArgeoMonitor;
import org.argeo.jcr.ArgeoJcrUtils;
import org.argeo.jcr.ArgeoNames;
import org.argeo.jcr.ArgeoTypes;
import org.argeo.jcr.JcrUtils;
-import org.argeo.slc.BasicNameVersion;
+import org.argeo.slc.DefaultNameVersion;
import org.argeo.slc.NameVersion;
import org.argeo.slc.SlcException;
+import org.argeo.slc.aether.ArtifactIdComparator;
import org.argeo.slc.jcr.SlcNames;
import org.argeo.slc.jcr.SlcTypes;
import org.argeo.slc.repo.maven.MavenConventionsUtils;
jarOut = new JarOutputStream(out, manifest);
JarEntry jarEntry = null;
while ((jarEntry = jarIn.getNextJarEntry()) != null) {
- jarOut.putNextEntry(jarEntry);
+ JarEntry newJarEntry = new JarEntry(jarEntry.getName());
+ jarOut.putNextEntry(newJarEntry);
IOUtils.copy(jarIn, jarOut);
jarIn.closeEntry();
jarOut.closeEntry();
throw new SlcException("Could not copy jar with MANIFEST "
+ manifest.getMainAttributes(), e);
} finally {
- IOUtils.closeQuietly(jarIn);
+ if (!(in instanceof ZipInputStream))
+ IOUtils.closeQuietly(jarIn);
IOUtils.closeQuietly(jarOut);
}
}
/** Read the OSGi {@link NameVersion} */
public static NameVersion readNameVersion(File artifactFile) {
- JarInputStream jarInputStream = null;
try {
- jarInputStream = new JarInputStream(new FileInputStream(
- artifactFile));
- return readNameVersion(jarInputStream.getManifest());
+ return readNameVersion(new FileInputStream(artifactFile));
} catch (Exception e) {
// probably not a jar, skipping
if (log.isDebugEnabled()) {
log.debug("Skipping " + artifactFile + " because of " + e);
// e.printStackTrace();
}
+ }
+ return null;
+ }
+
+ /** Read the OSGi {@link NameVersion} */
+ public static NameVersion readNameVersion(InputStream in) {
+ JarInputStream jarInputStream = null;
+ try {
+ jarInputStream = new JarInputStream(in);
+ return readNameVersion(jarInputStream.getManifest());
+ } catch (Exception e) {
+ // probably not a jar, skipping
+ if (log.isDebugEnabled()) {
+ log.debug("Skipping because of " + e);
+ e.printStackTrace();
+ }
} finally {
IOUtils.closeQuietly(jarInputStream);
}
/** Read the OSGi {@link NameVersion} */
public static NameVersion readNameVersion(Manifest manifest) {
- BasicNameVersion nameVersion = new BasicNameVersion();
+ DefaultNameVersion nameVersion = new DefaultNameVersion();
nameVersion.setName(manifest.getMainAttributes().getValue(
Constants.BUNDLE_SYMBOLICNAME));
}
}
+ /**
+ * The path to the PDE source related to this artifact (or artifact version
+ * base). There may or there may not be a node at this location (the
+ * returned path will typically be used to test whether PDE sources are
+ * attached to this artifact).
+ */
+ public static String relatedPdeSourcePath(String artifactBasePath,
+ Node artifactNode) throws RepositoryException {
+ Artifact artifact = asArtifact(artifactNode);
+ Artifact pdeSourceArtifact = new DefaultArtifact(artifact.getGroupId(),
+ artifact.getArtifactId() + ".source", artifact.getExtension(),
+ artifact.getVersion());
+ return MavenConventionsUtils.artifactPath(artifactBasePath,
+ pdeSourceArtifact);
+ }
+
/**
* Copy this bytes array as an artifact, relative to the root of the
* repository (typically the workspace root node)
throw new SlcException("Cannot connect to repository " + repoNode,
e);
}
-
}
/**
- * Reads credentials from node, using keyring if there is a password. Cann
+ * Reads credentials from node, using keyring if there is a password. Can
* return null if no credentials needed (local repo) at all, but returns
* {@link GuestCredentials} if user id is 'anonymous' .
*/
}
}
+ /**
+ * Shortcut to retrieve a session given variable information: Handle the
+ * case where we only have an URI of the repository, that we want to connect
+ * as anonymous or the case of a identified connection to a local or remote
+ * repository.
+ *
+ * Callers must close the session once it has been used
+ */
+ public static Session getRemoteSession(RepositoryFactory repositoryFactory,
+ Keyring keyring, Node repoNode, String uri, String workspaceName) {
+ try {
+ if (repoNode == null && uri == null)
+ throw new SlcException(
+ "At least one of repoNode and uri must be defined");
+ Repository currRepo = null;
+ Credentials credentials = null;
+ // Anonymous URI only workspace
+ if (repoNode == null)
+ // Anonymous
+ currRepo = ArgeoJcrUtils.getRepositoryByUri(repositoryFactory,
+ uri);
+ else {
+ currRepo = RepoUtils.getRepository(repositoryFactory, keyring,
+ repoNode);
+ credentials = RepoUtils.getRepositoryCredentials(keyring,
+ repoNode);
+ }
+ return currRepo.login(credentials, workspaceName);
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot connect to workspace "
+ + workspaceName + " of repository " + repoNode
+ + " with URI " + uri, e);
+ }
+ }
+
+ /**
+ * Shortcut to retrieve a session on a remote Jrc Repository from
+ * information stored in a local argeo node or from an URI: Handle the case
+ * where we only have an URI of the repository, that we want to connect as
+ * anonymous or the case of a identified connection to a local or remote
+ * repository.
+ *
+ * Callers must close the session once it has been used
+ */
+ public static Session getRemoteSession(RepositoryFactory repositoryFactory,
+ Keyring keyring, Repository localRepository, String repoNodePath,
+ String uri, String workspaceName) {
+ Session localSession = null;
+ Node repoNode = null;
+ try {
+ localSession = localRepository.login();
+ if (repoNodePath != null && localSession.nodeExists(repoNodePath))
+ repoNode = localSession.getNode(repoNodePath);
+
+ return RepoUtils.getRemoteSession(repositoryFactory, keyring,
+ repoNode, uri, workspaceName);
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot log to workspace " + workspaceName
+ + " for repo defined in " + repoNodePath, e);
+ } finally {
+ JcrUtils.logoutQuietly(localSession);
+ }
+ }
+
+ /**
+ * Write group indexes: 'binaries' lists all bundles and their versions,
+ * 'sources' list their sources, and 'sdk' aggregates both.
+ */
+ public static void writeGroupIndexes(Session session,
+ String artifactBasePath, String groupId, String version,
+ Set<Artifact> binaries, Set<Artifact> sources) {
+ try {
+ Set<Artifact> indexes = new TreeSet<Artifact>(
+ new ArtifactIdComparator());
+ Artifact binariesArtifact = writeIndex(session, artifactBasePath,
+ groupId, RepoConstants.BINARIES_ARTIFACT_ID, version,
+ binaries);
+ indexes.add(binariesArtifact);
+ if (sources != null) {
+ Artifact sourcesArtifact = writeIndex(session,
+ artifactBasePath, groupId,
+ RepoConstants.SOURCES_ARTIFACT_ID, version, sources);
+ indexes.add(sourcesArtifact);
+ }
+ // sdk
+ writeIndex(session, artifactBasePath, groupId,
+ RepoConstants.SDK_ARTIFACT_ID, version, indexes);
+ session.save();
+ } catch (RepositoryException e) {
+ throw new SlcException("Cannot write indexes for group " + groupId,
+ e);
+ }
+ }
+
+ /** Write a group index. */
+ private static Artifact writeIndex(Session session,
+ String artifactBasePath, String groupId, String artifactId,
+ String version, Set<Artifact> artifacts) throws RepositoryException {
+ Artifact artifact = new DefaultArtifact(groupId, artifactId, "pom",
+ version);
+ String pom = MavenConventionsUtils.artifactsAsDependencyPom(artifact,
+ artifacts, null);
+ Node node = RepoUtils.copyBytesAsArtifact(
+ session.getNode(artifactBasePath), artifact, pom.getBytes());
+ addMavenChecksums(node);
+ return artifact;
+ }
+
+ /** Add files containing the SHA-1 and MD5 checksums. */
+ public static void addMavenChecksums(Node node) throws RepositoryException {
+ // TODO optimize
+ String sha = JcrUtils.checksumFile(node, "SHA-1");
+ JcrUtils.copyBytesAsFile(node.getParent(), node.getName() + ".sha1",
+ sha.getBytes());
+ String md5 = JcrUtils.checksumFile(node, "MD5");
+ JcrUtils.copyBytesAsFile(node.getParent(), node.getName() + ".md5",
+ md5.getBytes());
+ }
+
/**
* Custom copy since the one in commons does not fit the needs when copying
* a workspace completely.
*/
public static void copy(Node fromNode, Node toNode) {
+ copy(fromNode, toNode, null);
+ }
+
+ public static void copy(Node fromNode, Node toNode, ArgeoMonitor monitor) {
try {
+ String fromPath = fromNode.getPath();
+ if (monitor != null)
+ monitor.subTask("copying node :" + fromPath);
if (log.isDebugEnabled())
- log.debug("copy node :" + fromNode.getPath());
+ log.debug("copy node :" + fromPath);
// FIXME : small hack to enable specific workspace copy
if (fromNode.isNodeType("rep:ACL")
if (toNode.isNodeType(SlcTypes.SLC_ARTIFACT))
toNode.getSession().save();
+ if (monitor != null)
+ monitor.worked(1);
+
} catch (RepositoryException e) {
throw new SlcException("Cannot copy " + fromNode + " to " + toNode,
e);