/*
* Copyright (C) The Spice Group. All rights reserved.
*
* This software is published under the terms of the Spice
* Software License version 1.1, a copy of which has been included
* with this distribution in the LICENSE.txt file.
*/
package org.realityforge.spice.jndikit;
import java.util.Hashtable;
import javax.naming.Binding;
import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.spi.ResolveResult;
/**
* Abstract JNDI Context that can be inherited from to provide a particular type of Context.
*/
public abstract class AbstractURLContext
extends AbstractContext
implements NameParser
{
private final String m_scheme;
public AbstractURLContext( final String scheme, final Hashtable<String, Object> environment )
{
super( environment );
m_scheme = scheme;
}
/**
* {@inheritDoc}
*/
public Name parse( final String name )
throws NamingException
{
return ( new CompositeName().add( name ) );
}
/**
* {@inheritDoc}
*/
protected NameParser getNameParser()
throws NamingException
{
return this;
}
/**
* {@inheritDoc}
*/
protected void bind( final Name name, final Object object, final boolean rebind )
throws NamingException
{
final ResolveResult resolveResult = getBaseURLContext( name, getRawEnvironment() );
final Context context = (Context) resolveResult.getResolvedObj();
try
{
if ( rebind )
{
context.rebind( resolveResult.getRemainingName(), object );
}
else
{
context.bind( resolveResult.getRemainingName(), object );
}
}
finally
{
context.close();
}
}
/**
* {@inheritDoc}
*/
public Context createSubcontext( final Name name )
throws NamingException
{
final ResolveResult resolveResult = getBaseURLContext( name, getRawEnvironment() );
final Context context = (Context) resolveResult.getResolvedObj();
try
{
return context.createSubcontext( resolveResult.getRemainingName() );
}
finally
{
context.close();
}
}
/**
* {@inheritDoc}
*/
public void destroySubcontext( final Name name )
throws NamingException
{
final ResolveResult resolveResult = getBaseURLContext( name, getRawEnvironment() );
final Context context = (Context) resolveResult.getResolvedObj();
try
{
context.destroySubcontext( resolveResult.getRemainingName() );
}
finally
{
context.close();
}
}
/**
* {@inheritDoc}
*/
public String getNameInNamespace()
throws NamingException
{
return "";
}
/**
* {@inheritDoc}
*/
public NamingEnumeration<NameClassPair> list( final Name name )
throws NamingException
{
final ResolveResult resolveResult = getBaseURLContext( name, getRawEnvironment() );
final Context context = (Context) resolveResult.getResolvedObj();
try
{
return context.list( resolveResult.getRemainingName() );
}
finally
{
context.close();
}
}
/**
* {@inheritDoc}
*/
public NamingEnumeration<Binding> listBindings( final Name name )
throws NamingException
{
final ResolveResult resolveResult = getBaseURLContext( name, getRawEnvironment() );
final Context context = (Context) resolveResult.getResolvedObj();
try
{
return context.listBindings( resolveResult.getRemainingName() );
}
finally
{
context.close();
}
}
/**
* {@inheritDoc}
*/
public Object lookup( final Name name )
throws NamingException
{
final ResolveResult resolveResult = getBaseURLContext( name, getRawEnvironment() );
final Context context = (Context) resolveResult.getResolvedObj();
try
{
return context.lookup( resolveResult.getRemainingName() );
}
finally
{
context.close();
}
}
/**
* {@inheritDoc}
*/
public void unbind( final Name name )
throws NamingException
{
final ResolveResult resolveResult = getBaseURLContext( name, getRawEnvironment() );
final Context context = (Context) resolveResult.getResolvedObj();
try
{
context.unbind( resolveResult.getRemainingName() );
}
finally
{
context.close();
}
}
protected ResolveResult getBaseURLContext( final Name name, final Hashtable environment )
throws NamingException
{
if ( name.isEmpty() )
{
throw new InvalidNameException( "Unable to locate URLContext will empty name" );
}
final String nameString = name.get( 0 ).toString();
int index = nameString.indexOf( ':' );
if ( -1 == index )
{
final String explanation = "Unable to build URLContext as it does not specify scheme";
throw new InvalidNameException( explanation );
}
final String scheme = nameString.substring( 0, index );
final int end = getEndIndexOfURLPart( nameString, index + 1 );
final String urlPart = nameString.substring( index + 1, end );
final String namePart = nameString.substring( end );
if ( !m_scheme.equals( scheme ) )
{
final String explanation = "Bad Scheme use to build URLContext (" + scheme + "). " + "Expected " + m_scheme;
throw new InvalidNameException( explanation );
}
final Context context = newContext( urlPart );
return new ResolveResult( context, new CompositeName( namePart ) );
}
/**
* Find end index of url part in string.
* Default implementation looks for
* //.../[name-part]
* ///[name-part]
* //... (no name part)
* [name-part]
*
* @param name the name
* @param index the index where "scheme:" ends
* @return the index where url ends
* @throws NamingException if an error occurs
*/
protected int getEndIndexOfURLPart( final String name, final int index )
throws NamingException
{
int result = 0;
//does it start with //
if ( name.startsWith( "//", index ) )
{
//does it have .../ following ???
int end = name.indexOf( "/", index + 2 );
if ( -1 != end )
{
result = end;
}
else
{
result = name.length();
}
}
return result;
}
/**
* Return a new instance of the base context for a URL.
* This must be implemented in particular URLContext.
*
* @param urlPart the part of url string not including "scheme:"
* @return a base URLContext for urlPart
* @throws javax.naming.NamingException if an error occurs
*/
protected abstract Context newContext( String urlPart )
throws NamingException;
}