| /** |
| * 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.aries.blueprint.di; |
| |
| import java.util.AbstractMap; |
| import java.util.ArrayList; |
| import java.util.Dictionary; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.SortedMap; |
| import java.util.TreeMap; |
| import java.util.Hashtable; |
| import java.util.concurrent.ConcurrentHashMap; |
| import java.util.concurrent.ConcurrentMap; |
| |
| import org.apache.aries.blueprint.utils.ReflectionUtils; |
| import org.osgi.service.blueprint.container.ComponentDefinitionException; |
| |
| /** |
| * @version $Rev: 896324 $ $Date: 2010-01-06 06:05:04 +0000 (Wed, 06 Jan 2010) $ |
| */ |
| public class MapRecipe extends AbstractRecipe { |
| |
| private final List<Recipe[]> entries; |
| private final Class typeClass; |
| |
| public MapRecipe(String name, Class type) { |
| super(name); |
| if (type == null) throw new NullPointerException("type is null"); |
| this.typeClass = type; |
| this.entries = new ArrayList<Recipe[]>(); |
| } |
| |
| public List<Recipe> getDependencies() { |
| List<Recipe> nestedRecipes = new ArrayList<Recipe>(entries.size() * 2); |
| for (Recipe[] entry : entries) { |
| nestedRecipes.add(entry[0]); |
| if (entry[1] != null) { |
| nestedRecipes.add(entry[1]); |
| } |
| } |
| return nestedRecipes; |
| } |
| |
| protected Object internalCreate() throws ComponentDefinitionException { |
| Class mapType = getMap(typeClass); |
| |
| if (!ReflectionUtils.hasDefaultConstructor(mapType)) { |
| throw new ComponentDefinitionException("Type does not have a default constructor " + mapType.getName()); |
| } |
| |
| Object o; |
| try { |
| o = mapType.newInstance(); |
| } catch (Exception e) { |
| throw new ComponentDefinitionException("Error while creating set instance: " + mapType.getName()); |
| } |
| |
| Map instance; |
| if (o instanceof Map) { |
| instance = (Map) o; |
| } else if (o instanceof Dictionary) { |
| instance = new DummyDictionaryAsMap((Dictionary) o); |
| } else { |
| throw new ComponentDefinitionException("Specified map type does not implement the Map interface: " + mapType.getName()); |
| } |
| |
| // add map entries |
| for (Recipe[] entry : entries) { |
| Object key = entry[0].create(); |
| Object value = entry[1] != null ? entry[1].create() : null; |
| instance.put(key, value); |
| } |
| return instance; |
| } |
| |
| public void put(Recipe key, Recipe value) { |
| if (key == null) throw new NullPointerException("key is null"); |
| entries.add(new Recipe[] { key, value}); |
| } |
| |
| public void putAll(Map<Recipe,Recipe> map) { |
| if (map == null) throw new NullPointerException("map is null"); |
| for (Map.Entry<Recipe,Recipe> entry : map.entrySet()) { |
| Recipe key = entry.getKey(); |
| Recipe value = entry.getValue(); |
| put(key, value); |
| } |
| } |
| |
| public static Class getMap(Class type) { |
| if (ReflectionUtils.hasDefaultConstructor(type)) { |
| return type; |
| } else if (SortedMap.class.isAssignableFrom(type)) { |
| return TreeMap.class; |
| } else if (ConcurrentMap.class.isAssignableFrom(type)) { |
| return ConcurrentHashMap.class; |
| } else { |
| return LinkedHashMap.class; |
| } |
| } |
| |
| public static class DummyDictionaryAsMap extends AbstractMap { |
| |
| private final Dictionary dictionary; |
| |
| public DummyDictionaryAsMap(Dictionary dictionary) { |
| this.dictionary = dictionary; |
| } |
| |
| @Override |
| public Object put(Object key, Object value) { |
| return dictionary.put(key, value); |
| } |
| |
| public Set entrySet() { |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| } |