001/**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.activemq.jndi;
018
019import java.util.Enumeration;
020import java.util.Hashtable;
021import java.util.Properties;
022
023import javax.naming.Context;
024import javax.naming.Name;
025import javax.naming.NamingException;
026import javax.naming.Reference;
027import javax.naming.StringRefAddr;
028import javax.naming.spi.ObjectFactory;
029
030import org.slf4j.Logger;
031import org.slf4j.LoggerFactory;
032
033/**
034 * Converts objects implementing JNDIStorable into a property fields so they can
035 * be stored and regenerated from JNDI
036 */
037public class JNDIReferenceFactory implements ObjectFactory {
038
039    static Logger log = LoggerFactory.getLogger(JNDIReferenceFactory.class);
040
041    /**
042     * This will be called by a JNDIprovider when a Reference is retrieved from
043     * a JNDI store - and generates the orignal instance
044     * 
045     * @param object the Reference object
046     * @param name the JNDI name
047     * @param nameCtx the context
048     * @param environment the environment settings used by JNDI
049     * @return the instance built from the Reference object
050     * @throws Exception if building the instance from Reference fails (usually
051     *                 class not found)
052     */
053    public Object getObjectInstance(Object object, Name name, Context nameCtx, Hashtable environment) throws Exception {
054        Object result = null;
055        if (object instanceof Reference) {
056            Reference reference = (Reference)object;
057
058            if (log.isTraceEnabled()) {
059                log.trace("Getting instance of " + reference.getClassName());
060            }
061
062            Class theClass = loadClass(this, reference.getClassName());
063            if (JNDIStorableInterface.class.isAssignableFrom(theClass)) {
064
065                JNDIStorableInterface store = (JNDIStorableInterface)theClass.newInstance();
066                Properties properties = new Properties();
067                for (Enumeration iter = reference.getAll(); iter.hasMoreElements();) {
068
069                    StringRefAddr addr = (StringRefAddr)iter.nextElement();
070                    properties.put(addr.getType(), (addr.getContent() == null) ? "" : addr.getContent());
071
072                }
073                store.setProperties(properties);
074                result = store;
075            }
076        } else {
077            log.error("Object " + object + " is not a reference - cannot load");
078            throw new RuntimeException("Object " + object + " is not a reference");
079        }
080        return result;
081    }
082
083    /**
084     * Create a Reference instance from a JNDIStorable object
085     * 
086     * @param instanceClassName
087     * @param po
088     * @return
089     * @throws NamingException
090     */
091
092    public static Reference createReference(String instanceClassName, JNDIStorableInterface po) throws NamingException {
093        if (log.isTraceEnabled()) {
094            log.trace("Creating reference: " + instanceClassName + "," + po);
095        }
096        Reference result = new Reference(instanceClassName, JNDIReferenceFactory.class.getName(), null);
097        try {
098            Properties props = po.getProperties();
099            for (Enumeration iter = props.propertyNames(); iter.hasMoreElements();) {
100                String key = (String)iter.nextElement();
101                String value = props.getProperty(key);
102                javax.naming.StringRefAddr addr = new javax.naming.StringRefAddr(key, value);
103                result.add(addr);
104            }
105        } catch (Exception e) {
106            log.error(e.getMessage(), e);
107            throw new NamingException(e.getMessage());
108        }
109        return result;
110    }
111
112    /**
113     * Retrieve the class loader for a named class
114     * 
115     * @param thisObj
116     * @param className
117     * @return
118     * @throws ClassNotFoundException
119     */
120
121    public static Class loadClass(Object thisObj, String className) throws ClassNotFoundException {
122        // tryu local ClassLoader first.
123        ClassLoader loader = thisObj.getClass().getClassLoader();
124        Class theClass;
125        if (loader != null) {
126            theClass = loader.loadClass(className);
127        } else {
128            // Will be null in jdk1.1.8
129            // use default classLoader
130            theClass = Class.forName(className);
131        }
132        return theClass;
133    }
134
135}