blob: 2587303f505ccb8deae25d58b1d2a9155bec9d9d [file] [log] [blame]
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed 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.naming.core;
import java.util.Enumeration;
import java.util.Hashtable;
import javax.naming.CompositeName;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NameParser;
import javax.naming.NamingException;
import javax.naming.OperationNotSupportedException;
import javax.naming.directory.Attributes;
import javax.naming.directory.DirContext;
import org.apache.tomcat.util.IntrospectionUtils;
// Based on a merge of various catalina naming contexts
// Name is used - it provide better oportunities for reuse and optimizations
/**
* This is the base class for our naming operations, for easy reading.
*
* <p>Creating a new context:
* <ul>
* <li>Create a new class, extending BaseContext or BaseDirContext ( second
* if you want to support attributes ).
* <li>Add setters for configuration. The setters will be called autmatically,
* like in ant, from the initial env settings.
* <li>Override methods that are defined in BaseNaming. Default behavior
* is provided for all.
* <li>If performance is a concern or have special behavior - override Context and
* DirContext methods. That shouldn't be needed in most cases.
* </ul>
*
* This class is designed to minimize the ammount of code that is required to
* create a new context. The usual DirContext interface has way too many methods,
* so implementation requires a lot of typing.
*
* Our contexts are mostly wrappers for files or in memory structures. That means
* some operations are cheaper, and we're far from the features that would be
* exposed for an LDAP or real Directory server.
*
* @author Remy Maucherat
* @author Costin Manolache
*/
public class BaseNaming {
/**
* Builds a base directory context.
*/
public BaseNaming() {
this.env=new Hashtable();
}
/**
* Builds a base directory context using the given environment.
*/
public BaseNaming(Hashtable env) {
this.env=new Hashtable();
if (env != null ) {
Enumeration envEntries = env.keys();
while (envEntries.hasMoreElements()) {
String entryName = (String) envEntries.nextElement();
Object entryValue=env.get(entryName);
this.env.put(entryName, entryValue);
try {
// XXX We need a mechanism to select properties for
// this task. Maybe all contexts should use as property prefix the
// class name ? Or base class name ?
IntrospectionUtils.setAttribute( this, entryName, entryValue );
} catch(Exception ex ) {
System.out.println("Unsuported property " + entryName + " " + ex.getMessage());
}
}
}
}
// ----------------------------------------------------- Instance Variables
/**
* Environment. All context config info.
*/
protected Hashtable env;
/**
* Default name parser for this context.
* XXX This should be combined with the Tomcat mapper, and
* optimized for MessageBytes.
*/
protected final NameParser nameParser = new NameParserImpl();
/** Prefix used for URL-based namming lookup. It must be removed
* from all names.
* Deprecated ? Do we need it ?
*/
protected String urlPrefix="";
// ------------------------------------------------------------- Properties
// Common properties, apply to all jtc naming contexts.
// XXX Introspection should be used to turn the Hashtable attributes
// into setters.
public void setURLPrefix( String s ) {
urlPrefix=s;
}
private boolean cached;
private int cacheTTL;
private int cacheObjectMaxSize;
public boolean isCached() {
return cached;
}
public void setCached(boolean cached) {
this.cached = cached;
}
public int getCacheTTL() {
return cacheTTL;
}
public void setCacheTTL(int cacheTTL) {
this.cacheTTL = cacheTTL;
}
public int getCacheObjectMaxSize() {
return cacheObjectMaxSize;
}
public void setCacheObjectMaxSize(int cacheObjectMaxSize) {
this.cacheObjectMaxSize = cacheObjectMaxSize;
}
// -------------------- Not so Abstract methods --------------------
// This is what a subclass should implement.
// XXX Base resolveLinks() method ?? And then use lookup without resolveLinks flag
/** The lookup method. This is the main method you should implement.
*
* @param name
* @param resolveLinks If false, this is a lookupLink call.
*/
public Object lookup(Name name, boolean resolveLinks)
throws NamingException
{
throw new OperationNotSupportedException();
}
/** The setter method. Implement it if the context is read/write.
*
* @param name
* @param obj The object to be bound.
* @param attrs Attributes - if this is a dir context, null otherwise
* @param rebind What to do if the name is already bound.
* XXX can be further simplified - do a lookup and implement it.
*/
public void bind(Name name, Object obj, Attributes attrs, boolean rebind )
throws NamingException
{
throw new OperationNotSupportedException();
}
/** Remove a binding. XXX do we need the isContext case ?
*/
public void unbind(Name name, boolean isContext)
throws NamingException
{
throw new OperationNotSupportedException();
}
/* XXX There are 2 ways to list the childs: array ( size/elementAt ) or
iterator/Enumeration. Since the JNDI interface uses iteration -
that's what we should use.
*/
/** Return the child elements, if any.
*
* This is a String or Name or Binding or NameClassPari enumeration -
* the Context implementation will wrap it as a NamingEnumeration and
* construct the right information.
*
* XXX name is all we need - all other info can be extracted - with some
* penalty. It's easy to do some instanceof tricks to avoid it, if possible,
* but the goal is to make it easy to write contexts, and name should be
* enough.
*/
public Enumeration getChildren() throws NamingException {
return null;
}
public DirContext createSubcontext(Name name, Attributes attrs)
throws NamingException
{
// XXX We can implement a decent default using bind and the current class.
throw new OperationNotSupportedException();
}
/** Implement for directories
*
*/
public Object getAttribute( Name name, String attName )
throws NamingException
{
throw new OperationNotSupportedException();
}
public void setAttribute( Name name, String attName, Object value )
throws NamingException
{
throw new OperationNotSupportedException();
}
public String[] getAttributeNames(Name name )
throws NamingException
{
throw new OperationNotSupportedException();
}
// -------------------- Utils --------------------
// XXX Implement this
/**
* Returns true if writing is allowed on this context.
*/
protected boolean isWritable(Name name) {
return true;
//return ContextAccessController.isWritable(name);
}
/**
* Throws a naming exception is Context is not writable.
*/
protected void checkWritable(Name n)
throws NamingException
{
if (!isWritable(n))
throw new NamingException("read only");
}
protected Name string2Name(String s ) throws InvalidNameException {
// XXX uniq
// try {
return new CompositeName( s );
// } catch( InvalidNameException ex ) {
// ex.printStackTrace();
// return null;
// }
}
// -------------------- Lifecycle methods ? --------------------
/**
* Allocate resources for this directory context.
*/
public void allocate() {
; // No action taken by the default implementation
}
/**
* Release any resources allocated for this directory context.
*/
public void release() {
; // No action taken by the default implementation
}
public void recycle() {
// nothing yet.
}
//-------------------- Helpers --------------------
/** Just a hack so that all DirContexts can be used as tasks.
* They'll do nothing - the setters will be called ( just like
* new Context(Hashtable) - since we use introspection ) and the
* context can be registred as a reference in the Project ns.
*
* Then other tasks could manipulate it by name.
*
* In a future version of ant we should have the 'references'
* pluggable and a possible impl should be JNDI.
*
* Alternative: there is a way to use tasks without this method,
* but for now it's simpler.
*/
public void execute() {
}
}