|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package com.sun.jndi.toolkit.dir; |
|
|
|
import javax.naming.*; |
|
import javax.naming.directory.*; |
|
import javax.naming.spi.*; |
|
import java.util.*; |
|
|
|
/** |
|
* A sample service provider that implements a hierarchical directory in memory. |
|
* Every operation begins by doing a lookup on the name passed to it and then |
|
* calls a corresponding "do<OperationName>" on the result of the lookup. The |
|
* "do<OperationName>" does the work without any further resolution (it assumes |
|
* that it is the target context). |
|
*/ |
|
|
|
public class HierMemDirCtx implements DirContext { |
|
|
|
static private final boolean debug = false; |
|
private static final NameParser defaultParser = new HierarchicalNameParser(); |
|
|
|
protected Hashtable<String, Object> myEnv; |
|
protected Hashtable<Name, Object> bindings; |
|
protected Attributes attrs; |
|
protected boolean ignoreCase = false; |
|
protected NamingException readOnlyEx = null; |
|
protected NameParser myParser = defaultParser; |
|
|
|
private boolean alwaysUseFactory; |
|
|
|
public void close() throws NamingException { |
|
myEnv = null; |
|
bindings = null; |
|
attrs = null; |
|
} |
|
|
|
public String getNameInNamespace() throws NamingException { |
|
throw new OperationNotSupportedException( |
|
"Cannot determine full name"); |
|
} |
|
|
|
public HierMemDirCtx() { |
|
this(null, false, false); |
|
} |
|
|
|
public HierMemDirCtx(boolean ignoreCase) { |
|
this(null, ignoreCase, false); |
|
} |
|
|
|
public HierMemDirCtx(Hashtable<String, Object> environment, boolean ignoreCase) { |
|
this(environment, ignoreCase, false); |
|
} |
|
|
|
protected HierMemDirCtx(Hashtable<String, Object> environment, |
|
boolean ignoreCase, boolean useFac) { |
|
myEnv = environment; |
|
this.ignoreCase = ignoreCase; |
|
init(); |
|
this.alwaysUseFactory = useFac; |
|
} |
|
|
|
private void init() { |
|
attrs = new BasicAttributes(ignoreCase); |
|
bindings = new Hashtable<>(11, 0.75f); |
|
} |
|
|
|
public Object lookup(String name) throws NamingException { |
|
return lookup(myParser.parse(name)); |
|
} |
|
|
|
public Object lookup(Name name) throws NamingException { |
|
return doLookup(name, alwaysUseFactory); |
|
} |
|
|
|
public Object doLookup(Name name, boolean useFactory) |
|
throws NamingException { |
|
|
|
Object target = null; |
|
name = canonizeName(name); |
|
|
|
switch(name.size()) { |
|
case 0: |
|
|
|
target = this; |
|
break; |
|
|
|
case 1: |
|
|
|
target = bindings.get(name); |
|
break; |
|
|
|
default: |
|
|
|
HierMemDirCtx ctx = (HierMemDirCtx)bindings.get(name.getPrefix(1)); |
|
if(ctx == null) { |
|
target = null; |
|
} else { |
|
target = ctx.doLookup(name.getSuffix(1), false); |
|
} |
|
break; |
|
} |
|
|
|
if(target == null) { |
|
throw new NameNotFoundException(name.toString()); |
|
} |
|
|
|
if (useFactory) { |
|
try { |
|
return DirectoryManager.getObjectInstance(target, |
|
name, this, myEnv, |
|
(target instanceof HierMemDirCtx) ? |
|
((HierMemDirCtx)target).attrs : null); |
|
} catch (NamingException e) { |
|
throw e; |
|
} catch (Exception e) { |
|
NamingException e2 = new NamingException( |
|
"Problem calling getObjectInstance"); |
|
e2.setRootCause(e); |
|
throw e2; |
|
} |
|
} else { |
|
return target; |
|
} |
|
} |
|
|
|
public void bind(String name, Object obj) throws NamingException { |
|
bind(myParser.parse(name), obj); |
|
} |
|
|
|
public void bind(Name name, Object obj) throws NamingException { |
|
doBind(name, obj, null, alwaysUseFactory); |
|
} |
|
|
|
public void bind(String name, Object obj, Attributes attrs) |
|
throws NamingException { |
|
bind(myParser.parse(name), obj, attrs); |
|
} |
|
|
|
public void bind(Name name, Object obj, Attributes attrs) |
|
throws NamingException { |
|
doBind(name, obj, attrs, alwaysUseFactory); |
|
} |
|
|
|
protected void doBind(Name name, Object obj, Attributes attrs, |
|
boolean useFactory) throws NamingException { |
|
if (name.isEmpty()) { |
|
throw new InvalidNameException("Cannot bind empty name"); |
|
} |
|
|
|
if (useFactory) { |
|
DirStateFactory.Result res = DirectoryManager.getStateToBind( |
|
obj, name, this, myEnv, attrs); |
|
obj = res.getObject(); |
|
attrs = res.getAttributes(); |
|
} |
|
|
|
HierMemDirCtx ctx= (HierMemDirCtx) doLookup(getInternalName(name), false); |
|
ctx.doBindAux(getLeafName(name), obj); |
|
|
|
if (attrs != null && attrs.size() > 0) { |
|
modifyAttributes(name, ADD_ATTRIBUTE, attrs); |
|
} |
|
} |
|
|
|
protected void doBindAux(Name name, Object obj) throws NamingException { |
|
if (readOnlyEx != null) { |
|
throw (NamingException) readOnlyEx.fillInStackTrace(); |
|
} |
|
|
|
if (bindings.get(name) != null) { |
|
throw new NameAlreadyBoundException(name.toString()); |
|
} |
|
if(obj instanceof HierMemDirCtx) { |
|
bindings.put(name, obj); |
|
} else { |
|
throw new SchemaViolationException( |
|
"This context only supports binding objects of it's own kind"); |
|
} |
|
} |
|
|
|
public void rebind(String name, Object obj) throws NamingException { |
|
rebind(myParser.parse(name), obj); |
|
} |
|
|
|
public void rebind(Name name, Object obj) throws NamingException { |
|
doRebind(name, obj, null, alwaysUseFactory); |
|
} |
|
|
|
public void rebind(String name, Object obj, Attributes attrs) |
|
throws NamingException { |
|
rebind(myParser.parse(name), obj, attrs); |
|
} |
|
|
|
public void rebind(Name name, Object obj, Attributes attrs) |
|
throws NamingException { |
|
doRebind(name, obj, attrs, alwaysUseFactory); |
|
} |
|
|
|
protected void doRebind(Name name, Object obj, Attributes attrs, |
|
boolean useFactory) throws NamingException { |
|
if (name.isEmpty()) { |
|
throw new InvalidNameException("Cannot rebind empty name"); |
|
} |
|
|
|
if (useFactory) { |
|
DirStateFactory.Result res = DirectoryManager.getStateToBind( |
|
obj, name, this, myEnv, attrs); |
|
obj = res.getObject(); |
|
attrs = res.getAttributes(); |
|
} |
|
|
|
HierMemDirCtx ctx= (HierMemDirCtx) doLookup(getInternalName(name), false); |
|
ctx.doRebindAux(getLeafName(name), obj); |
|
|
|
// |
|
// attrs == null -> use attrs from obj |
|
// attrs != null -> use attrs |
|
// |
|
// %%% Strictly speaking, when attrs is non-null, we should |
|
// take the explicit step of removing obj's attrs. |
|
// We don't do that currently. |
|
|
|
if (attrs != null && attrs.size() > 0) { |
|
modifyAttributes(name, ADD_ATTRIBUTE, attrs); |
|
} |
|
} |
|
|
|
protected void doRebindAux(Name name, Object obj) throws NamingException { |
|
if (readOnlyEx != null) { |
|
throw (NamingException) readOnlyEx.fillInStackTrace(); |
|
} |
|
if(obj instanceof HierMemDirCtx) { |
|
bindings.put(name, obj); |
|
|
|
} else { |
|
throw new SchemaViolationException( |
|
"This context only supports binding objects of it's own kind"); |
|
} |
|
} |
|
|
|
public void unbind(String name) throws NamingException { |
|
unbind(myParser.parse(name)); |
|
} |
|
|
|
public void unbind(Name name) throws NamingException { |
|
if (name.isEmpty()) { |
|
throw new InvalidNameException("Cannot unbind empty name"); |
|
} else { |
|
HierMemDirCtx ctx= |
|
(HierMemDirCtx) doLookup(getInternalName(name), false); |
|
ctx.doUnbind(getLeafName(name)); |
|
} |
|
} |
|
|
|
protected void doUnbind(Name name) throws NamingException { |
|
if (readOnlyEx != null) { |
|
throw (NamingException) readOnlyEx.fillInStackTrace(); |
|
} |
|
|
|
bindings.remove(name); |
|
} |
|
|
|
public void rename(String oldname, String newname) |
|
throws NamingException { |
|
rename(myParser.parse(oldname), myParser.parse(newname)); |
|
} |
|
|
|
public void rename(Name oldname, Name newname) |
|
throws NamingException { |
|
|
|
if(newname.isEmpty() || oldname.isEmpty()) { |
|
throw new InvalidNameException("Cannot rename empty name"); |
|
} |
|
|
|
if (!getInternalName(newname).equals(getInternalName(oldname))) { |
|
throw new InvalidNameException("Cannot rename across contexts"); |
|
} |
|
|
|
HierMemDirCtx ctx = |
|
(HierMemDirCtx) doLookup(getInternalName(newname), false); |
|
ctx.doRename(getLeafName(oldname), getLeafName(newname)); |
|
} |
|
|
|
protected void doRename(Name oldname, Name newname) throws NamingException { |
|
if (readOnlyEx != null) { |
|
throw (NamingException) readOnlyEx.fillInStackTrace(); |
|
} |
|
|
|
oldname = canonizeName(oldname); |
|
newname = canonizeName(newname); |
|
|
|
|
|
if (bindings.get(newname) != null) { |
|
throw new NameAlreadyBoundException(newname.toString()); |
|
} |
|
|
|
|
|
Object oldBinding = bindings.remove(oldname); |
|
if (oldBinding == null) { |
|
throw new NameNotFoundException(oldname.toString()); |
|
} |
|
|
|
bindings.put(newname, oldBinding); |
|
} |
|
|
|
public NamingEnumeration<NameClassPair> list(String name) throws NamingException { |
|
return list(myParser.parse(name)); |
|
} |
|
|
|
public NamingEnumeration<NameClassPair> list(Name name) throws NamingException { |
|
HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false); |
|
return ctx.doList(); |
|
} |
|
|
|
protected NamingEnumeration<NameClassPair> doList () throws NamingException { |
|
return new FlatNames(bindings.keys()); |
|
} |
|
|
|
|
|
public NamingEnumeration<Binding> listBindings(String name) throws NamingException { |
|
return listBindings(myParser.parse(name)); |
|
} |
|
|
|
public NamingEnumeration<Binding> listBindings(Name name) throws NamingException { |
|
HierMemDirCtx ctx = (HierMemDirCtx)doLookup(name, false); |
|
return ctx.doListBindings(alwaysUseFactory); |
|
} |
|
|
|
protected NamingEnumeration<Binding> doListBindings(boolean useFactory) |
|
throws NamingException { |
|
return new FlatBindings(bindings, myEnv, useFactory); |
|
} |
|
|
|
public void destroySubcontext(String name) throws NamingException { |
|
destroySubcontext(myParser.parse(name)); |
|
} |
|
|
|
public void destroySubcontext(Name name) throws NamingException { |
|
HierMemDirCtx ctx = |
|
(HierMemDirCtx) doLookup(getInternalName(name), false); |
|
ctx.doDestroySubcontext(getLeafName(name)); |
|
} |
|
|
|
protected void doDestroySubcontext(Name name) throws NamingException { |
|
|
|
if (readOnlyEx != null) { |
|
throw (NamingException) readOnlyEx.fillInStackTrace(); |
|
} |
|
name = canonizeName(name); |
|
bindings.remove(name); |
|
} |
|
|
|
public Context createSubcontext(String name) throws NamingException { |
|
return createSubcontext(myParser.parse(name)); |
|
} |
|
|
|
public Context createSubcontext(Name name) throws NamingException { |
|
return createSubcontext(name, null); |
|
} |
|
|
|
public DirContext createSubcontext(String name, Attributes attrs) |
|
throws NamingException { |
|
return createSubcontext(myParser.parse(name), attrs); |
|
} |
|
|
|
public DirContext createSubcontext(Name name, Attributes attrs) |
|
throws NamingException { |
|
HierMemDirCtx ctx = |
|
(HierMemDirCtx) doLookup(getInternalName(name), false); |
|
return ctx.doCreateSubcontext(getLeafName(name), attrs); |
|
} |
|
|
|
protected DirContext doCreateSubcontext(Name name, Attributes attrs) |
|
throws NamingException { |
|
if (readOnlyEx != null) { |
|
throw (NamingException) readOnlyEx.fillInStackTrace(); |
|
} |
|
|
|
name = canonizeName(name); |
|
|
|
if (bindings.get(name) != null) { |
|
throw new NameAlreadyBoundException(name.toString()); |
|
} |
|
HierMemDirCtx newCtx = createNewCtx(); |
|
bindings.put(name, newCtx); |
|
if(attrs != null) { |
|
newCtx.modifyAttributes("", ADD_ATTRIBUTE, attrs); |
|
} |
|
return newCtx; |
|
} |
|
|
|
|
|
public Object lookupLink(String name) throws NamingException { |
|
|
|
return lookupLink(myParser.parse(name)); |
|
} |
|
|
|
public Object lookupLink(Name name) throws NamingException { |
|
|
|
return lookup(name); |
|
} |
|
|
|
public NameParser getNameParser(String name) throws NamingException { |
|
return myParser; |
|
} |
|
|
|
public NameParser getNameParser(Name name) throws NamingException { |
|
return myParser; |
|
} |
|
|
|
public String composeName(String name, String prefix) |
|
throws NamingException { |
|
Name result = composeName(new CompositeName(name), |
|
new CompositeName(prefix)); |
|
return result.toString(); |
|
} |
|
|
|
public Name composeName(Name name, Name prefix) |
|
throws NamingException { |
|
name = canonizeName(name); |
|
prefix = canonizeName(prefix); |
|
Name result = (Name)(prefix.clone()); |
|
result.addAll(name); |
|
return result; |
|
} |
|
|
|
@SuppressWarnings("unchecked") |
|
public Object addToEnvironment(String propName, Object propVal) |
|
throws NamingException { |
|
myEnv = (myEnv == null) |
|
? new Hashtable<String, Object>(11, 0.75f) |
|
: (Hashtable<String, Object>)myEnv.clone(); |
|
|
|
return myEnv.put(propName, propVal); |
|
} |
|
|
|
@SuppressWarnings("unchecked") |
|
public Object removeFromEnvironment(String propName) |
|
throws NamingException { |
|
if (myEnv == null) |
|
return null; |
|
|
|
myEnv = (Hashtable<String, Object>)myEnv.clone(); |
|
return myEnv.remove(propName); |
|
} |
|
|
|
@SuppressWarnings("unchecked") |
|
public Hashtable<String, Object> getEnvironment() throws NamingException { |
|
if (myEnv == null) { |
|
return new Hashtable<>(5, 0.75f); |
|
} else { |
|
return (Hashtable<String, Object>)myEnv.clone(); |
|
} |
|
} |
|
|
|
public Attributes getAttributes(String name) |
|
throws NamingException { |
|
return getAttributes(myParser.parse(name)); |
|
} |
|
|
|
public Attributes getAttributes(Name name) |
|
throws NamingException { |
|
HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false); |
|
return ctx.doGetAttributes(); |
|
} |
|
|
|
protected Attributes doGetAttributes() throws NamingException { |
|
return (Attributes)attrs.clone(); |
|
} |
|
|
|
public Attributes getAttributes(String name, String[] attrIds) |
|
throws NamingException { |
|
return getAttributes(myParser.parse(name), attrIds); |
|
} |
|
|
|
public Attributes getAttributes(Name name, String[] attrIds) |
|
throws NamingException { |
|
HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false); |
|
return ctx.doGetAttributes(attrIds); |
|
} |
|
|
|
protected Attributes doGetAttributes(String[] attrIds) |
|
throws NamingException { |
|
|
|
if (attrIds == null) { |
|
return doGetAttributes(); |
|
} |
|
Attributes attrs = new BasicAttributes(ignoreCase); |
|
Attribute attr = null; |
|
for(int i=0; i<attrIds.length; i++) { |
|
attr = this.attrs.get(attrIds[i]); |
|
if (attr != null) { |
|
attrs.put(attr); |
|
} |
|
} |
|
return attrs; |
|
} |
|
|
|
public void modifyAttributes(String name, int mod_op, Attributes attrs) |
|
throws NamingException { |
|
modifyAttributes(myParser.parse(name), mod_op, attrs); |
|
} |
|
|
|
public void modifyAttributes(Name name, int mod_op, Attributes attrs) |
|
throws NamingException { |
|
|
|
if (attrs == null || attrs.size() == 0) { |
|
throw new IllegalArgumentException( |
|
"Cannot modify without an attribute"); |
|
} |
|
|
|
|
|
NamingEnumeration<? extends Attribute> attrEnum = attrs.getAll(); |
|
ModificationItem[] mods = new ModificationItem[attrs.size()]; |
|
for (int i = 0; i < mods.length && attrEnum.hasMoreElements(); i++) { |
|
mods[i] = new ModificationItem(mod_op, attrEnum.next()); |
|
} |
|
|
|
modifyAttributes(name, mods); |
|
} |
|
|
|
public void modifyAttributes(String name, ModificationItem[] mods) |
|
throws NamingException { |
|
modifyAttributes(myParser.parse(name), mods); |
|
} |
|
|
|
public void modifyAttributes(Name name, ModificationItem[] mods) |
|
throws NamingException { |
|
HierMemDirCtx ctx = (HierMemDirCtx) doLookup(name, false); |
|
ctx.doModifyAttributes(mods); |
|
} |
|
|
|
protected void doModifyAttributes(ModificationItem[] mods) |
|
throws NamingException { |
|
|
|
if (readOnlyEx != null) { |
|
throw (NamingException) readOnlyEx.fillInStackTrace(); |
|
} |
|
|
|
applyMods(mods, attrs); |
|
} |
|
|
|
protected static Attributes applyMods(ModificationItem[] mods, |
|
Attributes orig) throws NamingException { |
|
|
|
ModificationItem mod; |
|
Attribute existingAttr, modAttr; |
|
NamingEnumeration<?> modVals; |
|
|
|
for (int i = 0; i < mods.length; i++) { |
|
mod = mods[i]; |
|
modAttr = mod.getAttribute(); |
|
|
|
switch(mod.getModificationOp()) { |
|
case ADD_ATTRIBUTE: |
|
if (debug) { |
|
System.out.println("HierMemDSCtx: adding " + |
|
mod.getAttribute().toString()); |
|
} |
|
existingAttr = orig.get(modAttr.getID()); |
|
if (existingAttr == null) { |
|
orig.put((Attribute)modAttr.clone()); |
|
} else { |
|
|
|
modVals = modAttr.getAll(); |
|
while (modVals.hasMore()) { |
|
existingAttr.add(modVals.next()); |
|
} |
|
} |
|
break; |
|
case REPLACE_ATTRIBUTE: |
|
if (modAttr.size() == 0) { |
|
orig.remove(modAttr.getID()); |
|
} else { |
|
orig.put((Attribute)modAttr.clone()); |
|
} |
|
break; |
|
case REMOVE_ATTRIBUTE: |
|
existingAttr = orig.get(modAttr.getID()); |
|
if (existingAttr != null) { |
|
if (modAttr.size() == 0) { |
|
orig.remove(modAttr.getID()); |
|
} else { |
|
|
|
modVals = modAttr.getAll(); |
|
while (modVals.hasMore()) { |
|
existingAttr.remove(modVals.next()); |
|
} |
|
if (existingAttr.size() == 0) { |
|
orig.remove(modAttr.getID()); |
|
} |
|
} |
|
} |
|
break; |
|
default: |
|
throw new AttributeModificationException("Unknown mod_op"); |
|
} |
|
} |
|
|
|
return orig; |
|
} |
|
|
|
public NamingEnumeration<SearchResult> search(String name, |
|
Attributes matchingAttributes) |
|
throws NamingException { |
|
return search(name, matchingAttributes, null); |
|
} |
|
|
|
public NamingEnumeration<SearchResult> search(Name name, |
|
Attributes matchingAttributes) |
|
throws NamingException { |
|
return search(name, matchingAttributes, null); |
|
} |
|
|
|
public NamingEnumeration<SearchResult> search(String name, |
|
Attributes matchingAttributes, |
|
String[] attributesToReturn) |
|
throws NamingException { |
|
return search(myParser.parse(name), matchingAttributes, |
|
attributesToReturn); |
|
} |
|
|
|
public NamingEnumeration<SearchResult> search(Name name, |
|
Attributes matchingAttributes, |
|
String[] attributesToReturn) |
|
throws NamingException { |
|
|
|
HierMemDirCtx target = (HierMemDirCtx) doLookup(name, false); |
|
|
|
SearchControls cons = new SearchControls(); |
|
cons.setReturningAttributes(attributesToReturn); |
|
|
|
return new LazySearchEnumerationImpl( |
|
target.doListBindings(false), |
|
new ContainmentFilter(matchingAttributes), |
|
cons, this, myEnv, |
|
false); |
|
} |
|
|
|
public NamingEnumeration<SearchResult> search(Name name, |
|
String filter, |
|
SearchControls cons) |
|
throws NamingException { |
|
DirContext target = (DirContext) doLookup(name, false); |
|
|
|
SearchFilter stringfilter = new SearchFilter(filter); |
|
return new LazySearchEnumerationImpl( |
|
new HierContextEnumerator(target, |
|
(cons != null) ? cons.getSearchScope() : |
|
SearchControls.ONELEVEL_SCOPE), |
|
stringfilter, |
|
cons, this, myEnv, alwaysUseFactory); |
|
} |
|
|
|
public NamingEnumeration<SearchResult> search(Name name, |
|
String filterExpr, |
|
Object[] filterArgs, |
|
SearchControls cons) |
|
throws NamingException { |
|
|
|
String strfilter = SearchFilter.format(filterExpr, filterArgs); |
|
return search(name, strfilter, cons); |
|
} |
|
|
|
public NamingEnumeration<SearchResult> search(String name, |
|
String filter, |
|
SearchControls cons) |
|
throws NamingException { |
|
return search(myParser.parse(name), filter, cons); |
|
} |
|
|
|
public NamingEnumeration<SearchResult> search(String name, |
|
String filterExpr, |
|
Object[] filterArgs, |
|
SearchControls cons) |
|
throws NamingException { |
|
return search(myParser.parse(name), filterExpr, filterArgs, cons); |
|
} |
|
|
|
// This function is called whenever a new object needs to be created. |
|
// this is used so that if anyone subclasses us, they can override this |
|
|
|
protected HierMemDirCtx createNewCtx() throws NamingException { |
|
return new HierMemDirCtx(myEnv, ignoreCase); |
|
} |
|
|
|
// If the supplied name is a composite name, return the name that |
|
|
|
protected Name canonizeName(Name name) throws NamingException { |
|
Name canonicalName = name; |
|
|
|
if(!(name instanceof HierarchicalName)) { |
|
|
|
canonicalName = new HierarchicalName(); |
|
int n = name.size(); |
|
for(int i = 0; i < n; i++) { |
|
canonicalName.add(i, name.get(i)); |
|
} |
|
} |
|
|
|
return canonicalName; |
|
} |
|
|
|
protected Name getInternalName(Name name) throws NamingException { |
|
return (name.getPrefix(name.size() - 1)); |
|
} |
|
|
|
protected Name getLeafName(Name name) throws NamingException { |
|
return (name.getSuffix(name.size() - 1)); |
|
} |
|
|
|
|
|
public DirContext getSchema(String name) throws NamingException { |
|
throw new OperationNotSupportedException(); |
|
} |
|
|
|
public DirContext getSchema(Name name) throws NamingException { |
|
throw new OperationNotSupportedException(); |
|
} |
|
|
|
public DirContext getSchemaClassDefinition(String name) |
|
throws NamingException { |
|
throw new OperationNotSupportedException(); |
|
} |
|
|
|
public DirContext getSchemaClassDefinition(Name name) |
|
throws NamingException { |
|
throw new OperationNotSupportedException(); |
|
} |
|
|
|
|
|
public void setReadOnly(NamingException e) { |
|
readOnlyEx = e; |
|
} |
|
|
|
|
|
public void setIgnoreCase(boolean ignoreCase) { |
|
this.ignoreCase = ignoreCase; |
|
} |
|
|
|
public void setNameParser(NameParser parser) { |
|
myParser = parser; |
|
} |
|
|
|
|
|
|
|
*/ |
|
private abstract class BaseFlatNames<T> implements NamingEnumeration<T> { |
|
Enumeration<Name> names; |
|
|
|
BaseFlatNames (Enumeration<Name> names) { |
|
this.names = names; |
|
} |
|
|
|
public final boolean hasMoreElements() { |
|
try { |
|
return hasMore(); |
|
} catch (NamingException e) { |
|
return false; |
|
} |
|
} |
|
|
|
public final boolean hasMore() throws NamingException { |
|
return names.hasMoreElements(); |
|
} |
|
|
|
public final T nextElement() { |
|
try { |
|
return next(); |
|
} catch (NamingException e) { |
|
throw new NoSuchElementException(e.toString()); |
|
} |
|
} |
|
|
|
public abstract T next() throws NamingException; |
|
|
|
public final void close() { |
|
names = null; |
|
} |
|
} |
|
|
|
|
|
private final class FlatNames extends BaseFlatNames<NameClassPair> { |
|
FlatNames (Enumeration<Name> names) { |
|
super(names); |
|
} |
|
|
|
@Override |
|
public NameClassPair next() throws NamingException { |
|
Name name = names.nextElement(); |
|
String className = bindings.get(name).getClass().getName(); |
|
return new NameClassPair(name.toString(), className); |
|
} |
|
} |
|
|
|
|
|
private final class FlatBindings extends BaseFlatNames<Binding> { |
|
private Hashtable<Name, Object> bds; |
|
private Hashtable<String, Object> env; |
|
private boolean useFactory; |
|
|
|
FlatBindings(Hashtable<Name, Object> bindings, |
|
Hashtable<String, Object> env, |
|
boolean useFactory) { |
|
super(bindings.keys()); |
|
this.env = env; |
|
this.bds = bindings; |
|
this.useFactory = useFactory; |
|
} |
|
|
|
@Override |
|
public Binding next() throws NamingException { |
|
Name name = names.nextElement(); |
|
|
|
HierMemDirCtx obj = (HierMemDirCtx)bds.get(name); |
|
|
|
Object answer = obj; |
|
if (useFactory) { |
|
Attributes attrs = obj.getAttributes(""); |
|
try { |
|
answer = DirectoryManager.getObjectInstance(obj, |
|
name, HierMemDirCtx.this, env, attrs); |
|
} catch (NamingException e) { |
|
throw e; |
|
} catch (Exception e) { |
|
NamingException e2 = new NamingException( |
|
"Problem calling getObjectInstance"); |
|
e2.setRootCause(e); |
|
throw e2; |
|
} |
|
} |
|
|
|
return new Binding(name.toString(), answer); |
|
} |
|
} |
|
|
|
public class HierContextEnumerator extends ContextEnumerator { |
|
public HierContextEnumerator(Context context, int scope) |
|
throws NamingException { |
|
super(context, scope); |
|
} |
|
|
|
protected HierContextEnumerator(Context context, int scope, |
|
String contextName, boolean returnSelf) throws NamingException { |
|
super(context, scope, contextName, returnSelf); |
|
} |
|
|
|
protected NamingEnumeration<Binding> getImmediateChildren(Context ctx) |
|
throws NamingException { |
|
return ((HierMemDirCtx)ctx).doListBindings(false); |
|
} |
|
|
|
protected ContextEnumerator newEnumerator(Context ctx, int scope, |
|
String contextName, boolean returnSelf) throws NamingException { |
|
return new HierContextEnumerator(ctx, scope, contextName, |
|
returnSelf); |
|
} |
|
} |
|
} |
|
|
|
// CompundNames's HashCode() method isn't good enough for many string. |
|
// The only prupose of this subclass is to have a more discerning |
|
// hash function. We'll make up for the performance hit by caching |
|
// the hash value. |
|
|
|
final class HierarchicalName extends CompoundName { |
|
private int hashValue = -1; |
|
|
|
|
|
HierarchicalName() { |
|
super(new Enumeration<String>() { |
|
public boolean hasMoreElements() {return false;} |
|
public String nextElement() {throw new NoSuchElementException();} |
|
}, |
|
HierarchicalNameParser.mySyntax); |
|
} |
|
|
|
HierarchicalName(Enumeration<String> comps, Properties syntax) { |
|
super(comps, syntax); |
|
} |
|
|
|
HierarchicalName(String n, Properties syntax) throws InvalidNameException { |
|
super(n, syntax); |
|
} |
|
|
|
|
|
public int hashCode() { |
|
if (hashValue == -1) { |
|
|
|
String name = toString().toUpperCase(Locale.ENGLISH); |
|
int len = name.length(); |
|
int off = 0; |
|
char val[] = new char[len]; |
|
|
|
name.getChars(0, len, val, 0); |
|
|
|
for (int i = len; i > 0; i--) { |
|
hashValue = (hashValue * 37) + val[off++]; |
|
} |
|
} |
|
|
|
return hashValue; |
|
} |
|
|
|
public Name getPrefix(int posn) { |
|
Enumeration<String> comps = super.getPrefix(posn).getAll(); |
|
return (new HierarchicalName(comps, mySyntax)); |
|
} |
|
|
|
public Name getSuffix(int posn) { |
|
Enumeration<String> comps = super.getSuffix(posn).getAll(); |
|
return (new HierarchicalName(comps, mySyntax)); |
|
} |
|
|
|
public Object clone() { |
|
return (new HierarchicalName(getAll(), mySyntax)); |
|
} |
|
|
|
private static final long serialVersionUID = -6717336834584573168L; |
|
} |
|
|
|
|
|
final class HierarchicalNameParser implements NameParser { |
|
static final Properties mySyntax = new Properties(); |
|
static { |
|
mySyntax.put("jndi.syntax.direction", "left_to_right"); |
|
mySyntax.put("jndi.syntax.separator", "/"); |
|
mySyntax.put("jndi.syntax.ignorecase", "true"); |
|
mySyntax.put("jndi.syntax.escape", "\\"); |
|
mySyntax.put("jndi.syntax.beginquote", "\""); |
|
//mySyntax.put("jndi.syntax.separator.ava", "+"); |
|
|
|
mySyntax.put("jndi.syntax.trimblanks", "false"); |
|
}; |
|
|
|
public Name parse(String name) throws NamingException { |
|
return new HierarchicalName(name, mySyntax); |
|
} |
|
} |