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 }