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    }