/** * OpenAtlasForAndroid Project * The MIT License (MIT) Copyright (OpenAtlasForAndroid) 2015 Bunny Blue,achellies * <p> * Permission is hereby granted, free of charge, to any person obtaining a copy of this software * and associated documentation files (the "Software"), to deal in the Software * without restriction, including without limitation the rights to use, copy, modify, * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to * permit persons to whom the Software is furnished to do so, subject to the following conditions: * <p> * The above copyright notice and this permission notice shall be included in all copies * or substantial portions of the Software. * <p> * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * @author BunnyBlue **/ package com.openatlas.framework; import org.osgi.framework.Bundle; import org.osgi.framework.Constants; import org.osgi.framework.ServiceFactory; import org.osgi.framework.ServiceReference; import org.osgi.framework.ServiceRegistration; import java.util.ArrayList; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Locale; import java.util.Map; final class ServiceReferenceImpl implements ServiceReference { private static final HashSet<String> forbidden; private static long nextServiceID; Bundle bundle; private HashMap<Bundle, Object> cachedServices; private final boolean isServiceFactory; final Dictionary<String, Object> properties; ServiceRegistration registration; private Object service; final Map<Bundle, Integer> useCounters; private final class ServiceRegistrationImpl implements ServiceRegistration { private ServiceRegistrationImpl() { } @Override public ServiceReference getReference() { if (ServiceReferenceImpl.this.service != null) { return ServiceReferenceImpl.this; } throw new IllegalStateException( "Service has already been uninstalled"); } @Override public void setProperties(Dictionary<String, ?> dictionary) { if (ServiceReferenceImpl.this.service == null) { throw new IllegalStateException( "Service has already been uninstalled"); } HashMap hashMap = new HashMap( ServiceReferenceImpl.this.properties.size()); Enumeration keys = ServiceReferenceImpl.this.properties.keys(); while (keys.hasMoreElements()) { String str = (String) keys.nextElement(); String toLowerCase = str.toLowerCase(Locale.US); if (hashMap.containsKey(toLowerCase)) { throw new IllegalArgumentException( "Properties contain the same key in different case variants"); } hashMap.put(toLowerCase, str); } keys = dictionary.keys(); while (keys.hasMoreElements()) { String str = (String) keys.nextElement(); Object obj = dictionary.get(str); String toLowerCase2 = str.toLowerCase(Locale.US); if (!ServiceReferenceImpl.forbidden.contains(toLowerCase2)) { Object obj2 = hashMap.get(toLowerCase2); if (obj2 != null) { if (obj2.equals(str)) { ServiceReferenceImpl.this.properties.remove(obj2); } else { throw new IllegalArgumentException( "Properties already exists in Component different case variant"); } } ServiceReferenceImpl.this.properties.put(str, obj); } } Framework.notifyServiceListeners(2, ServiceReferenceImpl.this); } @Override public void unregister() { if (ServiceReferenceImpl.this.service == null) { throw new IllegalStateException( "Service has already been uninstalled"); } Framework.unregisterService(ServiceReferenceImpl.this); ServiceReferenceImpl.this.service = null; } } static { nextServiceID = 0; forbidden = new HashSet(); forbidden.add(Constants.SERVICE_ID.toLowerCase(Locale.US)); forbidden.add(Constants.OBJECTCLASS.toLowerCase(Locale.US)); } ServiceReferenceImpl(Bundle bundle, Object service, Dictionary<String, ?> properties, String[] clazzes) { this.useCounters = new HashMap<Bundle, Integer>(0); this.cachedServices = null; if (service instanceof ServiceFactory) { this.isServiceFactory = true; } else { this.isServiceFactory = false; checkService(service, clazzes); } this.bundle = bundle; this.service = service; this.properties = properties == null ? new Hashtable() : new Hashtable( properties.size()); if (properties != null) { Enumeration<String> keys = properties.keys(); while (keys.hasMoreElements()) { String str = keys.nextElement(); this.properties.put(str, properties.get(str)); } } this.properties.put(Constants.OBJECTCLASS, clazzes); Dictionary<String, Object> dictionary2 = this.properties; String str2 = Constants.SERVICE_ID; long j = nextServiceID + 1; nextServiceID = j; dictionary2.put(str2, Long.valueOf(j)); Integer num = properties == null ? null : (Integer) properties .get(Constants.SERVICE_RANKING); this.properties.put(Constants.SERVICE_RANKING, Integer.valueOf(num == null ? 0 : num.intValue())); this.registration = new ServiceRegistrationImpl(); } private void checkService(Object service, String[] clazzes) { int i = 0; while (i < clazzes.length) { try { if (Class.forName(clazzes[i], false, service.getClass().getClassLoader()).isInstance(service)) { i++; } else { throw new IllegalArgumentException("Service " + service.getClass().getName() + " does not implement the interface " + clazzes[i]); } } catch (ClassNotFoundException e) { throw new IllegalArgumentException("Interface " + clazzes[i] + " implemented by service " + service.getClass().getName() + " cannot be located: " + e.getMessage()); } } } void invalidate() { this.service = null; this.useCounters.clear(); this.bundle = null; this.registration = null; if (this.cachedServices != null) { this.cachedServices = null; } String[] propertyKeys = getPropertyKeys(); for (Object remove : propertyKeys) { this.properties.remove(remove); } } @Override public Bundle getBundle() { return this.bundle; } @Override public Object getProperty(String key) { Object obj = this.properties.get(key); if (obj != null) { return obj; } obj = this.properties.get(key.toLowerCase(Locale.US)); if (obj != null) { return obj; } Object obj2; Enumeration<String> keys = this.properties.keys(); while (keys.hasMoreElements()) { String str2 = keys.nextElement(); if (str2.equalsIgnoreCase(key)) { obj2 = this.properties.get(str2); break; } } obj2 = obj; return obj2; } @Override public String[] getPropertyKeys() { ArrayList<String> arrayList = new ArrayList<String>(this.properties.size()); Enumeration<String> keys = this.properties.keys(); while (keys.hasMoreElements()) { arrayList.add(keys.nextElement()); } return arrayList.toArray(new String[arrayList.size()]); } @Override public Bundle[] getUsingBundles() { Bundle[] bundleArr; synchronized (this.useCounters) { if (this.useCounters.isEmpty()) { bundleArr = null; } else { bundleArr = this.useCounters.keySet().toArray( new Bundle[this.useCounters.size()]); } } return bundleArr; } Object getService(Bundle bundle) { if (this.service == null) { return null; } synchronized (this.useCounters) { Object valueOf; Integer num = this.useCounters.get(bundle); if (num == null) { valueOf = Integer.valueOf(1); } else { valueOf = Integer.valueOf(num.intValue() + 1); } this.useCounters.put(bundle, (Integer) valueOf); if (this.isServiceFactory) { if (this.cachedServices == null) { this.cachedServices = new HashMap<Bundle, Object>(); } valueOf = this.cachedServices.get(bundle); if (valueOf != null) { return valueOf; } try { Object service = ((ServiceFactory) this.service) .getService(bundle, this.registration); checkService(service, (String[]) this.properties .get(Constants.OBJECTCLASS)); this.cachedServices.put(bundle, service); return service; } catch (Throwable e) { Framework.notifyFrameworkListeners(2, null, e); return null; } } valueOf = this.service; return valueOf; } } boolean ungetService(Bundle bundle) { synchronized (this.useCounters) { if (this.service == null) { return false; } Integer num = this.useCounters.get(bundle); if (num == null) { return false; } else if (num.intValue() == 1) { this.useCounters.remove(bundle); if (this.isServiceFactory) { ((ServiceFactory) this.service).ungetService(bundle, this.registration, this.cachedServices.get(bundle)); this.cachedServices.remove(bundle); } return false; } else { this.useCounters.put(bundle, Integer.valueOf(num.intValue() - 1)); return true; } } } @Override public String toString() { return "ServiceReference{" + this.service + "}"; } }