blob: 5bdc75ebd4e6b1dfb2bc89c4e4895983c2347011 [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.composite;
import java.io.File;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.List;
import java.util.Properties;
import org.apache.felix.ipojo.ComponentInstance;
import org.apache.felix.ipojo.Factory;
import org.apache.felix.ipojo.IPojoContext;
import org.apache.felix.ipojo.ServiceContext;
import org.apache.felix.ipojo.context.ServiceReferenceImpl;
import org.apache.felix.ipojo.context.ServiceRegistry;
import org.apache.felix.ipojo.util.Tracker;
import org.apache.felix.ipojo.util.TrackerCustomizer;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleListener;
import org.osgi.framework.Filter;
import org.osgi.framework.FrameworkListener;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
/**
* CompositeServiceContext Class. This class provides an implementation of the
* service context for composite.
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class CompositeServiceContext implements ServiceContext, TrackerCustomizer {
/**
* Structure storing the reference, the factory and the registration.
*/
private class Record {
/**
* Reference of the represented factory from the external context.
*/
private ServiceReference m_ref;
/**
* Registration of the factory in the internal context.
*/
private ServiceRegistration m_reg;
/**
* Represented Factory.
*/
private FactoryProxy m_fact;
}
/**
* List of imported factories.
*/
private List m_factories = new ArrayList();
/**
* Internal service registry.
*/
private ServiceRegistry m_registry;
/**
* Component Instance who creates this registry.
*/
private ComponentInstance m_instance;
/**
* Global service context.
*/
private BundleContext m_global;
/**
* Tracker tracking Factories to import.
*/
private Tracker m_tracker;
/**
* Constructor. This constructor instantiate a service registry with the
* given bundle context.
*
* @param context : the bundle context
*/
public CompositeServiceContext(BundleContext context) {
m_registry = new ServiceRegistry(context);
if (context instanceof IPojoContext) {
m_global = ((IPojoContext) context).getGlobalContext();
} else {
m_global = context; // the parent context is the global context
}
}
/**
* Constructor.
*
* @param context : the bundle context
* @param instance : the component instance owning this context
*/
public CompositeServiceContext(BundleContext context, ComponentInstance instance) {
this(context);
m_instance = instance;
}
/**
* Add a service listener.
* @param arg0 : The service listener to add
* @see org.apache.felix.ipojo.ServiceContext#addServiceListener(org.osgi.framework.ServiceListener)
*/
public void addServiceListener(ServiceListener arg0) {
m_registry.addServiceListener(arg0);
}
/**
* Add a filtered service listener.
* @param arg0 : the service listener object to add
* @param arg1 : the LDAP filter for this listener
* @throws InvalidSyntaxException : occurs if the LDAP filter is malformed
* @see org.apache.felix.ipojo.ServiceContext#addServiceListener(org.osgi.framework.ServiceListener,
* java.lang.String)
*/
public void addServiceListener(ServiceListener arg0, String arg1) throws InvalidSyntaxException {
m_registry.addServiceListener(arg0, arg1);
}
/**
* Get all service references.
* @param arg0 : The required service interface.
* @param arg1 : LDAP filter
* @return the list of all service reference matching with the query
* @throws InvalidSyntaxException : occurs when the given filter is malformed
* @see org.apache.felix.ipojo.ServiceContext#getAllServiceReferences(java.lang.String,
* java.lang.String)
*/
public ServiceReference[] getAllServiceReferences(String arg0, String arg1) throws InvalidSyntaxException {
return m_registry.getAllServiceReferences(arg0, arg1);
}
/**
* Get a service object for the given service reference.
* @param arg0 : the service reference
* @return the service object or null if the reference is no more valid or if the object is not accessible
* @see org.apache.felix.ipojo.ServiceContext#getService(org.osgi.framework.ServiceReference)
*/
public Object getService(ServiceReference arg0) {
if (arg0 instanceof ServiceReferenceImpl) {
return m_registry.getService(m_instance, arg0);
} else {
throw new RuntimeException("Cannot get a global service from the local registry");
}
}
/**
* Get a service reference for the required interface.
* @param arg0 : the required interface name
* @return the service reference or null if no available provider
* @see org.apache.felix.ipojo.ServiceContext#getServiceReference(java.lang.String)
*/
public ServiceReference getServiceReference(String arg0) {
return m_registry.getServiceReference(arg0);
}
/**
* Get all accessible service reference for the given query.
* @param clazz : required interface
* @param filter : LDAP filter
* @return the list (array) of service reference matching with the query.
* @throws InvalidSyntaxException : occurs when the LDAP filter is malformed
* @see org.apache.felix.ipojo.ServiceContext#getServiceReferences(java.lang.String, java.lang.String)
*/
public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
return m_registry.getServiceReferences(clazz, filter);
}
/**
* Register a service inside the composite context.
* @param arg0 : list of interfaces to register.
* @param arg1 : service object
* @param arg2 : properties list
* @return the service registration
* @see org.apache.felix.ipojo.ServiceContext#registerService(java.lang.String[], java.lang.Object, java.util.Dictionary)
*/
public ServiceRegistration registerService(String[] arg0, Object arg1, Dictionary arg2) {
return m_registry.registerService(m_instance, arg0, arg1, arg2);
}
/**
* Register a service inside the composite context.
* @param arg0 : interface to register.
* @param arg1 : service object
* @param arg2 : properties list
* @return the service registration
* @see org.apache.felix.ipojo.ServiceContext#registerService(java.lang.String, java.lang.Object, java.util.Dictionary)
*/
public ServiceRegistration registerService(String arg0, Object arg1, Dictionary arg2) {
return m_registry.registerService(m_instance, arg0, arg1, arg2);
}
/**
* Remove a service listener.
* @param arg0 : the service listener to remove
* @see org.apache.felix.ipojo.ServiceContext#removeServiceListener(org.osgi.framework.ServiceListener)
*/
public void removeServiceListener(ServiceListener arg0) {
m_registry.removeServiceListener(arg0);
}
/**
* Unget a service.
* @param arg0 the service reference to unget
* @return true
* @see org.apache.felix.ipojo.ServiceContext#ungetService(org.osgi.framework.ServiceReference)
*/
public boolean ungetService(ServiceReference arg0) {
return m_registry.ungetService(m_instance, arg0);
}
/**
* Import a factory form the parent to the internal registry.
*
* @param ref : the reference of the factory to import.
*/
private void importFactory(ServiceReference ref) {
Record rec = new Record();
m_factories.add(rec);
Dictionary dict = new Properties();
for (int j = 0; j < ref.getPropertyKeys().length; j++) {
dict.put(ref.getPropertyKeys()[j], ref.getProperty(ref.getPropertyKeys()[j]));
}
rec.m_fact = new FactoryProxy((Factory) m_tracker.getService(ref), this);
rec.m_reg = registerService(Factory.class.getName(), rec.m_fact, dict);
rec.m_ref = ref;
}
/**
* Remove a factory of the available factory list.
*
* @param ref : the reference on the factory to remove.
*/
private void removeFactory(ServiceReference ref) {
for (int i = 0; i < m_factories.size(); i++) {
Record rec = (Record) m_factories.get(i);
if (rec.m_ref == ref) {
if (rec.m_reg != null) {
rec.m_reg.unregister();
rec.m_fact = null;
}
m_tracker.ungetService(rec.m_ref);
m_factories.remove(rec);
return;
}
}
}
/**
* Start the registry management.
*/
public void start() {
m_tracker = new Tracker(m_global, Factory.class.getName(), this);
m_tracker.open();
}
/**
* Stop the registry management.
*/
public synchronized void stop() {
m_tracker.close();
m_registry.reset();
for (int i = 0; i < m_factories.size(); i++) {
Record rec = (Record) m_factories.get(i);
removeFactory(rec.m_ref);
}
m_tracker = null;
}
/**
* Check if the factory list contain the given reference.
*
* @param ref : the reference to find.
* @return true if the list contains the given reference.
*/
private boolean containsRef(ServiceReference ref) {
for (int i = 0; i < m_factories.size(); i++) {
Record rec = (Record) m_factories.get(i);
if (rec.m_ref == ref) {
return true;
}
}
return false;
}
/**
* Add a bundle listener.
* Delegate on the global bundle context.
* @param arg0 : bundle listener to add
* @see org.osgi.framework.BundleContext#addBundleListener(org.osgi.framework.BundleListener)
*/
public void addBundleListener(BundleListener arg0) {
m_global.addBundleListener(arg0);
}
/**
* Add a framework listener.
* Delegate on the global bundle context.
* @param arg0 : framework listener to add.
* @see org.osgi.framework.BundleContext#addFrameworkListener(org.osgi.framework.FrameworkListener)
*/
public void addFrameworkListener(FrameworkListener arg0) {
m_global.addFrameworkListener(arg0);
}
/**
* Create a LDAP filter.
* @param arg0 : String-form of the filter
* @return the created filter object
* @throws InvalidSyntaxException : if the given argument is not a valid against the LDAP grammar.
* @see org.osgi.framework.BundleContext#createFilter(java.lang.String)
*/
public Filter createFilter(String arg0) throws InvalidSyntaxException {
return m_global.createFilter(arg0);
}
/**
* Get the current bundle.
* @return the current bundle
* @see org.osgi.framework.BundleContext#getBundle()
*/
public Bundle getBundle() {
return m_global.getBundle();
}
/**
* Get the bundle object with the given id.
* @param bundleId : bundle id
* @return the bundle object
* @see org.osgi.framework.BundleContext#getBundle(long)
*/
public Bundle getBundle(long bundleId) {
return m_global.getBundle(bundleId);
}
/**
* Get installed bundles.
* @return the list of installed bundles
* @see org.osgi.framework.BundleContext#getBundles()
*/
public Bundle[] getBundles() {
return m_global.getBundles();
}
/**
* Get a data file.
* @param filename : File name.
* @return the File object
* @see org.osgi.framework.BundleContext#getDataFile(java.lang.String)
*/
public File getDataFile(String filename) {
return m_global.getDataFile(filename);
}
/**
* Get a property value.
* @param key : key of the asked property
* @return the property value (object) or null if no property are associated with the given key
* @see org.osgi.framework.BundleContext#getProperty(java.lang.String)
*/
public String getProperty(String key) {
return m_global.getProperty(key);
}
/**
* Install a bundle.
* @param location : URL of the bundle to install
* @return the installed bundle
* @throws BundleException : if the bundle cannot be installed correctly
* @see org.osgi.framework.BundleContext#installBundle(java.lang.String)
*/
public Bundle installBundle(String location) throws BundleException {
return m_global.installBundle(location);
}
/**
* Install a bundle.
* @param location : URL of the bundle to install
* @param input :
* @return the installed bundle
* @throws BundleException : if the bundle cannot be installed correctly
* @see org.osgi.framework.BundleContext#installBundle(java.lang.String, java.io.InputStream)
*/
public Bundle installBundle(String location, InputStream input) throws BundleException {
return m_global.installBundle(location, input);
}
/**
* Remove a bundle listener.
* @param listener : the listener to remove
* @see org.osgi.framework.BundleContext#removeBundleListener(org.osgi.framework.BundleListener)
*/
public void removeBundleListener(BundleListener listener) {
m_global.removeBundleListener(listener);
}
/**
* Remove a framework listener.
* @param listener : the listener to remove
* @see org.osgi.framework.BundleContext#removeFrameworkListener(org.osgi.framework.FrameworkListener)
*/
public void removeFrameworkListener(FrameworkListener listener) {
m_global.removeFrameworkListener(listener);
}
/**
* A new factory is detected.
* @param reference : service reference
* @return true if not already imported.
* @see org.apache.felix.ipojo.util.TrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
*/
public boolean addingService(ServiceReference reference) {
if (!containsRef(reference)) {
return true;
}
return false;
}
/**
* A matching reference has been added. The import factory can now be imported.
* @param reference : the added reference.
* @see org.apache.felix.ipojo.util.TrackerCustomizer#addedService(org.osgi.framework.ServiceReference)
*/
public void addedService(ServiceReference reference) {
importFactory(reference);
}
/**
* An imported factory is modified.
* @param reference : modified reference
* @param service : factory object.
* @see org.apache.felix.ipojo.util.TrackerCustomizer#modifiedService(org.osgi.framework.ServiceReference, java.lang.Object)
*/
public void modifiedService(ServiceReference reference, Object service) {
for (int i = 0; i < m_factories.size(); i++) {
Record rec = (Record) m_factories.get(i);
if (rec.m_ref == reference) {
Dictionary dict = new Properties();
for (int j = 0; j < reference.getPropertyKeys().length; j++) {
dict.put(reference.getPropertyKeys()[j], reference.getProperty(reference.getPropertyKeys()[j]));
}
rec.m_reg.setProperties(dict);
return;
}
}
}
/**
* An imported factory disappears.
* @param reference : reference
* @param service : factory object.
* @see org.apache.felix.ipojo.util.TrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
*/
public void removedService(ServiceReference reference, Object service) {
if (containsRef(reference)) {
removeFactory(reference);
}
}
}