001 // Copyright 2004, 2005 The Apache Software Foundation 002 // 003 // Licensed under the Apache License, Version 2.0 (the "License"); 004 // you may not use this file except in compliance with the License. 005 // You may obtain a copy of the License at 006 // 007 // http://www.apache.org/licenses/LICENSE-2.0 008 // 009 // Unless required by applicable law or agreed to in writing, software 010 // distributed under the License is distributed on an "AS IS" BASIS, 011 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012 // See the License for the specific language governing permissions and 013 // limitations under the License. 014 015 package org.apache.hivemind.lib.factory; 016 017 import java.lang.reflect.Constructor; 018 import java.util.HashMap; 019 import java.util.Iterator; 020 import java.util.List; 021 import java.util.Map; 022 023 import org.apache.hivemind.ApplicationRuntimeException; 024 import org.apache.hivemind.ErrorLog; 025 import org.apache.hivemind.HiveMind; 026 import org.apache.hivemind.impl.BaseLocatable; 027 import org.apache.hivemind.lib.BeanFactory; 028 029 /** 030 * Implementation of {@link org.apache.hivemind.lib.BeanFactory}. 031 * 032 * @author Howard Lewis Ship 033 */ 034 public class BeanFactoryImpl extends BaseLocatable implements BeanFactory 035 { 036 private ErrorLog _errorLog; 037 038 private Class _vendType; 039 040 private Map _contributions = new HashMap(); 041 042 private Map _cache = new HashMap(); 043 044 private boolean _defaultCacheable; 045 046 public BeanFactoryImpl(ErrorLog errorLog, Class vendType, List contributions, 047 boolean defaultCacheable) 048 { 049 _errorLog = errorLog; 050 _vendType = vendType; 051 _defaultCacheable = defaultCacheable; 052 053 processContributions(contributions); 054 } 055 056 public boolean contains(String locator) 057 { 058 int commax = locator.indexOf(','); 059 060 String name = commax < 0 ? locator.trim() : locator.substring(0, commax); 061 062 return _contributions.containsKey(name); 063 } 064 065 private void processContributions(List list) 066 { 067 Iterator i = list.iterator(); 068 069 while (i.hasNext()) 070 { 071 BeanFactoryContribution c = (BeanFactoryContribution) i.next(); 072 073 Class beanClass = c.getBeanClass(); 074 075 if (beanClass.isInterface() || beanClass.isArray() || beanClass.isPrimitive()) 076 { 077 _errorLog.error(FactoryMessages.invalidContributionClass(c), c.getLocation(), null); 078 continue; 079 } 080 081 if (!_vendType.isAssignableFrom(beanClass)) 082 { 083 _errorLog.error(FactoryMessages.wrongContributionType(c, _vendType), c 084 .getLocation(), null); 085 continue; 086 } 087 088 _contributions.put(c.getName(), c); 089 } 090 } 091 092 public synchronized Object get(String locator) 093 { 094 Object result = _cache.get(locator); 095 096 if (result == null) 097 result = create(locator); 098 099 return result; 100 } 101 102 // Implicitly synchronized by get() 103 104 private Object create(String locator) 105 { 106 int commax = locator.indexOf(','); 107 108 String name = commax < 0 ? locator.trim() : locator.substring(0, commax); 109 String initializer = commax < 0 ? null : locator.substring(commax + 1).trim(); 110 111 BeanFactoryContribution c = (BeanFactoryContribution) _contributions.get(name); 112 113 if (c == null) 114 throw new ApplicationRuntimeException(FactoryMessages.unknownContribution(name)); 115 116 Object result = construct(c, initializer); 117 118 if (c.getStoreResultInCache(_defaultCacheable)) 119 _cache.put(locator, result); 120 121 return result; 122 } 123 124 private Object construct(BeanFactoryContribution contribution, String initializer) 125 { 126 Class beanClass = contribution.getBeanClass(); 127 128 try 129 { 130 if (HiveMind.isBlank(initializer)) 131 return beanClass.newInstance(); 132 133 Constructor c = beanClass.getConstructor(new Class[] 134 { String.class }); 135 136 return c.newInstance(new Object[] 137 { initializer }); 138 } 139 catch (Exception ex) 140 { 141 throw new ApplicationRuntimeException(FactoryMessages 142 .unableToInstantiate(beanClass, ex), contribution.getLocation(), ex); 143 144 } 145 } 146 147 }