package org.argeo.slc.repo.maven;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.jar.Attributes.Name;
+import java.util.jar.Manifest;
+
+import javax.jcr.Binary;
+import javax.jcr.Node;
import javax.jcr.NodeIterator;
+import javax.jcr.Property;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+import javax.jcr.query.qom.Ordering;
+import javax.jcr.query.qom.QueryObjectModel;
import javax.jcr.query.qom.QueryObjectModelFactory;
+import javax.jcr.query.qom.Selector;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
import org.argeo.jcr.JcrUtils;
+import org.argeo.slc.NameVersion;
+import org.argeo.slc.SlcException;
+import org.argeo.slc.jcr.SlcNames;
+import org.argeo.slc.jcr.SlcTypes;
+import org.argeo.slc.repo.ArtifactIndexer;
+import org.argeo.slc.repo.JarFileIndexer;
+import org.argeo.slc.repo.RepoUtils;
+import org.argeo.slc.repo.osgi.OsgiProfile;
+import org.osgi.framework.Constants;
+import org.sonatype.aether.artifact.Artifact;
+import org.sonatype.aether.util.artifact.DefaultArtifact;
/**
* Migrate the distribution from 1.2 to 1.4 by cleaning naming and dependencies.
* The dependency to the SpringSource Enterprise Bundle repository is removed as
- * well as theire naming convention. All third party are move to org.argeo.tp
+ * well as their naming conventions. All third party are move to org.argeo.tp
* group IDs. Maven dependency for Eclipse artifacts don't use version ranges
* anymore. Verison constraints on javax.* packages are removed (since they lead
* to "use package conflicts" when Eclipse and Spring Security are used
* together).
*/
-public class Migration_01_03 implements Runnable {
+public class Migration_01_03 implements Runnable, SlcNames {
+ final String SPRING_SOURCE_PREFIX = "com.springsource";
+ private final static Log log = LogFactory.getLog(Migration_01_03.class);
private Repository repository;
private String sourceWorkspace;
private String targetWorkspace;
- private Session sourceSession;
+ private List<String> excludedBundles = new ArrayList<String>();
+ private Map<String, String> symbolicNamesMapping = new HashMap<String, String>();
+
+ private Session origSession;
private Session targetSession;
+ private List<String> systemPackages = OsgiProfile.PROFILE_JAVA_SE_1_6
+ .getSystemPackages();
+
+ private String artifactBasePath = "/";
+
+ private ArtifactIndexer artifactIndexer = new ArtifactIndexer();
+ private JarFileIndexer jarFileIndexer = new JarFileIndexer();
+
public void init() throws RepositoryException {
- sourceSession = JcrUtils.loginOrCreateWorkspace(repository,
+ origSession = JcrUtils.loginOrCreateWorkspace(repository,
sourceWorkspace);
targetSession = JcrUtils.loginOrCreateWorkspace(repository,
targetWorkspace);
+
+ // works only in OSGi!!
+ // systemPackages = Arrays.asList(System.getProperty(
+ // "org.osgi.framework.system.packages").split(","));
}
public void destroy() {
- JcrUtils.logoutQuietly(sourceSession);
+ JcrUtils.logoutQuietly(origSession);
JcrUtils.logoutQuietly(targetSession);
}
public void run() {
+ try {
+ // clear target
+ NodeIterator nit = targetSession.getNode(artifactBasePath)
+ .getNodes();
+ while (nit.hasNext()) {
+ Node node = nit.nextNode();
+ if (node.isNodeType(NodeType.NT_FOLDER)
+ || node.isNodeType(NodeType.NT_UNSTRUCTURED)) {
+ node.remove();
+ node.getSession().save();
+ if (log.isDebugEnabled())
+ log.debug("Cleared " + node);
+ }
+ }
+
+ NodeIterator origArtifacts = listArtifactVersions(origSession);
+ // process
+ while (origArtifacts.hasNext()) {
+ Node origArtifactNode = origArtifacts.nextNode();
+ if (log.isTraceEnabled())
+ log.trace(origArtifactNode);
+
+ processOrigArtifactVersion(origArtifactNode);
+ }
+ } catch (Exception e) {
+ throw new SlcException("Cannot perform v1.3 migration from "
+ + sourceWorkspace + " to " + targetWorkspace, e);
+ } finally {
+ JcrUtils.discardQuietly(targetSession);
+ }
+ }
+
+ protected void processOrigArtifactVersion(Node origArtifactNode)
+ throws RepositoryException, IOException {
+ Artifact origArtifact = RepoUtils.asArtifact(origArtifactNode);
+
+ // skip eclipse artifacts
+ if ((origArtifact.getGroupId().startsWith("org.eclipse") && !(origArtifact
+ .getArtifactId().equals("org.eclipse.osgi")
+ || origArtifact.getArtifactId().equals(
+ "org.eclipse.osgi.source") || origArtifact
+ .getArtifactId().startsWith("org.eclipse.rwt.widgets.upload")))
+ || origArtifact.getArtifactId().startsWith("com.ibm.icu")) {
+ if (log.isDebugEnabled())
+ log.debug("Skip " + origArtifact);
+ return;
+ }
+
+ // skip SpringSource ActiveMQ
+ if (origArtifact.getArtifactId().startsWith(
+ "com.springsource.org.apache.activemq"))
+ return;
+
+ String origJarNodeName = MavenConventionsUtils
+ .artifactFileName(origArtifact);
+ if (!origArtifactNode.hasNode(origJarNodeName))
+ throw new SlcException("Cannot find jar node for "
+ + origArtifactNode);
+ Node origJarNode = origArtifactNode.getNode(origJarNodeName);
+
+ // read MANIFEST
+ Binary manifestBinary = origJarNode.getProperty(SLC_MANIFEST)
+ .getBinary();
+ Manifest origManifest = new Manifest(manifestBinary.getStream());
+ JcrUtils.closeQuietly(manifestBinary);
+
+ Boolean manifestModified = false;
+ Manifest targetManifest = new Manifest(origManifest);
+
+ // transform symbolic name
+ String origSymbolicName = origManifest.getMainAttributes().getValue(
+ Constants.BUNDLE_SYMBOLICNAME);
+ final String targetSymbolicName;
+ if (symbolicNamesMapping.containsKey(origSymbolicName)) {
+ targetSymbolicName = symbolicNamesMapping.get(origSymbolicName);
+ } else if (origSymbolicName.startsWith(SPRING_SOURCE_PREFIX)
+ && !origSymbolicName.equals(SPRING_SOURCE_PREFIX + ".json")) {
+ targetSymbolicName = origSymbolicName
+ .substring(SPRING_SOURCE_PREFIX.length() + 1);
+ } else {
+ targetSymbolicName = origSymbolicName;
+ }
+
+ if (!targetSymbolicName.equals(origSymbolicName)) {
+ targetManifest.getMainAttributes().putValue(
+ Constants.BUNDLE_SYMBOLICNAME, targetSymbolicName);
+ manifestModified = true;
+ if (log.isDebugEnabled())
+ log.debug(Constants.BUNDLE_SYMBOLICNAME + " to "
+ + targetSymbolicName + " \t\tfrom " + origSymbolicName);
+ }
+
+ // skip excluded bundles
+ if (excludedBundles.contains(targetSymbolicName))
+ return;
+
+ // check fragment host
+ if (origManifest.getMainAttributes().containsKey(
+ new Name(Constants.FRAGMENT_HOST))) {
+ String origFragmentHost = origManifest.getMainAttributes()
+ .getValue(Constants.FRAGMENT_HOST);
+ String targetFragmentHost;
+ if (symbolicNamesMapping.containsKey(origFragmentHost)) {
+ targetFragmentHost = symbolicNamesMapping.get(origFragmentHost);
+ } else if (origFragmentHost.startsWith(SPRING_SOURCE_PREFIX)
+ && !origFragmentHost.equals(SPRING_SOURCE_PREFIX + ".json")) {
+ targetFragmentHost = origFragmentHost
+ .substring(SPRING_SOURCE_PREFIX.length() + 1);
+ } else if (origFragmentHost
+ .equals("org.argeo.dep.jacob;bundle-version=\"[1.14.3,1.14.4)\"")) {
+ // this one for those who think I cannot be pragmatic - mbaudier
+ targetFragmentHost = "com.jacob;bundle-version=\"[1.14.3,1.14.4)\"";
+ } else {
+ targetFragmentHost = origFragmentHost;
+ }
+
+ if (!targetFragmentHost.equals(origFragmentHost)) {
+ targetManifest.getMainAttributes().putValue(
+ Constants.FRAGMENT_HOST, targetFragmentHost);
+ manifestModified = true;
+ if (log.isDebugEnabled())
+ log.debug(Constants.FRAGMENT_HOST + " to "
+ + targetFragmentHost + " from " + origFragmentHost);
+ }
+ }
+
+ // we assume there is no Require-Bundle in com.springsource.* bundles
+
+ // javax with versions
+ StringBuffer targetImportPackages = new StringBuffer("");
+ NodeIterator origImportPackages = origJarNode.getNodes(SLC_
+ + Constants.IMPORT_PACKAGE);
+ Boolean importPackagesModified = false;
+ while (origImportPackages.hasNext()) {
+ Node importPackage = origImportPackages.nextNode();
+ String pkg = importPackage.getProperty(SLC_NAME).getString();
+ targetImportPackages.append(pkg);
+ if (importPackage.hasProperty(SLC_VERSION)) {
+ String sourceVersion = importPackage.getProperty(SLC_VERSION)
+ .getString();
+ String targetVersion = sourceVersion;
+ if (systemPackages.contains(pkg)) {
+ if (!(sourceVersion.trim().equals("0") || sourceVersion
+ .trim().equals("0.0.0"))) {
+ targetVersion = null;
+ importPackagesModified = true;
+ if (log.isDebugEnabled())
+ log.debug(origSymbolicName
+ + ": Nullify version of " + pkg + " from "
+ + sourceVersion);
+ }
+ }
+ if (targetVersion != null)
+ targetImportPackages.append(";version=\"")
+ .append(targetVersion).append("\"");
+ }
+ if (importPackage.hasProperty(SLC_OPTIONAL)) {
+ Boolean optional = importPackage.getProperty(SLC_OPTIONAL)
+ .getBoolean();
+ if (optional)
+ targetImportPackages.append(";resolution:=\"optional\"");
+
+ }
+ if (origImportPackages.hasNext())
+ targetImportPackages.append(",");
+ }
+
+ if (importPackagesModified) {
+ targetManifest.getMainAttributes().putValue(
+ Constants.IMPORT_PACKAGE, targetImportPackages.toString());
+ manifestModified = true;
+ }
+
+ if (!manifestModified && log.isTraceEnabled()) {
+ log.trace("MANIFEST of " + origSymbolicName + " was not modified");
+ }
+
+ // target coordinates
+ final String targetGroupId;
+ if (origArtifact.getArtifactId().startsWith(
+ "org.eclipse.rwt.widgets.upload"))
+ targetGroupId = "org.argeo.tp.rap";
+ else if (origArtifact.getArtifactId().startsWith("org.polymap"))
+ targetGroupId = "org.argeo.tp.rap";
+ else if (origArtifact.getGroupId().startsWith("org.eclipse")
+ && !origArtifact.getArtifactId().equals("org.eclipse.osgi"))
+ throw new SlcException(origArtifact + " should have been excluded");// targetGroupId
+ // =
+ // "org.argeo.tp.eclipse";
+ else
+ targetGroupId = "org.argeo.tp";
+
+ String targetArtifactId = targetSymbolicName.split(";")[0];
+ Artifact targetArtifact = new DefaultArtifact(targetGroupId,
+ targetArtifactId, "jar", origArtifact.getVersion());
+ String targetParentPath = MavenConventionsUtils.artifactParentPath(
+ artifactBasePath, targetArtifact);
+ String targetFileName = MavenConventionsUtils
+ .artifactFileName(targetArtifact);
+ String targetJarPath = targetParentPath + '/' + targetFileName;
+
+ // copy
+ Node targetParentNode = JcrUtils.mkfolders(targetSession,
+ targetParentPath);
+ targetSession.save();
+ if (manifestModified) {
+ Binary origBinary = origJarNode.getNode(Node.JCR_CONTENT)
+ .getProperty(Property.JCR_DATA).getBinary();
+ byte[] targetJarBytes = RepoUtils.modifyManifest(
+ origBinary.getStream(), targetManifest);
+ JcrUtils.copyBytesAsFile(targetParentNode, targetFileName,
+ targetJarBytes);
+ JcrUtils.closeQuietly(origBinary);
+ } else {// just copy
+ targetSession.getWorkspace().copy(sourceWorkspace,
+ origJarNode.getPath(), targetJarPath);
+ }
+ targetSession.save();
+
+ // reindex
+ Node targetJarNode = targetSession.getNode(targetJarPath);
+ artifactIndexer.index(targetJarNode);
+ jarFileIndexer.index(targetJarNode);
+
+ targetSession.save();
+
+ // sources
+ Artifact origSourceArtifact = new DefaultArtifact(
+ origArtifact.getGroupId(), origArtifact.getArtifactId()
+ + ".source", "jar", origArtifact.getVersion());
+ String origSourcePath = MavenConventionsUtils.artifactPath(
+ artifactBasePath, origSourceArtifact);
+ if (origSession.itemExists(origSourcePath)) {
+ Node origSourceJarNode = origSession.getNode(origSourcePath);
+
+ Artifact targetSourceArtifact = new DefaultArtifact(targetGroupId,
+ targetArtifactId + ".source", "jar",
+ origArtifact.getVersion());
+ String targetSourceParentPath = MavenConventionsUtils
+ .artifactParentPath(artifactBasePath, targetSourceArtifact);
+ String targetSourceFileName = MavenConventionsUtils
+ .artifactFileName(targetSourceArtifact);
+ String targetSourceJarPath = targetSourceParentPath + '/'
+ + targetSourceFileName;
+
+ Node targetSourceParentNode = JcrUtils.mkfolders(targetSession,
+ targetSourceParentPath);
+ targetSession.save();
+
+ if (!targetSymbolicName.equals(origSymbolicName)) {
+ Binary origBinary = origSourceJarNode.getNode(Node.JCR_CONTENT)
+ .getProperty(Property.JCR_DATA).getBinary();
+ NameVersion targetNameVersion = RepoUtils
+ .readNameVersion(targetManifest);
+ byte[] targetJarBytes = RepoUtils.packageAsPdeSource(
+ origBinary.getStream(), targetNameVersion);
+ JcrUtils.copyBytesAsFile(targetSourceParentNode,
+ targetSourceFileName, targetJarBytes);
+ JcrUtils.closeQuietly(origBinary);
+ } else {// just copy
+ targetSession.getWorkspace().copy(sourceWorkspace,
+ origSourceJarNode.getPath(), targetSourceJarPath);
+ }
+ targetSession.save();
+
+ // reindex
+ Node targetSourceJarNode = targetSession
+ .getNode(targetSourceJarPath);
+ artifactIndexer.index(targetSourceJarNode);
+ jarFileIndexer.index(targetSourceJarNode);
+
+ targetSession.save();
+ }
}
+ /*
+ * UTILITIES
+ */
+
static NodeIterator listArtifactVersions(Session session)
throws RepositoryException {
- QueryObjectModelFactory qomf = session.getWorkspace().getQueryManager()
- .getQOMFactory();
- return null;
+ QueryManager queryManager = session.getWorkspace().getQueryManager();
+ QueryObjectModelFactory factory = queryManager.getQOMFactory();
+
+ final String artifactVersionsSelector = "artifactVersions";
+ Selector source = factory.selector(SlcTypes.SLC_ARTIFACT_VERSION_BASE,
+ artifactVersionsSelector);
+
+ Ordering orderByArtifactId = factory.ascending(factory.propertyValue(
+ artifactVersionsSelector, SlcNames.SLC_ARTIFACT_ID));
+ Ordering[] orderings = { orderByArtifactId };
+
+ QueryObjectModel query = factory.createQuery(source, null, orderings,
+ null);
+
+ QueryResult result = query.execute();
+ return result.getNodes();
+ }
+
+ public void setRepository(Repository repository) {
+ this.repository = repository;
}
+
+ public void setSourceWorkspace(String sourceWorkspace) {
+ this.sourceWorkspace = sourceWorkspace;
+ }
+
+ public void setTargetWorkspace(String targetWorkspace) {
+ this.targetWorkspace = targetWorkspace;
+ }
+
+ public void setExcludedBundles(List<String> excludedBundles) {
+ this.excludedBundles = excludedBundles;
+ }
+
+ public void setSymbolicNamesMapping(Map<String, String> symbolicNamesMapping) {
+ this.symbolicNamesMapping = symbolicNamesMapping;
+ }
+
}