]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/maven/Migration_01_03.java
INtroduce symbolic names mapping
[gpl/argeo-slc.git] / runtime / org.argeo.slc.repo / src / main / java / org / argeo / slc / repo / maven / Migration_01_03.java
index 5a04ba1e72f77e2244a6432261089aa90e2d8490..56ffd7f67f5dd18cbba7863a8fc0448a33da1113 100644 (file)
 package org.argeo.slc.repo.maven;
 
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+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.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;
+
+       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);
+               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 {
+                               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.getGroupId().startsWith("org.eclipse"))
+                       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;
+       }
+
 }