1 package org
.argeo
.slc
.repo
;
3 import java
.io
.ByteArrayOutputStream
;
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
;
19 import javax
.jcr
.Node
;
20 import javax
.jcr
.RepositoryException
;
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
.jcr
.JcrUtils
;
27 import org
.argeo
.slc
.BasicNameVersion
;
28 import org
.argeo
.slc
.NameVersion
;
29 import org
.argeo
.slc
.SlcException
;
30 import org
.argeo
.slc
.jcr
.SlcNames
;
31 import org
.argeo
.slc
.jcr
.SlcTypes
;
32 import org
.argeo
.slc
.repo
.maven
.MavenConventionsUtils
;
33 import org
.osgi
.framework
.Constants
;
34 import org
.sonatype
.aether
.artifact
.Artifact
;
35 import org
.sonatype
.aether
.util
.artifact
.DefaultArtifact
;
37 /** Utilities around repo */
38 public class RepoUtils
implements SlcNames
{
39 private final static Log log
= LogFactory
.getLog(RepoUtils
.class);
41 /** Packages a regular sources jar as PDE source. */
42 public static void packagesAsPdeSource(File sourceFile
,
43 NameVersion nameVersion
, OutputStream out
) throws IOException
{
44 if (isAlreadyPdeSource(sourceFile
)) {
45 FileInputStream in
= new FileInputStream(sourceFile
);
46 IOUtils
.copy(in
, out
);
47 IOUtils
.closeQuietly(in
);
49 String sourceSymbolicName
= nameVersion
.getName() + ".source";
51 Manifest sourceManifest
= null;
52 sourceManifest
= new Manifest();
53 sourceManifest
.getMainAttributes().put(
54 Attributes
.Name
.MANIFEST_VERSION
, "1.0");
55 sourceManifest
.getMainAttributes().putValue("Bundle-SymbolicName",
57 sourceManifest
.getMainAttributes().putValue("Bundle-Version",
58 nameVersion
.getVersion());
59 sourceManifest
.getMainAttributes().putValue(
60 "Eclipse-SourceBundle",
61 nameVersion
.getName() + ";version="
62 + nameVersion
.getVersion());
63 copyJar(sourceFile
, out
, sourceManifest
);
67 public static byte[] packageAsPdeSource(InputStream sourceJar
,
68 NameVersion nameVersion
) {
69 String sourceSymbolicName
= nameVersion
.getName() + ".source";
71 Manifest sourceManifest
= null;
72 sourceManifest
= new Manifest();
73 sourceManifest
.getMainAttributes().put(
74 Attributes
.Name
.MANIFEST_VERSION
, "1.0");
75 sourceManifest
.getMainAttributes().putValue("Bundle-SymbolicName",
77 sourceManifest
.getMainAttributes().putValue("Bundle-Version",
78 nameVersion
.getVersion());
79 sourceManifest
.getMainAttributes().putValue("Eclipse-SourceBundle",
80 nameVersion
.getName() + ";version=" + nameVersion
.getVersion());
82 return modifyManifest(sourceJar
, sourceManifest
);
86 * Check whether the file as already been packaged as PDE source, in order
87 * not to mess with Jar signing
89 private static boolean isAlreadyPdeSource(File sourceFile
) {
90 JarInputStream jarInputStream
= null;
93 jarInputStream
= new JarInputStream(new FileInputStream(sourceFile
));
95 Manifest manifest
= jarInputStream
.getManifest();
96 Iterator
<?
> it
= manifest
.getMainAttributes().keySet().iterator();
98 // containsKey() does not work, iterating...
100 if (it
.next().toString().equals("Eclipse-SourceBundle")) {
104 // boolean res = manifest.getMainAttributes().get(
105 // "Eclipse-SourceBundle") != null;
107 log
.info(sourceFile
+ " is already a PDE source");
109 } catch (Exception e
) {
110 // probably not a jar, skipping
111 if (log
.isDebugEnabled())
112 log
.debug("Skipping " + sourceFile
+ " because of "
116 IOUtils
.closeQuietly(jarInputStream
);
121 * Copy a jar, replacing its manifest with the provided one
126 private static void copyJar(File source
, OutputStream out
, Manifest manifest
)
128 JarFile sourceJar
= null;
129 JarOutputStream output
= null;
131 output
= manifest
!= null ?
new JarOutputStream(out
, manifest
)
132 : new JarOutputStream(out
);
133 sourceJar
= new JarFile(source
);
135 entries
: for (Enumeration
<?
> entries
= sourceJar
.entries(); entries
136 .hasMoreElements();) {
137 JarEntry entry
= (JarEntry
) entries
.nextElement();
139 && entry
.getName().equals("META-INF/MANIFEST.MF"))
142 InputStream entryStream
= sourceJar
.getInputStream(entry
);
143 JarEntry newEntry
= new JarEntry(entry
.getName());
144 // newEntry.setMethod(JarEntry.DEFLATED);
145 output
.putNextEntry(newEntry
);
146 IOUtils
.copy(entryStream
, output
);
149 IOUtils
.closeQuietly(output
);
151 if (sourceJar
!= null)
153 } catch (IOException e
) {
159 /** Copy a jar changing onlythe manifest */
160 public static void copyJar(InputStream in
, OutputStream out
,
162 JarInputStream jarIn
= null;
163 JarOutputStream jarOut
= null;
165 jarIn
= new JarInputStream(in
);
166 jarOut
= new JarOutputStream(out
, manifest
);
167 JarEntry jarEntry
= null;
168 while ((jarEntry
= jarIn
.getNextJarEntry()) != null) {
169 jarOut
.putNextEntry(jarEntry
);
170 IOUtils
.copy(jarIn
, jarOut
);
174 } catch (IOException e
) {
175 throw new SlcException("Could not copy jar with MANIFEST "
176 + manifest
.getMainAttributes(), e
);
178 IOUtils
.closeQuietly(jarIn
);
179 IOUtils
.closeQuietly(jarOut
);
183 /** Reads a jar file, modify its manifest */
184 public static byte[] modifyManifest(InputStream in
, Manifest manifest
) {
185 ByteArrayOutputStream out
= new ByteArrayOutputStream(200 * 1024);
187 copyJar(in
, out
, manifest
);
188 return out
.toByteArray();
190 IOUtils
.closeQuietly(out
);
194 /** Read the OSGi {@link NameVersion} */
195 public static NameVersion
readNameVersion(Artifact artifact
) {
196 File artifactFile
= artifact
.getFile();
197 if (artifact
.getExtension().equals("pom")) {
198 // hack to process jars which weirdly appear as POMs
199 File jarFile
= new File(artifactFile
.getParentFile(),
200 FilenameUtils
.getBaseName(artifactFile
.getPath()) + ".jar");
201 if (jarFile
.exists()) {
202 log
.warn("Use " + jarFile
+ " instead of " + artifactFile
203 + " for " + artifact
);
204 artifactFile
= jarFile
;
207 return readNameVersion(artifactFile
);
210 /** Read the OSGi {@link NameVersion} */
211 public static NameVersion
readNameVersion(File artifactFile
) {
212 JarInputStream jarInputStream
= null;
214 jarInputStream
= new JarInputStream(new FileInputStream(
216 return readNameVersion(jarInputStream
.getManifest());
217 } catch (Exception e
) {
218 // probably not a jar, skipping
219 if (log
.isDebugEnabled()) {
220 log
.debug("Skipping " + artifactFile
+ " because of " + e
);
221 // e.printStackTrace();
224 IOUtils
.closeQuietly(jarInputStream
);
229 /** Read the OSGi {@link NameVersion} */
230 public static NameVersion
readNameVersion(Manifest manifest
) {
231 BasicNameVersion nameVersion
= new BasicNameVersion();
232 nameVersion
.setName(manifest
.getMainAttributes().getValue(
233 Constants
.BUNDLE_SYMBOLICNAME
));
235 // Skip additional specs such as
237 if (nameVersion
.getName().indexOf(';') > -1) {
239 .setName(new StringTokenizer(nameVersion
.getName(), " ;")
243 nameVersion
.setVersion(manifest
.getMainAttributes().getValue(
244 Constants
.BUNDLE_VERSION
));
252 /** The artifact described by this node */
253 public static Artifact
asArtifact(Node node
) throws RepositoryException
{
254 if (node
.isNodeType(SlcTypes
.SLC_ARTIFACT_VERSION_BASE
)) {
255 // FIXME update data model to store packaging at this level
256 String extension
= "jar";
257 return new DefaultArtifact(node
.getProperty(SLC_GROUP_ID
)
259 node
.getProperty(SLC_ARTIFACT_ID
).getString(), extension
,
260 node
.getProperty(SLC_ARTIFACT_VERSION
).getString());
261 } else if (node
.isNodeType(SlcTypes
.SLC_ARTIFACT
)) {
262 return new DefaultArtifact(node
.getProperty(SLC_GROUP_ID
)
264 node
.getProperty(SLC_ARTIFACT_ID
).getString(), node
265 .getProperty(SLC_ARTIFACT_CLASSIFIER
).getString(),
266 node
.getProperty(SLC_ARTIFACT_EXTENSION
).getString(), node
267 .getProperty(SLC_ARTIFACT_VERSION
).getString());
269 throw new SlcException("Unsupported node type for " + node
);
274 * Copy this bytes array as an artifact, relative to the root of the
275 * repository (typically the workspace root node)
277 public static Node
copyBytesAsArtifact(Node artifactsBase
,
278 Artifact artifact
, byte[] bytes
) throws RepositoryException
{
279 String parentPath
= MavenConventionsUtils
.artifactParentPath(
280 artifactsBase
.getPath(), artifact
);
281 Node folderNode
= JcrUtils
.mkfolders(artifactsBase
.getSession(),
283 return JcrUtils
.copyBytesAsFile(folderNode
,
284 MavenConventionsUtils
.artifactFileName(artifact
), bytes
);
287 private RepoUtils() {