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

org.jboss.naming.remote.client.RemoteContext Maven / Gradle / Ivy

There is a newer version: 2.0.5.Final
Show newest version
/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2012, Red Hat, Inc., and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
 *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */

package org.jboss.naming.remote.client;

import java.util.Collections;
import java.util.Hashtable;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicIntegerFieldUpdater;

import javax.naming.Binding;
import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.LinkRef;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.spi.ObjectFactory;

import org.jboss.logging.Logger;

import static org.jboss.naming.remote.client.ClientUtil.isEmpty;
import static org.jboss.naming.remote.client.ClientUtil.namingEnumeration;
import static org.jboss.naming.remote.client.ClientUtil.namingException;

/**
 *
 * @author John Bailey
 */
public class RemoteContext implements Context, NameParser {
    private static final Logger log = Logger.getLogger(RemoteContext.class);

    // Work around JVM's broken finalizer. All code touching these values has a purpose. Do not remove!
    public static int STATIC_KEEP_ALIVE;
    private static AtomicIntegerFieldUpdater keepAliveUpdater = AtomicIntegerFieldUpdater.newUpdater(RemoteContext.class, "keepAlive");
    private volatile int keepAlive = STATIC_KEEP_ALIVE;

    private final Name prefix;
    private final Hashtable environment;

    // All usage of namingStore must be surrounded with an update to keepAlive, to keep the context alive
    private final RemoteNamingStore namingStore;

    private final List closeTasks;

    private final AtomicBoolean closed = new AtomicBoolean();

    public RemoteContext(final RemoteNamingStore namingStore, final Hashtable environment) {
        this(namingStore, environment, Collections.emptyList());
    }

    public RemoteContext(final RemoteNamingStore namingStore, final Hashtable environment, final List closeTasks) {
        this(new CompositeName(), namingStore, environment, closeTasks);
    }

    public RemoteContext(final Name prefix, final RemoteNamingStore namingStore, final Hashtable environment) {
        this(prefix, namingStore, environment, Collections.emptyList());
    }

    public RemoteContext(final Name prefix, final RemoteNamingStore namingStore, final Hashtable environment, final List closeTasks) {
        this.prefix = prefix;
        this.namingStore = namingStore;
        this.environment = environment;
        this.closeTasks = closeTasks;
    }

    public Object lookup(final Name name) throws NamingException {
        try {
            return lookupInternal(name);
        } finally {
            keepAliveUpdater.lazySet(this, keepAlive + 1);
        }
    }

    private Object lookupInternal(Name name) throws NamingException {
        if (isEmpty(name)) {
            return new RemoteContext(prefix, namingStore, environment);
        }
        final Name absoluteName = getAbsoluteName(name);
        Object result = namingStore.lookup(absoluteName);
        if (result instanceof LinkRef) {
            result = resolveLink((LinkRef)result);
        }
        else if (result instanceof Reference) {
            result = getObjectInstance((Reference)result, name, environment);
            if (result instanceof LinkRef) {
                result = resolveLink((LinkRef)result);
            }
        }
        return result;
    }

    private Object getObjectInstance(final Reference reference, final Name name, final Hashtable environment) throws NamingException {
        try {
            final Class factoryClass = Thread.currentThread().getContextClassLoader().loadClass(reference.getFactoryClassName());
            ObjectFactory factory = ObjectFactory.class.cast(factoryClass.newInstance());
            return factory.getObjectInstance(reference, name, this, environment);
        } catch(NamingException e) {
            throw e;
        } catch(Throwable t) {
            throw namingException("failed to get object instance from reference", t);
        }
    }

    private Object resolveLink(LinkRef result) throws NamingException {
        final Object linkResult;
        try {
            final LinkRef linkRef = (LinkRef) result;
            final String referenceName = linkRef.getLinkName();
            if (referenceName.startsWith("./")) {
                linkResult = lookup(referenceName.substring(2));
            } else {
                linkResult = new InitialContext().lookup(referenceName);
            }
        } catch (Throwable t) {
            throw namingException("failed to deref link",t);
        }
        return linkResult;
    }
  
    public Object lookup(final String name) throws NamingException {
        return lookup(parse(name));
    }

    public void bind(final Name name, final Object object) throws NamingException {
        try {
            namingStore.bind(getAbsoluteName(name), object);
        } finally {
            keepAliveUpdater.lazySet(this, keepAlive + 1);
        }
    }

    public void bind(final String name, final Object object) throws NamingException {
        bind(parse(name), object);
    }

    public void rebind(final Name name, final Object object) throws NamingException {
        try {
            namingStore.rebind(name, object);
        } finally {
            keepAliveUpdater.lazySet(this, keepAlive + 1);
        }
    }

    public void rebind(final String name, final Object object) throws NamingException {
        rebind(parse(name), object);
    }

    public void unbind(final Name name) throws NamingException {
        try {
            namingStore.unbind(name);
        } finally {
            keepAliveUpdater.lazySet(this, keepAlive + 1);
        }
    }

    public void unbind(final String name) throws NamingException {
        unbind(parse(name));
    }

    public void rename(final Name name, final Name newName) throws NamingException {
        try {
            namingStore.rename(name, newName);
        } finally {
            keepAliveUpdater.lazySet(this, keepAlive + 1);
        }
    }

    public void rename(final String name, final String newName) throws NamingException {
        rename(parse(name), parse(newName));
    }

    public NamingEnumeration list(final Name name) throws NamingException {
        try {
            return namingEnumeration(namingStore.list(name));
        } finally {
            keepAliveUpdater.lazySet(this, keepAlive + 1);
        }
    }

    public NamingEnumeration list(final String name) throws NamingException {
        return list(parse(name));
    }

    public NamingEnumeration listBindings(final Name name) throws NamingException {
        try {
            return namingEnumeration(namingStore.listBindings(name));
        } finally {
            keepAliveUpdater.lazySet(this, keepAlive + 1);
        }
    }

    public NamingEnumeration listBindings(final String name) throws NamingException {
        return listBindings(parse(name));
    }

    public void destroySubcontext(final Name name) throws NamingException {
        try {
            namingStore.destroySubcontext(name);
        } finally {
            keepAliveUpdater.lazySet(this, keepAlive + 1);
        }
    }

    public void destroySubcontext(final String name) throws NamingException {
        destroySubcontext(parse(name));
    }

    public Context createSubcontext(final Name name) throws NamingException {
        try {
            return namingStore.createSubcontext(name);
        } finally {
            keepAliveUpdater.lazySet(this, keepAlive + 1);
        }
    }

    public Context createSubcontext(final String name) throws NamingException {
        return createSubcontext(parse(name));
    }

    public Object lookupLink(final Name name) throws NamingException {
        try {
            return namingStore.lookupLink(name);
        } finally {
            keepAliveUpdater.lazySet(this, keepAlive + 1);
        }
    }

    public Object lookupLink(final String name) throws NamingException {
        return lookupLink(parse(name));
    }

    public NameParser getNameParser(Name name) throws NamingException {
        return this;
    }

    public NameParser getNameParser(String s) throws NamingException {
        return this;
    }

    public Name composeName(Name name, Name prefix) throws NamingException {
        final Name result = (Name) prefix.clone();
        result.addAll(name);
        return result;
    }

    public String composeName(String name, String prefix) throws NamingException {
        return composeName(parse(name), parse(prefix)).toString();
    }

    public Object addToEnvironment(String s, Object o) throws NamingException {
        return environment.put(s, o);
    }

    public Object removeFromEnvironment(String s) throws NamingException {
        return environment.remove(s);
    }

    public Hashtable getEnvironment() throws NamingException {
        return environment;
    }

    public void close() throws NamingException {
        if(closed.compareAndSet(false, true)) {
            for (CloseTask closeTask : closeTasks) {
                closeTask.close(false);
            }
        }
    }

    public void finalize() {
        if(closed.compareAndSet(false, true)) {
            STATIC_KEEP_ALIVE = keepAlive;
            for (CloseTask closeTask : closeTasks) {
                closeTask.close(true);
            }
        }
    }

    public String getNameInNamespace() throws NamingException {
        return prefix.toString();
    }

    public Name parse(final String name) throws NamingException {
        return new CompositeName(name);
    }

    private Name getAbsoluteName(final Name name) throws NamingException {
        if (name.isEmpty()) {
            return composeName(name, prefix);
        }
        return composeName(name, prefix);
    }

    public static interface CloseTask {
        void close(boolean isFinalize);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy