| /* |
| * 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.ClassloaderAware; |
| import org.apache.tamaya.spi.ConfigurationProviderSpi; |
| import org.apache.tamaya.spi.ServiceContext; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.InvalidSyntaxException; |
| import org.osgi.framework.ServiceReference; |
| |
| import java.io.IOException; |
| import java.net.URL; |
| import java.util.*; |
| import java.util.function.Supplier; |
| import java.util.logging.Level; |
| import java.util.logging.Logger; |
| |
| /** |
| * ServiceContext implementation based on OSGI Service mechanisms. |
| */ |
| public class OSGIServiceContext implements ServiceContext{ |
| |
| private static final Logger LOG = Logger.getLogger(OSGIServiceContext.class.getName()); |
| private static final OSGIServiceComparator REF_COMPARATOR = new OSGIServiceComparator(); |
| |
| private final OSGIServiceLoader osgiServiceLoader; |
| |
| public OSGIServiceContext(OSGIServiceLoader osgiServiceLoader){ |
| this.osgiServiceLoader = Objects.requireNonNull(osgiServiceLoader); |
| } |
| |
| public boolean isInitialized(){ |
| return osgiServiceLoader != null; |
| } |
| |
| |
| @Override |
| public ClassLoader getClassLoader() { |
| return getClass().getClassLoader(); |
| } |
| |
| @Override |
| public void init(ClassLoader classLoader) { |
| throw new IllegalStateException("Classloader already setCurrent on this context."); |
| } |
| |
| |
| @Override |
| public int ordinal() { |
| return 10; |
| } |
| |
| @Override |
| public <T> T getService(Class<T> serviceType, Supplier<T> supplier) { |
| LOG.finest("TAMAYA Loading service: " + serviceType.getName()); |
| ServiceReference<T> ref = this.osgiServiceLoader.getBundleContext().getServiceReference(serviceType); |
| if(ref!=null){ |
| return this.osgiServiceLoader.getBundleContext().getService(ref); |
| } |
| if(ConfigurationProviderSpi.class==serviceType){ |
| @SuppressWarnings("unchecked") |
| T service = (T)new CoreConfigurationProvider(); |
| this.osgiServiceLoader.getBundleContext().registerService( |
| serviceType.getName(), |
| service, |
| new Hashtable<String, Object>()); |
| return service; |
| } |
| if(supplier!=null){ |
| T t = supplier.get(); |
| if(t instanceof ClassloaderAware){ |
| ((ClassloaderAware)t).init(getClassLoader()); |
| } |
| this.osgiServiceLoader.getBundleContext().registerService( |
| serviceType.getName(), |
| t, |
| new Hashtable<String, Object>()); |
| return t; |
| } |
| return null; |
| } |
| |
| |
| @Override |
| public <T> T create(Class<T> serviceType, Supplier<T> supplier) { |
| LOG.finest("TAMAYA Creating service: " + serviceType.getName()); |
| ServiceReference<T> ref = this.osgiServiceLoader.getBundleContext().getServiceReference(serviceType); |
| if(ref!=null){ |
| try { |
| return (T)this.osgiServiceLoader.getBundleContext().getService(ref).getClass().getConstructor() |
| .newInstance(); |
| } catch (Exception e) { |
| if(supplier!=null){ |
| return supplier.get(); |
| } |
| return null; |
| } |
| } |
| if(supplier!=null){ |
| return supplier.get(); |
| } |
| return null; |
| } |
| |
| @Override |
| public <T> List<T> getServices(Class<T> serviceType, Supplier<List<T>> supplier) { |
| LOG.finest("TAMAYA Loading services: " + serviceType.getName()); |
| List<T> services = loadServices(serviceType, null); |
| if(services.isEmpty() && supplier!=null) { |
| services = supplier.get(); |
| try { |
| for (T t : services) { |
| this.osgiServiceLoader.getBundleContext().registerService(serviceType, t, new Hashtable<>()); |
| } |
| } catch (Exception e) { |
| LOG.log(Level.SEVERE, "Error while getting service.", e); |
| } |
| } |
| return services; |
| } |
| |
| private <T> List<T> loadServices(Class<T> serviceType, Supplier<List<T>> supplier) { |
| LOG.finest("TAMAYA Loading services: " + serviceType.getName()); |
| List<ServiceReference<T>> refs = new ArrayList<>(); |
| List<T> services = new ArrayList<>(refs.size()); |
| try { |
| refs.addAll(this.osgiServiceLoader.getBundleContext().getServiceReferences(serviceType, null)); |
| Collections.sort(refs, REF_COMPARATOR); |
| for(ServiceReference<T> ref:refs){ |
| T service = osgiServiceLoader.getBundleContext().getService(ref); |
| if(service!=null) { |
| services.add(service); |
| } |
| } |
| } catch (InvalidSyntaxException e) { |
| LOG.log(Level.INFO,"No services found in OSGI: " + serviceType, e); |
| } |
| try{ |
| for(T service:ServiceLoader.load(serviceType)){ |
| services.add(service); |
| } |
| return services; |
| } catch (Exception e) { |
| LOG.log(Level.INFO, "No services found in ServiceLoader: " + serviceType, e); |
| } |
| if(services.isEmpty() && supplier!=null){ |
| return supplier.get(); |
| } |
| return services; |
| } |
| |
| @Override |
| public Enumeration<URL> getResources(String resource) throws IOException{ |
| LOG.finest("TAMAYA Loading resources: " + resource); |
| List<URL> result = new ArrayList<>(); |
| URL url = osgiServiceLoader.getBundleContext().getBundle() |
| .getEntry(resource); |
| if(url != null) { |
| LOG.finest("TAMAYA Resource: " + resource + " found in unregistered bundle " + |
| osgiServiceLoader.getBundleContext().getBundle().getSymbolicName()); |
| result.add(url); |
| } |
| for(Bundle bundle: osgiServiceLoader.getResourceBundles()) { |
| url = bundle.getEntry(resource); |
| if (url != null && !result.contains(url)) { |
| LOG.finest("TAMAYA Resource: " + resource + " found in registered bundle " + bundle.getSymbolicName()); |
| result.add(url); |
| } |
| } |
| for(Bundle bundle: osgiServiceLoader.getBundleContext().getBundles()) { |
| url = bundle.getEntry(resource); |
| if (url != null && !result.contains(url)) { |
| LOG.finest("TAMAYA Resource: " + resource + " found in unregistered bundle " + bundle.getSymbolicName()); |
| result.add(url); |
| } |
| } |
| return Collections.enumeration(result); |
| } |
| |
| @Override |
| public URL getResource(String resource){ |
| LOG.finest("TAMAYA Loading resource: " + resource); |
| URL url = osgiServiceLoader.getBundleContext().getBundle() |
| .getEntry(resource); |
| if(url!=null){ |
| LOG.finest("TAMAYA Resource: " + resource + " found in bundle " + |
| osgiServiceLoader.getBundleContext().getBundle().getSymbolicName()); |
| return url; |
| } |
| for(Bundle bundle: osgiServiceLoader.getResourceBundles()) { |
| url = bundle.getEntry(resource); |
| if(url != null){ |
| LOG.finest("TAMAYA Resource: " + resource + " found in registered bundle " + bundle.getSymbolicName()); |
| return url; |
| } |
| } |
| for(Bundle bundle: osgiServiceLoader.getBundleContext().getBundles()) { |
| url = bundle.getEntry(resource); |
| if(url != null){ |
| LOG.finest("TAMAYA Resource: " + resource + " found in unregistered bundle " + bundle.getSymbolicName()); |
| return url; |
| } |
| } |
| return null; |
| } |
| |
| @Override |
| public <T> T register(Class<T> serviceType, T instance, boolean force) { |
| Collection<ServiceReference<T>> refs; |
| try { |
| refs = this.osgiServiceLoader.getBundleContext().getServiceReferences(serviceType, null); |
| if(refs!=null && force){ |
| for(ServiceReference ref:refs) { |
| osgiServiceLoader.getBundleContext().ungetService(ref); |
| } |
| refs = null; |
| } |
| } catch (InvalidSyntaxException e) { |
| throw new IllegalStateException("Failed to access OSGI services", e); |
| } |
| if(refs!=null && !refs.isEmpty()){ |
| return (T)this.osgiServiceLoader.getBundleContext().getService(refs.iterator().next()); |
| } |
| this.osgiServiceLoader.getBundleContext().registerService( |
| serviceType, instance, new Hashtable<>() |
| ); |
| return instance; |
| } |
| |
| @Override |
| public <T> List<T> register(Class<T> serviceType, List<T> instances, boolean force) { |
| Collection<ServiceReference<T>> refs; |
| try { |
| refs = this.osgiServiceLoader.getBundleContext().getServiceReferences(serviceType, null); |
| if(refs!=null && force){ |
| for(ServiceReference ref:refs) { |
| osgiServiceLoader.getBundleContext().ungetService(ref); |
| } |
| refs = null; |
| } |
| } catch (InvalidSyntaxException e) { |
| throw new IllegalStateException("Failed to access OSGI services", e); |
| } |
| if(refs!=null && !refs.isEmpty()){ |
| List<T> result = new ArrayList<>(); |
| for(ServiceReference ref:refs) { |
| T item = (T) this.osgiServiceLoader.getBundleContext().getService(ref); |
| if (item != null) { |
| result.add(item); |
| } |
| } |
| return result; |
| }else{ |
| for(T instance:instances) { |
| this.osgiServiceLoader.getBundleContext().registerService( |
| serviceType, instance, new Hashtable<>() |
| ); |
| } |
| return instances; |
| } |
| } |
| |
| @Override |
| public void reset() { |
| |
| } |
| |
| } |