/****************************************************************************** * 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.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import org.eclipse.gemini.blueprint.blueprint.reflect.SimpleCollectionMetadata.CollectionType; import org.osgi.service.blueprint.reflect.MapEntry; import org.osgi.service.blueprint.reflect.Metadata; import org.osgi.service.blueprint.reflect.NonNullMetadata; import org.osgi.service.blueprint.reflect.NullMetadata; import org.springframework.beans.BeanMetadataElement; import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.config.BeanDefinition; import org.springframework.beans.factory.config.BeanDefinitionHolder; import org.springframework.beans.factory.config.BeanReferenceFactoryBean; import org.springframework.beans.factory.config.RuntimeBeanNameReference; import org.springframework.beans.factory.config.RuntimeBeanReference; import org.springframework.beans.factory.config.TypedStringValue; import org.springframework.beans.factory.support.ManagedArray; import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedMap; import org.springframework.beans.factory.support.ManagedProperties; import org.springframework.beans.factory.support.ManagedSet; /** * Adapter between Spring {@link BeanMetadataElement} and OSGi's Blueprint {@link Value}. * * @see BeanMetadataElementFactory * @author Costin Leau */ class ValueFactory { private static final String BEAN_REF_FB_CLASS_NAME = BeanReferenceFactoryBean.class.getName(); private static final String BEAN_REF_NAME_PROP = "targetBeanName"; /** * Creates the equivalent value for the given Spring metadata. Since Spring's metadata is a superset of the * Blueprint spec, not all Spring types are supported. * * @param metadata * @return */ @SuppressWarnings("unchecked") static Metadata buildValue(Object metadata) { if (metadata instanceof BeanMetadataElement) { // reference if (metadata instanceof RuntimeBeanReference) { RuntimeBeanReference reference = (RuntimeBeanReference) metadata; // check the special case of nested references being promoted return new SimpleRefMetadata(reference.getBeanName()); } // reference name if (metadata instanceof RuntimeBeanNameReference) { RuntimeBeanNameReference reference = (RuntimeBeanNameReference) metadata; return new SimpleIdRefMetadata(reference.getBeanName()); } // typed String if (metadata instanceof TypedStringValue) { // check if it's a <null/> TypedStringValue typedString = (TypedStringValue) metadata; return (typedString.getValue() == null ? NullMetadata.NULL : new SimpleValueMetadata(typedString)); } // bean definition if (metadata instanceof BeanDefinition) { // check special alias case BeanDefinition def = (BeanDefinition) metadata; if (BEAN_REF_FB_CLASS_NAME.equals(def.getBeanClassName())) { BeanDefinition unwrapped = ComponentMetadataFactory.unwrapImporterReference(def); if (unwrapped != null) { return ComponentMetadataFactory.buildMetadata(null, unwrapped); } else { return new SimpleRefMetadata((String) MetadataUtils.getValue(def.getPropertyValues(), BEAN_REF_NAME_PROP)); } } return MetadataFactory.buildComponentMetadataFor(null, def); } // bean definition holder (used for inner beans/components) if (metadata instanceof BeanDefinitionHolder) { BeanDefinitionHolder holder = (BeanDefinitionHolder) metadata; // we ignore the name even though one was specified return MetadataFactory.buildComponentMetadataFor(null, holder.getBeanDefinition()); } // managedXXX... if (metadata instanceof ManagedArray) { ManagedArray array = (ManagedArray) metadata; return new SimpleCollectionMetadata(getMetadata(array), CollectionType.ARRAY, array .getElementTypeName()); } if (metadata instanceof ManagedList) { ManagedList list = (ManagedList) metadata; return new SimpleCollectionMetadata(getMetadata(list), CollectionType.LIST, list.getElementTypeName()); } if (metadata instanceof ManagedSet) { ManagedSet set = (ManagedSet) metadata; return new SimpleCollectionMetadata(getMetadata(set), CollectionType.SET, set.getElementTypeName()); } if (metadata instanceof ManagedMap) { ManagedMap<Object, Object> map = (ManagedMap) metadata; return new SimpleMapMetadata(ValueFactory.getEntries(map), map.getKeyTypeName(), map.getValueTypeName()); } if (metadata instanceof ManagedProperties) { ManagedProperties properties = (ManagedProperties) metadata; return new SimplePropsMetadata(ValueFactory.getEntries(properties)); } throw new IllegalArgumentException("Unsupported metadata type " + metadata.getClass()); } // no metadata - probably some parser added the object directly // try to convert it into a String return new SimpleValueMetadata(null, metadata.toString()); } static <E> List<Metadata> getMetadata(Collection<E> collection) { if (collection.isEmpty()) { return Collections.emptyList(); } List<Metadata> list = new ArrayList<Metadata>(collection.size()); for (Object value : collection) { list.add(ValueFactory.buildValue(value)); } return Collections.unmodifiableList(list); } static <K, V> List<MapEntry> getEntries(Map<K, V> map) { if (map.isEmpty()) return Collections.emptyList(); List<MapEntry> entries = new ArrayList<MapEntry>(map.size()); // convert map objects for (Map.Entry<K, V> entry : map.entrySet()) { NonNullMetadata key = (NonNullMetadata) ValueFactory.buildValue(entry.getKey()); Metadata value = (Metadata) ValueFactory.buildValue(entry.getValue()); entries.add(new SimpleMapEntry(key, value)); } return Collections.unmodifiableList(entries); } }