blob: d9b98cc43a01922ddc1837172e4946f94d6624df [file] [log] [blame]
/*
* Copyright 2006 The Apache Software Foundation
*
* Licensed 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.handlers.providedService;
import java.util.logging.Level;
import org.apache.felix.ipojo.ComponentManager;
import org.apache.felix.ipojo.Handler;
import org.apache.felix.ipojo.Activator;
import org.apache.felix.ipojo.metadata.Element;
/**
* @author Clement Escoffier
*
*/
public class ProvidedServiceHandler implements Handler {
/**
* The list of the provided service.
*/
private ProvidedService[] m_providedServices = new ProvidedService[0];
/**
* The component manager.
*/
private ComponentManager m_componentManager;
private void addProvidedService(ProvidedService ps) {
// Verify that the provided service is not already in the array.
for (int i = 0; (m_providedServices != null) && (i < m_providedServices.length); i++) {
if (m_providedServices[i] == ps) { return; }
}
if (m_providedServices.length > 0) {
ProvidedService[] newPS = new ProvidedService[m_providedServices.length + 1];
System.arraycopy(m_providedServices, 0, newPS, 0, m_providedServices.length);
newPS[m_providedServices.length] = ps;
m_providedServices = newPS;
}
else { m_providedServices = new ProvidedService[] {ps}; }
}
/**
* @return the component manager.
*/
public ComponentManager getComponentManager() { return m_componentManager; }
/**
* @return the list of the provided service.
*/
public ProvidedService[] getProvidedService() { return m_providedServices; }
/**
* @see org.apache.felix.ipojo.Handler#configure(org.apache.felix.ipojo.ComponentManager, org.apache.felix.ipojo.metadata.Element)
*/
public void configure(ComponentManager cm, Element componentMetadata) {
// Fix the component managert & clean the provided service list
m_componentManager = cm;
m_providedServices = new ProvidedService[0];
// Create the dependency according to the component metadata
Element[] providedServices = componentMetadata.getElements("Provides");
for (int i = 0; i < providedServices.length; i++) {
// Create a ProvidedServiceMetadata object
// First : create the serviceSpecification array
String[] serviceSpecification = new String[0];
if (providedServices[i].containsAttribute("interface")) {
String serviceSpecificationStr = providedServices[i].getAttribute("interface");
//Get serviceSpecification if exist in the metadata
String[] spec = serviceSpecificationStr.split(",");
serviceSpecification = new String[spec.length];
for (int j = 0; j < spec.length; j++) { serviceSpecification[j] = spec[j].trim(); }
} else {
Element manipulation = m_componentManager.getComponentMetatada().getMetadata().getElements("Manipulation")[0];
serviceSpecification = new String[manipulation.getElements("Interface").length];
for (int j = 0; j < manipulation.getElements("Interface").length; j++) {
serviceSpecification[j] = manipulation.getElements("Interface")[j].getAttribute("name");
}
}
// Get the factory policy
int factory = ProvidedServiceMetadata.SINGLETON_FACTORY;
if (providedServices[i].containsAttribute("factory") && providedServices[i].getAttribute("factory").equals("service")) { factory = ProvidedService.SERVICE_FACTORY; }
// Then create the provided service metadata
ProvidedServiceMetadata psm = new ProvidedServiceMetadata(serviceSpecification, factory);
// Create properties
Element[] dynamicProps = providedServices[i].getElements("DynamicProperty");
Element[] staticProps = providedServices[i].getElements("StaticProperty");
Element[] props = providedServices[i].getElements("Property");
for (int j = 0; j < dynamicProps.length; j++) {
Activator.getLogger().log(Level.WARNING, "[" + m_componentManager.getComponentMetatada().getClassName() + "] Please use property instead of dynamic property");
String name = null;
if (dynamicProps[j].containsAttribute("name")) { name = dynamicProps[j].getAttribute("name"); }
String field = dynamicProps[j].getAttribute("field");
String value = null;
if (dynamicProps[j].containsAttribute("value")) { value = dynamicProps[j].getAttribute("value"); }
String type = null;
if (dynamicProps[j].containsAttribute("type")) { type = dynamicProps[j].getAttribute("type"); }
PropertyMetadata pm = new PropertyMetadata(name, field, type, value);
psm.addProperty(pm);
}
for (int j = 0; j < staticProps.length; j++) {
Activator.getLogger().log(Level.WARNING, "[" + m_componentManager.getComponentMetatada().getClassName() + "] Please use property instead of static property");
String name = staticProps[j].getAttribute("name");
String value = staticProps[j].getAttribute("value");
String type = staticProps[j].getAttribute("type");
PropertyMetadata pm = new PropertyMetadata(name, null, type, value);
psm.addProperty(pm);
}
for (int j = 0; j < props.length; j++) {
String name = null;
if (props[j].containsAttribute("name")) { name = props[j].getAttribute("name"); }
String value = null;
if (props[j].containsAttribute("value")) { value = props[j].getAttribute("value"); }
String type = null;
if (props[j].containsAttribute("type")) { type = props[j].getAttribute("type"); }
String field = null;
if (props[j].containsAttribute("field")) { field = props[j].getAttribute("field"); }
PropertyMetadata pm = new PropertyMetadata(name, field, type, value);
psm.addProperty(pm);
}
// Create the provided service object
ProvidedService ps = new ProvidedService(this, psm);
if (checkProvidedService(ps)) { addProvidedService(ps); }
else {
String itfs = "";
for (int j = 0; j < serviceSpecification.length; j++) {
itfs = itfs + " " + serviceSpecification[j];
}
Activator.getLogger().log(Level.SEVERE, "[" + m_componentManager.getComponentMetatada().getClassName() + "] The provided service" + itfs + " is not valid, it will be removed");
ps = null;
}
}
if (providedServices.length > 0) { m_componentManager.register(this); }
}
private boolean containsInterface(String s) {
Element manipulation = m_componentManager.getComponentMetatada().getMetadata().getElements("Manipulation")[0];
for (int i = 0; i < manipulation.getElements("Interface").length; i++) {
if (manipulation.getElements("Interface")[i].getAttribute("name").equals(s)) {
return true;
}
}
return false;
}
private boolean checkProvidedService(ProvidedService ps) {
for (int i = 0; i < ps.getMetadata().getServiceSpecification().length; i++) {
if (!containsInterface(ps.getMetadata().getServiceSpecification()[i])) {
Activator.getLogger().log(Level.SEVERE, "[" + m_componentManager.getComponentMetatada().getClassName() + "] The service specification " + ps.getMetadata().getServiceSpecification()[i] + " is not implemented by the component class");
return false;
}
}
// Fix internal property type
for (int i = 0; i < ps.getProperties().length; i++) {
Property prop = ps.getProperties()[i];
String field = prop.getMetadata().getField();
if (field == null) {
// Static dependency -> Nothing to check
return true;
} else {
Element manipulation = getComponentManager().getComponentMetatada().getMetadata().getElements("Manipulation")[0];
String type = null;
for (int j = 0; j < manipulation.getElements("Field").length; j++) {
if (field.equals(manipulation.getElements("Field")[j].getAttribute("name"))) {
type = manipulation.getElements("Field")[j].getAttribute("type");
break;
}
}
if (type == null) {
Activator.getLogger().log(Level.SEVERE, "[" + m_componentManager.getComponentMetatada().getClassName() + "] A declared property was not found in the class : " + prop.getMetadata().getField());
return false;
}
if (type != null) {
if (type.endsWith("[]")) {
// TODO array property
Activator.getLogger().log(Level.SEVERE, "[" + m_componentManager.getComponentMetatada().getClassName() + "] An array property was found in the class [Not implemented yet] : " + prop.getMetadata().getField());
return false;
}
if (prop.getMetadata().getType() == null) { prop.getMetadata().setType(type); }
if (!prop.getMetadata().getType().equals(type)) {
Activator.getLogger().log(Level.WARNING, "[" + m_componentManager.getComponentMetatada().getClassName() + "] The field type [" + type + "] and the declared type [" + prop.getMetadata().getType() + "] are not the same for " + prop.getMetadata().getField());
prop.getMetadata().setType(type);
}
}
else {
Activator.getLogger().log(Level.WARNING, "[" + m_componentManager.getComponentMetatada().getClassName() + "] The declared property " + prop.getMetadata().getField() + " does not exist in the code");
}
}
}
return true;
}
/**
* Stop the provided service handler : unregister all provided services.
* @see org.apache.felix.ipojo.Handler#stop()
*/
public void stop() {
for (int i = 0; i < m_providedServices.length; i++) {
m_providedServices[i].unregisterService();
}
}
/**
* Start the provided service handler : register the service if the component is resolved.
* Else do nothing and whait for a component state change event
* @see org.apache.felix.ipojo.Handler#start()
*/
public void start() {
Activator.getLogger().log(Level.INFO, "[" + m_componentManager.getComponentMetatada().getClassName() + "] Start the provided service handler");
for (int i = 0; (m_componentManager.getState() == ComponentManager.VALID) && i < m_providedServices.length; i++) {
m_providedServices[i].registerService();
}
}
/**
* @see org.apache.felix.ipojo.Handler#setterCallback(java.lang.String, java.lang.Object)
*/
public void setterCallback(String fieldName, Object value) {
// Verify that the field name coreespond to a dependency
for (int i = 0; i < m_providedServices.length; i++) {
ProvidedService ps = m_providedServices[i];
for (int j = 0; j < ps.getProperties().length; j++) {
Property prop = ps.getProperties()[j];
if (fieldName.equals(prop.getMetadata().getField())) {
// it is the associated property
prop.set(value);
}
}
}
//Else do nothing
}
/**
* @see org.apache.felix.ipojo.Handler#getterCallback(java.lang.String, java.lang.Object)
*/
public Object getterCallback(String fieldName, Object value) {
for (int i = 0; i < m_providedServices.length; i++) {
ProvidedService ps = m_providedServices[i];
for (int j = 0; j < ps.getProperties().length; j++) {
Property prop = ps.getProperties()[j];
if (fieldName.equals(prop.getMetadata().getField())) {
// it is the associated property
return prop.get();
}
}
}
// Else it is not a property
return value;
}
/**
* @see org.apache.felix.ipojo.Handler#isValid()
*/
public boolean isValid() {
// The provided service handler does not need to manipulate the field
// Return always true
return true;
}
/**
* Register the services if the new state is VALID.
* Unregister the services if the new state is UNRESOLVED.
* @see org.apache.felix.ipojo.Handler#stateChanged(int)
*/
public void stateChanged(int state) {
// If the new state is UNRESOLVED => unregister all the services
if (state == ComponentManager.INVALID) {
stop();
return;
}
// If the new state is VALID => regiter all the services
if (state == ComponentManager.VALID) {
start();
return;
}
}
}