You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@servicemix.apache.org by gn...@apache.org on 2009/02/18 18:04:03 UTC

svn commit: r745573 - in /servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler: Connection.java Parser.java Transformer.java URLHandler.java

Author: gnodet
Date: Wed Feb 18 17:04:03 2009
New Revision: 745573

URL: http://svn.apache.org/viewvc?rev=745573&view=rev
Log:
SMX4NMR-95: Allow the customization of the OSGi manifest when transforming a JBI artifact to an OSGi bundle

Added:
    servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Parser.java
Modified:
    servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Connection.java
    servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Transformer.java
    servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/URLHandler.java

Modified: servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Connection.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Connection.java?rev=745573&r1=745572&r2=745573&view=diff
==============================================================================
--- servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Connection.java (original)
+++ servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Connection.java Wed Feb 18 17:04:03 2009
@@ -24,6 +24,7 @@
 import java.io.InputStream;
 import java.net.URL;
 import java.net.URLConnection;
+import java.net.MalformedURLException;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
@@ -37,11 +38,11 @@
 
     private static Log logger = LogFactory.getLog(Connection.class);
 
-    private URLHandler urlHandler;
+    private final Parser parser;
 
-    public Connection(URL url, URLHandler urlHandler) {
+    public Connection(URL url) throws MalformedURLException {
         super(url);
-        this.urlHandler = urlHandler;
+        this.parser = new Parser(url.getPath());
     }
 
 
@@ -61,7 +62,7 @@
     @Override
     public InputStream getInputStream() throws IOException {
         try {
-            InputStream targetInputStream = urlHandler.getJbiArtifactURL().openConnection().getInputStream();
+            InputStream targetInputStream = parser.getJbiJarURL().openConnection().getInputStream();
             File jbiZipFile = File.createTempFile("jbi", ".zip");
             FileOutputStream jbiZip = new FileOutputStream(jbiZipFile);
 
@@ -70,7 +71,7 @@
             targetInputStream.close();
 
             File jbiBundle = File.createTempFile("jbi", ".jar");
-            Transformer.transformToOSGiBundle(jbiZipFile, jbiBundle);
+            Transformer.transformToOSGiBundle(jbiZipFile, jbiBundle, parser.getJbiProperties());
             return new FileInputStream(jbiBundle);
         } catch (Exception e) {
             logger.error("Error opening jbi protocol artifact", e);

Added: servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Parser.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Parser.java?rev=745573&view=auto
==============================================================================
--- servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Parser.java (added)
+++ servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Parser.java Wed Feb 18 17:04:03 2009
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.servicemix.jbi.deployer.handler;
+
+import java.util.regex.Pattern;
+import java.util.regex.Matcher;
+import java.util.Properties;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Parser for jbi: protocol URL.
+ */
+public class Parser {
+
+    /**
+     * Syntax for the url; to be shown on exception messages.
+     */
+    private static final String SYNTAX = "jbi:jbi-jar-uri[,jbi-instr-uri][$jbi-instructions]";
+    /**
+     * Separator between wrapped jar url and instructions.
+     */
+    private static final String INSTRUCTIONS_SEPARATOR = "$";
+    /**
+     * Separator between wrapped jar url and instructions file url.
+     */
+    private static final String INSTRUCTIONS_FILE_SEPARATOR = ",";
+    /**
+     * Regex pattern for matching jar, wrapping file and instructions.
+     */
+    private static final Pattern SYNTAX_JAR_BND_INSTR =
+            Pattern.compile("(.+?)" + INSTRUCTIONS_FILE_SEPARATOR + "(.+?)\\" + INSTRUCTIONS_SEPARATOR + "(.+?)");
+    /**
+     * Regex pattern for matching jar and instructions.
+     */
+    private static final Pattern SYNTAX_JAR_INSTR =
+            Pattern.compile("(.+?)\\" + INSTRUCTIONS_SEPARATOR + "(.+?)");
+    /**
+     * Regex pattern for matching jar and wrapping file.
+     */
+    private static final Pattern SYNTAX_JAR_BND =
+            Pattern.compile("(.+?)" + INSTRUCTIONS_FILE_SEPARATOR + "(.+?)");
+
+    /**
+     * Regex pattern for matching instructions when specified in url.
+     */
+    private static final Pattern INSTRUCTIONS_PATTERN =
+        Pattern.compile( "([a-zA-Z_0-9-]+)=([-!\"'()*+,.0-9A-Z_a-z%;=]+)" );
+
+    /**
+     * JBI jar URL.
+     */
+    private URL jbiJarURL;
+    /**
+     * JBI instructions URL.
+     */
+    private Properties jbiProperties;
+
+    /**
+     * Creates a new protocol parser.
+     *
+     * @param path the path part of the url (without starting jbi:)
+     * @throws MalformedURLException if provided path does not comply to expected syntax or has malformed urls
+     */
+    public Parser(final String path) throws MalformedURLException {
+        if (path == null || path.trim().length() == 0) {
+            throw new MalformedURLException("Path cannot be null or empty. Syntax " + SYNTAX);
+        }
+        if (path.startsWith(INSTRUCTIONS_SEPARATOR) || path.endsWith(INSTRUCTIONS_SEPARATOR)) {
+            throw new MalformedURLException(
+                    "Path cannot start or end with " + INSTRUCTIONS_SEPARATOR + ". Syntax " + SYNTAX
+            );
+        }
+        jbiProperties = new Properties();
+        Matcher matcher = SYNTAX_JAR_BND_INSTR.matcher(path);
+        if (matcher.matches()) {
+            // we have all the parts
+            jbiJarURL = new URL(matcher.group(1));
+            parseInstructionsFile(new URL(matcher.group(2)));
+            jbiProperties.putAll(parseInstructions(matcher.group(3)));
+        } else if ((matcher = SYNTAX_JAR_INSTR.matcher(path)).matches()) {
+            // we have a wrapped jar and instructions
+            jbiJarURL = new URL(matcher.group(1));
+            jbiProperties.putAll(parseInstructions(matcher.group(2)));
+        } else if ((matcher = SYNTAX_JAR_BND.matcher(path)).matches()) {
+            // we have a wraped jar and a wrapping instructions file
+            jbiJarURL = new URL(matcher.group(1));
+            parseInstructionsFile(new URL(matcher.group(2)));
+        } else {
+            //we have only a wrapped jar
+            jbiJarURL = new URL(path);
+        }
+    }
+
+    /**
+     * Loeads the propertis out of an url.
+     *
+     * @param bndFileURL url of the file containing the instructions
+     * @throws MalformedURLException if the file could not be read
+     */
+    private void parseInstructionsFile(final URL bndFileURL) throws MalformedURLException {
+        try {
+            InputStream is = null;
+            try {
+                is = bndFileURL.openStream();
+                jbiProperties.load(is);
+            }
+            finally {
+                if (is != null) {
+                    is.close();
+                }
+            }
+        }
+        catch (IOException e) {
+            throwAsMalformedURLException("Could not retrieve the instructions from [" + bndFileURL + "]", e);
+        }
+    }
+
+    /**
+     * Returns the JBI URL if present, null otherwise
+     *
+     * @return wraped jar URL
+     */
+    public URL getJbiJarURL() {
+        return jbiJarURL;
+    }
+
+    /**
+     * Returns the JBI instructions as Properties.
+     *
+     * @return wrapping instructions as Properties
+     */
+    public Properties getJbiProperties() {
+        return jbiProperties;
+    }
+
+    /**
+     * Parses bnd instructions out of an url query string.
+     *
+     * @param query query part of an url.
+     *
+     * @return parsed instructions as properties
+     *
+     * @throws java.net.MalformedURLException if provided path does not comply to syntax.
+     */
+    public static Properties parseInstructions( final String query )
+        throws MalformedURLException
+    {
+        final Properties instructions = new Properties();
+        if( query != null )
+        {
+            try
+            {
+                // just ignore for the moment and try out if we have valid properties separated by "&"
+                final String segments[] = query.split( "&" );
+                for( String segment : segments )
+                {
+                    // do not parse empty strings
+                    if( segment.trim().length() > 0 )
+                    {
+                        final Matcher matcher = INSTRUCTIONS_PATTERN.matcher( segment );
+                        if( matcher.matches() )
+                        {
+                            instructions.setProperty(
+                                matcher.group( 1 ),
+                                URLDecoder.decode( matcher.group( 2 ), "UTF-8" )
+                            );
+                        }
+                        else
+                        {
+                            throw new MalformedURLException( "Invalid syntax for instruction [" + segment
+                                                             + "]. Take a look at http://www.aqute.biz/Code/Bnd."
+                            );
+                        }
+                    }
+                }
+            }
+            catch( UnsupportedEncodingException e )
+            {
+                // thrown by URLDecoder but it should never happen
+                throwAsMalformedURLException( "Could not retrieve the instructions from [" + query + "]", e );
+            }
+        }
+        return instructions;
+    }
+
+    /**
+     * Creates an MalformedURLException with a message and a cause.
+     *
+     * @param message exception message
+     * @param cause   exception cause
+     * @throws MalformedURLException the created MalformedURLException
+     */
+    private static void throwAsMalformedURLException(final String message, final Exception cause)
+                        throws MalformedURLException {
+        final MalformedURLException exception = new MalformedURLException(message);
+        exception.initCause(cause);
+        throw exception;
+    }
+
+}

Modified: servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Transformer.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Transformer.java?rev=745573&r1=745572&r2=745573&view=diff
==============================================================================
--- servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Transformer.java (original)
+++ servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/Transformer.java Wed Feb 18 17:04:03 2009
@@ -27,6 +27,8 @@
 import java.util.jar.JarInputStream;
 import java.util.jar.JarOutputStream;
 import java.util.jar.Manifest;
+import java.util.Properties;
+import java.util.Enumeration;
 
 import org.apache.servicemix.jbi.deployer.descriptor.Descriptor;
 import org.apache.servicemix.jbi.deployer.descriptor.DescriptorFactory;
@@ -57,6 +59,23 @@
      * @throws Exception if an error occurs during the transformation process.
      */
     public static void transformToOSGiBundle(File jbiArtifact, File osgiBundle) throws Exception {
+        transformToOSGiBundle(jbiArtifact, osgiBundle, null);
+    }
+
+    /**
+     * Create an OSGi bundle from the JBI artifact.
+     * The process creates the following OSGi manifest entries:
+     * <ul>
+     * <li><b><code>Bundle-SymbolicName</code></b>: the name of the JBI artifact</li>
+     * <li><b><code>Bundle-Version</code></b>: retrieved from the <code>Implementation-Version</code> manifest entry</li>
+     * <li><b><code>DynamicImport-Package</code></b>: javax.*,org.xml.*,org.w3c.*</li>
+     * </ul>
+     *
+     * @param jbiArtifact the input JBI artifact.
+     * @param osgiBundle  the output OSGi bundle.
+     * @throws Exception if an error occurs during the transformation process.
+     */
+    public static void transformToOSGiBundle(File jbiArtifact, File osgiBundle, Properties properties) throws Exception {
         JarFile jar = new JarFile(jbiArtifact);
         Manifest m = jar.getManifest();
         if (m == null) {
@@ -87,6 +106,15 @@
         m.getMainAttributes().putValue("Bundle-Version", version);
         m.getMainAttributes().putValue("DynamicImport-Package", "javax.*,org.xml.*,org.w3c.*");
 
+        if (properties != null) {
+            Enumeration en = properties.propertyNames();
+            while (en.hasMoreElements()) {
+                String k = (String) en.nextElement();
+                String v = properties.getProperty(k);
+                m.getMainAttributes().putValue(k, v);
+            }
+        }
+
         osgiBundle.getParentFile().mkdirs();
         JarInputStream jis = new JarInputStream(new BufferedInputStream(new FileInputStream(jbiArtifact)));
         JarOutputStream jos = new JarOutputStream(new BufferedOutputStream(new FileOutputStream(osgiBundle)), m);

Modified: servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/URLHandler.java
URL: http://svn.apache.org/viewvc/servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/URLHandler.java?rev=745573&r1=745572&r2=745573&view=diff
==============================================================================
--- servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/URLHandler.java (original)
+++ servicemix/smx4/nmr/trunk/jbi/deployer/src/main/java/org/apache/servicemix/jbi/deployer/handler/URLHandler.java Wed Feb 18 17:04:03 2009
@@ -32,12 +32,6 @@
  */
 public class URLHandler extends AbstractURLStreamHandlerService {
 
-    private static Log logger = LogFactory.getLog(URLHandler.class);
-
-    private static String SYNTAX = "jbi: jbi-jar-uri";
-
-    private URL jbiArtifactURL;
-
     /**
      * Open the connection for the given URL.
      *
@@ -47,17 +41,7 @@
      */
     @Override
     public URLConnection openConnection(URL url) throws IOException {
-        if (url.getPath() == null || url.getPath().trim().length() == 0) {
-            throw new MalformedURLException("Path can not be null or empty. Syntax: " + SYNTAX);
-        }
-        jbiArtifactURL = new URL(url.getPath());
-
-        logger.debug("JBI artifact URL is: [" + jbiArtifactURL + "]");
-        return new Connection(url, this);
-    }
-
-    public URL getJbiArtifactURL() {
-        return jbiArtifactURL;
+        return new Connection(url);
     }
 
 }