[SMX4-1447]can't endorse activation smx activation-api-1.1 spec jar

git-svn-id: https://svn.apache.org/repos/asf/servicemix/smx4/specs/trunk@1470826 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/activator/pom.xml b/activator/pom.xml
index 19db0fe..96f2b66 100644
--- a/activator/pom.xml
+++ b/activator/pom.xml
@@ -36,7 +36,7 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.servicemix.specs</groupId>
-            <artifactId>org.apache.servicemix.specs.locator</artifactId>
+            <artifactId>org.apache.servicemix.specs.activation-api-1.1</artifactId>
             <version>${project.version}</version>
         </dependency>
         <dependency>
@@ -45,6 +45,11 @@
             <version>4.8</version>
             <scope>test</scope>
         </dependency>
+        <dependency>
+            <groupId>org.apache.geronimo.specs</groupId>
+            <artifactId>geronimo-activation_1.1_spec</artifactId>
+            <version>1.0.2</version>
+        </dependency>
     </dependencies>
 
     <build>
@@ -60,6 +65,37 @@
                     </archive>
                 </configuration>
             </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-dependency-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>create-endorsed-dir</id>
+                        <phase>validate</phase>
+                        <goals>
+                            <goal>copy</goal>
+                        </goals>
+                        <configuration>
+                            <artifactItems>
+                                <artifactItem>
+                                    <groupId>org.apache.servicemix.specs</groupId>
+                                    <artifactId>org.apache.servicemix.specs.activation-api-1.1</artifactId>
+                                    <outputDirectory>${basedir}/target/endorsed</outputDirectory>
+                                </artifactItem>
+                            </artifactItems>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <compilerArguments>
+                        <endorseddirs>${basedir}/target/endorsed</endorseddirs>
+                    </compilerArguments>
+                </configuration>
+            </plugin>
         </plugins>
     </build>
 
diff --git a/activator/src/main/java/org/apache/servicemix/specs/activator/Activator.java b/activator/src/main/java/org/apache/servicemix/specs/activator/Activator.java
index 26e0016..02f5c5f 100644
--- a/activator/src/main/java/org/apache/servicemix/specs/activator/Activator.java
+++ b/activator/src/main/java/org/apache/servicemix/specs/activator/Activator.java
@@ -17,6 +17,7 @@
 package org.apache.servicemix.specs.activator;
 
 import java.io.BufferedReader;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.net.URL;
 import java.util.Enumeration;
@@ -26,6 +27,9 @@
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 
+import javax.activation.CommandMap;
+import javax.activation.DataContentHandler;
+
 import org.apache.servicemix.specs.locator.OsgiLocator;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
@@ -40,6 +44,8 @@
     private ConcurrentMap<Long, Map<String, Callable<Class>>> factories = new ConcurrentHashMap<Long, Map<String, Callable<Class>>>();
 
     private BundleContext bundleContext;
+    
+    private Map<Long, MailCap> mailcaps = new ConcurrentHashMap<Long, MailCap>();
 
     static {
         try {
@@ -82,6 +88,7 @@
         }
         debugPrintln("deactivated");
         this.bundleContext = null;
+        CommandMap.setDefaultCommandMap(null);
     }
 
     public void bundleChanged(BundleEvent event) {
@@ -117,6 +124,26 @@
                 OsgiLocator.register(entry.getKey(), entry.getValue());
             }
         }
+        
+        URL url = bundle.getResource("/META-INF/mailcap");
+        if (url != null) {
+            debugPrintln("found mailcap at " + url);
+
+            try {
+                final Class<?> clazz = bundle
+                        .loadClass("javax.activation.DataContentHandler");
+                if (!clazz.isAssignableFrom(DataContentHandler.class)) {
+                    debugPrintln("incompatible DataContentHandler class in bundle "
+                            + bundle.getBundleId());
+                    return;
+                }
+            } catch (ClassNotFoundException ex) {
+                // ignored
+            }
+
+            mailcaps.put(bundle.getBundleId(), new MailCap(bundle, url));
+            rebuildCommandMap();
+        }
     }
 
     protected void unregister(long bundleId) {
@@ -127,6 +154,11 @@
                 OsgiLocator.unregister(entry.getKey(), entry.getValue());
             }
         }
+        MailCap mailcap = mailcaps.remove(bundleId);
+        if (mailcap != null ){
+            debugPrintln("removing mailcap at " + mailcap.url);
+            rebuildCommandMap();
+        }
     }
 
     private class BundleFactoryLoader implements Callable<Class> {
@@ -166,6 +198,46 @@
                 throw e;
             }
         }
+        
+        
+        private class MimeFactoryLoader implements Callable<Class> {
+            private final String mimeType;
+            private final URL u;
+            private final Bundle bundle;
+            private volatile Class<?> clazz;
+
+            public MimeFactoryLoader(String mimeType, URL u, Bundle bundle) {
+                this.mimeType = mimeType;
+                this.u = u;
+                this.bundle = bundle;
+            }
+
+            public Class call() throws Exception {
+                try {
+                    debugPrintln("loading factory for key: " + mimeType);
+                    
+                    if (clazz == null){
+                        synchronized (this) {
+                            if (clazz == null){
+                                debugPrintln("creating factory for key: " + factoryId);
+                                BufferedReader br = new BufferedReader(new InputStreamReader(u.openStream(), "UTF-8"));
+                                String factoryClassName = br.readLine();
+                                br.close();
+                                debugPrintln("factory implementation: " + factoryClassName);
+                                clazz = bundle.loadClass(factoryClassName);
+                            }
+                        }
+                    }
+                    return clazz;
+                } catch (Exception e) {
+                    debugPrintln("exception caught while creating factory: " + e);
+                    throw e;
+                } catch (Error e) {
+                    debugPrintln("error caught while creating factory: " + e);
+                    throw e;
+                }
+            }
+        }
 
         @Override
         public String toString() {
@@ -186,4 +258,41 @@
             }
         }
     }
+    
+    private void rebuildCommandMap() {
+        ClassLoader tccl = Thread.currentThread().getContextClassLoader();
+        try {
+            Thread.currentThread().setContextClassLoader(getClass().getClassLoader());
+            OsgiMailcapCommandMap commandMap = new OsgiMailcapCommandMap();
+            for (MailCap mailcap : mailcaps.values()) {
+                try {
+                    InputStream is = mailcap.url.openStream();
+                    try {
+                        BufferedReader br = new BufferedReader(new InputStreamReader(is));
+                        String line;
+                        while ((line = br.readLine()) != null) {
+                            commandMap.addMailcap(line, mailcap.bundle);
+                        }
+                    } finally {
+                        is.close();
+                    }
+                } catch (Exception e) {
+                    // Ignore
+                }
+            }
+            CommandMap.setDefaultCommandMap(commandMap);
+        } finally {
+            Thread.currentThread().setContextClassLoader(tccl);
+        }
+    }
+    
+    private static class MailCap {
+        Bundle bundle;
+        URL url;
+
+        private MailCap(Bundle bundle, URL url) {
+            this.bundle = bundle;
+            this.url = url;
+        }
+    }
 }
diff --git a/activator/src/main/java/org/apache/servicemix/specs/activator/OsgiMailcapCommandMap.java b/activator/src/main/java/org/apache/servicemix/specs/activator/OsgiMailcapCommandMap.java
new file mode 100644
index 0000000..257b448
--- /dev/null
+++ b/activator/src/main/java/org/apache/servicemix/specs/activator/OsgiMailcapCommandMap.java
@@ -0,0 +1,84 @@
+/*
+ * 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.specs.activator;
+
+import java.util.Map;
+import java.util.HashMap;
+
+import javax.activation.MailcapCommandMap;
+import javax.activation.CommandInfo;
+import javax.activation.DataContentHandler;
+
+import org.osgi.framework.Bundle;
+
+/**
+ * An OSGi enabled MailcapCommandMap
+ */
+public class OsgiMailcapCommandMap extends MailcapCommandMap {
+
+    private Bundle currentBundle;
+    private Map<CommandInfo, Bundle> bundles = new HashMap<CommandInfo, Bundle>();
+
+    public void addMailcap(String line, Bundle bundle) {
+        currentBundle = bundle;
+        addMailcap(line);
+    }
+
+    protected void addCommand(Map commandList, String mimeType, CommandInfo command) {
+        super.addCommand(commandList, mimeType, command);
+        if (currentBundle != null) {
+            bundles.put(command, currentBundle);
+        }
+    }
+
+    @Override
+    public DataContentHandler createDataContentHandler(String mimeType) {
+        CommandInfo info = getCommand(mimeType, "content-handler");
+        if (info == null) {
+            return null;
+        }
+
+        Bundle bundle = bundles.get(info);
+        if (bundle != null) {
+            try {
+                return (DataContentHandler) bundle.loadClass(info.getCommandClass()).newInstance();
+            } catch (ClassNotFoundException e) {
+                return null;
+            } catch (IllegalAccessException e) {
+                return null;
+            } catch (InstantiationException e) {
+                return null;
+            }
+        }
+
+        ClassLoader cl = Thread.currentThread().getContextClassLoader();
+        if (cl == null) {
+            cl = getClass().getClassLoader();
+        }
+        try {
+            return (DataContentHandler) cl.loadClass(info.getCommandClass()).newInstance();
+        } catch (ClassNotFoundException e) {
+            return null;
+        } catch (IllegalAccessException e) {
+            return null;
+        } catch (InstantiationException e) {
+            return null;
+        }
+    }
+}