feat(jdk8): move files to new folder to avoid resources compiled.
This commit is contained in:
41
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/AttrFilter.java
Normal file
41
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/AttrFilter.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 1999, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package com.sun.jndi.toolkit.dir;
|
||||
|
||||
import javax.naming.NamingException;
|
||||
import javax.naming.directory.Attributes;
|
||||
|
||||
/**
|
||||
* Is implemented by classes that can perform filter checks on
|
||||
* an attribute set.
|
||||
*/
|
||||
|
||||
public interface AttrFilter {
|
||||
|
||||
/**
|
||||
* Determines whether an attribute passes the filter.
|
||||
*/
|
||||
public boolean check(Attributes targetAttrs) throws NamingException;
|
||||
}
|
||||
83
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/ContainmentFilter.java
Normal file
83
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/ContainmentFilter.java
Normal file
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supports checking an attribute set satisfies a filter
|
||||
* that is specified as a set of "matching" attributes.
|
||||
* Checking is done by determining whether the given attribute set
|
||||
* is a superset of the matching ones.
|
||||
*
|
||||
* @author Rosanna Lee
|
||||
*/
|
||||
|
||||
package com.sun.jndi.toolkit.dir;
|
||||
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.*;
|
||||
|
||||
public class ContainmentFilter implements AttrFilter {
|
||||
private Attributes matchingAttrs;
|
||||
|
||||
public ContainmentFilter(Attributes match) {
|
||||
matchingAttrs = match;
|
||||
}
|
||||
|
||||
public boolean check(Attributes attrs) throws NamingException {
|
||||
return matchingAttrs == null ||
|
||||
matchingAttrs.size() == 0 ||
|
||||
contains(attrs, matchingAttrs);
|
||||
}
|
||||
|
||||
// returns true if superset contains subset
|
||||
public static boolean contains(Attributes superset, Attributes subset)
|
||||
throws NamingException {
|
||||
if (subset == null)
|
||||
return true; // an empty set is always a subset
|
||||
|
||||
NamingEnumeration<? extends Attribute> m = subset.getAll();
|
||||
while (m.hasMore()) {
|
||||
if (superset == null) {
|
||||
return false; // contains nothing
|
||||
}
|
||||
Attribute target = m.next();
|
||||
Attribute fromSuper = superset.get(target.getID());
|
||||
if (fromSuper == null) {
|
||||
return false;
|
||||
} else {
|
||||
// check whether attribute values match
|
||||
if (target.size() > 0) {
|
||||
NamingEnumeration<?> vals = target.getAll();
|
||||
while (vals.hasMore()) {
|
||||
if (!fromSuper.contains(vals.next())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
235
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/ContextEnumerator.java
Normal file
235
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/ContextEnumerator.java
Normal file
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package com.sun.jndi.toolkit.dir;
|
||||
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.SearchControls;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A class for recursively enumerating the contents of a Context;
|
||||
*
|
||||
* @author Jon Ruiz
|
||||
*/
|
||||
public class ContextEnumerator implements NamingEnumeration<Binding> {
|
||||
|
||||
private static boolean debug = false;
|
||||
private NamingEnumeration<Binding> children = null;
|
||||
private Binding currentChild = null;
|
||||
private boolean currentReturned = false;
|
||||
private Context root;
|
||||
private ContextEnumerator currentChildEnum = null;
|
||||
private boolean currentChildExpanded = false;
|
||||
private boolean rootProcessed = false;
|
||||
private int scope = SearchControls.SUBTREE_SCOPE;
|
||||
private String contextName = "";
|
||||
|
||||
public ContextEnumerator(Context context) throws NamingException {
|
||||
this(context, SearchControls.SUBTREE_SCOPE);
|
||||
}
|
||||
|
||||
public ContextEnumerator(Context context, int scope)
|
||||
throws NamingException {
|
||||
// return this object except when searching single-level
|
||||
this(context, scope, "", scope != SearchControls.ONELEVEL_SCOPE);
|
||||
}
|
||||
|
||||
protected ContextEnumerator(Context context, int scope, String contextName,
|
||||
boolean returnSelf)
|
||||
throws NamingException {
|
||||
if(context == null) {
|
||||
throw new IllegalArgumentException("null context passed");
|
||||
}
|
||||
|
||||
root = context;
|
||||
|
||||
// No need to list children if we're only searching object
|
||||
if (scope != SearchControls.OBJECT_SCOPE) {
|
||||
children = getImmediateChildren(context);
|
||||
}
|
||||
this.scope = scope;
|
||||
this.contextName = contextName;
|
||||
// pretend root is processed, if we're not supposed to return ourself
|
||||
rootProcessed = !returnSelf;
|
||||
prepNextChild();
|
||||
}
|
||||
|
||||
// Subclass should override if it wants to avoid calling obj factory
|
||||
protected NamingEnumeration<Binding> getImmediateChildren(Context ctx)
|
||||
throws NamingException {
|
||||
return ctx.listBindings("");
|
||||
}
|
||||
|
||||
// Subclass should override so that instance is of same type as subclass
|
||||
protected ContextEnumerator newEnumerator(Context ctx, int scope,
|
||||
String contextName, boolean returnSelf) throws NamingException {
|
||||
return new ContextEnumerator(ctx, scope, contextName, returnSelf);
|
||||
}
|
||||
|
||||
public boolean hasMore() throws NamingException {
|
||||
return !rootProcessed ||
|
||||
(scope != SearchControls.OBJECT_SCOPE && hasMoreDescendants());
|
||||
}
|
||||
|
||||
public boolean hasMoreElements() {
|
||||
try {
|
||||
return hasMore();
|
||||
} catch (NamingException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public Binding nextElement() {
|
||||
try {
|
||||
return next();
|
||||
} catch (NamingException e) {
|
||||
throw new NoSuchElementException(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public Binding next() throws NamingException {
|
||||
if (!rootProcessed) {
|
||||
rootProcessed = true;
|
||||
return new Binding("", root.getClass().getName(),
|
||||
root, true);
|
||||
}
|
||||
|
||||
if (scope != SearchControls.OBJECT_SCOPE && hasMoreDescendants()) {
|
||||
return getNextDescendant();
|
||||
}
|
||||
|
||||
throw new NoSuchElementException();
|
||||
}
|
||||
|
||||
public void close() throws NamingException {
|
||||
root = null;
|
||||
}
|
||||
|
||||
private boolean hasMoreChildren() throws NamingException {
|
||||
return children != null && children.hasMore();
|
||||
}
|
||||
|
||||
private Binding getNextChild() throws NamingException {
|
||||
Binding oldBinding = children.next();
|
||||
Binding newBinding = null;
|
||||
|
||||
// if the name is relative, we need to add it to the name of this
|
||||
// context to keep it relative w.r.t. the root context we are
|
||||
// enumerating
|
||||
if(oldBinding.isRelative() && !contextName.equals("")) {
|
||||
NameParser parser = root.getNameParser("");
|
||||
Name newName = parser.parse(contextName);
|
||||
newName.add(oldBinding.getName());
|
||||
if(debug) {
|
||||
System.out.println("ContextEnumerator: adding " + newName);
|
||||
}
|
||||
newBinding = new Binding(newName.toString(),
|
||||
oldBinding.getClassName(),
|
||||
oldBinding.getObject(),
|
||||
oldBinding.isRelative());
|
||||
} else {
|
||||
if(debug) {
|
||||
System.out.println("ContextEnumerator: using old binding");
|
||||
}
|
||||
newBinding = oldBinding;
|
||||
}
|
||||
|
||||
return newBinding;
|
||||
}
|
||||
|
||||
private boolean hasMoreDescendants() throws NamingException {
|
||||
// if the current child is expanded, see if it has more elements
|
||||
if (!currentReturned) {
|
||||
if(debug) {System.out.println("hasMoreDescendants returning " +
|
||||
(currentChild != null) ); }
|
||||
return currentChild != null;
|
||||
} else if (currentChildExpanded && currentChildEnum.hasMore()) {
|
||||
|
||||
if(debug) {System.out.println("hasMoreDescendants returning " +
|
||||
"true");}
|
||||
|
||||
return true;
|
||||
} else {
|
||||
if(debug) {System.out.println("hasMoreDescendants returning " +
|
||||
"hasMoreChildren");}
|
||||
return hasMoreChildren();
|
||||
}
|
||||
}
|
||||
|
||||
private Binding getNextDescendant() throws NamingException {
|
||||
|
||||
if (!currentReturned) {
|
||||
// returning parent
|
||||
if(debug) {System.out.println("getNextDescedant: simple case");}
|
||||
|
||||
currentReturned = true;
|
||||
return currentChild;
|
||||
|
||||
} else if (currentChildExpanded && currentChildEnum.hasMore()) {
|
||||
|
||||
if(debug) {System.out.println("getNextDescedant: expanded case");}
|
||||
|
||||
// if the current child is expanded, use it's enumerator
|
||||
return currentChildEnum.next();
|
||||
|
||||
} else {
|
||||
|
||||
// Ready to go onto next child
|
||||
if(debug) {System.out.println("getNextDescedant: next case");}
|
||||
|
||||
prepNextChild();
|
||||
return getNextDescendant();
|
||||
}
|
||||
}
|
||||
|
||||
private void prepNextChild() throws NamingException {
|
||||
if(hasMoreChildren()) {
|
||||
try {
|
||||
currentChild = getNextChild();
|
||||
currentReturned = false;
|
||||
} catch (NamingException e){
|
||||
if (debug) System.out.println(e);
|
||||
if (debug) e.printStackTrace();
|
||||
}
|
||||
} else {
|
||||
currentChild = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if(scope == SearchControls.SUBTREE_SCOPE &&
|
||||
currentChild.getObject() instanceof Context) {
|
||||
currentChildEnum = newEnumerator(
|
||||
(Context)(currentChild.getObject()),
|
||||
scope, currentChild.getName(),
|
||||
false);
|
||||
currentChildExpanded = true;
|
||||
if(debug) {System.out.println("prepNextChild: expanded");}
|
||||
} else {
|
||||
currentChildExpanded = false;
|
||||
currentChildEnum = null;
|
||||
if(debug) {System.out.println("prepNextChild: normal");}
|
||||
}
|
||||
}
|
||||
}
|
||||
70
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/DirSearch.java
Normal file
70
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/DirSearch.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package com.sun.jndi.toolkit.dir;
|
||||
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.*;
|
||||
|
||||
/**
|
||||
* A class for searching DirContexts
|
||||
*
|
||||
* @author Jon Ruiz
|
||||
*/
|
||||
public class DirSearch {
|
||||
public static NamingEnumeration<SearchResult> search(DirContext ctx,
|
||||
Attributes matchingAttributes,
|
||||
String[] attributesToReturn) throws NamingException {
|
||||
SearchControls cons = new SearchControls(
|
||||
SearchControls.ONELEVEL_SCOPE,
|
||||
0, 0, attributesToReturn,
|
||||
false, false);
|
||||
|
||||
return new LazySearchEnumerationImpl(
|
||||
new ContextEnumerator(ctx, SearchControls.ONELEVEL_SCOPE),
|
||||
new ContainmentFilter(matchingAttributes),
|
||||
cons);
|
||||
}
|
||||
|
||||
public static NamingEnumeration<SearchResult> search(DirContext ctx,
|
||||
String filter, SearchControls cons) throws NamingException {
|
||||
|
||||
if (cons == null)
|
||||
cons = new SearchControls();
|
||||
|
||||
return new LazySearchEnumerationImpl(
|
||||
new ContextEnumerator(ctx, cons.getSearchScope()),
|
||||
new SearchFilter(filter),
|
||||
cons);
|
||||
}
|
||||
|
||||
public static NamingEnumeration<SearchResult> search(DirContext ctx,
|
||||
String filterExpr, Object[] filterArgs, SearchControls cons)
|
||||
throws NamingException {
|
||||
|
||||
String strfilter = SearchFilter.format(filterExpr, filterArgs);
|
||||
return search(ctx, strfilter, cons);
|
||||
}
|
||||
}
|
||||
962
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/HierMemDirCtx.java
Normal file
962
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/HierMemDirCtx.java
Normal file
@@ -0,0 +1,962 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
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:
|
||||
// name is empty, caller wants this object
|
||||
target = this;
|
||||
break;
|
||||
|
||||
case 1:
|
||||
// name is atomic, caller wants one of this object's bindings
|
||||
target = bindings.get(name);
|
||||
break;
|
||||
|
||||
default:
|
||||
// name is compound, delegate to child context
|
||||
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); // attrs will also be removed along with ctx
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
// Check if new name exists
|
||||
if (bindings.get(newname) != null) {
|
||||
throw new NameAlreadyBoundException(newname.toString());
|
||||
}
|
||||
|
||||
// Check if old name is bound
|
||||
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 {
|
||||
// This context does not treat links specially
|
||||
return lookupLink(myParser.parse(name));
|
||||
}
|
||||
|
||||
public Object lookupLink(Name name) throws NamingException {
|
||||
// Flat namespace; no federation; just call string version
|
||||
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") // clone()
|
||||
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") // clone()
|
||||
public Object removeFromEnvironment(String propName)
|
||||
throws NamingException {
|
||||
if (myEnv == null)
|
||||
return null;
|
||||
|
||||
myEnv = (Hashtable<String, Object>)myEnv.clone();
|
||||
return myEnv.remove(propName);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // clone()
|
||||
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");
|
||||
}
|
||||
|
||||
// turn it into a modification Enumeration and pass it on
|
||||
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 {
|
||||
// Add new attribute values to existing attribute
|
||||
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 {
|
||||
// Remove attribute values from existing attribute
|
||||
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); // alwaysUseFactory ignored because objReturnFlag == 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
|
||||
// and return object of their own kind.
|
||||
protected HierMemDirCtx createNewCtx() throws NamingException {
|
||||
return new HierMemDirCtx(myEnv, ignoreCase);
|
||||
}
|
||||
|
||||
// If the supplied name is a composite name, return the name that
|
||||
// is its first component.
|
||||
protected Name canonizeName(Name name) throws NamingException {
|
||||
Name canonicalName = name;
|
||||
|
||||
if(!(name instanceof HierarchicalName)) {
|
||||
// If name is not of the correct type, make copy
|
||||
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();
|
||||
}
|
||||
|
||||
// Set context in readonly mode; throw e when update operation attempted.
|
||||
public void setReadOnly(NamingException e) {
|
||||
readOnlyEx = e;
|
||||
}
|
||||
|
||||
// Set context to support case-insensitive names
|
||||
public void setIgnoreCase(boolean ignoreCase) {
|
||||
this.ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
public void setNameParser(NameParser parser) {
|
||||
myParser = parser;
|
||||
}
|
||||
|
||||
/*
|
||||
* Common base class for FlatNames and FlatBindings.
|
||||
*/
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// Class for enumerating name/class pairs
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
// Class for enumerating bindings
|
||||
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(""); // only method available
|
||||
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;
|
||||
|
||||
// Creates an empty name
|
||||
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);
|
||||
}
|
||||
|
||||
// just like String.hashCode, only it pays no attention to length
|
||||
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;
|
||||
}
|
||||
|
||||
// This is the default name parser (used if setNameParser is not called)
|
||||
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.separator.typeval", "=");
|
||||
mySyntax.put("jndi.syntax.trimblanks", "false");
|
||||
};
|
||||
|
||||
public Name parse(String name) throws NamingException {
|
||||
return new HierarchicalName(name, mySyntax);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Given an enumeration of candidates, check whether each
|
||||
* item in enumeration satifies the given filter.
|
||||
* Each item is a Binding and the following is used to get its
|
||||
* attributes for used by the filter:
|
||||
*
|
||||
* ((DirContext)item.getObject()).getAttributes("").
|
||||
* If item.getObject() is not an DirContext, the item is skipped
|
||||
*
|
||||
* The items in the enumeration are obtained one at a time as
|
||||
* items from the search enumeration are requested.
|
||||
*
|
||||
* @author Rosanna Lee
|
||||
*/
|
||||
|
||||
package com.sun.jndi.toolkit.dir;
|
||||
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.*;
|
||||
import javax.naming.spi.DirectoryManager;
|
||||
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Hashtable;
|
||||
|
||||
final public class LazySearchEnumerationImpl
|
||||
implements NamingEnumeration<SearchResult> {
|
||||
private NamingEnumeration<Binding> candidates;
|
||||
private SearchResult nextMatch = null;
|
||||
private SearchControls cons;
|
||||
private AttrFilter filter;
|
||||
private Context context;
|
||||
private Hashtable<String, Object> env;
|
||||
private boolean useFactory = true;
|
||||
|
||||
public LazySearchEnumerationImpl(NamingEnumeration<Binding> candidates,
|
||||
AttrFilter filter, SearchControls cons) throws NamingException {
|
||||
this.candidates = candidates;
|
||||
this.filter = filter;
|
||||
|
||||
if(cons == null) {
|
||||
this.cons = new SearchControls();
|
||||
} else {
|
||||
this.cons = cons;
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // For Hashtable clone: env.clone()
|
||||
public LazySearchEnumerationImpl(NamingEnumeration<Binding> candidates,
|
||||
AttrFilter filter, SearchControls cons,
|
||||
Context ctx, Hashtable<String, Object> env, boolean useFactory)
|
||||
throws NamingException {
|
||||
|
||||
this.candidates = candidates;
|
||||
this.filter = filter;
|
||||
this.env = (Hashtable<String, Object>)
|
||||
((env == null) ? null : env.clone());
|
||||
this.context = ctx;
|
||||
this.useFactory = useFactory;
|
||||
|
||||
if(cons == null) {
|
||||
this.cons = new SearchControls();
|
||||
} else {
|
||||
this.cons = cons;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public LazySearchEnumerationImpl(NamingEnumeration<Binding> candidates,
|
||||
AttrFilter filter, SearchControls cons,
|
||||
Context ctx, Hashtable<String, Object> env) throws NamingException {
|
||||
this(candidates, filter, cons, ctx, env, true);
|
||||
}
|
||||
|
||||
public boolean hasMore() throws NamingException {
|
||||
// find and do not remove from list
|
||||
return findNextMatch(false) != null;
|
||||
}
|
||||
|
||||
public boolean hasMoreElements() {
|
||||
try {
|
||||
return hasMore();
|
||||
} catch (NamingException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public SearchResult nextElement() {
|
||||
try {
|
||||
return findNextMatch(true);
|
||||
} catch (NamingException e) {
|
||||
throw new NoSuchElementException(e.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public SearchResult next() throws NamingException {
|
||||
// find and remove from list
|
||||
return (findNextMatch(true));
|
||||
}
|
||||
|
||||
public void close() throws NamingException {
|
||||
if (candidates != null) {
|
||||
candidates.close();
|
||||
}
|
||||
}
|
||||
|
||||
private SearchResult findNextMatch(boolean remove) throws NamingException {
|
||||
SearchResult answer;
|
||||
if (nextMatch != null) {
|
||||
answer = nextMatch;
|
||||
if (remove) {
|
||||
nextMatch = null;
|
||||
}
|
||||
return answer;
|
||||
} else {
|
||||
// need to find next match
|
||||
Binding next;
|
||||
Object obj;
|
||||
Attributes targetAttrs;
|
||||
while (candidates.hasMore()) {
|
||||
next = candidates.next();
|
||||
obj = next.getObject();
|
||||
if (obj instanceof DirContext) {
|
||||
targetAttrs = ((DirContext)(obj)).getAttributes("");
|
||||
if (filter.check(targetAttrs)) {
|
||||
if (!cons.getReturningObjFlag()) {
|
||||
obj = null;
|
||||
} else if (useFactory) {
|
||||
try {
|
||||
// Give name only if context non-null,
|
||||
// otherewise, name will be interpreted relative
|
||||
// to initial context (not what we want)
|
||||
Name nm = (context != null ?
|
||||
new CompositeName(next.getName()) : null);
|
||||
obj = DirectoryManager.getObjectInstance(obj,
|
||||
nm, context, env, targetAttrs);
|
||||
} catch (NamingException e) {
|
||||
throw e;
|
||||
} catch (Exception e) {
|
||||
NamingException e2 = new NamingException(
|
||||
"problem generating object using object factory");
|
||||
e2.setRootCause(e);
|
||||
throw e2;
|
||||
}
|
||||
}
|
||||
answer = new SearchResult(next.getName(),
|
||||
next.getClassName(), obj,
|
||||
SearchFilter.selectAttributes(targetAttrs,
|
||||
cons.getReturningAttributes()),
|
||||
true);
|
||||
if (!remove)
|
||||
nextMatch = answer;
|
||||
return answer;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
677
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/SearchFilter.java
Normal file
677
jdkSrc/jdk8/com/sun/jndi/toolkit/dir/SearchFilter.java
Normal file
@@ -0,0 +1,677 @@
|
||||
/*
|
||||
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code 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
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
package com.sun.jndi.toolkit.dir;
|
||||
|
||||
import javax.naming.*;
|
||||
import javax.naming.directory.*;
|
||||
import java.util.Enumeration;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.Vector;
|
||||
import java.util.Locale;
|
||||
|
||||
/**
|
||||
* A class for parsing LDAP search filters (defined in RFC 1960, 2254)
|
||||
*
|
||||
* @author Jon Ruiz
|
||||
* @author Rosanna Lee
|
||||
*/
|
||||
public class SearchFilter implements AttrFilter {
|
||||
|
||||
interface StringFilter extends AttrFilter {
|
||||
public void parse() throws InvalidSearchFilterException;
|
||||
}
|
||||
|
||||
// %%% "filter" and "pos" are not declared "private" due to bug 4064984.
|
||||
String filter;
|
||||
int pos;
|
||||
private StringFilter rootFilter;
|
||||
|
||||
protected static final boolean debug = false;
|
||||
|
||||
protected static final char BEGIN_FILTER_TOKEN = '(';
|
||||
protected static final char END_FILTER_TOKEN = ')';
|
||||
protected static final char AND_TOKEN = '&';
|
||||
protected static final char OR_TOKEN = '|';
|
||||
protected static final char NOT_TOKEN = '!';
|
||||
protected static final char EQUAL_TOKEN = '=';
|
||||
protected static final char APPROX_TOKEN = '~';
|
||||
protected static final char LESS_TOKEN = '<';
|
||||
protected static final char GREATER_TOKEN = '>';
|
||||
protected static final char EXTEND_TOKEN = ':';
|
||||
protected static final char WILDCARD_TOKEN = '*';
|
||||
|
||||
public SearchFilter(String filter) throws InvalidSearchFilterException {
|
||||
this.filter = filter;
|
||||
pos = 0;
|
||||
normalizeFilter();
|
||||
rootFilter = this.createNextFilter();
|
||||
}
|
||||
|
||||
// Returns true if targetAttrs passes the filter
|
||||
public boolean check(Attributes targetAttrs) throws NamingException {
|
||||
if (targetAttrs == null)
|
||||
return false;
|
||||
|
||||
return rootFilter.check(targetAttrs);
|
||||
}
|
||||
|
||||
/*
|
||||
* Utility routines used by member classes
|
||||
*/
|
||||
|
||||
// does some pre-processing on the string to make it look exactly lik
|
||||
// what the parser expects. This only needs to be called once.
|
||||
protected void normalizeFilter() {
|
||||
skipWhiteSpace(); // get rid of any leading whitespaces
|
||||
|
||||
// Sometimes, search filters don't have "(" and ")" - add them
|
||||
if(getCurrentChar() != BEGIN_FILTER_TOKEN) {
|
||||
filter = BEGIN_FILTER_TOKEN + filter + END_FILTER_TOKEN;
|
||||
}
|
||||
// this would be a good place to strip whitespace if desired
|
||||
|
||||
if(debug) {System.out.println("SearchFilter: normalized filter:" +
|
||||
filter);}
|
||||
}
|
||||
|
||||
private void skipWhiteSpace() {
|
||||
while (Character.isWhitespace(getCurrentChar())) {
|
||||
consumeChar();
|
||||
}
|
||||
}
|
||||
|
||||
protected StringFilter createNextFilter()
|
||||
throws InvalidSearchFilterException {
|
||||
StringFilter filter;
|
||||
|
||||
skipWhiteSpace();
|
||||
|
||||
try {
|
||||
// make sure every filter starts with "("
|
||||
if(getCurrentChar() != BEGIN_FILTER_TOKEN) {
|
||||
throw new InvalidSearchFilterException("expected \"" +
|
||||
BEGIN_FILTER_TOKEN +
|
||||
"\" at position " +
|
||||
pos);
|
||||
}
|
||||
|
||||
// skip past the "("
|
||||
this.consumeChar();
|
||||
|
||||
skipWhiteSpace();
|
||||
|
||||
// use the next character to determine the type of filter
|
||||
switch(getCurrentChar()) {
|
||||
case AND_TOKEN:
|
||||
if (debug) {System.out.println("SearchFilter: creating AND");}
|
||||
filter = new CompoundFilter(true);
|
||||
filter.parse();
|
||||
break;
|
||||
case OR_TOKEN:
|
||||
if (debug) {System.out.println("SearchFilter: creating OR");}
|
||||
filter = new CompoundFilter(false);
|
||||
filter.parse();
|
||||
break;
|
||||
case NOT_TOKEN:
|
||||
if (debug) {System.out.println("SearchFilter: creating OR");}
|
||||
filter = new NotFilter();
|
||||
filter.parse();
|
||||
break;
|
||||
default:
|
||||
if (debug) {System.out.println("SearchFilter: creating SIMPLE");}
|
||||
filter = new AtomicFilter();
|
||||
filter.parse();
|
||||
break;
|
||||
}
|
||||
|
||||
skipWhiteSpace();
|
||||
|
||||
// make sure every filter ends with ")"
|
||||
if(getCurrentChar() != END_FILTER_TOKEN) {
|
||||
throw new InvalidSearchFilterException("expected \"" +
|
||||
END_FILTER_TOKEN +
|
||||
"\" at position " +
|
||||
pos);
|
||||
}
|
||||
|
||||
// skip past the ")"
|
||||
this.consumeChar();
|
||||
} catch (InvalidSearchFilterException e) {
|
||||
if (debug) {System.out.println("rethrowing e");}
|
||||
throw e; // just rethrow these
|
||||
|
||||
// catch all - any uncaught exception while parsing will end up here
|
||||
} catch (Exception e) {
|
||||
if(debug) {System.out.println(e.getMessage());e.printStackTrace();}
|
||||
throw new InvalidSearchFilterException("Unable to parse " +
|
||||
"character " + pos + " in \""+
|
||||
this.filter + "\"");
|
||||
}
|
||||
|
||||
return filter;
|
||||
}
|
||||
|
||||
protected char getCurrentChar() {
|
||||
return filter.charAt(pos);
|
||||
}
|
||||
|
||||
protected char relCharAt(int i) {
|
||||
return filter.charAt(pos + i);
|
||||
}
|
||||
|
||||
protected void consumeChar() {
|
||||
pos++;
|
||||
}
|
||||
|
||||
protected void consumeChars(int i) {
|
||||
pos += i;
|
||||
}
|
||||
|
||||
protected int relIndexOf(int ch) {
|
||||
return filter.indexOf(ch, pos) - pos;
|
||||
}
|
||||
|
||||
protected String relSubstring(int beginIndex, int endIndex){
|
||||
if(debug){System.out.println("relSubString: " + beginIndex +
|
||||
" " + endIndex);}
|
||||
return filter.substring(beginIndex+pos, endIndex+pos);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A class for dealing with compound filters ("and" & "or" filters).
|
||||
*/
|
||||
final class CompoundFilter implements StringFilter {
|
||||
private Vector<StringFilter> subFilters;
|
||||
private boolean polarity;
|
||||
|
||||
CompoundFilter(boolean polarity) {
|
||||
subFilters = new Vector<>();
|
||||
this.polarity = polarity;
|
||||
}
|
||||
|
||||
public void parse() throws InvalidSearchFilterException {
|
||||
SearchFilter.this.consumeChar(); // consume the "&"
|
||||
while(SearchFilter.this.getCurrentChar() != END_FILTER_TOKEN) {
|
||||
if (debug) {System.out.println("CompoundFilter: adding");}
|
||||
StringFilter filter = SearchFilter.this.createNextFilter();
|
||||
subFilters.addElement(filter);
|
||||
skipWhiteSpace();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean check(Attributes targetAttrs) throws NamingException {
|
||||
for(int i = 0; i<subFilters.size(); i++) {
|
||||
StringFilter filter = subFilters.elementAt(i);
|
||||
if(filter.check(targetAttrs) != this.polarity) {
|
||||
return !polarity;
|
||||
}
|
||||
}
|
||||
return polarity;
|
||||
}
|
||||
} /* CompoundFilter */
|
||||
|
||||
/**
|
||||
* A class for dealing with NOT filters
|
||||
*/
|
||||
final class NotFilter implements StringFilter {
|
||||
private StringFilter filter;
|
||||
|
||||
public void parse() throws InvalidSearchFilterException {
|
||||
SearchFilter.this.consumeChar(); // consume the "!"
|
||||
filter = SearchFilter.this.createNextFilter();
|
||||
}
|
||||
|
||||
public boolean check(Attributes targetAttrs) throws NamingException {
|
||||
return !filter.check(targetAttrs);
|
||||
}
|
||||
} /* notFilter */
|
||||
|
||||
// note: declared here since member classes can't have static variables
|
||||
static final int EQUAL_MATCH = 1;
|
||||
static final int APPROX_MATCH = 2;
|
||||
static final int GREATER_MATCH = 3;
|
||||
static final int LESS_MATCH = 4;
|
||||
|
||||
/**
|
||||
* A class for dealing wtih atomic filters
|
||||
*/
|
||||
final class AtomicFilter implements StringFilter {
|
||||
private String attrID;
|
||||
private String value;
|
||||
private int matchType;
|
||||
|
||||
public void parse() throws InvalidSearchFilterException {
|
||||
|
||||
skipWhiteSpace();
|
||||
|
||||
try {
|
||||
// find the end
|
||||
int endPos = SearchFilter.this.relIndexOf(END_FILTER_TOKEN);
|
||||
|
||||
//determine the match type
|
||||
int i = SearchFilter.this.relIndexOf(EQUAL_TOKEN);
|
||||
if(debug) {System.out.println("AtomicFilter: = at " + i);}
|
||||
int qualifier = SearchFilter.this.relCharAt(i-1);
|
||||
switch(qualifier) {
|
||||
case APPROX_TOKEN:
|
||||
if (debug) {System.out.println("Atomic: APPROX found");}
|
||||
matchType = APPROX_MATCH;
|
||||
attrID = SearchFilter.this.relSubstring(0, i-1);
|
||||
value = SearchFilter.this.relSubstring(i+1, endPos);
|
||||
break;
|
||||
|
||||
case GREATER_TOKEN:
|
||||
if (debug) {System.out.println("Atomic: GREATER found");}
|
||||
matchType = GREATER_MATCH;
|
||||
attrID = SearchFilter.this.relSubstring(0, i-1);
|
||||
value = SearchFilter.this.relSubstring(i+1, endPos);
|
||||
break;
|
||||
|
||||
case LESS_TOKEN:
|
||||
if (debug) {System.out.println("Atomic: LESS found");}
|
||||
matchType = LESS_MATCH;
|
||||
attrID = SearchFilter.this.relSubstring(0, i-1);
|
||||
value = SearchFilter.this.relSubstring(i+1, endPos);
|
||||
break;
|
||||
|
||||
case EXTEND_TOKEN:
|
||||
if(debug) {System.out.println("Atomic: EXTEND found");}
|
||||
throw new OperationNotSupportedException("Extensible match not supported");
|
||||
|
||||
default:
|
||||
if (debug) {System.out.println("Atomic: EQUAL found");}
|
||||
matchType = EQUAL_MATCH;
|
||||
attrID = SearchFilter.this.relSubstring(0,i);
|
||||
value = SearchFilter.this.relSubstring(i+1, endPos);
|
||||
break;
|
||||
}
|
||||
|
||||
attrID = attrID.trim();
|
||||
value = value.trim();
|
||||
|
||||
//update our position
|
||||
SearchFilter.this.consumeChars(endPos);
|
||||
|
||||
} catch (Exception e) {
|
||||
if (debug) {System.out.println(e.getMessage());
|
||||
e.printStackTrace();}
|
||||
InvalidSearchFilterException sfe =
|
||||
new InvalidSearchFilterException("Unable to parse " +
|
||||
"character " + SearchFilter.this.pos + " in \""+
|
||||
SearchFilter.this.filter + "\"");
|
||||
sfe.setRootCause(e);
|
||||
throw(sfe);
|
||||
}
|
||||
|
||||
if(debug) {System.out.println("AtomicFilter: " + attrID + "=" +
|
||||
value);}
|
||||
}
|
||||
|
||||
public boolean check(Attributes targetAttrs) {
|
||||
Enumeration<?> candidates;
|
||||
|
||||
try {
|
||||
Attribute attr = targetAttrs.get(attrID);
|
||||
if(attr == null) {
|
||||
return false;
|
||||
}
|
||||
candidates = attr.getAll();
|
||||
} catch (NamingException ne) {
|
||||
if (debug) {System.out.println("AtomicFilter: should never " +
|
||||
"here");}
|
||||
return false;
|
||||
}
|
||||
|
||||
while(candidates.hasMoreElements()) {
|
||||
String val = candidates.nextElement().toString();
|
||||
if (debug) {System.out.println("Atomic: comparing: " + val);}
|
||||
switch(matchType) {
|
||||
case APPROX_MATCH:
|
||||
case EQUAL_MATCH:
|
||||
if(substringMatch(this.value, val)) {
|
||||
if (debug) {System.out.println("Atomic: EQUAL match");}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case GREATER_MATCH:
|
||||
if (debug) {System.out.println("Atomic: GREATER match");}
|
||||
if(val.compareTo(this.value) >= 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case LESS_MATCH:
|
||||
if (debug) {System.out.println("Atomic: LESS match");}
|
||||
if(val.compareTo(this.value) <= 0) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (debug) {System.out.println("AtomicFilter: unkown " +
|
||||
"matchType");}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// used for substring comparisons (where proto has "*" wildcards
|
||||
private boolean substringMatch(String proto, String value) {
|
||||
// simple case 1: "*" means attribute presence is being tested
|
||||
if(proto.equals(new Character(WILDCARD_TOKEN).toString())) {
|
||||
if(debug) {System.out.println("simple presence assertion");}
|
||||
return true;
|
||||
}
|
||||
|
||||
// simple case 2: if there are no wildcards, call String.equals()
|
||||
if(proto.indexOf(WILDCARD_TOKEN) == -1) {
|
||||
return proto.equalsIgnoreCase(value);
|
||||
}
|
||||
|
||||
if(debug) {System.out.println("doing substring comparison");}
|
||||
// do the work: make sure all the substrings are present
|
||||
int currentPos = 0;
|
||||
StringTokenizer subStrs = new StringTokenizer(proto, "*", false);
|
||||
|
||||
// do we need to begin with the first token?
|
||||
if(proto.charAt(0) != WILDCARD_TOKEN &&
|
||||
!value.toLowerCase(Locale.ENGLISH).startsWith(
|
||||
subStrs.nextToken().toLowerCase(Locale.ENGLISH))) {
|
||||
if(debug) {
|
||||
System.out.println("faild initial test");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
while(subStrs.hasMoreTokens()) {
|
||||
String currentStr = subStrs.nextToken();
|
||||
if (debug) {System.out.println("looking for \"" +
|
||||
currentStr +"\"");}
|
||||
currentPos = value.toLowerCase(Locale.ENGLISH).indexOf(
|
||||
currentStr.toLowerCase(Locale.ENGLISH), currentPos);
|
||||
|
||||
if(currentPos == -1) {
|
||||
return false;
|
||||
}
|
||||
currentPos += currentStr.length();
|
||||
}
|
||||
|
||||
// do we need to end with the last token?
|
||||
if(proto.charAt(proto.length() - 1) != WILDCARD_TOKEN &&
|
||||
currentPos != value.length() ) {
|
||||
if(debug) {System.out.println("faild final test");}
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
} /* AtomicFilter */
|
||||
|
||||
// ----- static methods for producing string filters given attribute set
|
||||
// ----- or object array
|
||||
|
||||
|
||||
/**
|
||||
* Creates an LDAP filter as a conjuction of the attributes supplied.
|
||||
*/
|
||||
public static String format(Attributes attrs) throws NamingException {
|
||||
if (attrs == null || attrs.size() == 0) {
|
||||
return "objectClass=*";
|
||||
}
|
||||
|
||||
String answer;
|
||||
answer = "(& ";
|
||||
Attribute attr;
|
||||
for (NamingEnumeration<? extends Attribute> e = attrs.getAll();
|
||||
e.hasMore(); ) {
|
||||
attr = e.next();
|
||||
if (attr.size() == 0 || (attr.size() == 1 && attr.get() == null)) {
|
||||
// only checking presence of attribute
|
||||
answer += "(" + attr.getID() + "=" + "*)";
|
||||
} else {
|
||||
for (NamingEnumeration<?> ve = attr.getAll();
|
||||
ve.hasMore(); ) {
|
||||
String val = getEncodedStringRep(ve.next());
|
||||
if (val != null) {
|
||||
answer += "(" + attr.getID() + "=" + val + ")";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
answer += ")";
|
||||
//System.out.println("filter: " + answer);
|
||||
return answer;
|
||||
}
|
||||
|
||||
// Writes the hex representation of a byte to a StringBuffer.
|
||||
private static void hexDigit(StringBuffer buf, byte x) {
|
||||
char c;
|
||||
|
||||
c = (char) ((x >> 4) & 0xf);
|
||||
if (c > 9)
|
||||
c = (char) ((c-10) + 'A');
|
||||
else
|
||||
c = (char)(c + '0');
|
||||
|
||||
buf.append(c);
|
||||
c = (char) (x & 0xf);
|
||||
if (c > 9)
|
||||
c = (char)((c-10) + 'A');
|
||||
else
|
||||
c = (char)(c + '0');
|
||||
buf.append(c);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the string representation of an object (such as an attr value).
|
||||
* If obj is a byte array, encode each item as \xx, where xx is hex encoding
|
||||
* of the byte value.
|
||||
* Else, if obj is not a String, use its string representation (toString()).
|
||||
* Special characters in obj (or its string representation) are then
|
||||
* encoded appropriately according to RFC 2254.
|
||||
* * \2a
|
||||
* ( \28
|
||||
* ) \29
|
||||
* \ \5c
|
||||
* NUL \00
|
||||
*/
|
||||
private static String getEncodedStringRep(Object obj) throws NamingException {
|
||||
String str;
|
||||
if (obj == null)
|
||||
return null;
|
||||
|
||||
if (obj instanceof byte[]) {
|
||||
// binary data must be encoded as \hh where hh is a hex char
|
||||
byte[] bytes = (byte[])obj;
|
||||
StringBuffer b1 = new StringBuffer(bytes.length*3);
|
||||
for (int i = 0; i < bytes.length; i++) {
|
||||
b1.append('\\');
|
||||
hexDigit(b1, bytes[i]);
|
||||
}
|
||||
return b1.toString();
|
||||
}
|
||||
if (!(obj instanceof String)) {
|
||||
str = obj.toString();
|
||||
} else {
|
||||
str = (String)obj;
|
||||
}
|
||||
int len = str.length();
|
||||
StringBuffer buf = new StringBuffer(len);
|
||||
char ch;
|
||||
for (int i = 0; i < len; i++) {
|
||||
switch (ch=str.charAt(i)) {
|
||||
case '*':
|
||||
buf.append("\\2a");
|
||||
break;
|
||||
case '(':
|
||||
buf.append("\\28");
|
||||
break;
|
||||
case ')':
|
||||
buf.append("\\29");
|
||||
break;
|
||||
case '\\':
|
||||
buf.append("\\5c");
|
||||
break;
|
||||
case 0:
|
||||
buf.append("\\00");
|
||||
break;
|
||||
default:
|
||||
buf.append(ch);
|
||||
}
|
||||
}
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Finds the first occurrence of <tt>ch</tt> in <tt>val</tt> starting
|
||||
* from position <tt>start</tt>. It doesn't count if <tt>ch</tt>
|
||||
* has been escaped by a backslash (\)
|
||||
*/
|
||||
public static int findUnescaped(char ch, String val, int start) {
|
||||
int len = val.length();
|
||||
|
||||
while (start < len) {
|
||||
int where = val.indexOf(ch, start);
|
||||
// if at start of string, or not there at all, or if not escaped
|
||||
if (where == start || where == -1 || val.charAt(where-1) != '\\')
|
||||
return where;
|
||||
|
||||
// start search after escaped star
|
||||
start = where + 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Formats the expression <tt>expr</tt> using arguments from the array
|
||||
* <tt>args</tt>.
|
||||
*
|
||||
* <code>{i}</code> specifies the <code>i</code>'th element from
|
||||
* the array <code>args</code> is to be substituted for the
|
||||
* string "<code>{i}</code>".
|
||||
*
|
||||
* To escape '{' or '}' (or any other character), use '\'.
|
||||
*
|
||||
* Uses getEncodedStringRep() to do encoding.
|
||||
*/
|
||||
|
||||
public static String format(String expr, Object[] args)
|
||||
throws NamingException {
|
||||
|
||||
int param;
|
||||
int where = 0, start = 0;
|
||||
StringBuffer answer = new StringBuffer(expr.length());
|
||||
|
||||
while ((where = findUnescaped('{', expr, start)) >= 0) {
|
||||
int pstart = where + 1; // skip '{'
|
||||
int pend = expr.indexOf('}', pstart);
|
||||
|
||||
if (pend < 0) {
|
||||
throw new InvalidSearchFilterException("unbalanced {: " + expr);
|
||||
}
|
||||
|
||||
// at this point, pend should be pointing at '}'
|
||||
try {
|
||||
param = Integer.parseInt(expr.substring(pstart, pend));
|
||||
} catch (NumberFormatException e) {
|
||||
throw new InvalidSearchFilterException(
|
||||
"integer expected inside {}: " + expr);
|
||||
}
|
||||
|
||||
if (param >= args.length) {
|
||||
throw new InvalidSearchFilterException(
|
||||
"number exceeds argument list: " + param);
|
||||
}
|
||||
|
||||
answer.append(expr.substring(start, where)).append(getEncodedStringRep(args[param]));
|
||||
start = pend + 1; // skip '}'
|
||||
}
|
||||
|
||||
if (start < expr.length())
|
||||
answer.append(expr.substring(start));
|
||||
|
||||
return answer.toString();
|
||||
}
|
||||
|
||||
/*
|
||||
* returns an Attributes instance containing only attributeIDs given in
|
||||
* "attributeIDs" whose values come from the given DSContext.
|
||||
*/
|
||||
public static Attributes selectAttributes(Attributes originals,
|
||||
String[] attrIDs) throws NamingException {
|
||||
|
||||
if (attrIDs == null)
|
||||
return originals;
|
||||
|
||||
Attributes result = new BasicAttributes();
|
||||
|
||||
for(int i=0; i<attrIDs.length; i++) {
|
||||
Attribute attr = originals.get(attrIDs[i]);
|
||||
if(attr != null) {
|
||||
result.put(attr);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/* For testing filter
|
||||
public static void main(String[] args) {
|
||||
|
||||
Attributes attrs = new BasicAttributes(LdapClient.caseIgnore);
|
||||
attrs.put("cn", "Rosanna Lee");
|
||||
attrs.put("sn", "Lee");
|
||||
attrs.put("fn", "Rosanna");
|
||||
attrs.put("id", "10414");
|
||||
attrs.put("machine", "jurassic");
|
||||
|
||||
|
||||
try {
|
||||
System.out.println(format(attrs));
|
||||
|
||||
String expr = "(&(Age = {0})(Account Balance <= {1}))";
|
||||
Object[] fargs = new Object[2];
|
||||
// fill in the parameters
|
||||
fargs[0] = new Integer(65);
|
||||
fargs[1] = new Float(5000);
|
||||
|
||||
System.out.println(format(expr, fargs));
|
||||
|
||||
|
||||
System.out.println(format("bin={0}",
|
||||
new Object[] {new byte[] {0, 1, 2, 3, 4, 5}}));
|
||||
|
||||
System.out.println(format("bin=\\{anything}", null));
|
||||
|
||||
} catch (NamingException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user