blob: e7fd8a9ba389d4722ca4193dfaec95732837d144 [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;
import java.util.Dictionary;
import org.apache.felix.ipojo.util.Logger;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
/**
* An instance creator aims to create instances and to track their factories.
* It's allow to create instance from outside factories.
*
* @author <a href="mailto:dev@felix.apache.org">Felix Project Team</a>
*/
public class InstanceCreator implements ServiceListener {
/**
* Bundle Context.
*/
private BundleContext m_context;
/**
* Logger to log messages if error occurs.
*/
private Logger m_logger;
/**
* This structure aims to manage a configuration. It stores all necessary
* information to create an instance and to track the factory.
*/
private class ManagedConfiguration {
/**
* Configuration of the instance to create.
*/
private Dictionary m_configuration;
/**
* Factory name.
*/
private String m_factoryName;
/**
* Created instance.
*/
private ComponentInstance m_instance;
/**
* Constructor.
*
* @param conf : the configuration to create.
*/
ManagedConfiguration(Dictionary conf) {
m_configuration = conf;
}
/**
* Return the managed configuration.
* @return the configuration.
*/
Dictionary getConfiguration() {
return m_configuration;
}
/**
* Return the used factory name.
* @return the factory
*/
String getFactory() {
return m_factoryName;
}
/**
* Return the created instance.
* @return the instance (or null if no instance are created).
*/
ComponentInstance getInstance() {
return m_instance;
}
/**
* Set the factory name.
*
* @param name : the factory name.
*/
void setFactory(String name) {
m_factoryName = name;
}
/**
* Set the instance object.
*
* @param instance : the instance
*/
void setInstance(ComponentInstance instance) {
m_instance = instance;
}
}
/**
* Configurations to create and maintains.
*/
private ManagedConfiguration[] m_configurations = new ManagedConfiguration[0];
/**
* Constructor.
*
* @param context : the bundle context.
* @param configurations : configuration set to create and maintain.
*/
public InstanceCreator(BundleContext context, Dictionary[] configurations) {
m_context = context;
m_logger = new Logger(context, "InstanceCreator" + context.getBundle().getBundleId(), Logger.WARNING);
m_configurations = new ManagedConfiguration[configurations.length];
for (int i = 0; i < configurations.length; i++) {
ManagedConfiguration conf = new ManagedConfiguration(configurations[i]);
m_configurations[i] = conf;
// Get the component type name :
String componentType = (String) conf.getConfiguration().get("component");
Factory fact = null;
try {
String fil = "(|(" + org.osgi.framework.Constants.SERVICE_PID + "=" + componentType + ")(component.class=" + componentType + ")(component.type=" + componentType + ")";
ServiceReference[] refs = context.getServiceReferences(org.apache.felix.ipojo.Factory.class.getName(), fil);
if (refs != null) {
fact = (Factory) m_context.getService(refs[0]);
createInstance(fact, conf);
} else {
m_logger.log(Logger.WARNING, "No factory available for the type : " + componentType);
}
} catch (InvalidSyntaxException e) {
m_logger.log(Logger.ERROR, "Invalid syntax filter for the type : " + componentType, e);
}
}
// Register a service listenner on Factory Service
try {
m_context.addServiceListener(this, "(objectClass=" + Factory.class.getName() + ")");
} catch (InvalidSyntaxException e) {
m_logger.log(Logger.ERROR, "Invalid syntax filter when registering a listener on Factory Service", e);
}
}
/**
* Create an instance using the given factory and the given configuration.
*
* @param fact : the facotry name to used.
* @param config : the configuration.
*/
private void createInstance(Factory fact, ManagedConfiguration config) {
Dictionary conf = config.getConfiguration();
try {
config.setInstance(fact.createComponentInstance(conf));
config.setFactory(fact.getName());
} catch (UnacceptableConfiguration e) {
m_logger.log(Logger.ERROR, "A factory is available for the configuration but the configuration is not acceptable", e);
}
}
/**
* Service Listener implementation.
* @param ev : the service event
* @see org.osgi.framework.ServiceListener#serviceChanged(org.osgi.framework.ServiceEvent)
*/
public void serviceChanged(ServiceEvent ev) {
ServiceReference ref = ev.getServiceReference();
String factoryName = (String) ref.getProperty(org.osgi.framework.Constants.SERVICE_PID);
String componentClass = (String) ref.getProperty("component.class");
if (ev.getType() == ServiceEvent.REGISTERED) { // A new factory appears
for (int i = 0; i < m_configurations.length; i++) {
if (m_configurations[i].getInstance() == null
&& (m_configurations[i].getConfiguration().get("component").equals(factoryName) || m_configurations[i].getConfiguration().get(
"component").equals(componentClass))) {
Factory fact = (Factory) m_context.getService(ref);
createInstance(fact, m_configurations[i]);
}
}
return;
}
if (ev.getType() == ServiceEvent.UNREGISTERING) {
for (int i = 0; i < m_configurations.length; i++) {
if (m_configurations[i].getInstance() != null && m_configurations[i].getFactory().equals(factoryName)) {
m_configurations[i].setInstance(null);
m_configurations[i].setFactory(null);
m_context.ungetService(ref);
}
}
return;
}
}
/**
* Stop all created instances.
*/
public synchronized void stop() {
m_context.removeServiceListener(this);
for (int i = 0; i < m_configurations.length; i++) {
if (m_configurations[i].getInstance() != null) {
m_configurations[i].getInstance().dispose();
}
m_configurations[i].setInstance(null);
m_configurations[i].setFactory(null);
}
m_configurations = null;
}
}