/* * 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.junit4osgi.helpers; 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.Handler; import org.apache.felix.ipojo.HandlerFactory; import org.apache.felix.ipojo.ServiceContext; import org.apache.felix.ipojo.architecture.Architecture; import org.apache.felix.ipojo.junit4osgi.Helper; import org.apache.felix.ipojo.junit4osgi.OSGiTestCase; import org.apache.felix.ipojo.metadata.Element; import org.apache.felix.ipojo.parser.ManifestMetadataParser; import org.apache.felix.ipojo.parser.ParseException; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; import org.osgi.service.cm.ManagedServiceFactory; /** * iPOJO Helper. * This helper helps getting {@link Factory}, and managing * {@link ComponentInstance}. * @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a> */ public class IPOJOHelper extends Helper { /** * The bundle context. */ private BundleContext m_context; /** * The test case. */ private OSGiTestCase m_testcase; /** * List of instances. */ private List m_instances; /** * Creates a IPOJOHelper. * @param tc the OSGi Test Case */ public IPOJOHelper(OSGiTestCase tc) { super(tc); m_testcase = tc; m_context = m_testcase.getBundleContext(); m_instances = new ArrayList(); } /** * Disposes created instances. * @see org.apache.felix.ipojo.junit4osgi.Helper#dispose() */ public void dispose() { for (int i = 0; i < m_instances.size(); i++) { ((ComponentInstance) m_instances.get(i)).dispose(); } m_instances.clear(); } /** * Gets a created instance from the instance name. * @param name the instance name. * @return the created {@link ComponentInstance} or <code>null</code> * if the instance was not created during the session. */ public ComponentInstance getInstanceByName(String name) { for (int i = 0; i < m_instances.size(); i++) { if (((ComponentInstance) m_instances.get(i)).getInstanceName() .equals(name)) { return (ComponentInstance) m_instances.get(i); } } return null; } /** * Creates a new component instance with the given name (and empty * configuration), from the factory specified in the given bundle. * * @param bundle the bundle from which the component factory is defined. * @param factoryName the name of the component factory, defined in the * specified bundle. * @param instanceName the name of the component instance to create. * @return the newly created component instance. */ public static ComponentInstance createComponentInstance(Bundle bundle, String factoryName, String instanceName) { // Create the instance configuration Properties configuration = new Properties(); configuration.put("instance.name", instanceName); return createComponentInstance(bundle, factoryName, configuration); } /** * Creates a new component instance with the given configuration, from the * factory specified in the given bundle. * * @param bundle the bundle from which the component factory is defined. * @param factoryName the name of the component factory, defined in the * specified bundle. * @param configuration the configuration of the component instance to * create. * @return the newly created component instance. */ public static ComponentInstance createComponentInstance(Bundle bundle, String factoryName, Dictionary configuration) { // Retrieve the component factory. Factory fact = getFactory(bundle, factoryName); if (fact == null) { // Factory not found... throw new IllegalArgumentException( "Cannot find the component factory (" + factoryName + ") in the specified bundle (" + bundle.getSymbolicName() + ")."); } try { return fact.createComponentInstance(configuration); } catch (Exception e) { throw new IllegalArgumentException( "Cannot create the component instance with the given configuration:" + e.getMessage()); } } /** * Creates a new component instance with the given name and configuration, * from the factory specified in the given bundle. * * @param bundle the bundle from which the component factory is defined. * @param factoryName the name of the component factory, defined in the * specified bundle. * @param instanceName the name of the component instance to create. * @param configuration the configuration of the instance to create. * @return the newly created component instance. */ public static ComponentInstance createComponentInstance(Bundle bundle, String factoryName, String instanceName, Dictionary configuration) { // Add the instance name to the configuration configuration.put("instance.name", instanceName); return createComponentInstance(bundle, factoryName, configuration); } /** * Creates a new component instance with the given name (and an empty * configuration), from the factory specified in the given service context. * * @param serviceContext the service context in which the component factory * service is registered. * @param factoryName the name of the component factory, defined in the * specified service context. * @param instanceName the name of the component instance to create. * @return the newly created component instance. */ public static ComponentInstance createComponentInstance( ServiceContext serviceContext, String factoryName, String instanceName) { // Create the instance configuration Properties configuration = new Properties(); configuration.put("instance.name", instanceName); return createComponentInstance(serviceContext, factoryName, configuration); } /** * Creates a new component instance with the given name and configuration, * from the factory specified in the given service context. * * @param serviceContext the service context in which the component factory * service is registered. * @param factoryName the name of the component factory, defined in the * specified service context. * @param configuration the configuration of the instance to create. * @return the newly created component instance. */ public static ComponentInstance createComponentInstance( ServiceContext serviceContext, String factoryName, Dictionary configuration) { // Retrieve the component factory. Factory fact = getFactory(serviceContext, factoryName); if (fact == null) { // Factory not found... throw new IllegalArgumentException( "Cannot find the component factory (" + factoryName + ") in the specified service context."); } try { return fact.createComponentInstance(configuration); } catch (Exception e) { throw new IllegalArgumentException( "Cannot create the component instance with the given configuration: " + e.getMessage()); } } /** * Creates a new component instance with the given name and configuration, * from the factory specified in the given service context. * * @param serviceContext the service context in which the component factory * service is registered. * @param factoryName the name of the component factory, defined in the * specified service context. * @param instanceName the name of the component instance to create. * @param configuration the configuration of the instance to create. * @return the newly created component instance. */ public static ComponentInstance createComponentInstance( ServiceContext serviceContext, String factoryName, String instanceName, Dictionary configuration) { // Add the instance name to the configuration configuration.put("instance.name", instanceName); return createComponentInstance(serviceContext, factoryName, configuration); } /** * Creates a new component instance with the given name (and empty * configuration), from the factory specified in the local bundle. * * @param factoryName the name of the component factory, defined in the * local bundle. * @param instanceName the name of the component instance to create. * @return the newly created component instance. */ public ComponentInstance createComponentInstance(String factoryName, String instanceName) { ComponentInstance ci = createComponentInstance(m_context.getBundle(), factoryName, instanceName); m_instances.add(ci); return ci; } /** * Creates a new component instance with the given configuration, from the * factory specified in the local bundle. * * @param factoryName the name of the component factory, in the local * bundle. * @param configuration the configuration of the component instance to * create. * @return the newly created component instance. */ public ComponentInstance createComponentInstance(String factoryName, Dictionary configuration) { ComponentInstance ci = createComponentInstance(m_context.getBundle(), factoryName, configuration); m_instances.add(ci); return ci; } /** * Creates a new component instance with no configuration, from the factory * specified in the local bundle. * * @param factoryName the name of the component factory, in the local * bundle. * @return the newly created component instance. */ public ComponentInstance createComponentInstance(String factoryName) { ComponentInstance ci = createComponentInstance(m_context.getBundle(), factoryName, (Dictionary) null); m_instances.add(ci); return ci; } /** * Creates a new component instance with the given name and configuration, * from the factory specified in the given bundle. * * @param factoryName the name of the component factory, defined in the * specified bundle. * @param instanceName the name of the component instance to create. * @param configuration the configuration of the instance to create. * @return the newly created component instance. */ public ComponentInstance createComponentInstance(String factoryName, String instanceName, Dictionary configuration) { ComponentInstance ci = createComponentInstance(m_context.getBundle(), factoryName, instanceName, configuration); m_instances.add(ci); return ci; } /** * Returns the component factory with the given name in the local bundle. * * @param factoryName the name of the factory to retrieve. * @return the component factory with the given name in the local bundle, or * {@code null} if not found. */ public Factory getFactory(String factoryName) { return getFactory(m_context.getBundle(), factoryName); } /** * Returns the handler factory with the given name in the local bundle. * * @param factoryName the name of the handler factory to retrieve. * @return the handler factory with the given name in the local bundle, or * {@code null} if not found. */ public HandlerFactory getHandlerFactory(String factoryName) { return getHandlerFactory(m_context.getBundle(), factoryName); } /** * Returns the metadata description of the component defined in this bundle. * * @param component the name of the locally defined component. * @return the metadata description of the component with the given name, * defined in this given bundle, or {@code null} if not found. */ public Element getMetadata(String component) { return getMetadata(m_context.getBundle(), component); } /** * Returns the component factory with the given name in the given bundle. * * @param bundle the bundle from which the component factory is defined. * @param factoryName the name of the defined factory. * @return the component factory with the given name in the given bundle, or * {@code null} if not found. */ public static Factory getFactory(Bundle bundle, String factoryName) { ServiceReference[] refs; try { // Retrieves the component factories services in the bundle. refs = bundle.getBundleContext().getServiceReferences( Factory.class.getName(), "(factory.name=" + factoryName + ")"); if (refs != null) { return (Factory) bundle.getBundleContext().getService(refs[0]); } // Factory not found... return null; } catch (InvalidSyntaxException e) { throw new IllegalArgumentException( "Cannot get the component factory services: " + e.getMessage()); } } /** * Returns the component factory with the given name, registered in the * given service context. * * @param serviceContext the service context in which the factory service is * defined. * @param factoryName the name of the factory. * @return the component factory with the given name, registered in the * given service context. */ public static Factory getFactory(ServiceContext serviceContext, String factoryName) { ServiceReference[] refs; try { // Retrieves the component factories services in the service // context. refs = serviceContext.getServiceReferences(Factory.class.getName(), "(factory.name=" + factoryName + ")"); if (refs != null) { return (Factory) serviceContext.getService(refs[0]); } return null; } catch (InvalidSyntaxException e) { System.err.println("Cannot get the factory " + factoryName + " : " + e.getMessage()); return null; } } /** * Returns the handler factory with the given name in the given bundle. * * @param bundle the bundle from which the handler factory is defined. * @param factoryName the name of the handler factory to retrieve. * @return the handler factory with the given name in the given bundle, or * {@code null} if not found. */ public static HandlerFactory getHandlerFactory(Bundle bundle, String factoryName) { ServiceReference[] refs; try { // Retrieves the handler factories services in the bundle. refs = bundle.getBundleContext().getServiceReferences( HandlerFactory.class.getName(), "(" + Handler.HANDLER_NAME_PROPERTY + "=" + factoryName + ")"); if (refs != null) { return (HandlerFactory) bundle.getBundleContext().getService( refs[0]); } // Factory not found... return null; } catch (InvalidSyntaxException e) { throw new IllegalArgumentException( "Cannot get the handler factory services: " + e.getMessage()); } } /** * Returns the metadata description of the component with the given name, * defined in the given bundle. * * @param bundle the bundle from which the component is defined. * @param component the name of the defined component. * @return the metadata description of the component with the given name, * defined in the given bundle, or {@code null} if not found. */ public static Element getMetadata(Bundle bundle, String component) { // Retrieves the component description from the bundle's manifest. String elem = (String) bundle.getHeaders().get("iPOJO-Components"); if (elem == null) { throw new IllegalArgumentException( "Cannot find iPOJO-Components descriptor in the specified bundle (" + bundle.getSymbolicName() + "). Not an iPOJO bundle."); } // Parses the retrieved description and find the component with the // given name. try { Element element = ManifestMetadataParser.parseHeaderMetadata(elem); Element[] childs = element.getElements("component"); for (int i = 0; i < childs.length; i++) { String name = childs[i].getAttribute("name"); String clazz = childs[i].getAttribute("classname"); if (name != null && name.equalsIgnoreCase(component)) { return childs[i]; } if (clazz.equalsIgnoreCase(component)) { return childs[i]; } } // Component not found... return null; } catch (ParseException e) { throw new IllegalStateException( "Cannot parse the components from specified bundle (" + bundle.getSymbolicName() + "): " + e.getMessage()); } } /** * Returns the service object of a service registered in the specified * service context, offering the specified interface and matching the given * filter. * * @param serviceContext the service context in which the service is * searched. * @param itf the interface provided by the searched service. * @param filter an additional filter (can be {@code null}). * @return the service object provided by the specified bundle, offering the * specified interface and matching the given filter. */ public static Object getServiceObject(ServiceContext serviceContext, String itf, String filter) { ServiceReference ref = getServiceReference(serviceContext, itf, filter); if (ref != null) { return serviceContext.getService(ref); } else { return null; } } /** * Returns the service objects of the services registered in the specified * service context, offering the specified interface and matching the given * filter. * * @param serviceContext the service context in which services are searched. * @param itf the interface provided by the searched services. * @param filter an additional filter (can be {@code null}). * @return the service objects provided by the specified bundle, offering * the specified interface and matching the given filter. */ public static Object[] getServiceObjects(ServiceContext serviceContext, String itf, String filter) { ServiceReference[] refs = getServiceReferences(serviceContext, itf, filter); if (refs != null) { Object[] list = new Object[refs.length]; for (int i = 0; i < refs.length; i++) { list[i] = serviceContext.getService(refs[i]); } return list; } else { return new Object[0]; } } /** * Returns the service reference of a service registered in the specified * service context, offering the specified interface and matching the given * filter. * * @param serviceContext the service context in which services are searched. * @param itf the interface provided by the searched service. * @param filter an additional filter (can be {@code null}). * @return a service reference registered in the specified service context, * offering the specified interface and matching the given filter. * If no service is found, {@code null} is returned. */ public static ServiceReference getServiceReference( ServiceContext serviceContext, String itf, String filter) { ServiceReference[] refs = getServiceReferences(serviceContext, itf, filter); if (refs.length != 0) { return refs[0]; } else { // No service found return null; } } /** * Returns the service reference of the service registered in the specified * service context, offering the specified interface and having the given * persistent ID. * * @param serviceContext the service context in which services are searched. * @param itf the interface provided by the searched service. * @param pid the persistent ID of the searched service. * @return a service registered in the specified service context, offering * the specified interface and having the given persistent ID. */ public static ServiceReference getServiceReferenceByPID( ServiceContext serviceContext, String itf, String pid) { String filter = "(" + "service.pid" + "=" + pid + ")"; ServiceReference[] refs = getServiceReferences(serviceContext, itf, filter); if (refs == null) { return null; } else if (refs.length == 1) { return refs[0]; } else { throw new IllegalStateException( "A service lookup by PID returned several providers (" + refs.length + ")" + " for " + itf + " with pid=" + pid); } } /** * Returns the service reference of all the services registered in the * specified service context, offering the specified interface and matching * the given filter. * * @param serviceContext the service context in which services are searched. * @param itf the interface provided by the searched services. * @param filter an additional filter (can be {@code null}). * @return all the service references registered in the specified service * context, offering the specified interface and matching the given * filter. If no service matches, an empty array is returned. */ public static ServiceReference[] getServiceReferences( ServiceContext serviceContext, String itf, String filter) { ServiceReference[] refs = null; try { // Get all the service references refs = serviceContext.getServiceReferences(itf, filter); } catch (InvalidSyntaxException e) { throw new IllegalArgumentException( "Cannot get service references: " + e.getMessage()); } if (refs == null) { return new ServiceReference[0]; } else { return refs; } } /** * Returns the service reference of a service registered in the specified * service context, offering the specified interface and having the given * name. * * @param serviceContext the service context in which services are searched. * @param itf the interface provided by the searched service. * @param name the name of the searched service. * @return a service registered in the specified service context, offering * the specified interface and having the given name. */ public static ServiceReference getServiceReferenceByName( ServiceContext serviceContext, String itf, String name) { String filter = null; if (itf.equals(Factory.class.getName()) || itf.equals(ManagedServiceFactory.class.getName())) { filter = "(" + "factory.name" + "=" + name + ")"; } else if (itf.equals(Architecture.class.getName())) { filter = "(" + "architecture.instance" + "=" + name + ")"; } else { filter = "(" + "instance.name" + "=" + name + ")"; } return getServiceReference(serviceContext, itf, filter); } /** * Checks the availability of a service inside the given service context. * @param sc the service context * @param itf the service interface to found * @return <code>true</code> if the service is available in the service * context, <code>false</code> otherwise. */ public static boolean isServiceAvailable(ServiceContext sc, String itf) { ServiceReference ref = getServiceReference(sc, itf, null); return ref != null; } /** * Checks the availability of a service inside the given service context. * @param sc the service context * @param itf the service interface to found * @param name the service provider name * @return <code>true</code> if the service is available in the service * context, <code>false</code> otherwise. */ public static boolean isServiceAvailableByName(ServiceContext sc, String itf, String name) { ServiceReference ref = getServiceReferenceByName(sc, itf, name); return ref != null; } /** * Checks the availability of a service inside the given service context. * @param sc the service context * @param itf the service interface to found * @param pid the pid of the service * @return <code>true</code> if the service is available in the service * context, <code>false</code> otherwise. */ public static boolean isServiceAvailableByPID(ServiceContext sc, String itf, String pid) { ServiceReference ref = getServiceReferenceByPID(sc, itf, pid); return ref != null; } /** * Returns the service reference of a service provided by the specified * bundle, offering the specified interface and having the given name. * * @param bundle the bundle from which the service is searched. * @param itf the interface provided by the searched service. * @param name the name of the searched service. * @return a service provided by the specified bundle, offering the * specified interface and having the given name. */ public static ServiceReference getServiceReferenceByName(Bundle bundle, String itf, String name) { String filter = null; if (itf.equals(Factory.class.getName()) || itf.equals(ManagedServiceFactory.class.getName())) { filter = "(" + "factory.name" + "=" + name + ")"; } else if (itf.equals(Architecture.class.getName())) { filter = "(" + "architecture.instance" + "=" + name + ")"; } else { filter = "(" + "instance.name" + "=" + name + ")"; } return OSGiTestCase.getServiceReference(bundle, itf, filter); } /** * Returns the service reference of a service provided by the local bundle, * offering the specified interface and having the given name. * * @param itf the interface provided by the searched service. * @param name the name of the searched service. * @return a service provided by the specified bundle, offering the * specified interface and having the given name. */ public ServiceReference getServiceReferenceByName(String itf, String name) { return getServiceReferenceByName(m_context.getBundle(), itf, name); } /** * Checks if the service is available. * @param itf the service interface * @param name the service provider name * @return <code>true</code> if the service is available, <code>false</code> * otherwise. */ public boolean isServiceAvailableByName(String itf, String name) { ServiceReference ref = getServiceReferenceByName(itf, name); return ref != null; } }