]> git.argeo.org Git - gpl/argeo-slc.git/blobdiff - runtime/org.argeo.slc.repo/src/main/java/org/argeo/slc/repo/JarFileIndexer.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 / JarFileIndexer.java
index 55019c4d47caa64acee8bd749b871c6347c863e8..b07cade3367474c79e311e723687cc122d5a8821 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 2007-2012 Mathieu Baudier
+ * Copyright (C) 2007-2012 Argeo GmbH
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -17,10 +17,15 @@ package org.argeo.slc.repo;
 
 import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Properties;
 import java.util.jar.Attributes;
 import java.util.jar.Attributes.Name;
+import java.util.jar.JarEntry;
 import java.util.jar.JarInputStream;
 import java.util.jar.Manifest;
 
@@ -47,8 +52,9 @@ import org.osgi.framework.Version;
  * Indexes jar file, currently supports standard J2SE and OSGi metadata (both
  * from MANIFEST)
  */
-public class JarFileIndexer implements NodeIndexer {
+public class JarFileIndexer implements NodeIndexer, SlcNames {
        private final static Log log = LogFactory.getLog(JarFileIndexer.class);
+       private Boolean force = false;
 
        public Boolean support(String path) {
                return FilenameUtils.getExtension(path).equals("jar");
@@ -61,16 +67,19 @@ public class JarFileIndexer implements NodeIndexer {
                ByteArrayInputStream bi = null;
                Binary manifestBinary = null;
                try {
+                       if (!support(fileNode.getPath()))
+                               return;
+
+                       // Already indexed
+                       if (!force && fileNode.isNodeType(SlcTypes.SLC_JAR_FILE))
+                               return;
+
                        if (!fileNode.isNodeType(NodeType.NT_FILE))
                                return;
 
                        Session jcrSession = fileNode.getSession();
                        Node contentNode = fileNode.getNode(Node.JCR_CONTENT);
                        fileBinary = contentNode.getProperty(Property.JCR_DATA).getBinary();
-                       // jar file
-                       // if (!FilenameUtils.isExtension(fileNode.getName(), "jar")) {
-                       // return;
-                       // }
 
                        jarIn = new JarInputStream(fileBinary.getStream());
                        Manifest manifest = jarIn.getManifest();
@@ -78,18 +87,31 @@ public class JarFileIndexer implements NodeIndexer {
                                log.error(fileNode + " has no MANIFEST");
                                return;
                        }
+
                        bo = new ByteArrayOutputStream();
                        manifest.write(bo);
-                       bi = new ByteArrayInputStream(bo.toByteArray());
+                       byte[] newManifest = bo.toByteArray();
+                       if (fileNode.hasProperty(SLC_MANIFEST)) {
+                               byte[] storedManifest = JcrUtils.getBinaryAsBytes(fileNode
+                                               .getProperty(SLC_MANIFEST));
+                               if (Arrays.equals(newManifest, storedManifest)) {
+                                       if (log.isTraceEnabled())
+                                               log.trace("Manifest not changed, doing nothing "
+                                                               + fileNode);
+                                       return;
+                               }
+                       }
+
+                       bi = new ByteArrayInputStream(newManifest);
                        manifestBinary = jcrSession.getValueFactory().createBinary(bi);
 
                        // standard jar file
                        fileNode.addMixin(SlcTypes.SLC_JAR_FILE);
+
                        fileNode.setProperty(SlcNames.SLC_MANIFEST, manifestBinary);
                        Attributes attrs = manifest.getMainAttributes();
-                       if (log.isTraceEnabled())
-                               for (Object key : attrs.keySet())
-                                       log.trace(key + ": " + attrs.getValue(key.toString()));
+
+                       getI18nValues(fileBinary, attrs);
 
                        // standard J2SE MANIFEST attributes
                        addAttr(Attributes.Name.MANIFEST_VERSION, fileNode, attrs);
@@ -108,14 +130,15 @@ public class JarFileIndexer implements NodeIndexer {
                        // OSGi
                        if (attrs.containsKey(new Name(Constants.BUNDLE_SYMBOLICNAME))) {
                                addOsgiMetadata(fileNode, attrs);
-                               JcrUtils.updateLastModified(fileNode);
                                if (log.isTraceEnabled())
                                        log.trace("Indexed OSGi bundle " + fileNode);
                        } else {
-                               JcrUtils.updateLastModified(fileNode);
                                if (log.isTraceEnabled())
                                        log.trace("Indexed JAR file " + fileNode);
                        }
+
+                       JcrUtils.updateLastModified(fileNode);
+
                } catch (Exception e) {
                        throw new SlcException("Cannot index jar " + fileNode, e);
                } finally {
@@ -128,8 +151,95 @@ public class JarFileIndexer implements NodeIndexer {
 
        }
 
+       private void getI18nValues(Binary fileBinary, Attributes attrs)
+                       throws IOException {
+               JarInputStream jarIn = null;
+               try {
+                       jarIn = new JarInputStream(fileBinary.getStream());
+                       String bundleLocalization = null;
+
+                       String blKey = Constants.BUNDLE_LOCALIZATION; // "Bundle-Localization";
+                       Name blkName = new Name(blKey);
+
+                       browse: for (Object obj : attrs.keySet()) {
+                               String value = attrs.getValue((Attributes.Name) obj);
+                               if (value.startsWith("%")) {
+                                       if (attrs.containsKey(blkName)) {
+                                               bundleLocalization = attrs.getValue(blkName);
+                                               break browse;
+                                       }
+                               }
+                       }
+
+                       JarEntry jarEntry = null;
+                       byte[] propBytes = null;
+                       ByteArrayOutputStream baos = null;
+                       browse: if (bundleLocalization != null) {
+                               JarEntry entry = jarIn.getNextJarEntry();
+                               while (entry != null) {
+                                       if (entry.getName().equals(
+                                                       bundleLocalization + ".properties")) {
+                                               jarEntry = entry;
+
+                                               // if(je.getSize() != -1){
+                                               // propBytes = new byte[(int)je.getSize()];
+                                               // int len = (int) je.getSize();
+                                               // int offset = 0;
+                                               // while (offset != len)
+                                               // offset += jarIn.read(propBytes, offset, len -
+                                               // offset);
+                                               // } else {
+                                               baos = new ByteArrayOutputStream();
+                                               while (true) {
+                                                       int qwe = jarIn.read();
+                                                       if (qwe == -1)
+                                                               break;
+                                                       baos.write(qwe);
+                                               }
+                                               propBytes = baos.toByteArray();
+                                               break browse;
+                                       }
+                                       entry = jarIn.getNextJarEntry();
+                               }
+                       }
+
+                       if (jarEntry != null) {
+                               Properties prop = new Properties();
+                               InputStream is = new ByteArrayInputStream(propBytes);
+                               prop.load(is);
+
+                               for (Object obj : attrs.keySet()) {
+                                       String value = attrs.getValue((Attributes.Name) obj);
+                                       if (value.startsWith("%")) {
+                                               String newVal = prop.getProperty(value.substring(1));
+                                               if (newVal != null)
+                                                       attrs.put(obj, newVal);
+                                       }
+                               }
+                       }
+               } catch (RepositoryException e) {
+                       throw new SlcException(
+                                       "Error while reading the jar binary content " + fileBinary,
+                                       e);
+               } catch (IOException ioe) {
+                       throw new SlcException("unable to get internationalized values",
+                                       ioe);
+               } finally {
+                       IOUtils.closeQuietly(jarIn);
+               }
+       }
+
        protected void addOsgiMetadata(Node fileNode, Attributes attrs)
                        throws RepositoryException {
+
+               // TODO remove this ?
+               // Compulsory for the time being, because bundle artifact extends
+               // artifact
+               if (!fileNode.isNodeType(SlcTypes.SLC_ARTIFACT)) {
+                       ArtifactIndexer indexer = new ArtifactIndexer();
+                       indexer.index(fileNode);
+               }
+
                fileNode.addMixin(SlcTypes.SLC_BUNDLE_ARTIFACT);
 
                // symbolic name
@@ -195,7 +305,7 @@ public class JarFileIndexer implements NodeIndexer {
                cleanSubNodes(fileNode, SlcNames.SLC_ + Constants.IMPORT_PACKAGE);
                if (attrs.containsKey(new Name(Constants.IMPORT_PACKAGE))) {
                        String importPackages = attrs.getValue(Constants.IMPORT_PACKAGE);
-                       List<String> packages = parsePackages(importPackages);
+                       List<String> packages = parseCommaSeparated(importPackages);
                        for (String pkg : packages) {
                                String[] tokens = pkg.split(";");
                                Node node = fileNode.addNode(SlcNames.SLC_
@@ -222,7 +332,7 @@ public class JarFileIndexer implements NodeIndexer {
                if (attrs.containsKey(new Name(Constants.DYNAMICIMPORT_PACKAGE))) {
                        String importPackages = attrs
                                        .getValue(Constants.DYNAMICIMPORT_PACKAGE);
-                       List<String> packages = parsePackages(importPackages);
+                       List<String> packages = parseCommaSeparated(importPackages);
                        for (String pkg : packages) {
                                String[] tokens = pkg.split(";");
                                Node node = fileNode.addNode(SlcNames.SLC_
@@ -242,7 +352,7 @@ public class JarFileIndexer implements NodeIndexer {
                cleanSubNodes(fileNode, SlcNames.SLC_ + Constants.EXPORT_PACKAGE);
                if (attrs.containsKey(new Name(Constants.EXPORT_PACKAGE))) {
                        String exportPackages = attrs.getValue(Constants.EXPORT_PACKAGE);
-                       List<String> packages = parsePackages(exportPackages);
+                       List<String> packages = parseCommaSeparated(exportPackages);
                        for (String pkg : packages) {
                                String[] tokens = pkg.split(";");
                                Node node = fileNode.addNode(SlcNames.SLC_
@@ -278,7 +388,7 @@ public class JarFileIndexer implements NodeIndexer {
                cleanSubNodes(fileNode, SlcNames.SLC_ + Constants.REQUIRE_BUNDLE);
                if (attrs.containsKey(new Name(Constants.REQUIRE_BUNDLE))) {
                        String requireBundle = attrs.getValue(Constants.REQUIRE_BUNDLE);
-                       String[] bundles = requireBundle.split(",");
+                       List<String> bundles = parseCommaSeparated(requireBundle);
                        for (String bundle : bundles) {
                                String[] tokens = bundle.split(";");
                                Node node = fileNode.addNode(SlcNames.SLC_
@@ -346,7 +456,7 @@ public class JarFileIndexer implements NodeIndexer {
        }
 
        /** Parse package list with nested directive with ',' */
-       private List<String> parsePackages(String str) {
+       private List<String> parseCommaSeparated(String str) {
                List<String> res = new ArrayList<String>();
                StringBuffer curr = new StringBuffer("");
                boolean in = false;
@@ -381,4 +491,8 @@ public class JarFileIndexer implements NodeIndexer {
                                        version.getQualifier());
        }
 
+       public void setForce(Boolean force) {
+               this.force = force;
+       }
+
 }