Java tutorial
/* * jPOS Project [http://jpos.org] * Copyright (C) 2000-2016 Alejandro P. Revilla * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.jpos.q2; import org.jdom2.Element; import org.jpos.core.Configurable; import org.jpos.core.Configuration; import org.jpos.core.ConfigurationException; import org.jpos.core.XmlConfigurable; import org.jpos.q2.qbean.QConfig; import org.jpos.util.LogSource; import org.jpos.util.Logger; import org.jpos.util.NameRegistrar; import javax.management.*; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.net.MalformedURLException; import java.util.Collection; import java.util.List; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.StringTokenizer; /** * @author <a href="mailto:taherkordy@dpi2.dpi.net.ir">Alireza Taherkordi</a> * @author <a href="mailto:apr@cs.com.uy">Alejandro P. Revilla</a> * @version $Revision$ $Date$ */ @SuppressWarnings("unchecked") public class QFactory { ObjectName loaderName; Q2 q2; ResourceBundle classMapping; ConfigurationFactory defaultConfigurationFactory = new SimpleConfigurationFactory(); public QFactory(ObjectName loaderName, Q2 q2) { super(); this.loaderName = loaderName; this.q2 = q2; classMapping = ResourceBundle.getBundle(this.getClass().getName()); } @SuppressWarnings("PMD.EmptyCatchBlock") public Object instantiate(Q2 server, Element e) throws ReflectionException, MBeanException, InstanceNotFoundException { String clazz = e.getAttributeValue("class"); if (clazz == null) { try { clazz = classMapping.getString(e.getName()); } catch (MissingResourceException ex) { // no class attribute, no mapping // let MBeanServer do the yelling } } MBeanServer mserver = server.getMBeanServer(); getExtraPath(server.getLoader(), e); return mserver.instantiate(clazz, loaderName); } public ObjectInstance createQBean(Q2 server, Element e, Object obj) throws ClassNotFoundException, InstantiationException, IllegalAccessException, MalformedObjectNameException, MalformedURLException, InstanceAlreadyExistsException, InstanceNotFoundException, MBeanException, NotCompliantMBeanException, InvalidAttributeValueException, ReflectionException, ConfigurationException { String name = e.getAttributeValue("name"); if (name == null) name = e.getName(); ObjectName objectName = new ObjectName(Q2.QBEAN_NAME + name); MBeanServer mserver = server.getMBeanServer(); if (mserver.isRegistered(objectName)) { throw new InstanceAlreadyExistsException(name + " has already been deployed in another file."); } ObjectInstance instance = mserver.registerMBean(obj, objectName); try { setAttribute(mserver, objectName, "Name", name); String logger = e.getAttributeValue("logger"); if (logger != null) setAttribute(mserver, objectName, "Logger", logger); String realm = e.getAttributeValue("realm"); if (realm != null) setAttribute(mserver, objectName, "Realm", realm); setAttribute(mserver, objectName, "Server", server); setAttribute(mserver, objectName, "Persist", e); configureQBean(mserver, objectName, e); setConfiguration(obj, e); // handle legacy (QSP v1) Configurables if (obj instanceof QBean) mserver.invoke(objectName, "init", null, null); } catch (ConfigurationException ce) { mserver.unregisterMBean(objectName); ce.fillInStackTrace(); throw ce; } return instance; } public Q2 getQ2() { return q2; } public void getExtraPath(QClassLoader loader, Element e) { Element classpathElement = e.getChild("classpath"); if (classpathElement != null) { try { loader = loader.scan(true); // force a new classloader } catch (Throwable t) { getQ2().getLog().error(t); } for (Object o : classpathElement.getChildren("url")) { Element u = (Element) o; try { loader.addURL(u.getTextTrim()); } catch (MalformedURLException ex) { q2.getLog().warn(u.getTextTrim(), ex); } } } } @SuppressWarnings("PMD.EmptyCatchBlock") public void setAttribute(MBeanServer server, ObjectName objectName, String attribute, Object value) throws InstanceNotFoundException, MBeanException, InvalidAttributeValueException, ReflectionException { try { server.setAttribute(objectName, new Attribute(attribute, value)); } catch (AttributeNotFoundException ex) { // okay to fail } catch (InvalidAttributeValueException ex) { // okay to fail (produced by some application servers instead of AttributeNotFoundException) } } public void startQBean(Q2 server, ObjectName objectName) throws ClassNotFoundException, InstantiationException, IllegalAccessException, MalformedObjectNameException, MalformedURLException, InstanceAlreadyExistsException, InstanceNotFoundException, MBeanException, NotCompliantMBeanException, InvalidAttributeValueException, ReflectionException { MBeanServer mserver = server.getMBeanServer(); mserver.invoke(objectName, "start", null, null); } public void destroyQBean(Q2 server, ObjectName objectName, Object obj) throws ClassNotFoundException, InstantiationException, IllegalAccessException, MalformedObjectNameException, MalformedURLException, InstanceAlreadyExistsException, InstanceNotFoundException, MBeanException, NotCompliantMBeanException, InvalidAttributeValueException, ReflectionException { MBeanServer mserver = server.getMBeanServer(); if (obj instanceof QBean) { mserver.invoke(objectName, "stop", null, null); mserver.invoke(objectName, "destroy", null, null); } if (objectName != null) mserver.unregisterMBean(objectName); } public void configureQBean(MBeanServer server, ObjectName objectName, Element e) throws ConfigurationException { try { AttributeList attributeList = getAttributeList(e); for (Object anAttributeList : attributeList) server.setAttribute(objectName, (Attribute) anAttributeList); } catch (Exception e1) { throw new ConfigurationException(e1); } } public AttributeList getAttributeList(Element e) throws ConfigurationException { AttributeList attributeList = new AttributeList(); List childs = e.getChildren("attr"); for (Object child : childs) { Element childElement = (Element) child; String name = childElement.getAttributeValue("name"); name = getAttributeName(name); Attribute attr = new Attribute(name, getObject(childElement)); attributeList.add(attr); } return attributeList; } /** * Creates an object from a definition element. * The element may have an attribute called type indicating the type of the object * to create, if this attribute is not present java.lang.String is assumed. * int, long and boolean are converted to their wrappers. * @return The created object. * @param childElement Dom Element with the definition of the object. * @throws ConfigurationException If an exception is found trying to create the object. */ @SuppressWarnings("unchecked") protected Object getObject(Element childElement) throws ConfigurationException { String type = childElement.getAttributeValue("type", "java.lang.String"); if ("int".equals(type)) type = "java.lang.Integer"; else if ("long".equals(type)) type = "java.lang.Long"; else if ("boolean".equals(type)) type = "java.lang.Boolean"; String value = childElement.getText(); try { Class attributeType = Class.forName(type); if (Collection.class.isAssignableFrom(attributeType)) return getCollection(attributeType, childElement); else { Class[] parameterTypes = { "".getClass() }; Object[] parameterValues = { value }; return attributeType.getConstructor(parameterTypes).newInstance(parameterValues); } } catch (Exception e1) { throw new ConfigurationException(e1); } } /** Creats a collection from a definition element with the format. * <PRE> * <{attr|item} type="..."> * <item [type="..."]>...</item> * ... * </attr> * </PRE> * @param type class type * @param e the Element * @throws ConfigurationException * @return the object collection */ @SuppressWarnings("unchecked") protected Collection getCollection(Class type, Element e) throws ConfigurationException { try { Collection<Object> col = (Collection<Object>) type.newInstance(); for (Object o : e.getChildren("item")) { col.add(getObject((Element) o)); } return col; } catch (Exception e1) { throw new ConfigurationException(e1); } } /** * sets the first character of the string to the upper case * @param name attribute name * @return attribute name */ public String getAttributeName(String name) { StringBuilder tmp = new StringBuilder(name); if (tmp.length() > 0) tmp.setCharAt(0, name.toUpperCase().charAt(0)); return tmp.toString(); } public Object newInstance(String clazz) throws ConfigurationException { try { MBeanServer mserver = q2.getMBeanServer(); return mserver.instantiate(clazz, loaderName); } catch (Exception e) { throw new ConfigurationException(clazz, e); } } public Configuration getConfiguration(Element e) throws ConfigurationException { String configurationFactoryClazz = e.getAttributeValue("configuration-factory"); ConfigurationFactory cf = configurationFactoryClazz != null ? (ConfigurationFactory) newInstance(configurationFactoryClazz) : defaultConfigurationFactory; Configuration cfg = cf.getConfiguration(e); String merge = e.getAttributeValue("merge-configuration"); if (merge != null) { StringTokenizer st = new StringTokenizer(merge, ", "); while (st.hasMoreElements()) { try { Configuration c = QConfig.getConfiguration(st.nextToken()); for (String k : c.keySet()) { if (cfg.get(k, null) == null) { String[] v = c.getAll(k); switch (v.length) { case 0: break; case 1: cfg.put(k, v[0]); break; default: cfg.put(k, v); } } } } catch (NameRegistrar.NotFoundException ex) { throw new ConfigurationException(ex.getMessage()); } } } return cfg; } public void setLogger(Object obj, Element e) { if (obj instanceof LogSource) { String loggerName = e.getAttributeValue("logger"); if (loggerName != null) { String realm = e.getAttributeValue("realm"); if (realm == null) realm = e.getName(); Logger logger = Logger.getLogger(loggerName); ((LogSource) obj).setLogger(logger, realm); } } } public void setConfiguration(Object obj, Element e) throws ConfigurationException { try { if (obj instanceof Configurable) ((Configurable) obj).setConfiguration(getConfiguration(e)); if (obj instanceof XmlConfigurable) ((XmlConfigurable) obj).setConfiguration(e); } catch (ConfigurationException ex) { throw new ConfigurationException(ex); } } /** * Try to invoke a method (usually a setter) on the given object * silently ignoring if method does not exist * @param obj the object * @param m method to invoke * @param p parameter * @throws ConfigurationException if method happens to throw an exception */ public static void invoke(Object obj, String m, Object p) throws ConfigurationException { invoke(obj, m, p, p != null ? p.getClass() : null); } /** * Try to invoke a method (usually a setter) on the given object * silently ignoring if method does not exist * @param obj the object * @param m method to invoke * @param p parameter * @param pc parameter class * @throws ConfigurationException if method happens to throw an exception */ @SuppressWarnings("PMD.EmptyCatchBlock") public static void invoke(Object obj, String m, Object p, Class pc) throws ConfigurationException { try { if (p != null) { Class[] paramTemplate = { pc }; Method method = obj.getClass().getMethod(m, paramTemplate); Object[] param = new Object[1]; param[0] = p; method.invoke(obj, param); } else { Method method = obj.getClass().getMethod(m); method.invoke(obj); } } catch (NoSuchMethodException ignored) { } catch (NullPointerException ignored) { } catch (IllegalAccessException ignored) { } catch (InvocationTargetException e) { throw new ConfigurationException(obj.getClass().getName() + "." + m + "(" + p + ")", e.getTargetException()); } } }