/* | |
* 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.felix.ipojo.composite.service.provides; | |
import java.util.Comparator; | |
import java.util.Dictionary; | |
import java.util.HashMap; | |
import java.util.Iterator; | |
import java.util.Map; | |
import java.util.Properties; | |
import java.util.Set; | |
import org.apache.felix.ipojo.ServiceContext; | |
import org.apache.felix.ipojo.composite.CompositeManager; | |
import org.apache.felix.ipojo.util.DependencyModel; | |
import org.apache.felix.ipojo.util.DependencyStateListener; | |
import org.apache.felix.ipojo.util.SecurityHelper; | |
import org.osgi.framework.BundleContext; | |
import org.osgi.framework.Filter; | |
import org.osgi.framework.ServiceReference; | |
import org.osgi.framework.ServiceRegistration; | |
/** | |
* Export an service from the scope to the parent context. | |
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> | |
*/ | |
public class ServiceExporter extends DependencyModel { | |
/** | |
* Destination context. | |
*/ | |
private BundleContext m_destination; | |
/** | |
* Composite Manager. | |
*/ | |
private CompositeManager m_manager; | |
/** | |
* Map of service reference - service registration storing exported services. | |
*/ | |
private Map/*<ServiceReference, ServiceRegistration>*/m_registrations = new HashMap(); | |
/** | |
* Constructor. | |
* | |
* @param specification : exported service specification. | |
* @param filter : LDAP filter | |
* @param multiple : is the export an aggregate export? | |
* @param optional : is the export optional? | |
* @param cmp : comparator to use in the dependency | |
* @param policy : binding policy. | |
* @param from : internal service context | |
* @param dest : parent bundle context | |
* @param listener : dependency lifecycle listener to notify when the dependency state change. | |
* @param manager : composite manager | |
*/ | |
public ServiceExporter(Class specification, Filter filter, boolean multiple, boolean optional, Comparator cmp, int policy, ServiceContext from, BundleContext dest, DependencyStateListener listener, CompositeManager manager) { | |
super(specification, multiple, optional, filter, cmp, policy, from, listener, manager); | |
m_destination = dest; | |
m_manager = manager; | |
} | |
/** | |
* Transform service reference property in a dictionary. | |
* instance.name and factory.name are injected too. | |
* @param ref : the service reference. | |
* @return the dictionary containing all property of the given service reference. | |
*/ | |
private Dictionary getProps(ServiceReference ref) { | |
Properties prop = new Properties(); | |
String[] keys = ref.getPropertyKeys(); | |
for (int i = 0; i < keys.length; i++) { | |
prop.put(keys[i], ref.getProperty(keys[i])); | |
} | |
prop.put("instance.name", m_manager.getInstanceName()); | |
prop.put("factory.name", m_manager.getFactory().getName()); | |
return prop; | |
} | |
/** | |
* Stop an exporter. | |
* Remove the service listener | |
* Unregister all exported services. | |
*/ | |
public void stop() { | |
super.stop(); | |
Set refs = m_registrations.keySet(); | |
Iterator iterator = refs.iterator(); | |
while (iterator.hasNext()) { | |
ServiceReference ref = (ServiceReference) iterator.next(); | |
ServiceRegistration reg = (ServiceRegistration) m_registrations.get(ref); | |
try { | |
reg.unregister(); | |
} catch (IllegalStateException e) { | |
// The service is already unregistered | |
// Do nothing silently | |
} | |
} | |
m_registrations.clear(); | |
} | |
/** | |
* A service has been injected. Register it. | |
* @param reference : the new reference. | |
* @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference) | |
*/ | |
public void onServiceArrival(ServiceReference reference) { | |
Object svc = getService(reference); | |
// Security Check | |
if (SecurityHelper.hasPermissionToRegisterService(getSpecification().getName(), m_destination)) { | |
ServiceRegistration reg = m_destination | |
.registerService(getSpecification().getName(), svc, getProps(reference)); | |
m_registrations.put(reference, reg); | |
} else { | |
throw new SecurityException("The bundle " + m_destination.getBundle().getBundleId() + " does not have the " | |
+ "permission to register the service " + getSpecification().getName()); | |
} | |
} | |
/** | |
* An exported service was modified. | |
* @param reference : modified reference | |
* @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object) | |
*/ | |
public void onServiceModification(ServiceReference reference) { | |
ServiceRegistration reg = (ServiceRegistration) m_registrations.get(reference); | |
if (reg != null) { | |
reg.setProperties(getProps(reference)); | |
} | |
} | |
/** | |
* An exported service disappears. | |
* @param reference : service reference | |
* @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object) | |
*/ | |
public void onServiceDeparture(ServiceReference reference) { | |
ServiceRegistration reg = (ServiceRegistration) m_registrations.get(reference); | |
if (reg != null) { | |
reg.unregister(); | |
} | |
m_registrations.remove(reference); | |
} | |
/** | |
* On Dependency Reconfiguration notification method. | |
* @param departs : leaving service references. | |
* @param arrivals : new injected service references. | |
* @see org.apache.felix.ipojo.util.DependencyModel#onDependencyReconfiguration(org.osgi.framework.ServiceReference[], org.osgi.framework.ServiceReference[]) | |
*/ | |
public void onDependencyReconfiguration(ServiceReference[] departs, ServiceReference[] arrivals) { | |
throw new UnsupportedOperationException("Dynamic dependency reconfiguration is not supported by service exporter"); | |
} | |
} |