001/*
002 * jPOS Project [http://jpos.org]
003 * Copyright (C) 2000-2026 jPOS Software SRL
004 *
005 * This program is free software: you can redistribute it and/or modify
006 * it under the terms of the GNU Affero General Public License as
007 * published by the Free Software Foundation, either version 3 of the
008 * License, or (at your option) any later version.
009 *
010 * This program is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
013 * GNU Affero General Public License for more details.
014 *
015 * You should have received a copy of the GNU Affero General Public License
016 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
017 */
018
019package org.jpos.q2.qbean;
020
021import org.jdom2.Element;
022import org.jpos.core.ConfigurationException;
023import org.jpos.q2.QBeanSupport;
024import org.jpos.q2.QFactory;
025import org.jpos.util.NameRegistrar;
026
027import java.util.*;
028
029@SuppressWarnings("unchecked")
030public class QBeanFactory extends QBeanSupport implements QBeanFactoryMBean {
031  
032    private static Map beanMap = new WeakHashMap();
033    private Map privateList; // list of beans in the config file
034
035    public void initService() throws Exception {
036        Element e = getPersist();
037        privateList = new HashMap();
038        List beans = e.getChildren("bean");
039        for (Object bean1 : beans) {
040            Element bean = (Element) bean1;
041            String id = bean.getAttributeValue("id");
042            privateList.put(id, bean);
043        }
044
045    }
046
047    public void start() {
048        super.start();
049        NameRegistrar.register("QBeanFactory." + getName(), this);
050    }
051
052    public void stop() {
053        super.stop();
054        NameRegistrar.unregister("QBeanFactory." + getName());
055    }
056    // Support methods for bean life cycle
057    public void startService() {
058        Iterator keys = privateList.keySet().iterator();
059        while (keys.hasNext()) {
060            Element bean = (Element) privateList.get(keys.next());
061            String id = bean.getAttributeValue("id");
062            String lazy = bean.getAttributeValue("lazy");
063            // Load the bean only when lazy="false". default value true
064            if (lazy != null && lazy.equalsIgnoreCase("false")) {
065                getBean(id);
066            }
067        }
068    }
069
070    public void stopService() {
071        Iterator keys = privateList.keySet().iterator();
072        while (keys.hasNext()) {
073            Element bean = (Element) privateList.get(keys.next());
074            String id = bean.getAttributeValue("id");// id and key are same
075            Object beanInstance=beanMap.remove(id);
076            String stopMethod = bean.getAttributeValue("stop-method");
077            if(beanInstance!=null && stopMethod!=null){
078                try{
079                    QFactory.invoke(beanInstance, stopMethod, null);
080                }catch(Exception e){
081                    log.warn(e);
082                }
083            }
084        }
085    }
086
087    public Object getBean(String id) {
088
089        // Hack to support a global ref bean across multiple
090        // deployment files. We may need to support lazy loading here but now
091        // not supported
092        Element bean = (Element) privateList.get(id);
093        if (bean == null) {
094            return beanMap.get(id);
095        }
096        // Need to create a new instance when singleton="false"
097        // It is true by default
098        String singleton = bean.getAttributeValue("singleton");
099       try{ 
100        if(singleton != null && singleton.equals("false")){// create new instance every time
101            return newBean(bean,false);
102        }else{
103            return newBean(bean,true); 
104        }
105        }catch(Exception e){
106            log.fatal(e);
107            return null;
108        }
109       
110    }
111    private Object newBean(Element bean,boolean useCache) throws ConfigurationException{
112        String id = bean.getAttributeValue("id");
113        
114        if(useCache && beanMap.containsKey(id)){
115            return beanMap.get(id);
116        }
117        
118        String className = bean.getAttributeValue("class");
119        Object beanInstance = getFactory().newInstance(className);
120        List propertyList = bean.getChildren("property");
121        for (Object aPropertyList : propertyList) {
122            Element propertyElement = (Element) aPropertyList;
123            String pName = propertyElement.getAttributeValue("name");
124            String pValue = propertyElement.getAttributeValue("value");
125            String pRef = propertyElement.getAttributeValue("ref");
126            String methodName = "set"
127                    + Character.toUpperCase(pName.charAt(0))
128                    + pName.substring(1);
129            if (pValue == null) {
130                QFactory.invoke(beanInstance, methodName, getBean(pRef));
131            } else {
132                QFactory.invoke(beanInstance, methodName, pValue);
133            }
134        }
135        String startMethod = bean.getAttributeValue("start-method");
136        if(startMethod!=null){
137            QFactory.invoke(beanInstance, startMethod, null);
138        }
139        if(useCache)//indication for a singleton 
140          beanMap.put(id, beanInstance);   
141        // Return the bean instance
142        return beanInstance;
143    }
144
145}