tamaya-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From anat...@apache.org
Subject incubator-tamaya git commit: TAMAYA-129: OSGI: Added OSGI BundleListener that also registers an OSGI based ServiceContext and ensures configured services are registered as SOGI services. The service ranking is used by reading @Priority annotations as ava
Date Mon, 09 Nov 2015 03:19:16 GMT
Repository: incubator-tamaya
Updated Branches:
  refs/heads/master 306b2bb8a -> e941425fb


TAMAYA-129: OSGI: Added OSGI BundleListener that also registers an OSGI based ServiceContext
and ensures configured services are registered as SOGI services. The service ranking is used
by reading @Priority annotations as available.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/commit/e941425f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/tree/e941425f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tamaya/diff/e941425f

Branch: refs/heads/master
Commit: e941425fbb1316070f0ec50cd2408f3bbb9a1c15
Parents: 306b2bb
Author: anatole <anatole@apache.org>
Authored: Mon Nov 9 04:18:53 2015 +0100
Committer: anatole <anatole@apache.org>
Committed: Mon Nov 9 04:19:07 2015 +0100

----------------------------------------------------------------------
 api/pom.xml                                     |   9 ++
 core/pom.xml                                    |  72 +++++++++
 .../tamaya/core/internal/OSGIActivator.java     |  48 ++++++
 .../core/internal/OSGIServiceComparator.java    |  69 +++++++++
 .../core/internal/OSGIServiceContext.java       |  83 +++++++++++
 .../tamaya/core/internal/OSGIServiceLoader.java | 145 +++++++++++++++++++
 .../internal/PriorityServiceComparator.java     |  13 +-
 7 files changed, 438 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e941425f/api/pom.xml
----------------------------------------------------------------------
diff --git a/api/pom.xml b/api/pom.xml
index 0cca428..3d3871d 100644
--- a/api/pom.xml
+++ b/api/pom.xml
@@ -54,6 +54,15 @@ under the License.
                             org.apache.tamaya,
                             org.apache.tamaya.spi
                         </Export-Package>
+                        <!--<Require-Capability>-->
+                            <!--osgi.extender;-->
+                            <!--filter:="(osgi.extender=osgi.serviceloader.processor)",-->
+                            <!--osgi.serviceloader;-->
+                            <!--filter:="(org.apache.tamaya.spi.ServiceContext)";-->
+                            <!--cardinality:=multiple;-->
+                            <!--filter:="(org.apache.tamaya.spi.ConfigurationProviderSpi)";-->
+                            <!--cardinality:=multiple-->
+                        <!--</Require-Capability>-->
                     </instructions>
                 </configuration>
             </plugin>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e941425f/core/pom.xml
----------------------------------------------------------------------
diff --git a/core/pom.xml b/core/pom.xml
index 1b35dab..27200df 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -30,6 +30,10 @@ under the License.
     <name>Apache Tamaya Core Implementation</name>
     <packaging>bundle</packaging>
 
+    <properties>
+        <osgi.compendium.version>5.0.0</osgi.compendium.version>
+     </properties>
+
     <dependencies>
         <dependency>
             <groupId>org.apache.tamaya</groupId>
@@ -48,6 +52,20 @@ under the License.
             <groupId>org.hamcrest</groupId>
             <artifactId>hamcrest-core</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+            <version>${osgi.compendium.version}</version>
+            <optional>true</optional>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <version>${osgi.version}</version>
+            <scope>provided</scope>
+            <optional>true</optional>
+        </dependency>
     </dependencies>
 
     <build>
@@ -68,6 +86,60 @@ under the License.
                             org.apache.tamaya.core.internal,
                             org.apache.tamaya.core.internal.converters
                         </Private-Package>
+                        <!--<Require-Capability>-->
+                            <!--osgi.extender;-->
+                            <!--filter:="(osgi.extender=osgi.serviceloader.processor)",-->
+                            <!--osgi.serviceloader;-->
+                            <!--filter:="(org.apache.tamaya.Configuration)";-->
+                            <!--cardinality:=multiple-->
+                        <!--</Require-Capability>-->
+                        <!--<Require-Capability>-->
+                            <!--osgi.extender;-->
+                            <!--filter:="(osgi.extender=osgi.serviceloader.processor)",-->
+                            <!--osgi.serviceloader;-->
+                            <!--filter:="(org.apache.tamaya.spi.ConfigurationContextBuilder)";-->
+                            <!--cardinality:=multiple-->
+                        <!--</Require-Capability>-->
+                        <!--<Require-Capability>-->
+                            <!--osgi.extender;-->
+                            <!--filter:="(osgi.extender=osgi.serviceloader.processor)",-->
+                            <!--osgi.serviceloader;-->
+                            <!--filter:="(org.apache.tamaya.spi.PropertyConverter)";-->
+                            <!--cardinality:=multiple-->
+                        <!--</Require-Capability>-->
+                        <!--<Require-Capability>-->
+                            <!--osgi.extender;-->
+                            <!--filter:="(osgi.extender=osgi.serviceloader.processor)",-->
+                            <!--osgi.serviceloader;-->
+                            <!--filter:="(org.apache.tamaya.spi.PropertyFilter)";-->
+                            <!--cardinality:=multiple-->
+                        <!--</Require-Capability>-->
+                        <!--<Require-Capability>-->
+                            <!--osgi.extender;-->
+                            <!--filter:="(osgi.extender=osgi.serviceloader.processor)",-->
+                            <!--osgi.serviceloader;-->
+                            <!--filter:="(org.apache.tamaya.spi.PropertySource)";-->
+                            <!--cardinality:=multiple-->
+                        <!--</Require-Capability>-->
+                        <!--<Require-Capability>-->
+                            <!--osgi.extender;-->
+                            <!--filter:="(osgi.extender=osgi.serviceloader.processor)",-->
+                            <!--osgi.serviceloader;-->
+                            <!--filter:="(org.apache.tamaya.spi.PropertySourceProvider)";-->
+                            <!--cardinality:=multiple-->
+                        <!--</Require-Capability>-->
+                        <!--<Require-Capability>osgi.extender;-->
+                            <!--filter:="(osgi.extender=osgi.serviceloader.registrar)"-->
+                        <!--</Require-Capability>-->
+                        <!--<Provide-Capability>osgi.serviceloader;-->
+                            <!--org.apache.tamaya.Configuration,-->
+                            <!--org.apache.tamaya.spi.ConfigurationContextBuilder,-->
+                            <!--org.apache.tamaya.spi.ConfigurationProviderSpi,-->
+                            <!--org.apache.tamaya.spi.PropertyConverter,-->
+                            <!--org.apache.tamaya.spi.PropertyFilter,-->
+                            <!--org.apache.tamaya.spi.PropertySource,-->
+                            <!--org.apache.tamaya.spi.PropertySourceProvider-->
+                        <!--</Provide-Capability>-->
                     </instructions>
                 </configuration>
             </plugin>

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e941425f/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java b/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java
new file mode 100644
index 0000000..3d80cd2
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/OSGIActivator.java
@@ -0,0 +1,48 @@
+/*
+ * 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.tamaya.core.internal;
+
+
+
+import org.apache.tamaya.spi.ServiceContextManager;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+
+/**
+ * A bundle activator that registers the {@link OSGIServiceLoader}.
+ */
+public class OSGIActivator implements BundleActivator {
+
+    private OSGIServiceLoader serviceLoader;
+
+    @Override
+    public void start(BundleContext context) {
+        // Register marker service
+        ServiceContextManager.set(new OSGIServiceContext(context));
+        serviceLoader =new OSGIServiceLoader();
+        context.addBundleListener(serviceLoader);
+    }
+
+    @Override
+    public void stop(BundleContext context) {
+        if(serviceLoader!=null) {
+            context.removeBundleListener(serviceLoader);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e941425f/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java
b/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java
new file mode 100644
index 0000000..bfc34bc
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceComparator.java
@@ -0,0 +1,69 @@
+/*
+ * 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.tamaya.core.internal;
+
+import org.osgi.framework.ServiceReference;
+
+import javax.annotation.Priority;
+import java.util.Comparator;
+
+/**
+ * Comparator implementation for odering services loaded based on their increasing priority
values.
+ */
+class OSGIServiceComparator implements Comparator<ServiceReference> {
+
+    @Override
+    public int compare(ServiceReference o1, ServiceReference o2) {
+        int prio = getPriority(o1) - getPriority(o2);
+        if (prio < 0) {
+            return 1;
+        } else if (prio > 0) {
+            return -1;
+        } else {
+            return 0; //o1.getClass().getSimpleName().compareTo(o2.getClass().getSimpleName());
+        }
+    }
+
+    /**
+     * Checks the given instance for a @Priority annotation. If present the annotation's
value s evaluated. If no such
+     * annotation is present, a default priority is returned (1);
+     *
+     * @param o the instance, not null.
+     * @return a priority, by default 1.
+     */
+    public static int getPriority(Object o) {
+        return getPriority(o.getClass());
+    }
+
+    /**
+     * Checks the given type optionally annotated with a @Priority. If present the annotation's
value s evaluated.
+     * If no such annotation is present, a default priority is returned (1);
+     *
+     * @param type the type, not null.
+     * @return a priority, by default 1.
+     */
+    public static int getPriority(Class type) {
+        int prio = 1;
+        Priority priority = (Priority)type.getAnnotation(Priority.class);
+        if (priority != null) {
+            prio = priority.value();
+        }
+        return prio;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e941425f/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java b/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
new file mode 100644
index 0000000..d4be430
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceContext.java
@@ -0,0 +1,83 @@
+/*
+ * 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.tamaya.core.internal;
+
+import org.apache.tamaya.spi.ServiceContext;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * ServiceContext implementation based on OSGI Service mechanisms.
+ */
+public class OSGIServiceContext implements ServiceContext{
+
+    private static final OSGIServiceComparator REF_COMPARATOR = new OSGIServiceComparator();
+
+    private BundleContext bundleContext;
+
+    public OSGIServiceContext(BundleContext bundleContext){
+        this.bundleContext = Objects.requireNonNull(bundleContext);
+    }
+
+    public boolean isInitialized(){
+        return bundleContext != null;
+    }
+
+
+    @Override
+    public int ordinal() {
+        return 10;
+    }
+
+    @Override
+    public <T> T getService(Class<T> serviceType) {
+        ServiceReference<T> ref = this.bundleContext.getServiceReference(serviceType);
+        if(ref!=null){
+            return this.bundleContext.getService(ref);
+        }
+        return null;
+    }
+
+    @Override
+    public <T> List<T> getServices(Class<T> serviceType) {
+        List<ServiceReference<T>> refs = new ArrayList<>();
+        try {
+            refs.addAll(this.bundleContext.getServiceReferences(serviceType, "*"));
+            Collections.sort(refs, REF_COMPARATOR);
+            List<T> services = new ArrayList<>(refs.size());
+            for(ServiceReference<T> ref:refs){
+                T service = bundleContext.getService(ref);
+                if(service!=null) {
+                    services.add(service);
+                }
+            }
+            return services;
+        } catch (InvalidSyntaxException e) {
+            e.printStackTrace();
+            return Collections.emptyList();
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e941425f/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java b/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
new file mode 100644
index 0000000..90b0e26
--- /dev/null
+++ b/core/src/main/java/org/apache/tamaya/core/internal/OSGIServiceLoader.java
@@ -0,0 +1,145 @@
+/*
+ * 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.tamaya.core.internal;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+
+/**
+ * An bundle listener that registers services defined in META-INF/services, when a bundle
is starting.
+ *
+ * @author anatole@apache.org
+ */
+public class OSGIServiceLoader implements BundleListener
+{
+    // Provide logging
+    private static final Logger log = Logger.getLogger(OSGIServiceLoader.class.getName());
+
+    @Override
+    public void bundleChanged(BundleEvent bundleEvent) {
+        // Parse and create metadta on STARTING
+        if (bundleEvent.getType() == BundleEvent.STARTING) {
+            Bundle bundle = bundleEvent.getBundle();
+            if (bundle.getEntry("META-INF/services/") == null) {
+                return;
+            }
+            Enumeration<String> entryPaths = bundle.getEntryPaths("META-INF/services/");
+            while (entryPaths.hasMoreElements()) {
+                String entryPath = entryPaths.nextElement();
+                if(!entryPath.endsWith("/")) {
+                    processEntryPath(bundle, entryPath);
+                }
+            }
+        }
+    }
+
+    private void processEntryPath(Bundle bundle, String entryPath) {
+        try {
+            String serviceName = entryPath.substring("META-INF/services/".length());
+            Class<?> serviceClass = bundle.loadClass(serviceName);
+
+            URL child = bundle.getEntry(entryPath);
+            InputStream inStream = child.openStream();
+
+            BufferedReader br = new BufferedReader(new InputStreamReader(inStream, "UTF-8"));
+            String implClassName = br.readLine();
+            while (implClassName != null){
+                int hashIndex = implClassName.indexOf("#");
+                if (hashIndex > 0) {
+                    implClassName = implClassName.substring(0, hashIndex);
+                }
+
+                implClassName = implClassName.trim();
+
+                if (implClassName.length() > 0) {
+                    // Load the service class
+                    Class<?> implClass = (Class<?>)bundle.loadClass(implClassName);
+                    if (serviceClass.isAssignableFrom(implClass) == false) {
+                        log.warning("Configured service: " + implClassName + " is not assignble
to " +
+                                serviceClass.getName());
+                        continue;
+                    }
+                    // Provide service properties
+                    Hashtable<String, String> props = new Hashtable<String, String>();
+                    props.put(Constants.VERSION_ATTRIBUTE, bundle.getVersion().toString());
+                    String vendor = (String)bundle.getHeaders().get(Constants.BUNDLE_VENDOR);
+                    props.put(Constants.SERVICE_VENDOR, (vendor != null ? vendor : "anonymous"));
+                    // Translate annotated @Priority into a service ranking
+                    props.put(Constants.SERVICE_RANKING,
+                            String.valueOf(PriorityServiceComparator.getPriority(implClass)));
+
+                    // Register the service factory on behalf of the intercepted bundle
+                   JDKUtilServiceFactory factory = new JDKUtilServiceFactory(implClass);
+                    BundleContext bundleContext = bundle.getBundleContext();
+                    bundleContext.registerService(serviceName, factory, props);
+                }
+                implClassName = br.readLine();
+            }
+            br.close();
+        }
+        catch (RuntimeException rte) {
+            throw rte;
+        }
+        catch (Exception e) {
+            log.log(Level.SEVERE, "Failed to read services from: " + entryPath, e);
+        }
+    }
+
+
+    /**
+     * Service factory simply instantiating the configured service.
+     */
+    static class JDKUtilServiceFactory implements ServiceFactory
+    {
+        private Class<?> serviceClass;
+
+        public JDKUtilServiceFactory(Class<?> serviceClass) {
+            this.serviceClass = serviceClass;
+        }
+
+        @Override
+        public Object getService(Bundle bundle, ServiceRegistration registration) {
+            try {
+                Object serviceInstance = serviceClass.newInstance();
+                return serviceInstance;
+            }
+            catch (Exception ex) {
+                throw new IllegalStateException("Cannot instanciate service", ex);
+            }
+        }
+
+        @Override
+        public void ungetService(Bundle bundle, ServiceRegistration registration, Object
service) {
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tamaya/blob/e941425f/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
b/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
index b667900..c0cfca6 100644
--- a/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
+++ b/core/src/main/java/org/apache/tamaya/core/internal/PriorityServiceComparator.java
@@ -46,8 +46,19 @@ public class PriorityServiceComparator implements Comparator<Object>
{
      * @return a priority, by default 1.
      */
     public static int getPriority(Object o) {
+        return getPriority(o.getClass());
+    }
+
+    /**
+     * Checks the given type optionally annotated with a @Priority. If present the annotation's
value s evaluated.
+     * If no such annotation is present, a default priority is returned (1);
+     *
+     * @param type the type, not null.
+     * @return a priority, by default 1.
+     */
+    public static int getPriority(Class type) {
         int prio = 1;
-        Priority priority = o.getClass().getAnnotation(Priority.class);
+        Priority priority = (Priority)type.getAnnotation(Priority.class);
         if (priority != null) {
             prio = priority.value();
         }


Mime
View raw message