/******************************************************************************
* Copyright (c) 2006, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Apache License v2.0 which accompanies this distribution.
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html and the Apache License v2.0
* is available at http://www.opensource.org/licenses/apache2.0.php.
* You may elect to redistribute this code under either of these licenses.
*
* Contributors:
* VMware Inc.
*****************************************************************************/
package org.eclipse.gemini.blueprint.blueprint.reflect;
import java.util.Collection;
import java.util.List;
import org.eclipse.gemini.blueprint.service.exporter.support.DefaultInterfaceDetector;
import org.osgi.service.blueprint.reflect.BeanArgument;
import org.osgi.service.blueprint.reflect.BeanMetadata;
import org.osgi.service.blueprint.reflect.BeanProperty;
import org.osgi.service.blueprint.reflect.ComponentMetadata;
import org.osgi.service.blueprint.reflect.ReferenceListMetadata;
import org.osgi.service.blueprint.reflect.ReferenceMetadata;
import org.osgi.service.blueprint.reflect.ServiceMetadata;
import org.osgi.service.blueprint.reflect.ServiceReferenceMetadata;
import org.osgi.service.blueprint.reflect.Target;
import org.springframework.beans.BeanMetadataElement;
import org.springframework.beans.MutablePropertyValues;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConstructorArgumentValues;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.util.StringUtils;
/**
* Adapter factory that allows translating OSGi Blueprint metadata into Spring's {@link BeanDefinition}.
*
* @author Costin Leau
*/
class BeanDefinitionFactory implements MetadataConstants {
BeanDefinition buildBeanDefinitionFor(ComponentMetadata metadata) {
// shortcut (to avoid re-rewrapping)
if (metadata instanceof SimpleComponentMetadata) {
return ((SimpleComponentMetadata) metadata).getBeanDefinition();
}
AbstractBeanDefinition definition = buildBeanDefinition(metadata);
// add common properties
definition.setAttribute(MetadataConstants.COMPONENT_METADATA_ATTRIBUTE, metadata);
definition.setAttribute(MetadataConstants.COMPONENT_NAME, metadata.getId());
// Set<String> dependencies = metadata.;
// definition.setDependsOn(dependencies.toArray(new String[dependencies.size()]));
throw new UnsupportedOperationException("move depends on for BeanMetadata");
// return definition;
}
private AbstractBeanDefinition buildBeanDefinition(ComponentMetadata metadata) {
if (metadata instanceof BeanMetadata) {
return buildLocalComponent((BeanMetadata) metadata);
}
if (metadata instanceof ServiceMetadata) {
return buildExporter((ServiceMetadata) metadata);
}
if (metadata instanceof ServiceReferenceMetadata) {
if (metadata instanceof ReferenceListMetadata) {
return buildReferenceCollection((ReferenceListMetadata) metadata);
}
if (metadata instanceof ReferenceMetadata) {
return buildReferenceProxy((ReferenceMetadata) metadata);
}
}
// unknown rich metadata type, unable to perform conversion
throw new IllegalArgumentException("Unknown metadata type" + metadata.getClass());
}
@SuppressWarnings("unchecked")
private AbstractBeanDefinition buildLocalComponent(BeanMetadata metadata) {
// add basic definition properties
BeanDefinitionBuilder builder =
BeanDefinitionBuilder.genericBeanDefinition(metadata.getClassName()).setInitMethodName(
metadata.getInitMethod()).setDestroyMethodName(metadata.getDestroyMethod()).setLazyInit(
getLazy(metadata)).setScope(metadata.getScope());
// add factory-method/factory-bean
String factoryMethod = metadata.getFactoryMethod();
if (StringUtils.hasText(factoryMethod)) {
builder.setFactoryMethod(factoryMethod);
Target factory = metadata.getFactoryComponent();
if (factory != null) {
builder.getRawBeanDefinition().setFactoryBeanName(((ComponentMetadata) factory).getId());
}
}
// add constructor props
List<BeanArgument> beanArguments = metadata.getArguments();
ConstructorArgumentValues cargs = builder.getRawBeanDefinition().getConstructorArgumentValues();
for (BeanArgument arg : beanArguments) {
int index = arg.getIndex();
Object val = BeanMetadataElementFactory.buildBeanMetadata(arg.getValue());
if (index > -1) {
cargs.addGenericArgumentValue(val, arg.getValueType());
} else {
cargs.addIndexedArgumentValue(index, val, arg.getValueType());
}
}
// add property values
Collection<BeanProperty> props = metadata.getProperties();
MutablePropertyValues pvs = new MutablePropertyValues();
for (BeanProperty injection : props) {
pvs.addPropertyValue(injection.getName(), BeanMetadataElementFactory
.buildBeanMetadata(injection.getValue()));
}
return builder.getBeanDefinition();
}
private boolean getLazy(ComponentMetadata metadata) {
return (metadata.getActivation() == ComponentMetadata.ACTIVATION_LAZY ? true : false);
}
private AbstractBeanDefinition buildExporter(ServiceMetadata metadata) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(EXPORTER_CLASS);
// add properties
builder.addPropertyValue(EXPORTER_RANKING_PROP, metadata.getRanking());
builder.addPropertyValue(EXPORTER_INTFS_PROP, metadata.getInterfaces());
builder.addPropertyValue(EXPORTER_PROPS_PROP, metadata.getServiceProperties());
builder.addPropertyValue(EXPORTER_AUTO_EXPORT_PROP,
DefaultInterfaceDetector.values()[metadata.getAutoExport() - 1]);
BeanMetadataElement beanMetadata = BeanMetadataElementFactory.buildBeanMetadata(metadata.getServiceComponent());
if (beanMetadata instanceof RuntimeBeanReference) {
builder.addPropertyValue(EXPORTER_TARGET_BEAN_NAME_PROP, beanMetadata);
} else {
builder.addPropertyValue(EXPORTER_TARGET_BEAN_PROP, beanMetadata);
}
// FIXME: add registration listeners
return builder.getBeanDefinition();
}
private AbstractBeanDefinition buildReferenceCollection(ReferenceListMetadata metadata) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(MULTI_SERVICE_IMPORTER_CLASS);
addServiceReferenceProperties(metadata, builder);
throw new UnsupportedOperationException("not implemented yet");
// return builder.getBeanDefinition();
}
private AbstractBeanDefinition buildReferenceProxy(ReferenceMetadata metadata) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(SINGLE_SERVICE_IMPORTER_CLASS);
addServiceReferenceProperties(metadata, builder);
throw new UnsupportedOperationException("not implemented yet");
// return builder.getBeanDefinition();
}
private void addServiceReferenceProperties(ServiceReferenceMetadata referenceMetadata, BeanDefinitionBuilder builder) {
builder.addPropertyValue(IMPORTER_FILTER_PROP, referenceMetadata.getFilter());
builder.addPropertyValue(IMPORTER_INTFS_PROP, referenceMetadata.getInterface());
// FIXME: add binding listeners
}
}