]> git.argeo.org Git - gpl/argeo-slc.git/blob - runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/RepoUtils.java
MIgrate binaries to target workspace
[gpl/argeo-slc.git] / runtime / org.argeo.slc.repo / src / main / java / org / argeo / slc / repo / RepoUtils.java
1 package org.argeo.slc.repo;
2
3 import java.io.ByteArrayOutputStream;
4 import java.io.File;
5 import java.io.FileInputStream;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.OutputStream;
9 import java.util.Enumeration;
10 import java.util.Iterator;
11 import java.util.StringTokenizer;
12 import java.util.jar.Attributes;
13 import java.util.jar.JarEntry;
14 import java.util.jar.JarFile;
15 import java.util.jar.JarInputStream;
16 import java.util.jar.JarOutputStream;
17 import java.util.jar.Manifest;
18
19 import javax.jcr.Node;
20 import javax.jcr.RepositoryException;
21
22 import org.apache.commons.io.FilenameUtils;
23 import org.apache.commons.io.IOUtils;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.argeo.slc.BasicNameVersion;
27 import org.argeo.slc.NameVersion;
28 import org.argeo.slc.SlcException;
29 import org.argeo.slc.jcr.SlcNames;
30 import org.argeo.slc.jcr.SlcTypes;
31 import org.sonatype.aether.artifact.Artifact;
32 import org.sonatype.aether.util.artifact.DefaultArtifact;
33
34 /** Utilities around repo */
35 public class RepoUtils implements SlcNames {
36 private final static Log log = LogFactory.getLog(RepoUtils.class);
37
38 /** Packages a regular sources jar as PDE source. */
39 public static void packagesAsPdeSource(File sourceFile,
40 NameVersion nameVersion, OutputStream out) throws IOException {
41 if (isAlreadyPdeSource(sourceFile)) {
42 FileInputStream in = new FileInputStream(sourceFile);
43 IOUtils.copy(in, out);
44 IOUtils.closeQuietly(in);
45 } else {
46 String sourceSymbolicName = nameVersion.getName() + ".source";
47
48 Manifest sourceManifest = null;
49 sourceManifest = new Manifest();
50 sourceManifest.getMainAttributes().put(
51 Attributes.Name.MANIFEST_VERSION, "1.0");
52 sourceManifest.getMainAttributes().putValue("Bundle-SymbolicName",
53 sourceSymbolicName);
54 sourceManifest.getMainAttributes().putValue("Bundle-Version",
55 nameVersion.getVersion());
56 sourceManifest.getMainAttributes().putValue(
57 "Eclipse-SourceBundle",
58 nameVersion.getName() + ";version="
59 + nameVersion.getVersion());
60 copyJar(sourceFile, out, sourceManifest);
61 }
62 }
63
64 /**
65 * Check whether the file as already been packaged as PDE source, in order
66 * not to mess with Jar signing
67 */
68 private static boolean isAlreadyPdeSource(File sourceFile) {
69 JarInputStream jarInputStream = null;
70
71 try {
72 jarInputStream = new JarInputStream(new FileInputStream(sourceFile));
73
74 Manifest manifest = jarInputStream.getManifest();
75 Iterator<?> it = manifest.getMainAttributes().keySet().iterator();
76 boolean res = false;
77 // containsKey() does not work, iterating...
78 while (it.hasNext())
79 if (it.next().toString().equals("Eclipse-SourceBundle")) {
80 res = true;
81 break;
82 }
83 // boolean res = manifest.getMainAttributes().get(
84 // "Eclipse-SourceBundle") != null;
85 if (res)
86 log.info(sourceFile + " is already a PDE source");
87 return res;
88 } catch (Exception e) {
89 // probably not a jar, skipping
90 if (log.isDebugEnabled())
91 log.debug("Skipping " + sourceFile + " because of "
92 + e.getMessage());
93 return false;
94 } finally {
95 IOUtils.closeQuietly(jarInputStream);
96 }
97 }
98
99 /**
100 * Copy a jar, replacing its manifest with the provided one
101 *
102 * @param manifest
103 * can be null
104 */
105 private static void copyJar(File source, OutputStream out, Manifest manifest)
106 throws IOException {
107 JarFile sourceJar = null;
108 JarOutputStream output = null;
109 try {
110 output = manifest != null ? new JarOutputStream(out, manifest)
111 : new JarOutputStream(out);
112 sourceJar = new JarFile(source);
113
114 entries: for (Enumeration<?> entries = sourceJar.entries(); entries
115 .hasMoreElements();) {
116 JarEntry entry = (JarEntry) entries.nextElement();
117 if (manifest != null
118 && entry.getName().equals("META-INF/MANIFEST.MF"))
119 continue entries;
120
121 InputStream entryStream = sourceJar.getInputStream(entry);
122 JarEntry newEntry = new JarEntry(entry.getName());
123 // newEntry.setMethod(JarEntry.DEFLATED);
124 output.putNextEntry(newEntry);
125 IOUtils.copy(entryStream, output);
126 }
127 } finally {
128 IOUtils.closeQuietly(output);
129 try {
130 if (sourceJar != null)
131 sourceJar.close();
132 } catch (IOException e) {
133 // silent
134 }
135 }
136 }
137
138 /** Copy a jar changing onlythe manifest */
139 public static void copyJar(InputStream in, OutputStream out,
140 Manifest manifest) {
141 JarInputStream jarIn = null;
142 JarOutputStream jarOut = null;
143 try {
144 jarIn = new JarInputStream(in);
145 jarOut = new JarOutputStream(out, manifest);
146 JarEntry jarEntry = null;
147 while ((jarEntry = jarIn.getNextJarEntry()) != null) {
148 jarOut.putNextEntry(jarEntry);
149 IOUtils.copy(jarIn, jarOut);
150 jarIn.closeEntry();
151 jarOut.closeEntry();
152 }
153 } catch (IOException e) {
154 throw new SlcException("Could not copy jar with MANIFEST "
155 + manifest.getMainAttributes(), e);
156 } finally {
157 IOUtils.closeQuietly(jarIn);
158 IOUtils.closeQuietly(jarOut);
159 }
160 }
161
162 /** Reads a jar file, modify its manifest */
163 public static byte[] modifyManifest(InputStream in, Manifest manifest) {
164 ByteArrayOutputStream out = new ByteArrayOutputStream(200 * 1024);
165 try {
166 copyJar(in, out, manifest);
167 return out.toByteArray();
168 } finally {
169 IOUtils.closeQuietly(out);
170 }
171 }
172
173 /** Read the OSGi {@link NameVersion} */
174 public static NameVersion readNameVersion(Artifact artifact) {
175 File artifactFile = artifact.getFile();
176 if (artifact.getExtension().equals("pom")) {
177 // hack to process jars which weirdly appear as POMs
178 File jarFile = new File(artifactFile.getParentFile(),
179 FilenameUtils.getBaseName(artifactFile.getPath()) + ".jar");
180 if (jarFile.exists()) {
181 log.warn("Use " + jarFile + " instead of " + artifactFile
182 + " for " + artifact);
183 artifactFile = jarFile;
184 }
185 }
186 return readNameVersion(artifactFile);
187 }
188
189 /** Read the OSGi {@link NameVersion} */
190 public static NameVersion readNameVersion(File artifactFile) {
191 JarInputStream jarInputStream = null;
192
193 try {
194 BasicNameVersion nameVersion = new BasicNameVersion();
195 jarInputStream = new JarInputStream(new FileInputStream(
196 artifactFile));
197 nameVersion.setName(jarInputStream.getManifest()
198 .getMainAttributes().getValue("Bundle-SymbolicName"));
199
200 // Skip additional specs such as
201 // ; singleton:=true
202 if (nameVersion.getName().indexOf(';') > -1) {
203 nameVersion.setName(new StringTokenizer(nameVersion.getName(),
204 " ;").nextToken());
205 }
206
207 nameVersion.setVersion(jarInputStream.getManifest()
208 .getMainAttributes().getValue("Bundle-Version"));
209
210 return nameVersion;
211 } catch (Exception e) {
212 // probably not a jar, skipping
213 if (log.isDebugEnabled()) {
214 log.debug("Skipping " + artifactFile + " because of " + e);
215 // e.printStackTrace();
216 }
217 } finally {
218 IOUtils.closeQuietly(jarInputStream);
219 }
220 return null;
221 }
222
223 /*
224 * DATA MODEL
225 */
226 /** The artifact described by this node */
227 public static Artifact asArtifact(Node node) throws RepositoryException {
228 if (node.isNodeType(SlcTypes.SLC_ARTIFACT_VERSION_BASE)) {
229 // FIXME update data model to store packaging at this level
230 String extension = "jar";
231 return new DefaultArtifact(node.getProperty(SLC_GROUP_ID)
232 .getString(),
233 node.getProperty(SLC_ARTIFACT_ID).getString(), extension,
234 node.getProperty(SLC_ARTIFACT_VERSION).getString());
235 } else if (node.isNodeType(SlcTypes.SLC_ARTIFACT)) {
236 return new DefaultArtifact(node.getProperty(SLC_GROUP_ID)
237 .getString(),
238 node.getProperty(SLC_ARTIFACT_ID).getString(), node
239 .getProperty(SLC_ARTIFACT_CLASSIFIER).getString(),
240 node.getProperty(SLC_ARTIFACT_EXTENSION).getString(), node
241 .getProperty(SLC_ARTIFACT_VERSION).getString());
242 } else {
243 throw new SlcException("Unsupported node type for " + node);
244 }
245 }
246
247 private RepoUtils() {
248 }
249 }