]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/maven/Migration_01_03.java
Make import more robust
[gpl/argeo-slc.git] / runtime / org.argeo.slc.repo / src / main / java / org / argeo / slc / repo / maven / Migration_01_03.java
1 package org.argeo.slc.repo.maven;
2
3 import java.io.IOException;
4 import java.util.ArrayList;
5 import java.util.HashMap;
6 import java.util.List;
7 import java.util.Map;
8 import java.util.jar.Attributes.Name;
9 import java.util.jar.Manifest;
10
11 import javax.jcr.Binary;
12 import javax.jcr.Node;
13 import javax.jcr.NodeIterator;
14 import javax.jcr.Property;
15 import javax.jcr.Repository;
16 import javax.jcr.RepositoryException;
17 import javax.jcr.Session;
18 import javax.jcr.nodetype.NodeType;
19 import javax.jcr.query.QueryManager;
20 import javax.jcr.query.QueryResult;
21 import javax.jcr.query.qom.Ordering;
22 import javax.jcr.query.qom.QueryObjectModel;
23 import javax.jcr.query.qom.QueryObjectModelFactory;
24 import javax.jcr.query.qom.Selector;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.argeo.jcr.JcrUtils;
29 import org.argeo.slc.NameVersion;
30 import org.argeo.slc.SlcException;
31 import org.argeo.slc.jcr.SlcNames;
32 import org.argeo.slc.jcr.SlcTypes;
33 import org.argeo.slc.repo.ArtifactIndexer;
34 import org.argeo.slc.repo.JarFileIndexer;
35 import org.argeo.slc.repo.RepoUtils;
36 import org.argeo.slc.repo.osgi.OsgiProfile;
37 import org.osgi.framework.Constants;
38 import org.sonatype.aether.artifact.Artifact;
39 import org.sonatype.aether.util.artifact.DefaultArtifact;
40
41 /**
42 * Migrate the distribution from 1.2 to 1.4 by cleaning naming and dependencies.
43 * The dependency to the SpringSource Enterprise Bundle repository is removed as
44 * well as their naming conventions. All third party are move to org.argeo.tp
45 * group IDs. Maven dependency for Eclipse artifacts don't use version ranges
46 * anymore. Verison constraints on javax.* packages are removed (since they lead
47 * to "use package conflicts" when Eclipse and Spring Security are used
48 * together).
49 */
50 public class Migration_01_03 implements Runnable, SlcNames {
51 final String SPRING_SOURCE_PREFIX = "com.springsource";
52 private final static Log log = LogFactory.getLog(Migration_01_03.class);
53
54 private Repository repository;
55 private String sourceWorkspace;
56 private String targetWorkspace;
57
58 private List<String> excludedBundles = new ArrayList<String>();
59 private Map<String, String> symbolicNamesMapping = new HashMap<String, String>();
60
61 private Session origSession;
62 private Session targetSession;
63
64 private List<String> systemPackages = OsgiProfile.PROFILE_JAVA_SE_1_6
65 .getSystemPackages();
66
67 private String artifactBasePath = "/";
68
69 private ArtifactIndexer artifactIndexer = new ArtifactIndexer();
70 private JarFileIndexer jarFileIndexer = new JarFileIndexer();
71
72 public void init() throws RepositoryException {
73 origSession = JcrUtils.loginOrCreateWorkspace(repository,
74 sourceWorkspace);
75 targetSession = JcrUtils.loginOrCreateWorkspace(repository,
76 targetWorkspace);
77
78 // works only in OSGi!!
79 // systemPackages = Arrays.asList(System.getProperty(
80 // "org.osgi.framework.system.packages").split(","));
81 }
82
83 public void destroy() {
84 JcrUtils.logoutQuietly(origSession);
85 JcrUtils.logoutQuietly(targetSession);
86 }
87
88 public void run() {
89
90 try {
91 // clear target
92 NodeIterator nit = targetSession.getNode(artifactBasePath)
93 .getNodes();
94 while (nit.hasNext()) {
95 Node node = nit.nextNode();
96 if (node.isNodeType(NodeType.NT_FOLDER)
97 || node.isNodeType(NodeType.NT_UNSTRUCTURED)) {
98 node.remove();
99 node.getSession().save();
100 if (log.isDebugEnabled())
101 log.debug("Cleared " + node);
102 }
103 }
104
105 NodeIterator origArtifacts = listArtifactVersions(origSession);
106 // process
107 while (origArtifacts.hasNext()) {
108 Node origArtifactNode = origArtifacts.nextNode();
109 if (log.isTraceEnabled())
110 log.trace(origArtifactNode);
111
112 processOrigArtifactVersion(origArtifactNode);
113 }
114 } catch (Exception e) {
115 throw new SlcException("Cannot perform v1.3 migration from "
116 + sourceWorkspace + " to " + targetWorkspace, e);
117 } finally {
118 JcrUtils.discardQuietly(targetSession);
119 }
120 }
121
122 protected void processOrigArtifactVersion(Node origArtifactNode)
123 throws RepositoryException, IOException {
124 Artifact origArtifact = RepoUtils.asArtifact(origArtifactNode);
125
126 // skip eclipse artifacts
127 if ((origArtifact.getGroupId().startsWith("org.eclipse") && !(origArtifact
128 .getArtifactId().equals("org.eclipse.osgi")
129 || origArtifact.getArtifactId().equals(
130 "org.eclipse.osgi.source") || origArtifact
131 .getArtifactId().startsWith("org.eclipse.rwt.widgets.upload")))
132 || origArtifact.getArtifactId().startsWith("com.ibm.icu")) {
133 if (log.isDebugEnabled())
134 log.debug("Skip " + origArtifact);
135 return;
136 }
137
138 String origJarNodeName = MavenConventionsUtils
139 .artifactFileName(origArtifact);
140 if (!origArtifactNode.hasNode(origJarNodeName))
141 throw new SlcException("Cannot find jar node for "
142 + origArtifactNode);
143 Node origJarNode = origArtifactNode.getNode(origJarNodeName);
144
145 // read MANIFEST
146 Binary manifestBinary = origJarNode.getProperty(SLC_MANIFEST)
147 .getBinary();
148 Manifest origManifest = new Manifest(manifestBinary.getStream());
149 JcrUtils.closeQuietly(manifestBinary);
150
151 Boolean manifestModified = false;
152 Manifest targetManifest = new Manifest(origManifest);
153
154 // transform symbolic name
155 String origSymbolicName = origManifest.getMainAttributes().getValue(
156 Constants.BUNDLE_SYMBOLICNAME);
157 final String targetSymbolicName;
158 if (symbolicNamesMapping.containsKey(origSymbolicName)) {
159 targetSymbolicName = symbolicNamesMapping.get(origSymbolicName);
160 } else if (origSymbolicName.startsWith(SPRING_SOURCE_PREFIX)
161 && !origSymbolicName.equals(SPRING_SOURCE_PREFIX + ".json")) {
162 targetSymbolicName = origSymbolicName
163 .substring(SPRING_SOURCE_PREFIX.length() + 1);
164 } else {
165 targetSymbolicName = origSymbolicName;
166 }
167
168 if (!targetSymbolicName.equals(origSymbolicName)) {
169 targetManifest.getMainAttributes().putValue(
170 Constants.BUNDLE_SYMBOLICNAME, targetSymbolicName);
171 manifestModified = true;
172 if (log.isDebugEnabled())
173 log.debug(Constants.BUNDLE_SYMBOLICNAME + " to "
174 + targetSymbolicName + " \t\tfrom " + origSymbolicName);
175 }
176
177 // skip excluded bundles
178 if (excludedBundles.contains(targetSymbolicName))
179 return;
180
181 // check fragment host
182 if (origManifest.getMainAttributes().containsKey(
183 new Name(Constants.FRAGMENT_HOST))) {
184 String origFragmentHost = origManifest.getMainAttributes()
185 .getValue(Constants.FRAGMENT_HOST);
186 String targetFragmentHost;
187 if (symbolicNamesMapping.containsKey(origFragmentHost)) {
188 targetFragmentHost = symbolicNamesMapping.get(origFragmentHost);
189 } else if (origFragmentHost.startsWith(SPRING_SOURCE_PREFIX)
190 && !origFragmentHost.equals(SPRING_SOURCE_PREFIX + ".json")) {
191 targetFragmentHost = origFragmentHost
192 .substring(SPRING_SOURCE_PREFIX.length() + 1);
193 } else if (origFragmentHost
194 .equals("org.argeo.dep.jacob;bundle-version=\"[1.14.3,1.14.4)\"")) {
195 // this one for those who think I cannot be pragmatic - mbaudier
196 targetFragmentHost = "com.jacob;bundle-version=\"[1.14.3,1.14.4)\"";
197 } else {
198 targetFragmentHost = origFragmentHost;
199 }
200
201 if (!targetFragmentHost.equals(origFragmentHost)) {
202 targetManifest.getMainAttributes().putValue(
203 Constants.FRAGMENT_HOST, targetFragmentHost);
204 manifestModified = true;
205 if (log.isDebugEnabled())
206 log.debug(Constants.FRAGMENT_HOST + " to "
207 + targetFragmentHost + " from " + origFragmentHost);
208 }
209 }
210
211 // we assume there is no Require-Bundle in com.springsource.* bundles
212
213 // javax with versions
214 StringBuffer targetImportPackages = new StringBuffer("");
215 NodeIterator origImportPackages = origJarNode.getNodes(SLC_
216 + Constants.IMPORT_PACKAGE);
217 Boolean importPackagesModified = false;
218 while (origImportPackages.hasNext()) {
219 Node importPackage = origImportPackages.nextNode();
220 String pkg = importPackage.getProperty(SLC_NAME).getString();
221 targetImportPackages.append(pkg);
222 if (importPackage.hasProperty(SLC_VERSION)) {
223 String sourceVersion = importPackage.getProperty(SLC_VERSION)
224 .getString();
225 String targetVersion = sourceVersion;
226 if (systemPackages.contains(pkg)) {
227 if (!(sourceVersion.trim().equals("0") || sourceVersion
228 .trim().equals("0.0.0"))) {
229 targetVersion = null;
230 importPackagesModified = true;
231 if (log.isDebugEnabled())
232 log.debug(origSymbolicName
233 + ": Nullify version of " + pkg + " from "
234 + sourceVersion);
235 }
236 }
237 if (targetVersion != null)
238 targetImportPackages.append(";version=\"")
239 .append(targetVersion).append("\"");
240 }
241 if (importPackage.hasProperty(SLC_OPTIONAL)) {
242 Boolean optional = importPackage.getProperty(SLC_OPTIONAL)
243 .getBoolean();
244 if (optional)
245 targetImportPackages.append(";resolution:=\"optional\"");
246
247 }
248 if (origImportPackages.hasNext())
249 targetImportPackages.append(",");
250 }
251
252 if (importPackagesModified) {
253 targetManifest.getMainAttributes().putValue(
254 Constants.IMPORT_PACKAGE, targetImportPackages.toString());
255 manifestModified = true;
256 }
257
258 if (!manifestModified && log.isTraceEnabled()) {
259 log.trace("MANIFEST of " + origSymbolicName + " was not modified");
260 }
261
262 // target coordinates
263 final String targetGroupId;
264 if (origArtifact.getArtifactId().startsWith(
265 "org.eclipse.rwt.widgets.upload"))
266 targetGroupId = "org.argeo.tp.rap";
267 else if (origArtifact.getArtifactId().startsWith("org.polymap"))
268 targetGroupId = "org.argeo.tp.rap";
269 else if (origArtifact.getGroupId().startsWith("org.eclipse")
270 && !origArtifact.getArtifactId().equals("org.eclipse.osgi"))
271 throw new SlcException(origArtifact + " should have been excluded");// targetGroupId
272 // =
273 // "org.argeo.tp.eclipse";
274 else
275 targetGroupId = "org.argeo.tp";
276
277 String targetArtifactId = targetSymbolicName.split(";")[0];
278 Artifact targetArtifact = new DefaultArtifact(targetGroupId,
279 targetArtifactId, "jar", origArtifact.getVersion());
280 String targetParentPath = MavenConventionsUtils.artifactParentPath(
281 artifactBasePath, targetArtifact);
282 String targetFileName = MavenConventionsUtils
283 .artifactFileName(targetArtifact);
284 String targetJarPath = targetParentPath + '/' + targetFileName;
285
286 // copy
287 Node targetParentNode = JcrUtils.mkfolders(targetSession,
288 targetParentPath);
289 targetSession.save();
290 if (manifestModified) {
291 Binary origBinary = origJarNode.getNode(Node.JCR_CONTENT)
292 .getProperty(Property.JCR_DATA).getBinary();
293 byte[] targetJarBytes = RepoUtils.modifyManifest(
294 origBinary.getStream(), targetManifest);
295 JcrUtils.copyBytesAsFile(targetParentNode, targetFileName,
296 targetJarBytes);
297 JcrUtils.closeQuietly(origBinary);
298 } else {// just copy
299 targetSession.getWorkspace().copy(sourceWorkspace,
300 origJarNode.getPath(), targetJarPath);
301 }
302 targetSession.save();
303
304 // reindex
305 Node targetJarNode = targetSession.getNode(targetJarPath);
306 artifactIndexer.index(targetJarNode);
307 jarFileIndexer.index(targetJarNode);
308
309 targetSession.save();
310
311 // sources
312 Artifact origSourceArtifact = new DefaultArtifact(
313 origArtifact.getGroupId(), origArtifact.getArtifactId()
314 + ".source", "jar", origArtifact.getVersion());
315 String origSourcePath = MavenConventionsUtils.artifactPath(
316 artifactBasePath, origSourceArtifact);
317 if (origSession.itemExists(origSourcePath)) {
318 Node origSourceJarNode = origSession.getNode(origSourcePath);
319
320 Artifact targetSourceArtifact = new DefaultArtifact(targetGroupId,
321 targetArtifactId + ".source", "jar",
322 origArtifact.getVersion());
323 String targetSourceParentPath = MavenConventionsUtils
324 .artifactParentPath(artifactBasePath, targetSourceArtifact);
325 String targetSourceFileName = MavenConventionsUtils
326 .artifactFileName(targetSourceArtifact);
327 String targetSourceJarPath = targetSourceParentPath + '/'
328 + targetSourceFileName;
329
330 Node targetSourceParentNode = JcrUtils.mkfolders(targetSession,
331 targetSourceParentPath);
332 targetSession.save();
333
334 if (!targetSymbolicName.equals(origSymbolicName)) {
335 Binary origBinary = origSourceJarNode.getNode(Node.JCR_CONTENT)
336 .getProperty(Property.JCR_DATA).getBinary();
337 NameVersion targetNameVersion = RepoUtils
338 .readNameVersion(targetManifest);
339 byte[] targetJarBytes = RepoUtils.packageAsPdeSource(
340 origBinary.getStream(), targetNameVersion);
341 JcrUtils.copyBytesAsFile(targetSourceParentNode,
342 targetSourceFileName, targetJarBytes);
343 JcrUtils.closeQuietly(origBinary);
344 } else {// just copy
345 targetSession.getWorkspace().copy(sourceWorkspace,
346 origSourceJarNode.getPath(), targetSourceJarPath);
347 }
348 targetSession.save();
349
350 // reindex
351 Node targetSourceJarNode = targetSession
352 .getNode(targetSourceJarPath);
353 artifactIndexer.index(targetSourceJarNode);
354 jarFileIndexer.index(targetSourceJarNode);
355
356 targetSession.save();
357 }
358 }
359
360 /*
361 * UTILITIES
362 */
363
364 static NodeIterator listArtifactVersions(Session session)
365 throws RepositoryException {
366 QueryManager queryManager = session.getWorkspace().getQueryManager();
367 QueryObjectModelFactory factory = queryManager.getQOMFactory();
368
369 final String artifactVersionsSelector = "artifactVersions";
370 Selector source = factory.selector(SlcTypes.SLC_ARTIFACT_VERSION_BASE,
371 artifactVersionsSelector);
372
373 Ordering orderByArtifactId = factory.ascending(factory.propertyValue(
374 artifactVersionsSelector, SlcNames.SLC_ARTIFACT_ID));
375 Ordering[] orderings = { orderByArtifactId };
376
377 QueryObjectModel query = factory.createQuery(source, null, orderings,
378 null);
379
380 QueryResult result = query.execute();
381 return result.getNodes();
382 }
383
384 public void setRepository(Repository repository) {
385 this.repository = repository;
386 }
387
388 public void setSourceWorkspace(String sourceWorkspace) {
389 this.sourceWorkspace = sourceWorkspace;
390 }
391
392 public void setTargetWorkspace(String targetWorkspace) {
393 this.targetWorkspace = targetWorkspace;
394 }
395
396 public void setExcludedBundles(List<String> excludedBundles) {
397 this.excludedBundles = excludedBundles;
398 }
399
400 public void setSymbolicNamesMapping(Map<String, String> symbolicNamesMapping) {
401 this.symbolicNamesMapping = symbolicNamesMapping;
402 }
403
404 }