Repository: tomee
Updated Branches:
  refs/heads/tomee-1.7.x d240be66c -> 5c4316b51


http://git-wip-us.apache.org/repos/asf/tomee/blob/5c4316b5/server/openejb-client/src/main/java/org/apache/openejb/client/JNDIContext.java
----------------------------------------------------------------------
diff --git 
a/server/openejb-client/src/main/java/org/apache/openejb/client/JNDIContext.java
 
b/server/openejb-client/src/main/java/org/apache/openejb/client/JNDIContext.java
index df34d43..852ebae 100644
--- 
a/server/openejb-client/src/main/java/org/apache/openejb/client/JNDIContext.java
+++ 
b/server/openejb-client/src/main/java/org/apache/openejb/client/JNDIContext.java
@@ -1,904 +1,907 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.openejb.client;
-
-import org.apache.openejb.client.event.RemoteInitialContextCreated;
-import org.apache.openejb.client.serializer.EJBDSerializer;
-import org.omg.CORBA.ORB;
-
-import javax.naming.AuthenticationException;
-import javax.naming.Binding;
-import javax.naming.CompoundName;
-import javax.naming.ConfigurationException;
-import javax.naming.Context;
-import javax.naming.InvalidNameException;
-import javax.naming.Name;
-import javax.naming.NameClassPair;
-import javax.naming.NameNotFoundException;
-import javax.naming.NameParser;
-import javax.naming.NamingEnumeration;
-import javax.naming.NamingException;
-import javax.naming.OperationNotSupportedException;
-import javax.naming.Reference;
-import javax.naming.ServiceUnavailableException;
-import javax.naming.spi.InitialContextFactory;
-import javax.naming.spi.NamingManager;
-import javax.sql.DataSource;
-import java.io.Serializable;
-import java.lang.reflect.Constructor;
-import java.net.ConnectException;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.rmi.RemoteException;
-import java.util.ArrayList;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Properties;
-import java.util.concurrent.BlockingQueue;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.LinkedBlockingDeque;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.RejectedExecutionHandler;
-import java.util.concurrent.ThreadFactory;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-/**
- * @version $Rev$ $Date$
- */
-public class JNDIContext implements InitialContextFactory, Context {
-    private static final Logger LOGGER = Logger.getLogger("OpenEJB.client");
-
-    @SuppressWarnings("UnusedDeclaration")
-    public static final String DEFAULT_PROVIDER_URL = "ejbd://localhost:4201";
-    public static final String SERIALIZER = "openejb.ejbd.serializer";
-    public static final String AUTHENTICATE_WITH_THE_REQUEST = 
"openejb.ejbd.authenticate-with-request";
-    public static final String POOL_QUEUE_SIZE = 
"openejb.client.invoker.queue";
-    @SuppressWarnings("UnusedDeclaration")
-    public static final String POOL_THREAD_NUMBER = 
"openejb.client.invoker.threads";
-    public static final String AUTHENTICATION_REALM_NAME = 
"openejb.authentication.realmName";
-    public static final String IDENTITY_TIMEOUT = 
"tomee.authentication.identity.timeout";
-
-    private final AtomicBoolean isShutdown = new AtomicBoolean(false);
-    private String tail = "/";
-    private ServerMetaData server;
-    private ClientMetaData client;
-    private Hashtable env;
-    private String moduleId;
-    private ClientInstance clientIdentity;
-
-    private static final ThreadPoolExecutor GLOBAL_CLIENT_POOL = 
newExecutor(10, null);
-
-    static {
-        final ClassLoader classLoader = Client.class.getClassLoader();
-        Class<?> container;
-        try {
-            container = Class.forName("org.apache.openejb.OpenEJB", false, 
classLoader);
-        } catch (final Throwable e) {
-            container = null;
-        }
-        if (classLoader == ClassLoader.getSystemClassLoader() || 
Boolean.getBoolean("openejb.client.flus-tasks")
-                || (container != null && container.getClassLoader() == 
classLoader)) {
-            Runtime.getRuntime().addShutdownHook(new Thread() {
-                @Override
-                public void run() {
-                    waitForShutdown(GLOBAL_CLIENT_POOL);
-                }
-            });
-        }
-    }
-
-    private AuthenticationInfo authenticationInfo = null;
-
-    //TODO figure out how to configure and manage the thread pool on the 
client side, this will do for now...
-    private transient int threads;
-    private transient LinkedBlockingQueue<Runnable> blockingQueue;
-
-    protected transient ThreadPoolExecutor executorService;
-
-    public static ThreadPoolExecutor globalExecutor() {
-        return GLOBAL_CLIENT_POOL;
-    }
-
-    private ThreadPoolExecutor executor() {
-        if (executorService != null) {
-            return executorService;
-        }
-        if (threads < 0) {
-            return GLOBAL_CLIENT_POOL;
-        }
-        synchronized (this) {
-            if (executorService != null) {
-                return executorService;
-            }
-            executorService = newExecutor(threads, blockingQueue);
-        }
-        return executorService;
-    }
-
-    public static ThreadPoolExecutor newExecutor(final int threads, final 
BlockingQueue<Runnable> blockingQueue) {
-        /**
-         This thread pool starts with 3 core threads and can grow to the limit 
defined by 'threads'.
-         If a pool thread is idle for more than 1 minute it will be discarded, 
unless the core size is reached.
-         It can accept up to the number of processes defined by 'queue'.
-         If the queue is full then an attempt is made to add the process to 
the queue for 10 seconds.
-         Failure to add to the queue in this time will either result in a 
logged rejection, or if 'block'
-         is true then a final attempt is made to run the process in the 
current thread (the service thread).
-         */
-
-        final ThreadPoolExecutor executorService = new ThreadPoolExecutor(3, 
(threads < 3 ? 3 : threads), 1, TimeUnit.MINUTES, blockingQueue == null ? new 
LinkedBlockingDeque<Runnable>(Integer.parseInt(getProperty(null, 
POOL_QUEUE_SIZE, "2"))) : blockingQueue);
-        executorService.setThreadFactory(new ThreadFactory() {
-
-            private final AtomicInteger i = new AtomicInteger(0);
-
-            @Override
-            public Thread newThread(final Runnable r) {
-                final Thread t = new Thread(r, "OpenEJB.Client." + 
i.incrementAndGet());
-                t.setDaemon(true);
-                t.setUncaughtExceptionHandler(new 
Thread.UncaughtExceptionHandler() {
-                    @Override
-                    public void uncaughtException(final Thread t, final 
Throwable e) {
-                        
Logger.getLogger(EJBObjectHandler.class.getName()).log(Level.SEVERE, "Uncaught 
error in: " + t.getName(), e);
-                    }
-                });
-
-                return t;
-            }
-
-        });
-
-        executorService.setRejectedExecutionHandler(new 
RejectedExecutionHandler() {
-            @Override
-            public void rejectedExecution(final Runnable r, final 
ThreadPoolExecutor tpe) {
-
-                if (null == r || null == tpe || tpe.isShutdown() || 
tpe.isTerminated() || tpe.isTerminating()) {
-                    return;
-                }
-
-                final Logger log = 
Logger.getLogger(EJBObjectHandler.class.getName());
-
-                if (log.isLoggable(Level.WARNING)) {
-                    log.log(Level.WARNING, "EJBObjectHandler ExecutorService 
at capacity for process: " + r);
-                }
-
-                boolean offer = false;
-                try {
-                    offer = tpe.getQueue().offer(r, 10, TimeUnit.SECONDS);
-                } catch (final InterruptedException e) {
-                    //Ignore
-                }
-
-                if (!offer) {
-                    log.log(Level.SEVERE, "EJBObjectHandler ExecutorService 
failed to run asynchronous process: " + r);
-                }
-            }
-        });
-        return executorService;
-    }
-
-    public JNDIContext() {
-    }
-
-    /*
-     * A neater version of clone
-     */
-    public JNDIContext(final JNDIContext that) {
-        this.tail = that.tail;
-        this.server = that.server;
-        this.client = that.client;
-        this.moduleId = that.moduleId;
-        this.env = (Hashtable) that.env.clone();
-        this.clientIdentity = that.clientIdentity;
-    }
-
-    private JNDIResponse request(final JNDIRequest req) throws Exception {
-        req.setServerHash(server.buildHash());
-
-        final JNDIResponse response = new JNDIResponse();
-        Client.request(req, response, server);
-        if (null != response.getServer()) {
-            server.merge(response.getServer());
-        }
-        return response;
-    }
-
-    protected AuthenticationResponse requestAuthorization(final 
AuthenticationRequest req) throws RemoteException {
-        return (AuthenticationResponse) Client.request(req, new 
AuthenticationResponse(), server);
-    }
-
-    @Override
-    public Context getInitialContext(final Hashtable environment) throws 
NamingException {
-        if (environment == null) {
-            throw new NamingException("Invalid argument, hashtable cannot be 
null.");
-        } else {
-            env = (Hashtable) environment.clone();
-        }
-
-        final String userID = (String) env.get(Context.SECURITY_PRINCIPAL);
-        final String psswrd = (String) env.get(Context.SECURITY_CREDENTIALS);
-        String providerUrl = (String) env.get(Context.PROVIDER_URL);
-
-        final boolean authWithRequest = 
"true".equalsIgnoreCase(String.class.cast(env.get(AUTHENTICATE_WITH_THE_REQUEST)));
-        moduleId = (String) env.get("openejb.client.moduleId");
-
-        final URI location;
-        try {
-            providerUrl = addMissingParts(providerUrl);
-            location = new URI(providerUrl);
-        } catch (final URISyntaxException e) {
-            throw (ConfigurationException) new 
ConfigurationException("Property value for " +
-                    Context.PROVIDER_URL +
-                    " invalid: " +
-                    providerUrl +
-                    " - " +
-                    e.getMessage()).initCause(e);
-        }
-        this.server = new ServerMetaData(location);
-
-        final Client.Context context = Client.getContext(this.server);
-        context.getProperties().putAll(environment);
-
-        final String strategy = 
context.getOptions().get("openejb.client.connection.strategy", "default");
-        context.getClusterMetaData().setConnectionStrategy(strategy);
-
-        Client.fireEvent(new RemoteInitialContextCreated(location));
-
-        //TODO: Either aggressively initiate authentication or wait for the 
server to send us an authentication challenge.
-        if (userID != null) {
-            if (!authWithRequest) {
-                authenticate(userID, psswrd, false);
-            } else {
-                authenticationInfo = new 
AuthenticationInfo(String.class.cast(env.get(AUTHENTICATION_REALM_NAME)), 
userID, psswrd.toCharArray(), getTimeout(env));
-            }
-        }
-        if (client == null) {
-            client = new ClientMetaData();
-        }
-
-        seedClientSerializer();
-
-        final int queue = Integer.parseInt(getProperty(env, 
JNDIContext.POOL_QUEUE_SIZE, "2"));
-        blockingQueue = new LinkedBlockingQueue<Runnable>((queue < 2 ? 2 : 
queue));
-        threads = Integer.parseInt(getProperty(env, 
"openejb.client.invoker.threads", "-1"));
-
-        return this;
-    }
-
-    private void seedClientSerializer() {
-        final String serializer = (String) env.get(SERIALIZER);
-        if (serializer != null) {
-            try {
-                
client.setSerializer(EJBDSerializer.class.cast(Thread.currentThread().getContextClassLoader().loadClass(serializer).newInstance()));
-            } catch (final Exception e) {
-                // no-op
-            }
-        }
-    }
-
-    private long getTimeout(final Hashtable env) {
-        final Object o = env.get(IDENTITY_TIMEOUT);
-        if (null != o) {
-            final Long l = Long.class.cast(o);
-            //noinspection ConstantConditions
-            if(null != l){
-                return l;
-            }
-        }
-
-        return 0L;
-    }
-
-    private static String getProperty(final Hashtable env, final String key, 
final String defaultValue) {
-        final Object value = env == null ? null : env.get(key);
-        if (value != null) {
-            return value.toString();
-        }
-        return System.getProperty(key, defaultValue);
-    }
-
-    /**
-     * Add missing parts - expected only part of the required providerUrl
-     * <p/>
-     * TODO: Move the check to a place where it really belongs - 
ConnectionManager, ConnectionFactory or such
-     * This method (class in general) doesn't really know what is required as 
far as connection details go
-     * Assuming that java.net.URI or java.net.URL are going to be used is 
overly stated
-     */
-    String addMissingParts(String providerUrl) throws URISyntaxException {
-
-        final int port = Integer.parseInt(System.getProperty("ejbd.port", 
"4201"));
-
-        if (providerUrl == null || providerUrl.length() == 0) {
-            providerUrl = "ejbd://localhost:" + port;
-        } else {
-
-            final int colonIndex = providerUrl.indexOf(":");
-            final int slashesIndex = providerUrl.indexOf("//");
-
-            if (colonIndex == -1 && slashesIndex == -1) {   // hostname or ip 
address only
-                providerUrl = "ejbd://" + providerUrl + ":" + port;
-            } else if (colonIndex == -1) {
-                final URI providerUri = new URI(providerUrl);
-                final String scheme = providerUri.getScheme();
-                if (!(scheme.equals("http") || scheme.equals("https"))) {
-                    providerUrl = providerUrl + ":" + port;
-                }
-            } else if (slashesIndex == -1) {
-                providerUrl = "ejbd://" + providerUrl;
-            }
-        }
-        return providerUrl;
-    }
-
-    public void authenticate(final String userID, final String psswrd, final 
boolean logout) throws AuthenticationException {
-
-        final AuthenticationRequest req = new 
AuthenticationRequest(String.class.cast(env.get(AUTHENTICATION_REALM_NAME)), 
userID, psswrd, getTimeout(env));
-        req.setLogout(logout);
-
-        final AuthenticationResponse res;
-        try {
-            res = requestAuthorization(req);
-        } catch (final RemoteException e) {
-            throw new AuthenticationException(e.getLocalizedMessage());
-        }
-
-        switch (res.getResponseCode()) {
-            case ResponseCodes.AUTH_GRANTED:
-                client = logout ? new ClientMetaData() : res.getIdentity();
-                break;
-            case ResponseCodes.AUTH_REDIRECT:
-                client = logout ? new ClientMetaData() : res.getIdentity();
-                server = res.getServer();
-                break;
-            case ResponseCodes.AUTH_DENIED:
-                throw (AuthenticationException) new 
AuthenticationException("This principle is not 
authorized.").initCause(res.getDeniedCause());
-        }
-
-        seedClientSerializer();
-    }
-
-    public EJBHomeProxy createEJBHomeProxy(final EJBMetaDataImpl ejbData) {
-        final EJBHomeHandler handler = 
EJBHomeHandler.createEJBHomeHandler(executor(), ejbData, server, client, 
authenticationInfo);
-        final EJBHomeProxy proxy = handler.createEJBHomeProxy();
-        handler.ejb.ejbHomeProxy = proxy;
-
-        return proxy;
-
-    }
-
-    private Object createBusinessObject(final Object result) {
-        final EJBMetaDataImpl ejb = (EJBMetaDataImpl) result;
-        final Object primaryKey = ejb.getPrimaryKey();
-
-        final EJBObjectHandler handler = 
EJBObjectHandler.createEJBObjectHandler(executor(), ejb, server, client, 
primaryKey, authenticationInfo);
-        return handler.createEJBObjectProxy();
-    }
-
-    @Override
-    public Object lookup(String name) throws NamingException {
-
-        checkState();
-
-        if (name == null) {
-            throw new InvalidNameException("The name cannot be null");
-        } else if (name.equals("")) {
-            return new JNDIContext(this);
-        } else if (name.startsWith("java:")) {
-            name = name.replaceFirst("^java:", "");
-        } else if (!name.startsWith("/")) {
-            name = tail + name;
-        }
-
-        final String prop = name.replaceFirst("comp/env/", "");
-        String value = System.getProperty(prop);
-        if (value != null) {
-            return parseEntry(prop, value);
-        }
-
-        if (name.equals("comp/ORB")) {
-            return getDefaultOrb();
-        }
-
-        final JNDIRequest req = new JNDIRequest();
-        req.setRequestMethod(RequestMethodCode.JNDI_LOOKUP);
-        req.setRequestString(name);
-        req.setModuleId(moduleId);
-
-        final JNDIResponse res;
-        try {
-            res = request(req);
-        } catch (Exception e) {
-            if (e instanceof RemoteException && e.getCause() instanceof 
ConnectException) {
-                e = (Exception) e.getCause();
-                throw (ServiceUnavailableException) new 
ServiceUnavailableException("Cannot lookup '" + name + "'.").initCause(e);
-            }
-            throw (NamingException) new NamingException("Cannot lookup '" + 
name + "'.").initCause(e);
-        }
-
-        switch (res.getResponseCode()) {
-            case ResponseCodes.JNDI_EJBHOME:
-                return createEJBHomeProxy((EJBMetaDataImpl) res.getResult());
-
-            case ResponseCodes.JNDI_BUSINESS_OBJECT:
-                return createBusinessObject(res.getResult());
-
-            case ResponseCodes.JNDI_OK:
-                return res.getResult();
-
-            case ResponseCodes.JNDI_INJECTIONS:
-                return res.getResult();
-
-            case ResponseCodes.JNDI_CONTEXT:
-                final JNDIContext subCtx = new JNDIContext(this);
-                if (!name.endsWith("/")) {
-                    name += '/';
-                }
-                subCtx.tail = name;
-                return subCtx;
-
-            case ResponseCodes.JNDI_DATA_SOURCE:
-                return createDataSource((DataSourceMetaData) res.getResult());
-
-            case ResponseCodes.JNDI_WEBSERVICE:
-                return createWebservice((WsMetaData) res.getResult());
-
-            case ResponseCodes.JNDI_RESOURCE:
-                final String type = (String) res.getResult();
-                value = System.getProperty("Resource/" + type);
-                if (value == null) {
-                    return null;
-                }
-                return parseEntry(prop, value);
-
-            case ResponseCodes.JNDI_REFERENCE:
-                final Reference ref = (Reference) res.getResult();
-                try {
-                    return NamingManager.getObjectInstance(ref, 
getNameParser(name).parse(name), this, env);
-                } catch (final Exception e) {
-                    throw (NamingException) new NamingException("Could not 
dereference " + ref).initCause(e);
-                }
-
-            case ResponseCodes.JNDI_NOT_FOUND:
-                throw new NameNotFoundException(name + " does not exist in the 
system.  Check that the app was successfully deployed.");
-
-            case ResponseCodes.JNDI_NAMING_EXCEPTION:
-                final Throwable throwable = ((ThrowableArtifact) 
res.getResult()).getThrowable();
-                if (throwable instanceof NamingException) {
-                    throw (NamingException) throwable;
-                }
-                throw (NamingException) new 
NamingException().initCause(throwable);
-
-            case ResponseCodes.JNDI_RUNTIME_EXCEPTION:
-                throw (RuntimeException) res.getResult();
-
-            case ResponseCodes.JNDI_ERROR:
-                throw (Error) res.getResult();
-
-            default:
-                throw new ClientRuntimeException("Invalid response from 
server: " + res.getResponseCode());
-        }
-    }
-
-    private Object parseEntry(final String name, String value) throws 
NamingException {
-        try {
-            URI uri = new URI(value);
-            final String scheme = uri.getScheme();
-            if (scheme.equals("link")) {
-                value = System.getProperty(uri.getSchemeSpecificPart());
-                if (value == null) {
-                    return null;
-                }
-                return parseEntry(name, value);
-            } else if (scheme.equals("datasource")) {
-                uri = new URI(uri.getSchemeSpecificPart());
-                final String driver = uri.getScheme();
-                final String url = uri.getSchemeSpecificPart();
-                return new ClientDataSource(driver, url, null, null);
-            } else if (scheme.equals("connectionfactory")) {
-                return build(uri);
-            } else if (scheme.equals("javamail")) {
-                return javax.mail.Session.getDefaultInstance(new Properties());
-            } else if (scheme.equals("orb")) {
-                return getDefaultOrb();
-            } else if (scheme.equals("queue")) {
-                return build(uri);
-            } else if (scheme.equals("topic")) {
-                return build(uri);
-            } else {
-                throw new UnsupportedOperationException("Unsupported Naming 
URI scheme '" + scheme + "'");
-            }
-        } catch (final URISyntaxException e) {
-            throw (NamingException) new NamingException("Unparsable jndi entry 
'" + name + "=" + value + "'.  Exception: " + e.getMessage()).initCause(e);
-        }
-    }
-
-    private Object build(final URI inputUri) throws URISyntaxException {
-        final URI uri = new URI(inputUri.getSchemeSpecificPart());
-        final String driver = uri.getScheme();
-        final String url = uri.getSchemeSpecificPart();
-        final ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
-        if (classLoader == null) {
-            getClass().getClassLoader();
-        }
-        if (classLoader == null) {
-            ClassLoader.getSystemClassLoader();
-        }
-        try {
-            final Class<?> clazz = Class.forName(driver, true, classLoader);
-            final Constructor<?> constructor = 
clazz.getConstructor(String.class);
-            return constructor.newInstance(url);
-        } catch (final Exception e) {
-            throw new IllegalStateException("Cannot use " + driver + " with 
parameter " + url, e);
-        }
-    }
-
-    private DataSource createDataSource(final DataSourceMetaData 
dataSourceMetaData) {
-        return new ClientDataSource(dataSourceMetaData);
-    }
-
-    private Object createWebservice(final WsMetaData webserviceMetaData) 
throws NamingException {
-        try {
-            return webserviceMetaData.createWebservice();
-        } catch (final Exception e) {
-            throw (NamingException) new NamingException("Error creating 
webservice").initCause(e);
-        }
-    }
-
-    private ORB getDefaultOrb() {
-        return ORB.init();
-    }
-
-    @Override
-    public Object lookup(final Name name) throws NamingException {
-        return lookup(name.toString());
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public NamingEnumeration<NameClassPair> list(String name) throws 
NamingException {
-
-        checkState();
-
-        if (name == null) {
-            throw new InvalidNameException("The name cannot be null");
-        } else if (name.startsWith("java:")) {
-            name = name.replaceFirst("^java:", "");
-        } else if (!name.startsWith("/")) {
-            name = tail + name;
-        }
-
-        final JNDIRequest req = new JNDIRequest(RequestMethodCode.JNDI_LIST, 
name);
-        req.setModuleId(moduleId);
-
-        final JNDIResponse res;
-        try {
-            res = request(req);
-        } catch (Exception e) {
-            if (e instanceof RemoteException && e.getCause() instanceof 
ConnectException) {
-                e = (Exception) e.getCause();
-                throw (ServiceUnavailableException) new 
ServiceUnavailableException("Cannot list '" + name + "'.").initCause(e);
-            }
-            throw (NamingException) new NamingException("Cannot list '" + name 
+ "'.").initCause(e);
-        }
-
-        switch (res.getResponseCode()) {
-
-            case ResponseCodes.JNDI_OK:
-                return null;
-
-            case ResponseCodes.JNDI_ENUMERATION:
-                return (NamingEnumeration) res.getResult();
-
-            case ResponseCodes.JNDI_NOT_FOUND:
-                throw new NameNotFoundException(name);
-
-            case ResponseCodes.JNDI_NAMING_EXCEPTION:
-                final Throwable throwable = ((ThrowableArtifact) 
res.getResult()).getThrowable();
-                if (throwable instanceof NamingException) {
-                    throw (NamingException) throwable;
-                }
-                throw (NamingException) new 
NamingException().initCause(throwable);
-
-            case ResponseCodes.JNDI_ERROR:
-                throw (Error) res.getResult();
-
-            default:
-                throw new ClientRuntimeException("Invalid response from server 
:" + res.getResponseCode());
-        }
-
-    }
-
-    @Override
-    public NamingEnumeration<NameClassPair> list(final Name name) throws 
NamingException {
-        return list(name.toString());
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public NamingEnumeration<Binding> listBindings(final String name) throws 
NamingException {
-        final Object o = lookup(name);
-        if (o instanceof Context) {
-            final Context context = (Context) o;
-            final NamingEnumeration<NameClassPair> enumeration = 
context.list("");
-            final List<NameClassPair> bindings = new 
ArrayList<NameClassPair>();
-
-            while (enumeration.hasMoreElements()) {
-                final NameClassPair pair = enumeration.nextElement();
-                bindings.add(new LazyBinding(pair.getName(), 
pair.getClassName(), context));
-            }
-
-            return new NameClassPairEnumeration(bindings);
-
-        } else {
-            return null;
-        }
-
-    }
-
-    private static class LazyBinding extends Binding {
-
-        private static final long serialVersionUID = 1L;
-        private RuntimeException failed;
-        private final Context context;
-
-        public LazyBinding(final String name, final String className, final 
Context context) {
-            super(name, className, null);
-            this.context = context;
-        }
-
-        @Override
-        public synchronized Object getObject() {
-            if (super.getObject() == null) {
-                if (failed != null) {
-                    throw failed;
-                }
-                try {
-                    super.setObject(context.lookup(getName()));
-                } catch (final NamingException e) {
-                    throw failed = new ClientRuntimeException("Failed to 
lazily fetch the binding '" + getName() + "'", e);
-                }
-            }
-            return super.getObject();
-        }
-    }
-
-    @Override
-    public NamingEnumeration<Binding> listBindings(final Name name) throws 
NamingException {
-        return listBindings(name.toString());
-    }
-
-    @Override
-    public Object lookupLink(final String name) throws NamingException {
-        return lookup(name);
-    }
-
-    @Override
-    public Object lookupLink(final Name name) throws NamingException {
-        return lookupLink(name.toString());
-    }
-
-    @Override
-    public NameParser getNameParser(final String name) throws NamingException {
-        return new SimpleNameParser();
-    }
-
-    @Override
-    public NameParser getNameParser(final Name name) throws NamingException {
-        return new SimpleNameParser();
-    }
-
-    @Override
-    public String composeName(final String name, final String prefix) throws 
NamingException {
-        throw new OperationNotSupportedException("TODO: Needs to be 
implemented");
-    }
-
-    @Override
-    public Name composeName(final Name name, final Name prefix) throws 
NamingException {
-        throw new OperationNotSupportedException("TODO: Needs to be 
implemented");
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    public Object addToEnvironment(final String key, final Object value) 
throws NamingException {
-        return env.put(key, value);
-    }
-
-    @Override
-    public Object removeFromEnvironment(final String key) throws 
NamingException {
-        return env.remove(key);
-    }
-
-    @Override
-    public Hashtable getEnvironment() throws NamingException {
-        return (Hashtable) env.clone();
-    }
-
-    @Override
-    public String getNameInNamespace() throws NamingException {
-        return "";
-    }
-
-    private void checkState() throws NamingException {
-        if (isShutdown.get()) {
-            throw new NamingException("Context has been closed. Please create 
a new instance.");
-        }
-    }
-
-    @Override
-    public void close() throws NamingException {
-
-        if (isShutdown.getAndSet(true)) {
-            return;
-        }
-
-        waitForShutdown(executorService);
-
-        final String userID = (String) env.get(Context.SECURITY_PRINCIPAL);
-
-        if (userID != null) {
-            final String psswrd = (String) 
env.get(Context.SECURITY_CREDENTIALS);
-            final boolean logout = true;
-            try {
-                this.authenticate(userID, psswrd, logout);
-            } catch (final Exception ignore) {
-                //no-op
-            }
-        }
-    }
-
-    private static void waitForShutdown(final ExecutorService executor) {
-        if (executor == null || executor.isShutdown()) {
-            return;
-        }
-
-        final List<Runnable> runnables = executor.shutdownNow();
-        for (final Runnable r : runnables) {
-            try {
-                r.run();
-            } catch (final Throwable th) {
-                LOGGER.log(Level.SEVERE, th.getMessage(), th);
-            }
-        }
-    }
-
-    @Override
-    public void bind(final String name, final Object obj) throws 
NamingException {
-        throw new OperationNotSupportedException();
-    }
-
-    @Override
-    public void bind(final Name name, final Object obj) throws NamingException 
{
-        bind(name.toString(), obj);
-    }
-
-    @Override
-    public void rebind(final String name, final Object obj) throws 
NamingException {
-        throw new OperationNotSupportedException();
-    }
-
-    @Override
-    public void rebind(final Name name, final Object obj) throws 
NamingException {
-        rebind(name.toString(), obj);
-    }
-
-    @Override
-    public void unbind(final String name) throws NamingException {
-        throw new OperationNotSupportedException();
-    }
-
-    @Override
-    public void unbind(final Name name) throws NamingException {
-        unbind(name.toString());
-    }
-
-    @Override
-    public void rename(final String oldname, final String newname) throws 
NamingException {
-        throw new OperationNotSupportedException();
-    }
-
-    @Override
-    public void rename(final Name oldname, final Name newname) throws 
NamingException {
-        rename(oldname.toString(), newname.toString());
-    }
-
-    @Override
-    public void destroySubcontext(final String name) throws NamingException {
-        throw new OperationNotSupportedException();
-    }
-
-    @Override
-    public void destroySubcontext(final Name name) throws NamingException {
-        destroySubcontext(name.toString());
-    }
-
-    @Override
-    public Context createSubcontext(final String name) throws NamingException {
-        throw new OperationNotSupportedException();
-    }
-
-    @Override
-    public Context createSubcontext(final Name name) throws NamingException {
-        return createSubcontext(name.toString());
-    }
-
-    @Override
-    protected void finalize() throws Throwable {
-        try {
-            close();
-        } finally {
-            super.finalize();
-        }
-    }
-
-    private static final class SimpleNameParser implements NameParser {
-
-        private static final Properties PARSER_PROPERTIES = new Properties();
-
-        static {
-            PARSER_PROPERTIES.put("jndi.syntax.direction", "left_to_right");
-            PARSER_PROPERTIES.put("jndi.syntax.separator", "/");
-        }
-
-        private SimpleNameParser() {
-        }
-
-        @Override
-        public Name parse(final String name) throws NamingException {
-            return new CompoundName(name, PARSER_PROPERTIES);
-        }
-    }
-
-    public static class AuthenticationInfo implements Serializable {
-
-        private static final long serialVersionUID = -8898613592355280735L;
-        private final String realm;
-        private final String user;
-        private final char[] password;
-        private final long timeout;
-
-        public AuthenticationInfo(final String realm, final String user, final 
char[] chars) {
-            this(realm, user, chars, 0);
-        }
-
-        public AuthenticationInfo(final String realm, final String user, final 
char[] password, final long timeout) {
-            this.realm = realm;
-            this.user = user;
-            this.password = password;
-            this.timeout = timeout;
-        }
-
-        public String getRealm() {
-            return realm;
-        }
-
-        public String getUser() {
-            return user;
-        }
-
-        public char[] getPassword() {
-            return password;
-        }
-
-        public long getTimeout() {
-            return timeout;
-        }
-    }
-}
-
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.client;
+
+import org.apache.openejb.client.event.RemoteInitialContextCreated;
+import org.apache.openejb.client.serializer.EJBDSerializer;
+import org.omg.CORBA.ORB;
+
+import javax.naming.AuthenticationException;
+import javax.naming.Binding;
+import javax.naming.CompoundName;
+import javax.naming.ConfigurationException;
+import javax.naming.Context;
+import javax.naming.InvalidNameException;
+import javax.naming.Name;
+import javax.naming.NameClassPair;
+import javax.naming.NameNotFoundException;
+import javax.naming.NameParser;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.OperationNotSupportedException;
+import javax.naming.Reference;
+import javax.naming.ServiceUnavailableException;
+import javax.naming.spi.InitialContextFactory;
+import javax.naming.spi.NamingManager;
+import javax.sql.DataSource;
+import java.io.Serializable;
+import java.lang.reflect.Constructor;
+import java.net.ConnectException;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.rmi.RemoteException;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.LinkedBlockingDeque;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ * @version $Rev$ $Date$
+ */
+public class JNDIContext implements InitialContextFactory, Context {
+    private static final Logger LOGGER = Logger.getLogger("OpenEJB.client");
+
+    @SuppressWarnings("UnusedDeclaration")
+    public static final String DEFAULT_PROVIDER_URL = "ejbd://localhost:4201";
+    public static final String SERIALIZER = "openejb.ejbd.serializer";
+    public static final String AUTHENTICATE_WITH_THE_REQUEST = 
"openejb.ejbd.authenticate-with-request";
+    public static final String POOL_QUEUE_SIZE = 
"openejb.client.invoker.queue";
+    @SuppressWarnings("UnusedDeclaration")
+    public static final String POOL_THREAD_NUMBER = 
"openejb.client.invoker.threads";
+    public static final String AUTHENTICATION_REALM_NAME = 
"openejb.authentication.realmName";
+    public static final String IDENTITY_TIMEOUT = 
"tomee.authentication.identity.timeout";
+
+    private final AtomicBoolean isShutdown = new AtomicBoolean(false);
+    private String tail = "/";
+    private ServerMetaData server;
+    private ClientMetaData client;
+    private Hashtable env;
+    private String moduleId;
+    private ClientInstance clientIdentity;
+
+    private static final ThreadPoolExecutor GLOBAL_CLIENT_POOL = 
newExecutor(10, null);
+
+    static {
+        final ClassLoader classLoader = Client.class.getClassLoader();
+        Class<?> container;
+        try {
+            container = Class.forName("org.apache.openejb.OpenEJB", false, 
classLoader);
+        } catch (final Throwable e) {
+            container = null;
+        }
+        if (classLoader == ClassLoader.getSystemClassLoader() || 
Boolean.getBoolean("openejb.client.flus-tasks")
+                || (container != null && container.getClassLoader() == 
classLoader)) {
+            Runtime.getRuntime().addShutdownHook(new Thread() {
+                @Override
+                public void run() {
+                    waitForShutdown(GLOBAL_CLIENT_POOL);
+                }
+            });
+        }
+    }
+
+    private AuthenticationInfo authenticationInfo = null;
+
+    //TODO figure out how to configure and manage the thread pool on the 
client side, this will do for now...
+    private transient int threads;
+    private transient LinkedBlockingQueue<Runnable> blockingQueue;
+
+    protected transient ThreadPoolExecutor executorService;
+
+    public static ThreadPoolExecutor globalExecutor() {
+        return GLOBAL_CLIENT_POOL;
+    }
+
+    private ThreadPoolExecutor executor() {
+        if (executorService != null) {
+            return executorService;
+        }
+        if (threads < 0) {
+            return GLOBAL_CLIENT_POOL;
+        }
+        synchronized (this) {
+            if (executorService != null) {
+                return executorService;
+            }
+            executorService = newExecutor(threads, blockingQueue);
+        }
+        return executorService;
+    }
+
+    public static ThreadPoolExecutor newExecutor(final int threads, final 
BlockingQueue<Runnable> blockingQueue) {
+        /**
+         This thread pool starts with 3 core threads and can grow to the limit 
defined by 'threads'.
+         If a pool thread is idle for more than 1 minute it will be discarded, 
unless the core size is reached.
+         It can accept up to the number of processes defined by 'queue'.
+         If the queue is full then an attempt is made to add the process to 
the queue for 10 seconds.
+         Failure to add to the queue in this time will either result in a 
logged rejection, or if 'block'
+         is true then a final attempt is made to run the process in the 
current thread (the service thread).
+         */
+
+        final ThreadPoolExecutor executorService = new ThreadPoolExecutor(3, 
(threads < 3 ? 3 : threads), 1, TimeUnit.MINUTES, blockingQueue == null ? new 
LinkedBlockingDeque<Runnable>(Integer.parseInt(getProperty(null, 
POOL_QUEUE_SIZE, "2"))) : blockingQueue);
+        executorService.setThreadFactory(new ThreadFactory() {
+
+            private final AtomicInteger i = new AtomicInteger(0);
+
+            @Override
+            public Thread newThread(final Runnable r) {
+                final Thread t = new Thread(r, "OpenEJB.Client." + 
i.incrementAndGet());
+                t.setDaemon(true);
+                t.setUncaughtExceptionHandler(new 
Thread.UncaughtExceptionHandler() {
+                    @Override
+                    public void uncaughtException(final Thread t, final 
Throwable e) {
+                        
Logger.getLogger(EJBObjectHandler.class.getName()).log(Level.SEVERE, "Uncaught 
error in: " + t.getName(), e);
+                    }
+                });
+
+                return t;
+            }
+
+        });
+
+        executorService.setRejectedExecutionHandler(new 
RejectedExecutionHandler() {
+            @Override
+            public void rejectedExecution(final Runnable r, final 
ThreadPoolExecutor tpe) {
+
+                if (null == r || null == tpe || tpe.isShutdown() || 
tpe.isTerminated() || tpe.isTerminating()) {
+                    return;
+                }
+
+                final Logger log = 
Logger.getLogger(EJBObjectHandler.class.getName());
+
+                if (log.isLoggable(Level.WARNING)) {
+                    log.log(Level.WARNING, "EJBObjectHandler ExecutorService 
at capacity for process: " + r);
+                }
+
+                boolean offer = false;
+                try {
+                    offer = tpe.getQueue().offer(r, 10, TimeUnit.SECONDS);
+                } catch (final InterruptedException e) {
+                    //Ignore
+                }
+
+                if (!offer) {
+                    log.log(Level.SEVERE, "EJBObjectHandler ExecutorService 
failed to run asynchronous process: " + r);
+                }
+            }
+        });
+        return executorService;
+    }
+
+    public JNDIContext() {
+    }
+
+    /*
+     * A neater version of clone
+     */
+    public JNDIContext(final JNDIContext that) {
+        this.tail = that.tail;
+        this.server = that.server;
+        this.client = that.client;
+        this.moduleId = that.moduleId;
+        this.env = (Hashtable) that.env.clone();
+        this.clientIdentity = that.clientIdentity;
+    }
+
+    private JNDIResponse request(final JNDIRequest req) throws Exception {
+        req.setServerHash(server.buildHash());
+
+        final JNDIResponse response = new JNDIResponse();
+        Client.request(req, response, server);
+        if (null != response.getServer()) {
+            server.merge(response.getServer());
+        }
+        return response;
+    }
+
+    protected AuthenticationResponse requestAuthorization(final 
AuthenticationRequest req) throws RemoteException {
+        return (AuthenticationResponse) Client.request(req, new 
AuthenticationResponse(), server);
+    }
+
+    @Override
+    public Context getInitialContext(final Hashtable environment) throws 
NamingException {
+        if (environment == null) {
+            throw new NamingException("Invalid argument, hashtable cannot be 
null.");
+        } else {
+            env = (Hashtable) environment.clone();
+        }
+
+        final String userID = (String) env.get(Context.SECURITY_PRINCIPAL);
+        final String psswrd = (String) env.get(Context.SECURITY_CREDENTIALS);
+        String providerUrl = (String) env.get(Context.PROVIDER_URL);
+
+        final boolean authWithRequest = 
"true".equalsIgnoreCase(String.class.cast(env.get(AUTHENTICATE_WITH_THE_REQUEST)));
+        moduleId = (String) env.get("openejb.client.moduleId");
+
+        final URI location;
+        try {
+            providerUrl = addMissingParts(providerUrl);
+            location = new URI(providerUrl);
+        } catch (final URISyntaxException e) {
+            throw (ConfigurationException) new 
ConfigurationException("Property value for " +
+                    Context.PROVIDER_URL +
+                    " invalid: " +
+                    providerUrl +
+                    " - " +
+                    e.getMessage()).initCause(e);
+        }
+        this.server = new ServerMetaData(location);
+
+        final Client.Context context = Client.getContext(this.server);
+        context.getProperties().putAll(environment);
+
+        final String strategy = 
context.getOptions().get("openejb.client.connection.strategy", "default");
+        context.getClusterMetaData().setConnectionStrategy(strategy);
+
+        Client.fireEvent(new RemoteInitialContextCreated(location));
+
+        //TODO: Either aggressively initiate authentication or wait for the 
server to send us an authentication challenge.
+        if (userID != null) {
+            if (!authWithRequest) {
+                authenticate(userID, psswrd, false);
+            } else {
+                authenticationInfo = new 
AuthenticationInfo(String.class.cast(env.get(AUTHENTICATION_REALM_NAME)), 
userID, psswrd.toCharArray(), getTimeout(env));
+            }
+        }
+        if (client == null) {
+            client = new ClientMetaData();
+        }
+
+        seedClientSerializer();
+
+        final int queue = Integer.parseInt(getProperty(env, 
JNDIContext.POOL_QUEUE_SIZE, "2"));
+        blockingQueue = new LinkedBlockingQueue<Runnable>((queue < 2 ? 2 : 
queue));
+        threads = Integer.parseInt(getProperty(env, 
"openejb.client.invoker.threads", "-1"));
+
+        return this;
+    }
+
+    private void seedClientSerializer() {
+        final String serializer = (String) env.get(SERIALIZER);
+        if (serializer != null) {
+            try {
+                
client.setSerializer(EJBDSerializer.class.cast(Thread.currentThread().getContextClassLoader().loadClass(serializer).newInstance()));
+            } catch (final Exception e) {
+                // no-op
+            }
+        }
+    }
+
+    private long getTimeout(final Hashtable env) {
+        final Object o = env.get(IDENTITY_TIMEOUT);
+        if (null != o) {
+            final Long l = Long.class.cast(o);
+            //noinspection ConstantConditions
+            if (null != l) {
+                return l;
+            }
+        }
+
+        return 0L;
+    }
+
+    private static String getProperty(final Hashtable env, final String key, 
final String defaultValue) {
+        final Object value = env == null ? null : env.get(key);
+        if (value != null) {
+            return value.toString();
+        }
+        return System.getProperty(key, defaultValue);
+    }
+
+    /**
+     * Add missing parts - expected only part of the required providerUrl
+     * <p/>
+     * TODO: Move the check to a place where it really belongs - 
ConnectionManager, ConnectionFactory or such
+     * This method (class in general) doesn't really know what is required as 
far as connection details go
+     * Assuming that java.net.URI or java.net.URL are going to be used is 
overly stated
+     */
+    String addMissingParts(String providerUrl) throws URISyntaxException {
+
+        final int port = Integer.parseInt(System.getProperty("ejbd.port", 
"4201"));
+
+        if (providerUrl == null || providerUrl.length() == 0) {
+            providerUrl = "ejbd://localhost:" + port;
+        } else {
+
+            final int colonIndex = providerUrl.indexOf(":");
+            final int slashesIndex = providerUrl.indexOf("//");
+
+            if (colonIndex == -1 && slashesIndex == -1) {   // hostname or ip 
address only
+                providerUrl = "ejbd://" + providerUrl + ":" + port;
+            } else if (colonIndex == -1) {
+                final URI providerUri = new URI(providerUrl);
+                final String scheme = providerUri.getScheme();
+                if (!(scheme.equals("http") || scheme.equals("https"))) {
+                    providerUrl = providerUrl + ":" + port;
+                }
+            } else if (slashesIndex == -1) {
+                providerUrl = "ejbd://" + providerUrl;
+            }
+        }
+        return providerUrl;
+    }
+
+    public void authenticate(final String userID, final String psswrd, final 
boolean logout) throws AuthenticationException {
+
+        final AuthenticationRequest req = new 
AuthenticationRequest(String.class.cast(env.get(AUTHENTICATION_REALM_NAME)), 
userID, psswrd, getTimeout(env));
+
+        if (logout) {
+            req.setLogoutIdentity(null != client ? client.getClientIdentity() 
: null);
+        }
+
+        final AuthenticationResponse res;
+        try {
+            res = requestAuthorization(req);
+        } catch (final RemoteException e) {
+            throw new AuthenticationException(e.getLocalizedMessage());
+        }
+
+        switch (res.getResponseCode()) {
+            case ResponseCodes.AUTH_GRANTED:
+                client = logout ? new ClientMetaData() : res.getIdentity();
+                break;
+            case ResponseCodes.AUTH_REDIRECT:
+                client = logout ? new ClientMetaData() : res.getIdentity();
+                server = res.getServer();
+                break;
+            case ResponseCodes.AUTH_DENIED:
+                throw (AuthenticationException) new 
AuthenticationException("This principle is not 
authorized.").initCause(res.getDeniedCause());
+        }
+
+        seedClientSerializer();
+    }
+
+    public EJBHomeProxy createEJBHomeProxy(final EJBMetaDataImpl ejbData) {
+        final EJBHomeHandler handler = 
EJBHomeHandler.createEJBHomeHandler(executor(), ejbData, server, client, 
authenticationInfo);
+        final EJBHomeProxy proxy = handler.createEJBHomeProxy();
+        handler.ejb.ejbHomeProxy = proxy;
+
+        return proxy;
+
+    }
+
+    private Object createBusinessObject(final Object result) {
+        final EJBMetaDataImpl ejb = (EJBMetaDataImpl) result;
+        final Object primaryKey = ejb.getPrimaryKey();
+
+        final EJBObjectHandler handler = 
EJBObjectHandler.createEJBObjectHandler(executor(), ejb, server, client, 
primaryKey, authenticationInfo);
+        return handler.createEJBObjectProxy();
+    }
+
+    @Override
+    public Object lookup(String name) throws NamingException {
+
+        checkState();
+
+        if (name == null) {
+            throw new InvalidNameException("The name cannot be null");
+        } else if (name.equals("")) {
+            return new JNDIContext(this);
+        } else if (name.startsWith("java:")) {
+            name = name.replaceFirst("^java:", "");
+        } else if (!name.startsWith("/")) {
+            name = tail + name;
+        }
+
+        final String prop = name.replaceFirst("comp/env/", "");
+        String value = System.getProperty(prop);
+        if (value != null) {
+            return parseEntry(prop, value);
+        }
+
+        if (name.equals("comp/ORB")) {
+            return getDefaultOrb();
+        }
+
+        final JNDIRequest req = new JNDIRequest();
+        req.setRequestMethod(RequestMethodCode.JNDI_LOOKUP);
+        req.setRequestString(name);
+        req.setModuleId(moduleId);
+
+        final JNDIResponse res;
+        try {
+            res = request(req);
+        } catch (Exception e) {
+            if (e instanceof RemoteException && e.getCause() instanceof 
ConnectException) {
+                e = (Exception) e.getCause();
+                throw (ServiceUnavailableException) new 
ServiceUnavailableException("Cannot lookup '" + name + "'.").initCause(e);
+            }
+            throw (NamingException) new NamingException("Cannot lookup '" + 
name + "'.").initCause(e);
+        }
+
+        switch (res.getResponseCode()) {
+            case ResponseCodes.JNDI_EJBHOME:
+                return createEJBHomeProxy((EJBMetaDataImpl) res.getResult());
+
+            case ResponseCodes.JNDI_BUSINESS_OBJECT:
+                return createBusinessObject(res.getResult());
+
+            case ResponseCodes.JNDI_OK:
+                return res.getResult();
+
+            case ResponseCodes.JNDI_INJECTIONS:
+                return res.getResult();
+
+            case ResponseCodes.JNDI_CONTEXT:
+                final JNDIContext subCtx = new JNDIContext(this);
+                if (!name.endsWith("/")) {
+                    name += '/';
+                }
+                subCtx.tail = name;
+                return subCtx;
+
+            case ResponseCodes.JNDI_DATA_SOURCE:
+                return createDataSource((DataSourceMetaData) res.getResult());
+
+            case ResponseCodes.JNDI_WEBSERVICE:
+                return createWebservice((WsMetaData) res.getResult());
+
+            case ResponseCodes.JNDI_RESOURCE:
+                final String type = (String) res.getResult();
+                value = System.getProperty("Resource/" + type);
+                if (value == null) {
+                    return null;
+                }
+                return parseEntry(prop, value);
+
+            case ResponseCodes.JNDI_REFERENCE:
+                final Reference ref = (Reference) res.getResult();
+                try {
+                    return NamingManager.getObjectInstance(ref, 
getNameParser(name).parse(name), this, env);
+                } catch (final Exception e) {
+                    throw (NamingException) new NamingException("Could not 
dereference " + ref).initCause(e);
+                }
+
+            case ResponseCodes.JNDI_NOT_FOUND:
+                throw new NameNotFoundException(name + " does not exist in the 
system.  Check that the app was successfully deployed.");
+
+            case ResponseCodes.JNDI_NAMING_EXCEPTION:
+                final Throwable throwable = ((ThrowableArtifact) 
res.getResult()).getThrowable();
+                if (throwable instanceof NamingException) {
+                    throw (NamingException) throwable;
+                }
+                throw (NamingException) new 
NamingException().initCause(throwable);
+
+            case ResponseCodes.JNDI_RUNTIME_EXCEPTION:
+                throw (RuntimeException) res.getResult();
+
+            case ResponseCodes.JNDI_ERROR:
+                throw (Error) res.getResult();
+
+            default:
+                throw new ClientRuntimeException("Invalid response from 
server: " + res.getResponseCode());
+        }
+    }
+
+    private Object parseEntry(final String name, String value) throws 
NamingException {
+        try {
+            URI uri = new URI(value);
+            final String scheme = uri.getScheme();
+            if (scheme.equals("link")) {
+                value = System.getProperty(uri.getSchemeSpecificPart());
+                if (value == null) {
+                    return null;
+                }
+                return parseEntry(name, value);
+            } else if (scheme.equals("datasource")) {
+                uri = new URI(uri.getSchemeSpecificPart());
+                final String driver = uri.getScheme();
+                final String url = uri.getSchemeSpecificPart();
+                return new ClientDataSource(driver, url, null, null);
+            } else if (scheme.equals("connectionfactory")) {
+                return build(uri);
+            } else if (scheme.equals("javamail")) {
+                return javax.mail.Session.getDefaultInstance(new Properties());
+            } else if (scheme.equals("orb")) {
+                return getDefaultOrb();
+            } else if (scheme.equals("queue")) {
+                return build(uri);
+            } else if (scheme.equals("topic")) {
+                return build(uri);
+            } else {
+                throw new UnsupportedOperationException("Unsupported Naming 
URI scheme '" + scheme + "'");
+            }
+        } catch (final URISyntaxException e) {
+            throw (NamingException) new NamingException("Unparsable jndi entry 
'" + name + "=" + value + "'.  Exception: " + e.getMessage()).initCause(e);
+        }
+    }
+
+    private Object build(final URI inputUri) throws URISyntaxException {
+        final URI uri = new URI(inputUri.getSchemeSpecificPart());
+        final String driver = uri.getScheme();
+        final String url = uri.getSchemeSpecificPart();
+        final ClassLoader classLoader = 
Thread.currentThread().getContextClassLoader();
+        if (classLoader == null) {
+            getClass().getClassLoader();
+        }
+        if (classLoader == null) {
+            ClassLoader.getSystemClassLoader();
+        }
+        try {
+            final Class<?> clazz = Class.forName(driver, true, classLoader);
+            final Constructor<?> constructor = 
clazz.getConstructor(String.class);
+            return constructor.newInstance(url);
+        } catch (final Exception e) {
+            throw new IllegalStateException("Cannot use " + driver + " with 
parameter " + url, e);
+        }
+    }
+
+    private DataSource createDataSource(final DataSourceMetaData 
dataSourceMetaData) {
+        return new ClientDataSource(dataSourceMetaData);
+    }
+
+    private Object createWebservice(final WsMetaData webserviceMetaData) 
throws NamingException {
+        try {
+            return webserviceMetaData.createWebservice();
+        } catch (final Exception e) {
+            throw (NamingException) new NamingException("Error creating 
webservice").initCause(e);
+        }
+    }
+
+    private ORB getDefaultOrb() {
+        return ORB.init();
+    }
+
+    @Override
+    public Object lookup(final Name name) throws NamingException {
+        return lookup(name.toString());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public NamingEnumeration<NameClassPair> list(String name) throws 
NamingException {
+
+        checkState();
+
+        if (name == null) {
+            throw new InvalidNameException("The name cannot be null");
+        } else if (name.startsWith("java:")) {
+            name = name.replaceFirst("^java:", "");
+        } else if (!name.startsWith("/")) {
+            name = tail + name;
+        }
+
+        final JNDIRequest req = new JNDIRequest(RequestMethodCode.JNDI_LIST, 
name);
+        req.setModuleId(moduleId);
+
+        final JNDIResponse res;
+        try {
+            res = request(req);
+        } catch (Exception e) {
+            if (e instanceof RemoteException && e.getCause() instanceof 
ConnectException) {
+                e = (Exception) e.getCause();
+                throw (ServiceUnavailableException) new 
ServiceUnavailableException("Cannot list '" + name + "'.").initCause(e);
+            }
+            throw (NamingException) new NamingException("Cannot list '" + name 
+ "'.").initCause(e);
+        }
+
+        switch (res.getResponseCode()) {
+
+            case ResponseCodes.JNDI_OK:
+                return null;
+
+            case ResponseCodes.JNDI_ENUMERATION:
+                return (NamingEnumeration) res.getResult();
+
+            case ResponseCodes.JNDI_NOT_FOUND:
+                throw new NameNotFoundException(name);
+
+            case ResponseCodes.JNDI_NAMING_EXCEPTION:
+                final Throwable throwable = ((ThrowableArtifact) 
res.getResult()).getThrowable();
+                if (throwable instanceof NamingException) {
+                    throw (NamingException) throwable;
+                }
+                throw (NamingException) new 
NamingException().initCause(throwable);
+
+            case ResponseCodes.JNDI_ERROR:
+                throw (Error) res.getResult();
+
+            default:
+                throw new ClientRuntimeException("Invalid response from server 
:" + res.getResponseCode());
+        }
+
+    }
+
+    @Override
+    public NamingEnumeration<NameClassPair> list(final Name name) throws 
NamingException {
+        return list(name.toString());
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public NamingEnumeration<Binding> listBindings(final String name) throws 
NamingException {
+        final Object o = lookup(name);
+        if (o instanceof Context) {
+            final Context context = (Context) o;
+            final NamingEnumeration<NameClassPair> enumeration = 
context.list("");
+            final List<NameClassPair> bindings = new 
ArrayList<NameClassPair>();
+
+            while (enumeration.hasMoreElements()) {
+                final NameClassPair pair = enumeration.nextElement();
+                bindings.add(new LazyBinding(pair.getName(), 
pair.getClassName(), context));
+            }
+
+            return new NameClassPairEnumeration(bindings);
+
+        } else {
+            return null;
+        }
+
+    }
+
+    private static class LazyBinding extends Binding {
+
+        private static final long serialVersionUID = 1L;
+        private RuntimeException failed;
+        private final Context context;
+
+        public LazyBinding(final String name, final String className, final 
Context context) {
+            super(name, className, null);
+            this.context = context;
+        }
+
+        @Override
+        public synchronized Object getObject() {
+            if (super.getObject() == null) {
+                if (failed != null) {
+                    throw failed;
+                }
+                try {
+                    super.setObject(context.lookup(getName()));
+                } catch (final NamingException e) {
+                    throw failed = new ClientRuntimeException("Failed to 
lazily fetch the binding '" + getName() + "'", e);
+                }
+            }
+            return super.getObject();
+        }
+    }
+
+    @Override
+    public NamingEnumeration<Binding> listBindings(final Name name) throws 
NamingException {
+        return listBindings(name.toString());
+    }
+
+    @Override
+    public Object lookupLink(final String name) throws NamingException {
+        return lookup(name);
+    }
+
+    @Override
+    public Object lookupLink(final Name name) throws NamingException {
+        return lookupLink(name.toString());
+    }
+
+    @Override
+    public NameParser getNameParser(final String name) throws NamingException {
+        return new SimpleNameParser();
+    }
+
+    @Override
+    public NameParser getNameParser(final Name name) throws NamingException {
+        return new SimpleNameParser();
+    }
+
+    @Override
+    public String composeName(final String name, final String prefix) throws 
NamingException {
+        throw new OperationNotSupportedException("TODO: Needs to be 
implemented");
+    }
+
+    @Override
+    public Name composeName(final Name name, final Name prefix) throws 
NamingException {
+        throw new OperationNotSupportedException("TODO: Needs to be 
implemented");
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public Object addToEnvironment(final String key, final Object value) 
throws NamingException {
+        return env.put(key, value);
+    }
+
+    @Override
+    public Object removeFromEnvironment(final String key) throws 
NamingException {
+        return env.remove(key);
+    }
+
+    @Override
+    public Hashtable getEnvironment() throws NamingException {
+        return (Hashtable) env.clone();
+    }
+
+    @Override
+    public String getNameInNamespace() throws NamingException {
+        return "";
+    }
+
+    private void checkState() throws NamingException {
+        if (isShutdown.get()) {
+            throw new NamingException("Context has been closed. Please create 
a new instance.");
+        }
+    }
+
+    @Override
+    public void close() throws NamingException {
+
+        if (isShutdown.getAndSet(true)) {
+            return;
+        }
+
+        waitForShutdown(executorService);
+
+        final String userID = (String) env.get(Context.SECURITY_PRINCIPAL);
+
+        if (userID != null) {
+            final String psswrd = (String) 
env.get(Context.SECURITY_CREDENTIALS);
+            final boolean logout = true;
+            try {
+                this.authenticate(userID, psswrd, logout);
+            } catch (final Exception ignore) {
+                //no-op
+            }
+        }
+    }
+
+    private static void waitForShutdown(final ExecutorService executor) {
+        if (executor == null || executor.isShutdown()) {
+            return;
+        }
+
+        final List<Runnable> runnables = executor.shutdownNow();
+        for (final Runnable r : runnables) {
+            try {
+                r.run();
+            } catch (final Throwable th) {
+                LOGGER.log(Level.SEVERE, th.getMessage(), th);
+            }
+        }
+    }
+
+    @Override
+    public void bind(final String name, final Object obj) throws 
NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    @Override
+    public void bind(final Name name, final Object obj) throws NamingException 
{
+        bind(name.toString(), obj);
+    }
+
+    @Override
+    public void rebind(final String name, final Object obj) throws 
NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    @Override
+    public void rebind(final Name name, final Object obj) throws 
NamingException {
+        rebind(name.toString(), obj);
+    }
+
+    @Override
+    public void unbind(final String name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    @Override
+    public void unbind(final Name name) throws NamingException {
+        unbind(name.toString());
+    }
+
+    @Override
+    public void rename(final String oldname, final String newname) throws 
NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    @Override
+    public void rename(final Name oldname, final Name newname) throws 
NamingException {
+        rename(oldname.toString(), newname.toString());
+    }
+
+    @Override
+    public void destroySubcontext(final String name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    @Override
+    public void destroySubcontext(final Name name) throws NamingException {
+        destroySubcontext(name.toString());
+    }
+
+    @Override
+    public Context createSubcontext(final String name) throws NamingException {
+        throw new OperationNotSupportedException();
+    }
+
+    @Override
+    public Context createSubcontext(final Name name) throws NamingException {
+        return createSubcontext(name.toString());
+    }
+
+    @Override
+    protected void finalize() throws Throwable {
+        try {
+            close();
+        } finally {
+            super.finalize();
+        }
+    }
+
+    private static final class SimpleNameParser implements NameParser {
+
+        private static final Properties PARSER_PROPERTIES = new Properties();
+
+        static {
+            PARSER_PROPERTIES.put("jndi.syntax.direction", "left_to_right");
+            PARSER_PROPERTIES.put("jndi.syntax.separator", "/");
+        }
+
+        private SimpleNameParser() {
+        }
+
+        @Override
+        public Name parse(final String name) throws NamingException {
+            return new CompoundName(name, PARSER_PROPERTIES);
+        }
+    }
+
+    public static class AuthenticationInfo implements Serializable {
+
+        private static final long serialVersionUID = -8898613592355280735L;
+        private final String realm;
+        private final String user;
+        private final char[] password;
+        private final long timeout;
+
+        public AuthenticationInfo(final String realm, final String user, final 
char[] chars) {
+            this(realm, user, chars, 0);
+        }
+
+        public AuthenticationInfo(final String realm, final String user, final 
char[] password, final long timeout) {
+            this.realm = realm;
+            this.user = user;
+            this.password = password;
+            this.timeout = timeout;
+        }
+
+        public String getRealm() {
+            return realm;
+        }
+
+        public String getUser() {
+            return user;
+        }
+
+        public char[] getPassword() {
+            return password;
+        }
+
+        public long getTimeout() {
+            return timeout;
+        }
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/tomee/blob/5c4316b5/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/AuthRequestHandler.java
----------------------------------------------------------------------
diff --git 
a/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/AuthRequestHandler.java
 
b/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/AuthRequestHandler.java
index 2d2f83b..08835cd 100644
--- 
a/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/AuthRequestHandler.java
+++ 
b/server/openejb-ejbd/src/main/java/org/apache/openejb/server/ejbd/AuthRequestHandler.java
@@ -1,119 +1,121 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.openejb.server.ejbd;
-
-import org.apache.openejb.client.AuthenticationRequest;
-import org.apache.openejb.client.AuthenticationResponse;
-import org.apache.openejb.client.ClientMetaData;
-import org.apache.openejb.client.ProtocolMetaData;
-import org.apache.openejb.client.Response;
-import org.apache.openejb.client.ResponseCodes;
-import org.apache.openejb.loader.SystemInstance;
-import org.apache.openejb.spi.SecurityService;
-import org.apache.openejb.util.LogCategory;
-import org.apache.openejb.util.Logger;
-import org.apache.openejb.util.Messages;
-
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-
-class AuthRequestHandler extends RequestHandler {
-
-    Messages _messages = new 
Messages("org.apache.openejb.server.util.resources");
-    private static final Logger logger = 
Logger.getInstance(LogCategory.OPENEJB_SERVER_REMOTE.createChild("auth"), 
"org.apache.openejb.server.util.resources");
-    private static final boolean debug = logger.isDebugEnabled();
-
-    protected AuthRequestHandler(final EjbDaemon daemon) {
-        super(daemon);
-    }
-
-    @Override
-    public String getName() {
-        return "Authentication";
-    }
-
-    @Override
-    public Logger getLogger() {
-        return logger;
-    }
-
-    @Override
-    public Response processRequest(final ObjectInputStream in, final 
ProtocolMetaData metaData) throws Exception {
-
-        final AuthenticationRequest req = new AuthenticationRequest();
-        req.setMetaData(metaData);
-
-        final AuthenticationResponse res = new AuthenticationResponse();
-        res.setMetaData(metaData);
-
-        try {
-            req.readExternal(in);
-
-            final String securityRealm = req.getRealm();
-            final String username = req.getUsername();
-            final String password = req.getCredentials();
-            final long timeout = req.getTimeout();
-            final boolean logout = req.isLogout();
-
-            final SecurityService securityService = 
SystemInstance.get().getComponent(SecurityService.class);
-
-            final Object token = securityService.login(securityRealm, 
username, password);
-
-            if(logout){
-                securityService.logout(token);
-            }
-
-            final ClientMetaData client = new ClientMetaData();
-            client.setMetaData(metaData);
-            client.setClientIdentity(token);
-
-            res.setIdentity(client);
-            res.setResponseCode(ResponseCodes.AUTH_GRANTED);
-        } catch (final Throwable t) {
-            res.setResponseCode(ResponseCodes.AUTH_DENIED);
-            res.setDeniedCause(t);
-        } finally {
-            if (debug) {
-                try {
-                    logger.debug("AUTH REQUEST: " + req + " -- RESPONSE: " + 
res);
-                } catch (final Exception e) {
-                    //Ignore
-                }
-            }
-        }
-
-        return res;
-    }
-
-    @Override
-    public void processResponse(final Response response, final 
ObjectOutputStream out, final ProtocolMetaData metaData) throws Exception {
-
-        if (AuthenticationResponse.class.isInstance(response)) {
-
-            final AuthenticationResponse res = (AuthenticationResponse) 
response;
-            res.setMetaData(metaData);
-
-            try {
-                res.writeExternal(out);
-            } catch (final Exception e) {
-                logger.fatal("Could not write AuthenticationResponse to output 
stream", e);
-            }
-        } else {
-            logger.error("AuthRequestHandler cannot process an instance of: " 
+ response.getClass().getName());
-        }
-    }
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.openejb.server.ejbd;
+
+import org.apache.openejb.client.AuthenticationRequest;
+import org.apache.openejb.client.AuthenticationResponse;
+import org.apache.openejb.client.ClientMetaData;
+import org.apache.openejb.client.ProtocolMetaData;
+import org.apache.openejb.client.Response;
+import org.apache.openejb.client.ResponseCodes;
+import org.apache.openejb.loader.SystemInstance;
+import org.apache.openejb.spi.SecurityService;
+import org.apache.openejb.util.LogCategory;
+import org.apache.openejb.util.Logger;
+
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+class AuthRequestHandler extends RequestHandler {
+
+    //Messages _messages = new 
Messages("org.apache.openejb.server.util.resources");
+    private static final Logger logger = 
Logger.getInstance(LogCategory.OPENEJB_SERVER_REMOTE.createChild("auth"), 
"org.apache.openejb.server.util.resources");
+    private static final boolean debug = logger.isDebugEnabled();
+
+    protected AuthRequestHandler(final EjbDaemon daemon) {
+        super(daemon);
+    }
+
+    @Override
+    public String getName() {
+        return "Authentication";
+    }
+
+    @Override
+    public Logger getLogger() {
+        return logger;
+    }
+
+    @Override
+    public Response processRequest(final ObjectInputStream in, final 
ProtocolMetaData metaData) throws Exception {
+
+        final AuthenticationRequest req = new AuthenticationRequest();
+        req.setMetaData(metaData);
+
+        final AuthenticationResponse res = new AuthenticationResponse();
+        res.setMetaData(metaData);
+
+        try {
+            req.readExternal(in);
+
+            final String securityRealm = req.getRealm();
+            final String username = req.getUsername();
+            final String password = req.getCredentials();
+            final long timeout = req.getTimeout();
+            final Object logoutIdentity = req.getLogoutIdentity();
+
+            final SecurityService securityService = 
SystemInstance.get().getComponent(SecurityService.class);
+            final Object token;
+
+            if (null != logoutIdentity) {
+                //noinspection unchecked
+                securityService.logout(logoutIdentity);
+                token = logoutIdentity;
+            } else {
+                token = securityService.login(securityRealm, username, 
password, timeout);
+            }
+
+            final ClientMetaData client = new ClientMetaData();
+            client.setMetaData(metaData);
+            client.setClientIdentity(token);
+
+            res.setIdentity(client);
+            res.setResponseCode(ResponseCodes.AUTH_GRANTED);
+        } catch (final Throwable t) {
+            res.setResponseCode(ResponseCodes.AUTH_DENIED);
+            res.setDeniedCause(t);
+        } finally {
+            if (debug) {
+                try {
+                    logger.debug("AUTH REQUEST: " + req + " -- RESPONSE: " + 
res);
+                } catch (final Exception e) {
+                    //Ignore
+                }
+            }
+        }
+
+        return res;
+    }
+
+    @Override
+    public void processResponse(final Response response, final 
ObjectOutputStream out, final ProtocolMetaData metaData) throws Exception {
+
+        if (AuthenticationResponse.class.isInstance(response)) {
+
+            final AuthenticationResponse res = (AuthenticationResponse) 
response;
+            res.setMetaData(metaData);
+
+            try {
+                res.writeExternal(out);
+            } catch (final Exception e) {
+                logger.fatal("Could not write AuthenticationResponse to output 
stream", e);
+            }
+        } else {
+            logger.error("AuthRequestHandler cannot process an instance of: " 
+ response.getClass().getName());
+        }
+    }
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/tomee/blob/5c4316b5/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java
----------------------------------------------------------------------
diff --git 
a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java
 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java
index b6afe27..8167124 100644
--- 
a/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java
+++ 
b/tomee/tomee-catalina/src/main/java/org/apache/tomee/catalina/TomcatSecurityService.java
@@ -81,6 +81,10 @@ public class TomcatSecurityService extends 
AbstractSecurityService {
     }
 
     public UUID login(final String realmName, final String username, final 
String password) throws LoginException {
+        return this.login(realmName, username, password, 0);
+    }
+
+    public UUID login(final String realmName, final String username, final 
String password, final long accessTimeout) throws LoginException {
         final Realm realm = findRealm(realmName);
         if (realm == null) {
             throw new LoginException("No Tomcat realm available");
@@ -92,7 +96,7 @@ public class TomcatSecurityService extends 
AbstractSecurityService {
         }
 
         final Subject subject = createSubject(realm, principal);
-        return registerSubject(subject);
+        return registerSubject(subject, accessTimeout);
     }
 
     private Realm findRealm(final String realmName) {

Reply via email to