All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.flowlogix.ejb.JNDIObjectLocator Maven / Gradle / Ivy

There is a newer version: 9.0.7
Show newest version
package com.flowlogix.ejb;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.Serializable;
import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.regex.Pattern;
import javax.ejb.Remote;
import javax.naming.InitialContext;
import javax.naming.NameNotFoundException;
import javax.naming.NamingException;
import lombok.Getter;
import lombok.Setter;
import lombok.SneakyThrows;

/**
 * JNDIObjectLocator is used to centralize all JNDI lookups. It minimizes the overhead of JNDI lookups by caching the
 * objects it looks up.
 * 
 * See Documentation
 * 
 * @author Geoff Callendar
 * Enhancements by Lenny Primak
 */
public class JNDIObjectLocator implements Serializable
{
    public JNDIObjectLocator()
    {
        this(PORTABLE_NAME_PREFIX);
    }
    
    
    public JNDIObjectLocator(String portableNamePrefix)
    {
        this(null, portableNamePrefix);
    }

    
    public JNDIObjectLocator(Hashtable env)
    {
        this(env, PORTABLE_NAME_PREFIX);
    }

    
    public JNDIObjectLocator(Hashtable env, String portableNamePrefix)
    {
        this.env = env;
        this.portableNamePrefix = portableNamePrefix;
    }
    
    
    @SneakyThrows(NamingException.class)
    public T getObject(Class beanClass)
    {
        boolean remote = beanClass.isAnnotationPresent(Remote.class);
        String name = guessByType(beanClass.getName());
        return getObject(prependPortableName(name), remote && !cacheRemote);
    }
    
    
    public T getObject(String jndiName) throws NamingException
    {
        return getObject(jndiName, false);
    }

    
    @SuppressWarnings("unchecked")
    public T getObject(String jndiName, boolean noCaching) throws NamingException
    {
        return (T)getJNDIObject(jndiName, noCaching);
    }

    
    public synchronized void clear()
    {
        jndiObjectCache.clear();
    }
    
    
    public T getJNDIObject(String jndiName) throws NamingException
    {
        return getJNDIObject(jndiName, false);
    }
    
    
    public T getJNDIObject(String jndiName, boolean noCaching) throws NamingException
    {
        if(noCaching || this.noCaching)
        {
            return lookup(jndiName, true);
        }
        
        @SuppressWarnings("unchecked")
        T jndiObject = (T)jndiObjectCache.get(jndiName);

        if (jndiObject == null && !jndiObjectCache.containsKey(jndiName))
        {
            try
            {
                jndiObject = lookup(jndiName, false);
                jndiObjectCache.put(jndiName, jndiObject);
            } catch (NamingException e)
            {
                clear();
                throw e;
            }
        }
        return jndiObject;
    }
    
    
    public String prependPortableName(String lookupname)
    {
        //convert to jndi name
        if (!lookupname.startsWith("java:")) 
        {
            lookupname = portableNamePrefix + "/" + lookupname;
        }
        return lookupname;
    }
    
    
    public static String guessByType(String type) 
    {
        String lookupname = type.substring(type.lastIndexOf(".") + 1);
        // support naming convention that strips Local/Remote from the
        // end of an interface class to try to determine the actual bean name,
        // to avoid @EJB(beanName="myBeanName"), and just use plain old @EJB
        String uc = lookupname.toUpperCase();
        if (uc.endsWith(LOCAL) || uc.endsWith(REMOTE)) {
            lookupname = StripInterfaceSuffixPattern.matcher(lookupname).replaceFirst("");
        }
        return lookupname + "!" + type;
    }
    
    
    private InitialContext getInitialContext() throws NamingException
    {
        if(env == null)
        {
            return new InitialContext();
        }
        else
        {
            return new InitialContext(env);
        }
    }

    
    @SuppressWarnings("unchecked")
    private synchronized T lookup(String name, boolean noCaching) throws NamingException
    {
        if(this.noCaching || noCaching)
        {
            return (T)getInitialContext().lookup(name);
        }
        // Recheck the cache because the name we're looking for may have been added while we were waiting for sync.

        if (!jndiObjectCache.containsKey(name))
        {
            try
            {
                return (T)getInitialContext().lookup(name);
            } catch (NameNotFoundException e)
            {
                clear();
                throw e;
            }
        } else
        {
            return (T)jndiObjectCache.get(name);
        }
    }
    
    
    private void readObject(ObjectInputStream is) throws IOException, ClassNotFoundException
    {
        is.defaultReadObject();
        jndiObjectCache = Collections.synchronizedMap(new HashMap());
    }

    
    private final Hashtable env;
    private @Getter @Setter String portableNamePrefix;
    private @Getter @Setter boolean noCaching = false;
    private @Getter @Setter boolean cacheRemote = false;
    private transient Map jndiObjectCache = Collections.synchronizedMap(new HashMap());
        
    public static final String REMOTE = "REMOTE";
    public static final String LOCAL = "LOCAL";
    private static final String PORTABLE_NAME_PREFIX = "java:module";
    public static final Pattern StripInterfaceSuffixPattern = Pattern.compile(LOCAL + "|" + REMOTE, Pattern.CASE_INSENSITIVE);
    private static final long serialVersionUID = 1L;
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy