blob: 0dc8dfb8b954ca33743d562ead8c85b53856d67c [file] [log] [blame]
/*
* 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.context;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.felix.ipojo.ComponentInstance;
import org.apache.felix.ipojo.InstanceManager;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
/**
* Internal service registration implementation. This class is used for in the
* composition.
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class ServiceRegistrationImpl implements ServiceRegistration {
/**
* Service Registry.
*/
private ServiceRegistry m_registry = null;
/**
* Interfaces associated with the service object.
*/
private String[] m_classes = null;
/**
* Service Id associated with the service object.
*/
private Long m_serviceId = null;
/**
* Service object.
*/
private Object m_svcObj = null;
/**
* Service factory interface.
*/
private ServiceFactory m_factory = null;
/**
* Associated property dictionary.
*/
private Map m_propMap = null;
/**
* Re-usable service reference.
*/
private ServiceReferenceImpl m_ref = null;
/**
* Property Keys List.
*/
private List m_list = new ArrayList();
/**
* Constructor.
*
* @param registry : the service registry
* @param instance : component instance
* @param classes : published interfaces array
* @param serviceId : the unique service id
* @param svcObj : the service object or the service factory object
* @param dict : service properties
*/
public ServiceRegistrationImpl(ServiceRegistry registry, ComponentInstance instance, String[] classes, Long serviceId, Object svcObj, Dictionary dict) {
m_registry = registry;
m_classes = classes;
m_serviceId = serviceId;
m_svcObj = svcObj;
if (m_svcObj instanceof ServiceFactory) { m_factory = (ServiceFactory) m_svcObj; }
initializeProperties(dict);
// This reference is the "standard" reference for this service and will
// always be returned by getReference().
// Since all reference to this service are supposed to be equal, we use
// the hash code of this reference for
// a references to this service in ServiceReference.
m_ref = new ServiceReferenceImpl(instance, this);
}
/**
* Check if the service registration still valid.
* @return true if the service registration is valid.
*/
protected boolean isValid() {
return m_svcObj != null;
}
/**
* Get the service reference attached with this service registration.
* @return the service reference
* @see org.osgi.framework.ServiceRegistration#getReference()
*/
public ServiceReference getReference() {
return m_ref;
}
/**
* Add properties to a service registration.
* @param dict : the properties to add
* @see org.osgi.framework.ServiceRegistration#setProperties(java.util.Dictionary)
*/
public void setProperties(Dictionary dict) {
// Make sure registration is valid.
if (!isValid()) {
throw new IllegalStateException("The service registration is no longer valid.");
}
// Set the properties.
initializeProperties(dict);
// Tell registry about it.
m_registry.servicePropertiesModified(this);
}
/**
* Unregister the service.
* @see org.osgi.framework.ServiceRegistration#unregister()
*/
public void unregister() {
if (m_svcObj == null) {
throw new IllegalStateException("Service already unregistered.");
} else {
m_registry.unregisterService(this);
m_svcObj = null;
m_factory = null;
}
}
/**
* Look for a property in the service properties.
* @param key : property key
* @return the object associated with the key or null if the key is not
* present.
*/
protected Object getProperty(String key) {
return m_propMap.get(key);
}
/**
* Get the property keys.
* @return the property keys list.
*/
protected String[] getPropertyKeys() {
synchronized (m_propMap) {
m_list.clear();
Iterator iterator = m_propMap.entrySet().iterator();
while (iterator.hasNext()) {
Map.Entry entry = (Map.Entry) iterator.next();
m_list.add(entry.getKey());
}
return (String[]) m_list.toArray(new String[m_list.size()]);
}
}
/**
* Gets the published properties.
* @return the dictionary containing each published properties.
*/
protected Dictionary getProperties() {
synchronized (m_propMap) {
Dictionary dict = new Properties();
Iterator keys = m_propMap.keySet().iterator();
while (keys.hasNext()) {
String key = (String) keys.next();
dict.put(key, m_propMap.get(key));
}
return dict;
}
}
/**
* Get the service object.
* @return the service object. Call the service factory if needed.
*/
protected Object getService() {
// If the service object is a service factory, then
// let it create the service object.
if (m_factory == null) {
return m_svcObj;
} else {
return getFactoryUnchecked();
}
}
/**
* Initialize properties.
* @param dict : service properties to publish.
*/
private void initializeProperties(Dictionary dict) {
// Create a case insensitive map.
if (m_propMap == null) {
m_propMap = new StringMap(false);
} else {
m_propMap.clear();
}
if (dict != null) {
Enumeration keys = dict.keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
m_propMap.put(key, dict.get(key));
}
}
// Add the framework assigned properties.
m_propMap.put(Constants.OBJECTCLASS, m_classes);
m_propMap.put(Constants.SERVICE_ID, m_serviceId);
}
/**
* Get a service object via a service factory.
* @return the service object via the service factory invocation.
*/
private Object getFactoryUnchecked() {
return m_factory.getService(null, this);
}
/**
* Unget a service. (Internal Method)
*
* @param instance : component instance using the service.
* @param svcObj : the unget service object.
*/
private void ungetFactoryUnchecked(ComponentInstance instance, Object svcObj) {
if (instance instanceof InstanceManager) {
m_factory.ungetService(((InstanceManager) instance).getContext().getBundle(), this, svcObj);
}
}
/**
* Unget a service.
*
* @param instance : component instance using the service.
* @param srvObj : the unget service object.
*/
public void ungetService(ComponentInstance instance, Object srvObj) {
// If the service object is a service factory, then let is release the
// service object.
if (m_factory != null) {
ungetFactoryUnchecked(instance, srvObj);
}
}
}