]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/osgi/ArchiveWrapper.java
Main free licences
[gpl/argeo-slc.git] / runtime / org.argeo.slc.repo / src / main / java / org / argeo / slc / repo / osgi / ArchiveWrapper.java
1 package org.argeo.slc.repo.osgi;
2
3 import java.io.ByteArrayInputStream;
4 import java.io.ByteArrayOutputStream;
5 import java.util.ArrayList;
6 import java.util.HashMap;
7 import java.util.Iterator;
8 import java.util.List;
9 import java.util.Map;
10 import java.util.Set;
11 import java.util.TreeSet;
12 import java.util.zip.ZipEntry;
13 import java.util.zip.ZipInputStream;
14
15 import javax.jcr.Node;
16 import javax.jcr.Property;
17 import javax.jcr.RepositoryException;
18 import javax.jcr.Session;
19
20 import org.apache.commons.io.FilenameUtils;
21 import org.apache.commons.io.IOUtils;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.argeo.jcr.JcrUtils;
25 import org.argeo.slc.DefaultNameVersion;
26 import org.argeo.slc.ModuleSet;
27 import org.argeo.slc.NameVersion;
28 import org.argeo.slc.SlcException;
29 import org.argeo.slc.aether.ArtifactIdComparator;
30 import org.argeo.slc.build.Distribution;
31 import org.argeo.slc.build.License;
32 import org.argeo.slc.repo.OsgiFactory;
33 import org.argeo.slc.repo.RepoUtils;
34 import org.sonatype.aether.artifact.Artifact;
35 import org.sonatype.aether.util.artifact.DefaultArtifact;
36 import org.springframework.util.AntPathMatcher;
37 import org.springframework.util.PathMatcher;
38
39 /**
40 * Download a software distribution and generates the related OSGi bundles from
41 * the jars, or import them directly if they are already OSGi bundles and don't
42 * need further modification.
43 */
44 public class ArchiveWrapper implements Runnable, ModuleSet, Distribution {
45 private final static Log log = LogFactory.getLog(ArchiveWrapper.class);
46
47 private OsgiFactory osgiFactory;
48 private String version;
49 private License license;
50
51 private String uri;
52
53 /** Jars to wrap as OSGi bundles */
54 private Map<String, BndWrapper> wrappers = new HashMap<String, BndWrapper>();
55
56 // pattern of OSGi bundles to import
57 private PathMatcher pathMatcher = new AntPathMatcher();
58 private Map<String, String> includes = new HashMap<String, String>();
59 private List<String> excludes = new ArrayList<String>();
60
61 private Boolean mavenGroupIndexes = false;
62
63 public void init() {
64 for (BndWrapper wrapper : wrappers.values()) {
65 wrapper.setFactory(this);
66 if (version != null && wrapper.getVersion() == null)
67 wrapper.setVersion(version);
68 if (license != null && wrapper.getLicense() == null)
69 wrapper.setLicense(license);
70 }
71 }
72
73 public void destroy() {
74
75 }
76
77 public String getDistributionId() {
78 return uri;
79 }
80
81 public Iterator<? extends NameVersion> nameVersions() {
82 return wrappers.values().iterator();
83 }
84
85 public void run() {
86 if (mavenGroupIndexes && (version == null))
87 throw new SlcException(
88 "'mavenGroupIndexes' requires 'version' to be set");
89
90 Map<String, Set<Artifact>> binaries = new HashMap<String, Set<Artifact>>();
91 Map<String, Set<Artifact>> sources = new HashMap<String, Set<Artifact>>();
92
93 Session distSession = null;
94 Session javaSession = null;
95 ZipInputStream zin = null;
96 try {
97 javaSession = osgiFactory.openJavaSession();
98 distSession = osgiFactory.openDistSession();
99
100 if (log.isDebugEnabled())
101 log.debug("Wrapping " + uri);
102
103 Node distNode = osgiFactory.getDist(distSession, uri);
104 zin = new ZipInputStream(distNode.getNode(Node.JCR_CONTENT)
105 .getProperty(Property.JCR_DATA).getBinary().getStream());
106
107 ZipEntry zentry = null;
108 entries: while ((zentry = zin.getNextEntry()) != null) {
109 String name = zentry.getName();
110
111 // sources autodetect
112 String baseName = FilenameUtils.getBaseName(name);
113 if (baseName.endsWith("-sources")) {
114 String bundle = baseName.substring(0, baseName.length()
115 - "-sources".length());
116 log.debug(name + "," + baseName + ", " + bundle);
117 String bundlePath = FilenameUtils.getPath(name) + bundle
118 + ".jar";
119 if (wrappers.containsKey(bundlePath)) {
120 BndWrapper wrapper = wrappers.get(bundlePath);
121 NameVersion bundleNv = new DefaultNameVersion(
122 wrapper.getName(), wrapper.getVersion());
123 byte[] pdeSource = RepoUtils.packageAsPdeSource(zin,
124 bundleNv);
125 Node pdeSourceNode = RepoUtils.copyBytesAsArtifact(
126 javaSession.getRootNode(),
127 new DefaultArtifact(wrapper.getCategory(),
128 wrapper.getName() + ".source", "jar",
129 wrapper.getVersion()), pdeSource);
130 osgiFactory.indexNode(pdeSourceNode);
131 }
132 } else if (baseName.endsWith(".source")) {
133 // TODO Eclipse source already available
134 }
135
136 // binaries
137 if (wrappers.containsKey(name)) {
138 BndWrapper wrapper = (BndWrapper) wrappers.get(name);
139 // we must copy since the stream is closed by BND
140 byte[] sourceJarBytes = IOUtils.toByteArray(zin);
141 Artifact artifact = wrapZipEntry(javaSession, zentry,
142 sourceJarBytes, wrapper);
143 addArtifactToIndex(binaries, wrapper.getGroupId(), artifact);
144 } else {
145 for (String wrapperKey : wrappers.keySet())
146 if (pathMatcher.match(wrapperKey, name)) {
147 // first matched is taken
148 BndWrapper wrapper = (BndWrapper) wrappers
149 .get(wrapperKey);
150 // we must copy since the stream is closed by BND
151 byte[] sourceJarBytes = IOUtils.toByteArray(zin);
152 Artifact artifact = wrapZipEntry(javaSession,
153 zentry, sourceJarBytes, wrapper);
154 addArtifactToIndex(binaries, wrapper.getGroupId(),
155 artifact);
156 continue entries;
157 } else {
158 if (log.isTraceEnabled())
159 log.trace(name + " not matched by "
160 + wrapperKey);
161 }
162
163 for (String exclude : excludes)
164 if (pathMatcher.match(exclude, name))
165 continue entries;
166
167 for (String include : includes.keySet()) {
168 if (pathMatcher.match(include, name)) {
169 String groupId = includes.get(include);
170 byte[] sourceJarBytes = IOUtils.toByteArray(zin);
171 Artifact artifact = importZipEntry(javaSession,
172 zentry, sourceJarBytes, groupId);
173 if (artifact.getArtifactId().endsWith(".source"))
174 addArtifactToIndex(sources, groupId, artifact);
175 else
176 addArtifactToIndex(binaries, groupId, artifact);
177 }
178 }
179 }
180 }
181
182 // indexes
183 if (mavenGroupIndexes && version != null) {
184 for (String groupId : binaries.keySet()) {
185 RepoUtils.writeGroupIndexes(javaSession, "/", groupId,
186 version, binaries.get(groupId),
187 sources.containsKey(groupId) ? sources.get(groupId)
188 : null);
189 }
190 }
191
192 } catch (Exception e) {
193 throw new SlcException("Cannot wrap distribution " + uri, e);
194 } finally {
195 IOUtils.closeQuietly(zin);
196 JcrUtils.logoutQuietly(distSession);
197 JcrUtils.logoutQuietly(javaSession);
198 }
199 }
200
201 protected Artifact wrapZipEntry(Session javaSession, ZipEntry zentry,
202 byte[] sourceJarBytes, BndWrapper wrapper)
203 throws RepositoryException {
204 ByteArrayOutputStream out = null;
205 ByteArrayInputStream in = null;
206 Node newJarNode;
207 try {
208 out = new ByteArrayOutputStream((int) zentry.getSize());
209 in = new ByteArrayInputStream(sourceJarBytes);
210 wrapper.wrapJar(in, out);
211
212 Artifact artifact = wrapper.getArtifact();
213 newJarNode = RepoUtils.copyBytesAsArtifact(
214 javaSession.getRootNode(), artifact, out.toByteArray());
215 osgiFactory.indexNode(newJarNode);
216 newJarNode.getSession().save();
217 if (log.isDebugEnabled())
218 log.debug("Wrapped jar " + zentry.getName() + " to "
219 + newJarNode.getPath());
220 return artifact;
221 } finally {
222 IOUtils.closeQuietly(in);
223 IOUtils.closeQuietly(out);
224 }
225 }
226
227 protected Artifact importZipEntry(Session javaSession, ZipEntry zentry,
228 byte[] sourceJarBytes, String groupId) throws RepositoryException {
229 ByteArrayInputStream in = null;
230 Node newJarNode;
231 try {
232 in = new ByteArrayInputStream(sourceJarBytes);
233 NameVersion nameVersion = RepoUtils.readNameVersion(in);
234 Artifact artifact = new DefaultArtifact(groupId,
235 nameVersion.getName(), "jar", nameVersion.getVersion());
236 newJarNode = RepoUtils.copyBytesAsArtifact(
237 javaSession.getRootNode(), artifact, sourceJarBytes);
238 osgiFactory.indexNode(newJarNode);
239 newJarNode.getSession().save();
240 if (log.isDebugEnabled())
241 log.debug("Imported OSGi bundle " + zentry.getName() + " to "
242 + newJarNode.getPath());
243 return artifact;
244 } finally {
245 IOUtils.closeQuietly(in);
246 }
247 }
248
249 private void addArtifactToIndex(Map<String, Set<Artifact>> index,
250 String groupId, Artifact artifact) {
251 if (!index.containsKey(groupId))
252 index.put(groupId,
253 new TreeSet<Artifact>(new ArtifactIdComparator()));
254 index.get(groupId).add(artifact);
255 }
256
257 public void setUri(String uri) {
258 this.uri = uri;
259 }
260
261 public void setWrappers(Map<String, BndWrapper> wrappers) {
262 this.wrappers = wrappers;
263 }
264
265 public void setOsgiFactory(OsgiFactory osgiFactory) {
266 this.osgiFactory = osgiFactory;
267 }
268
269 public void setVersion(String version) {
270 this.version = version;
271 }
272
273 public void setLicense(License license) {
274 this.license = license;
275 }
276
277 public void setPathMatcher(PathMatcher pathMatcher) {
278 this.pathMatcher = pathMatcher;
279 }
280
281 public void setIncludes(Map<String, String> includes) {
282 this.includes = includes;
283 }
284
285 public void setExcludes(List<String> excludes) {
286 this.excludes = excludes;
287 }
288
289 public void setMavenGroupIndexes(Boolean mavenGroupIndexes) {
290 this.mavenGroupIndexes = mavenGroupIndexes;
291 }
292
293 }