001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 */ 019package org.javamoney.moneta.internal; 020 021import org.javamoney.moneta.spi.PriorityServiceComparator; 022import org.osgi.framework.*; 023 024import javax.money.spi.ServiceProvider; 025import java.io.IOException; 026import java.net.URL; 027import java.util.*; 028import java.util.logging.Level; 029import java.util.logging.Logger; 030 031/** 032 * ServiceContext implementation based on OSGI Service mechanisms. 033 */ 034public class OSGIServiceProvider implements ServiceProvider{ 035 036 private static final Logger LOG = Logger.getLogger(OSGIServiceProvider.class.getName()); 037 private static final OSGIServiceComparator REF_COMPARATOR = new OSGIServiceComparator(); 038 039 private BundleContext bundleContext; 040 041 public OSGIServiceProvider( BundleContext bundleContext){ 042 this.bundleContext = bundleContext; 043 } 044 045 public boolean isInitialized(){ 046 return true; 047 } 048 049 050 @Override 051 public int getPriority() { 052 return 10; 053 } 054 055 @Override 056 public <T> T getService(Class<T> serviceType) { 057 LOG.finest("TAMAYA Loading service: " + serviceType.getName()); 058 ServiceReference<T> ref = this.bundleContext.getServiceReference(serviceType); 059 if(ref!=null){ 060 return this.bundleContext.getService(ref); 061 } 062 return null; 063 } 064 065 @SuppressWarnings("unchecked") 066 public <T> T create(Class<T> serviceType) { 067 LOG.finest("TAMAYA Creating service: " + serviceType.getName()); 068 ServiceReference<T> ref = this.bundleContext.getServiceReference(serviceType); 069 if(ref!=null){ 070 try { 071 return (T)this.bundleContext.getService(ref).getClass().newInstance(); 072 } catch (Exception e) { 073 return null; 074 } 075 } 076 return null; 077 } 078 079 @Override 080 public <T> List<T> getServices(Class<T> serviceType) { 081 LOG.finest("TAMAYA Loading services: " + serviceType.getName()); 082 List<ServiceReference<T>> refs = new ArrayList<>(); 083 List<T> services = new ArrayList<>(refs.size()); 084 try { 085 refs.addAll(this.bundleContext.getServiceReferences(serviceType, null)); 086 Collections.sort(refs, REF_COMPARATOR); 087 for(ServiceReference<T> ref:refs){ 088 T service = bundleContext.getService(ref); 089 if(service!=null) { 090 services.add(service); 091 } 092 } 093 } catch (InvalidSyntaxException e) { 094 e.printStackTrace(); 095 } 096 try{ 097 for(T service:ServiceLoader.load(serviceType)){ 098 services.add(service); 099 } 100 return services; 101 } catch (Exception e) { 102 e.printStackTrace(); 103 } 104 return services; 105 } 106 107 public Enumeration<URL> getResources(String resource, ClassLoader cl) throws IOException{ 108 LOG.finest("TAMAYA Loading resources: " + resource); 109 List<URL> result = new ArrayList<>(); 110 URL url = bundleContext.getBundle() 111 .getEntry(resource); 112 if(url != null) { 113 LOG.finest("TAMAYA Resource: " + resource + " found in unregistered bundle " + 114 bundleContext.getBundle().getSymbolicName()); 115 result.add(url); 116 } 117 for(Bundle bundle: bundleContext.getBundles()) { 118 url = bundle.getEntry(resource); 119 if (url != null && !result.contains(url)) { 120 LOG.finest("TAMAYA Resource: " + resource + " found in registered bundle " + bundle.getSymbolicName()); 121 result.add(url); 122 } 123 } 124 for(Bundle bundle: bundleContext.getBundles()) { 125 url = bundle.getEntry(resource); 126 if (url != null && !result.contains(url)) { 127 LOG.finest("TAMAYA Resource: " + resource + " found in unregistered bundle " + bundle.getSymbolicName()); 128 result.add(url); 129 } 130 } 131 return Collections.enumeration(result); 132 } 133 134 public static <T> void registerService(Bundle bundle, Class<T> serviceClass, Class<? extends T> implClass) { 135 try { 136 // Load the service class 137 LOG.info("Loaded Service Factory (" + serviceClass.getName() + "): " + implClass.getName()); 138 // Provide service properties 139 Hashtable<String, String> props = new Hashtable<>(); 140 props.put(Constants.VERSION_ATTRIBUTE, bundle.getVersion().toString()); 141 String vendor = bundle.getHeaders().get(Constants.BUNDLE_VENDOR); 142 props.put(Constants.SERVICE_VENDOR, (vendor != null ? vendor : "anonymous")); 143 // Translate annotated @Priority into a service ranking 144 props.put(Constants.SERVICE_RANKING, 145 String.valueOf(PriorityServiceComparator.getPriority(implClass))); 146 147 // Register the service factory on behalf of the intercepted bundle 148 JDKUtilServiceFactory factory = new JDKUtilServiceFactory(implClass); 149 BundleContext bundleContext = bundle.getBundleContext(); 150 bundleContext.registerService(serviceClass.getName(), factory, props); 151 LOG.info("Registered Tamaya service class: " + implClass.getName() + "(" + serviceClass.getName() + ")"); 152 } catch (Exception e) { 153 LOG.log(Level.SEVERE, "Failed to load service: " + implClass.getName(), e); 154 } 155 } 156 157 public static <T> void unregisterService(Bundle bundle, Class<T> serviceClass, Class<? extends T> implClass) { 158 try { 159 LOG.fine("Unloading Service (" + serviceClass.getName() + "): " + implClass.getName()); 160 ServiceReference<?> ref = bundle.getBundleContext().getServiceReference(implClass); 161 if (ref != null) { 162 bundle.getBundleContext().ungetService(ref); 163 } 164 } catch (Exception e) { 165 LOG.log(Level.SEVERE, "Failed to unload service: " + implClass.getName(), e); 166 } 167 } 168 169 /** 170 * Service factory simply instantiating the configured service. 171 */ 172 static class JDKUtilServiceFactory implements ServiceFactory { 173 private final Class<?> serviceClass; 174 175 public JDKUtilServiceFactory(Class<?> serviceClass) { 176 this.serviceClass = serviceClass; 177 } 178 179 @Override 180 public Object getService(Bundle bundle, ServiceRegistration registration) { 181 try { 182 LOG.fine("Creating Service...:" + serviceClass.getName()); 183 return serviceClass.newInstance(); 184 } catch (Exception ex) { 185 ex.printStackTrace(); 186 throw new IllegalStateException("Failed to create service: " + serviceClass.getName(), ex); 187 } 188 } 189 190 @Override 191 public void ungetService(Bundle bundle, ServiceRegistration registration, Object service) { 192 } 193 } 194 195}