]> 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
8b15eaea292a4c240722fc156028d428cf9188c0
[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") || origArtifact
129 .getArtifactId().equals("org.eclipse.osgi.source")))
130 || origArtifact.getArtifactId().startsWith("org.polymap")
131 || origArtifact.getArtifactId().startsWith("com.ibm.icu")) {
132 if (log.isDebugEnabled())
133 log.debug("Skip " + origArtifact);
134 return;
135 }
136
137 String origJarNodeName = MavenConventionsUtils
138 .artifactFileName(origArtifact);
139 if (!origArtifactNode.hasNode(origJarNodeName))
140 throw new SlcException("Cannot find jar node for "
141 + origArtifactNode);
142 Node origJarNode = origArtifactNode.getNode(origJarNodeName);
143
144 // read MANIFEST
145 Binary manifestBinary = origJarNode.getProperty(SLC_MANIFEST)
146 .getBinary();
147 Manifest origManifest = new Manifest(manifestBinary.getStream());
148 JcrUtils.closeQuietly(manifestBinary);
149
150 Boolean manifestModified = false;
151 Manifest targetManifest = new Manifest(origManifest);
152
153 // transform symbolic name
154 String origSymbolicName = origManifest.getMainAttributes().getValue(
155 Constants.BUNDLE_SYMBOLICNAME);
156 final String targetSymbolicName;
157 if (symbolicNamesMapping.containsKey(origSymbolicName)) {
158 targetSymbolicName = symbolicNamesMapping.get(origSymbolicName);
159 } else if (origSymbolicName.startsWith(SPRING_SOURCE_PREFIX)
160 && !origSymbolicName.equals(SPRING_SOURCE_PREFIX + ".json")) {
161 targetSymbolicName = origSymbolicName
162 .substring(SPRING_SOURCE_PREFIX.length() + 1);
163 } else {
164 targetSymbolicName = origSymbolicName;
165 }
166
167 if (!targetSymbolicName.equals(origSymbolicName)) {
168 targetManifest.getMainAttributes().putValue(
169 Constants.BUNDLE_SYMBOLICNAME, targetSymbolicName);
170 manifestModified = true;
171 if (log.isDebugEnabled())
172 log.debug(Constants.BUNDLE_SYMBOLICNAME + " to "
173 + targetSymbolicName + " \t\tfrom " + origSymbolicName);
174 }
175
176 // skip excluded bundles
177 if (excludedBundles.contains(targetSymbolicName))
178 return;
179
180 // check fragment host
181 if (origManifest.getMainAttributes().containsKey(
182 new Name(Constants.FRAGMENT_HOST))) {
183 String origFragmentHost = origManifest.getMainAttributes()
184 .getValue(Constants.FRAGMENT_HOST);
185 String targetFragmentHost;
186 if (symbolicNamesMapping.containsKey(origFragmentHost)) {
187 targetFragmentHost = symbolicNamesMapping.get(origFragmentHost);
188 } else if (origFragmentHost.startsWith(SPRING_SOURCE_PREFIX)
189 && !origFragmentHost.equals(SPRING_SOURCE_PREFIX + ".json")) {
190 targetFragmentHost = origFragmentHost
191 .substring(SPRING_SOURCE_PREFIX.length() + 1);
192 } else if (origFragmentHost
193 .equals("org.argeo.dep.jacob;bundle-version=\"[1.14.3,1.14.4)\"")) {
194 // this one for those who think I cannot be pragmatic - mbaudier
195 targetFragmentHost = "com.jacob;bundle-version=\"[1.14.3,1.14.4)\"";
196 } else {
197 targetFragmentHost = origFragmentHost;
198 }
199
200 if (!targetFragmentHost.equals(origFragmentHost)) {
201 targetManifest.getMainAttributes().putValue(
202 Constants.FRAGMENT_HOST, targetFragmentHost);
203 manifestModified = true;
204 if (log.isDebugEnabled())
205 log.debug(Constants.FRAGMENT_HOST + " to "
206 + targetFragmentHost + " from " + origFragmentHost);
207 }
208 }
209
210 // we assume there is no Require-Bundle in com.springsource.* bundles
211
212 // javax with versions
213 StringBuffer targetImportPackages = new StringBuffer("");
214 NodeIterator origImportPackages = origJarNode.getNodes(SLC_
215 + Constants.IMPORT_PACKAGE);
216 Boolean importPackagesModified = false;
217 while (origImportPackages.hasNext()) {
218 Node importPackage = origImportPackages.nextNode();
219 String pkg = importPackage.getProperty(SLC_NAME).getString();
220 targetImportPackages.append(pkg);
221 if (importPackage.hasProperty(SLC_VERSION)) {
222 String sourceVersion = importPackage.getProperty(SLC_VERSION)
223 .getString();
224 String targetVersion = sourceVersion;
225 if (systemPackages.contains(pkg)) {
226 if (!(sourceVersion.trim().equals("0") || sourceVersion
227 .trim().equals("0.0.0"))) {
228 targetVersion = null;
229 importPackagesModified = true;
230 if (log.isDebugEnabled())
231 log.debug(origSymbolicName
232 + ": Nullify version of " + pkg + " from "
233 + sourceVersion);
234 }
235 }
236 if (targetVersion != null)
237 targetImportPackages.append(";version=\"")
238 .append(targetVersion).append("\"");
239 }
240 if (importPackage.hasProperty(SLC_OPTIONAL)) {
241 Boolean optional = importPackage.getProperty(SLC_OPTIONAL)
242 .getBoolean();
243 if (optional)
244 targetImportPackages.append(";resolution:=\"optional\"");
245
246 }
247 if (origImportPackages.hasNext())
248 targetImportPackages.append(",");
249 }
250
251 if (importPackagesModified) {
252 targetManifest.getMainAttributes().putValue(
253 Constants.IMPORT_PACKAGE, targetImportPackages.toString());
254 manifestModified = true;
255 }
256
257 if (!manifestModified && log.isTraceEnabled()) {
258 log.trace("MANIFEST of " + origSymbolicName + " was not modified");
259 }
260
261 // target coordinates
262 final String targetGroupId;
263 if (origArtifact.getGroupId().startsWith("org.eclipse")
264 && !origArtifact.getArtifactId().equals("org.eclipse.osgi"))
265 targetGroupId = "org.argeo.tp.eclipse";
266 else
267 targetGroupId = "org.argeo.tp";
268
269 String targetArtifactId = targetSymbolicName.split(";")[0];
270 Artifact targetArtifact = new DefaultArtifact(targetGroupId,
271 targetArtifactId, "jar", origArtifact.getVersion());
272 String targetParentPath = MavenConventionsUtils.artifactParentPath(
273 artifactBasePath, targetArtifact);
274 String targetFileName = MavenConventionsUtils
275 .artifactFileName(targetArtifact);
276 String targetJarPath = targetParentPath + '/' + targetFileName;
277
278 // copy
279 Node targetParentNode = JcrUtils.mkfolders(targetSession,
280 targetParentPath);
281 targetSession.save();
282 if (manifestModified) {
283 Binary origBinary = origJarNode.getNode(Node.JCR_CONTENT)
284 .getProperty(Property.JCR_DATA).getBinary();
285 byte[] targetJarBytes = RepoUtils.modifyManifest(
286 origBinary.getStream(), targetManifest);
287 JcrUtils.copyBytesAsFile(targetParentNode, targetFileName,
288 targetJarBytes);
289 JcrUtils.closeQuietly(origBinary);
290 } else {// just copy
291 targetSession.getWorkspace().copy(sourceWorkspace,
292 origJarNode.getPath(), targetJarPath);
293 }
294 targetSession.save();
295
296 // reindex
297 Node targetJarNode = targetSession.getNode(targetJarPath);
298 artifactIndexer.index(targetJarNode);
299 jarFileIndexer.index(targetJarNode);
300
301 targetSession.save();
302
303 // sources
304 Artifact origSourceArtifact = new DefaultArtifact(
305 origArtifact.getGroupId(), origArtifact.getArtifactId()
306 + ".source", "jar", origArtifact.getVersion());
307 String origSourcePath = MavenConventionsUtils.artifactPath(
308 artifactBasePath, origSourceArtifact);
309 if (origSession.itemExists(origSourcePath)) {
310 Node origSourceJarNode = origSession.getNode(origSourcePath);
311
312 Artifact targetSourceArtifact = new DefaultArtifact(targetGroupId,
313 targetArtifactId + ".source", "jar",
314 origArtifact.getVersion());
315 String targetSourceParentPath = MavenConventionsUtils
316 .artifactParentPath(artifactBasePath, targetSourceArtifact);
317 String targetSourceFileName = MavenConventionsUtils
318 .artifactFileName(targetSourceArtifact);
319 String targetSourceJarPath = targetSourceParentPath + '/'
320 + targetSourceFileName;
321
322 Node targetSourceParentNode = JcrUtils.mkfolders(targetSession,
323 targetSourceParentPath);
324 targetSession.save();
325
326 if (!targetSymbolicName.equals(origSymbolicName)) {
327 Binary origBinary = origSourceJarNode.getNode(Node.JCR_CONTENT)
328 .getProperty(Property.JCR_DATA).getBinary();
329 NameVersion targetNameVersion = RepoUtils
330 .readNameVersion(targetManifest);
331 byte[] targetJarBytes = RepoUtils.packageAsPdeSource(
332 origBinary.getStream(), targetNameVersion);
333 JcrUtils.copyBytesAsFile(targetSourceParentNode,
334 targetSourceFileName, targetJarBytes);
335 JcrUtils.closeQuietly(origBinary);
336 } else {// just copy
337 targetSession.getWorkspace().copy(sourceWorkspace,
338 origSourceJarNode.getPath(), targetSourceJarPath);
339 }
340 targetSession.save();
341
342 // reindex
343 Node targetSourceJarNode = targetSession
344 .getNode(targetSourceJarPath);
345 artifactIndexer.index(targetSourceJarNode);
346 jarFileIndexer.index(targetSourceJarNode);
347
348 targetSession.save();
349 }
350 }
351
352 /*
353 * UTILITIES
354 */
355
356 static NodeIterator listArtifactVersions(Session session)
357 throws RepositoryException {
358 QueryManager queryManager = session.getWorkspace().getQueryManager();
359 QueryObjectModelFactory factory = queryManager.getQOMFactory();
360
361 final String artifactVersionsSelector = "artifactVersions";
362 Selector source = factory.selector(SlcTypes.SLC_ARTIFACT_VERSION_BASE,
363 artifactVersionsSelector);
364
365 Ordering orderByArtifactId = factory.ascending(factory.propertyValue(
366 artifactVersionsSelector, SlcNames.SLC_ARTIFACT_ID));
367 Ordering[] orderings = { orderByArtifactId };
368
369 QueryObjectModel query = factory.createQuery(source, null, orderings,
370 null);
371
372 QueryResult result = query.execute();
373 return result.getNodes();
374 }
375
376 public void setRepository(Repository repository) {
377 this.repository = repository;
378 }
379
380 public void setSourceWorkspace(String sourceWorkspace) {
381 this.sourceWorkspace = sourceWorkspace;
382 }
383
384 public void setTargetWorkspace(String targetWorkspace) {
385 this.targetWorkspace = targetWorkspace;
386 }
387
388 public void setExcludedBundles(List<String> excludedBundles) {
389 this.excludedBundles = excludedBundles;
390 }
391
392 public void setSymbolicNamesMapping(Map<String, String> symbolicNamesMapping) {
393 this.symbolicNamesMapping = symbolicNamesMapping;
394 }
395
396 }