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

uk.org.retep.kernel.naming.MemoryContext Maven / Gradle / Ivy

The newest version!
/*
 * 

Copyright (c) 1998-2010, Peter T Mount
* All rights reserved.

* *

* This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. *

* *

* This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. *

* *

* You should have received a copy of the GNU General Public License along * with this program. If not, see . *

* *

* GNU GENERAL PUBLIC LICENSE - CLASSPATH EXCEPTION *

* *

* Linking this library statically or dynamically with other modules * is making a combined work based on this library. Thus, the terms * and conditions of the GNU General Public License cover the whole * combination. *

* *

* As a special exception, the copyright holders of this library give * you permission to link this library with independent modules to * produce an executable, regardless of the license terms of these * independent modules, and to copy and distribute the resulting * executable under terms of your choice, provided that you also meet, * for each linked independent module, the terms and conditions of the * license of that module. *

* *

* An independent module is a module which is either not derived from or based * on this library, or a module who's classes extend those within this library * as part of the implementation of the library. *

* *

* If you modify this library, you may extend this exception to your version * of the library, but you are not obligated to do so. If you do not wish to * do so, delete this exception statement from your version. *

*/ package uk.org.retep.kernel.naming; import java.util.HashMap; import java.util.HashSet; import java.util.Hashtable; import java.util.Iterator; import java.util.Map; import java.util.NoSuchElementException; import javax.naming.Binding; import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.InvalidNameException; import javax.naming.LinkRef; import javax.naming.Name; import javax.naming.NameAlreadyBoundException; import javax.naming.NameClassPair; import javax.naming.NameNotFoundException; import javax.naming.NameParser; import javax.naming.NamingEnumeration; import javax.naming.NamingException; import javax.naming.NotContextException; import javax.naming.Reference; import javax.naming.Referenceable; import javax.naming.spi.NamingManager; import javax.annotation.concurrent.ThreadSafe; import uk.org.retep.annotations.ReadLock; import uk.org.retep.annotations.WriteLock; import uk.org.retep.util.concurrent.ConcurrencySupport; /** * In memory Context implementation for the built in JNDI server * @author peter */ @ThreadSafe public class MemoryContext extends ConcurrencySupport implements Context { private static final NameParser defaultNameParser = new NameParser() { public Name parse( String name ) throws NamingException { // We only deal with the standard composite names. return new CompositeName( name ); } }; private final Map bindings = new HashMap(); private final Hashtable env; public MemoryContext() { this( new Hashtable() ); } public MemoryContext( Hashtable env ) { this.env = env; } /** * If the first part of the name contains empty parts, we discard * them and keep on looking in this context. * * @param name Name to trim * @param fail true to throw InvalidNameException if empty * @return trimmed Name * @throws javax.naming.NamingException */ private static Name trimName( Name name, boolean fail ) throws NamingException { while( !name.isEmpty() && name.get( 0 ).length() == 0 ) { name = name.getSuffix( 1 ); } if( fail && name.isEmpty() ) { throw new InvalidNameException( "Name cannot be empty" ); } return name; } @ReadLock private Object get( final String name ) { return bindings.get( name ); } @WriteLock private Object put( final String name, final Object value, final boolean overwrite ) throws NamingException { if( !overwrite && bindings.containsKey( name ) ) { throw new NameAlreadyBoundException( name + " already bound, use rebind instead" ); } return bindings.put( name, value ); } @WriteLock private Object remove( final String name ) { return bindings.remove( name ); } public Object lookup( Name name ) throws NamingException { return lookupImpl( name, true ); } private Object lookupImpl( Name name, boolean resolveLink ) throws NamingException { name = trimName( name, false ); if( name.isEmpty() ) { return this; } final String simple = name.get( 0 ); Object value = get( simple ); if( name.size() > 1 ) { return parseContext( simple, name, value, resolveLink, true ); } else { return parseValue( simple, name, value, resolveLink ); } } private Object parseContext( String simple, Name name, Object value, boolean resolveLink, boolean lookup ) throws NamingException { // Resolve the Reference, this should give us another Context or Reference while( value instanceof Reference ) { try { value = NamingManager.getObjectInstance( value, name, this, env ); } catch( Exception ex ) { throw new NamingException( ex.getMessage() ); } } if( lookup && name.size() > 1 ) { if( value instanceof MemoryContext ) { return MemoryContext.class.cast( value ).lookupImpl( name.getSuffix( 1 ), resolveLink ); } if( value instanceof Context ) { return Context.class.cast( value ).lookup( name.getSuffix( 1 ) ); } throw new NotContextException( simple + " is not a subcontext" ); } else { return value; } } private Object parseValue( String simple, Name name, Object value, boolean resolveLink ) throws NamingException { if( value == null ) { throw new NameNotFoundException( simple + " not found" ); } else if( value instanceof LinkRef && resolveLink ) { String link = LinkRef.class.cast( value ).getLinkName(); if( link.startsWith( "." ) ) { return lookup( link.substring( 1 ) ); } return NamingManager.getInitialContext( env ).lookup( link ); } else if( value instanceof Reference ) { // Reconstruct a reference. try { return NamingManager.getObjectInstance( value, name, this, env ); } catch( Exception ex ) { throw new NamingException( ex.getMessage() ); } } else { // Simplest case, just return the bound object. return value; } } public Object lookup( String name ) throws NamingException { return lookup( new CompositeName( name ) ); } public void bind( Name name, Object value ) throws NamingException { bindImpl( name, value, false ); } private void bindImpl( Name name, Object value, final boolean overwrite ) throws NamingException { name = trimName( name, true ); final String simple = name.get( 0 ); if( name.size() > 1 ) { Object next = parseContext( simple, name, get( simple ), true, false ); if( next instanceof Context ) { Context.class.cast( next ).bind( name.get( name.size() - 1 ), value ); } else { throw new NotContextException( simple + " is not a subcontext" ); } } else { if( value instanceof Referenceable ) { put( simple, Referenceable.class.cast( value ).getReference(), overwrite ); } else { put( simple, value, overwrite ); } } } public void bind( String name, Object value ) throws NamingException { bind( new CompositeName( name ), value ); } public void rebind( Name name, Object value ) throws NamingException { bindImpl( name, value, true ); } public void rebind( String name, Object value ) throws NamingException { rebind( new CompositeName( name ), value ); } public void unbind( Name name ) throws NamingException { name = trimName( name, true ); final String simple = name.get( 0 ); if( name.size() > 1 ) { Object next = parseContext( simple, name, get( simple ), true, false ); if( next instanceof Context ) { Context.class.cast( next ).unbind( name.get( name.size() - 1 ) ); } else { throw new NotContextException( simple + " is not a subcontext" ); } } else { remove( simple ); } } public void unbind( String arg0 ) throws NamingException { unbind( new CompositeName( arg0 ) ); } public void rename( Name oldName, Name newName ) throws NamingException { oldName = trimName( oldName, true ); newName = trimName( newName, true ); bind( newName, lookup( oldName ) ); unbind( oldName ); } public void rename( String arg0, String arg1 ) throws NamingException { rename( new CompositeName( arg0 ), new CompositeName( arg1 ) ); } public NamingEnumeration list( Name name ) throws NamingException { name = trimName( name, true ); final String simple = name.get( 0 ); if( name.size() > 1 ) { Object next = parseContext( simple, name, get( simple ), true, false ); if( next instanceof Context ) { Context.class.cast( next ).list( name.getSuffix( 1 ) ); } else { throw new NotContextException( simple + " is not a subcontext" ); } } return new AbstractEnumeration() { protected NameClassPair create( final String name, final Object value ) { return new NameClassPair( name, value.getClass().getName(), true ); } }; } public NamingEnumeration list( String arg0 ) throws NamingException { return list( new CompositeName( arg0 ) ); } public NamingEnumeration listBindings( Name name ) throws NamingException { name = trimName( name, true ); final String simple = name.get( 0 ); if( name.size() > 1 ) { Object next = parseContext( simple, name, get( simple ), true, false ); if( next instanceof Context ) { Context.class.cast( next ).list( name.getSuffix( 1 ) ); } else { throw new NotContextException( simple + " is not a subcontext" ); } } return new AbstractEnumeration() { protected Binding create( final String name, final Object value ) { return new Binding( name, value ); } }; } public NamingEnumeration listBindings( String arg0 ) throws NamingException { return listBindings( new CompositeName( arg0 ) ); } public void destroySubcontext( Name name ) throws NamingException { name = trimName( name, true ); final String simple = name.get( 0 ); if( name.size() > 1 ) { Object next = parseContext( simple, name, get( simple ), true, false ); if( next instanceof Context ) { Context.class.cast( next ).destroySubcontext( name.getSuffix( 1 ) ); } else { throw new NotContextException( simple + " is not a subcontext" ); } } else { writeLock().lock(); try { Object value = bindings.get( simple ); if( value instanceof Context ) { bindings.remove( simple ); } else { throw new NotContextException( simple + " is not a subcontext" ); } } finally { writeLock().unlock(); } } } public void destroySubcontext( String arg0 ) throws NamingException { destroySubcontext( new CompositeName( arg0 ) ); } public Context createSubcontext( Name name ) throws NamingException { Context ctx = new MemoryContext(); bind( name, ctx ); return ctx; } public Context createSubcontext( String arg0 ) throws NamingException { return createSubcontext( new CompositeName( arg0 ) ); } public Object lookupLink( Name name ) throws NamingException { return lookupImpl( name, false ); } public Object lookupLink( String arg0 ) throws NamingException { return lookupLink( new CompositeName( arg0 ) ); } public NameParser getNameParser( Name name ) throws NamingException { name = trimName( name, false ); if( name.size() > 1 ) { final String simple = name.get( 0 ); Object value = parseContext( simple, name, get( simple ), true, false ); if( value instanceof Context ) { return Context.class.cast( value ).getNameParser( name.getSuffix( 1 ) ); } else { throw new NotContextException( simple + " is not a subcontext" ); } } return defaultNameParser; } public NameParser getNameParser( String arg0 ) throws NamingException { return getNameParser( new CompositeName( arg0 ) ); } public Name composeName( Name name, Name prefix ) throws NamingException { return Name.class.cast( prefix.clone() ).addAll( name ); } public String composeName( String arg0, String arg1 ) throws NamingException { return composeName( new CompositeName( arg0 ), new CompositeName( arg1 ) ).toString(); } public Object addToEnvironment( String name, Object value ) throws NamingException { return env.put( name, value ); } public Object removeFromEnvironment( String arg0 ) throws NamingException { return env.remove( arg0 ); } public Hashtable getEnvironment() throws NamingException { return env; } public void close() throws NamingException { // ignore - do nothing } public String getNameInNamespace() throws NamingException { throw new UnsupportedOperationException( "Not supported yet." ); } private abstract class AbstractEnumeration implements NamingEnumeration { protected boolean hasNext; protected T next; private Iterator names; public AbstractEnumeration() { this.names = new HashSet( bindings.keySet() ).iterator(); fetch(); } protected abstract T create( final String name, final Object value ); protected void fetch() { while( hasNextName() ) { final String name = nextName(); final Object value = get( name ); if( value != null ) { next = create( name, value ); hasNext = true; } } next = null; hasNext = false; } protected final boolean hasNextName() { return names.hasNext(); } protected final String nextName() { return names.next(); } public void close() throws NamingException { names = null; } public T next() throws NoSuchElementException { if( next == null ) { throw new NoSuchElementException( "No more elements in enumeration" ); } try { return next; } finally { fetch(); } } public boolean hasMore() throws NamingException { return hasNext; } public boolean hasMoreElements() { return hasNext; } public T nextElement() { return next(); } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy