/* * 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); } } }