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