/** * Copyright 2011-2012 Universite Joseph Fourier, LIG, ADELE team * Licensed 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 fr.imag.adele.apam.apform.legacy.osgi; import java.security.AccessController; import java.security.PrivilegedAction; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.ServiceReference; import fr.imag.adele.apam.Component; import fr.imag.adele.apam.Instance; import fr.imag.adele.apam.Specification; import fr.imag.adele.apam.apform.ApformInstance; import fr.imag.adele.apam.declarations.InstanceDeclaration; import fr.imag.adele.apam.declarations.PropertyDefinition; import fr.imag.adele.apam.declarations.references.components.ImplementationReference; import fr.imag.adele.apam.declarations.references.components.VersionedReference; import fr.imag.adele.apam.impl.BaseApformComponent; import fr.imag.adele.apam.impl.ComponentImpl.InvalidConfiguration; /** * This class represents an OSGi service interface reified as an APAM instance. * * The same OSGi service can be reified as an instance of different specifications (if * it matches the interfaces and properties defined in the specification) so several * ApformOSGiInstances can in fact point to the same service reference. * * */ public class ApformOSGiInstance extends BaseApformComponent<Instance,InstanceDeclaration> implements ApformInstance { /** * The APAM specification implemented by this service */ private final Specification specification; /** * The osgi service reference represented by this object */ private final ServiceReference<?> reference; /** * The bundle that registered the instance */ private final Bundle bundle; /** * The bundle context that registered the instance */ private final BundleContext bundleContext; /** * The cached service object */ private Object service; /** * An apform instance to represent a legacy component discovered in the OSGi registry * * @param ipojoInstance */ public ApformOSGiInstance(Specification specification, ServiceReference<?> reference) { super(new InstanceDeclaration(VersionedReference.any(generateImplementationName(specification,reference)), generateInstanceName(specification,reference))); this.specification = specification; for (PropertyDefinition property : specification.getDeclaration().getPropertyDefinitions()) { Object value = reference.getProperty(property.getName()); if (value != null) this.declaration.getProperties().put(property.getName(), value.toString()); } this.reference = reference; this.bundle = reference.getBundle(); this.bundleContext = AccessController.doPrivileged(new PrivilegedAction<BundleContext>() { public BundleContext run() { return bundle.getBundleContext();} }); this.service = null; } /** * The underlying OSGi service reference */ public ServiceReference<?> getServiceReference() { return reference; } /** * The APAM specification implemented */ public Specification getSpecification() { return specification; } @Override public Bundle getBundle() { return bundle; } @Override public Object getServiceObject() { /* * return cached value if available */ if (service != null) return service; /* * Get the service reference, this may activate delayed component in the case of * declarative services */ synchronized (this) { service = bundleContext.getService(reference); } return service; } @Override public void setApamComponent(Component apamInstance) throws InvalidConfiguration { super.setApamComponent(apamInstance); if (apamInstance == null) dispose(); } public void dispose() { service = null; if (bundleContext != null) bundleContext.ungetService(reference); } @Override public void setProperty(String attr, String value) { } /** * Generate the uniques name of the implementation associated with this instance in Apam */ private static ImplementationReference<?> generateImplementationName(Specification specification, ServiceReference<?> reference) { String bundle = reference.getBundle().getSymbolicName(); if (bundle == null) bundle = (String)reference.getBundle().getHeaders().get("Bundle-Name"); return new ApformOSGiImplementation.Reference(specification.getName()+"[provider.bundle="+bundle+"]"); } /** * Generate the name of the instance in APAM */ private static String generateInstanceName(Specification specification, ServiceReference<?> reference) { return generateImplementationName(specification,reference).getName()+"-"+reference.getProperty(Constants.SERVICE_ID); } }