Package org.apache.harmony.jndi.provider.ldap

Source Code of org.apache.harmony.jndi.provider.ldap.LdapSchemaContextImpl

/*
*  Licensed to the Apache Software Foundation (ASF) under one or more
*  contributor license agreements.  See the NOTICE file distributed with
*  this work for additional information regarding copyright ownership.
*  The ASF licenses this file to You under the Apache License, Version 2.0
*  (the "License"); you may not use this file except in compliance with
*  the License.  You may obtain a copy of the License at
*
*     http://www.apache.org/licenses/LICENSE-2.0
*
*  Unless required by applicable law or agreed to in writing, software
*  distributed under the License is distributed on an "AS IS" BASIS,
*  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*  See the License for the specific language governing permissions and
*  limitations under the License.
*/
package org.apache.harmony.jndi.provider.ldap;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;

import javax.naming.Binding;
import javax.naming.CompositeName;
import javax.naming.ConfigurationException;
import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NameClassPair;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.OperationNotSupportedException;
import javax.naming.ReferralException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.InvalidSearchFilterException;
import javax.naming.directory.ModificationItem;
import javax.naming.directory.SchemaViolationException;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;

import org.apache.harmony.jndi.internal.nls.Messages;
import org.apache.harmony.jndi.internal.parser.AttributeTypeAndValuePair;
import org.apache.harmony.jndi.provider.ldap.parser.FilterParser;
import org.apache.harmony.jndi.provider.ldap.parser.ParseException;

public class LdapSchemaContextImpl extends LdapContextImpl {

    public static final String CLASS_DEFINITION = "classdefinition";

    public static final String ATTRIBUTE_DEFINITION = "attributedefinition";

    public static final String SYNTAX_DEFINITION = "syntaxdefinition";

    public static final String MATCHING_RULE = "matchingrule";

    public static final String OBJECT_CLASSES = "objectclasses";

    public static final String ATTRIBUTE_TYPES = "attributetypes";

    public static final String LDAP_SYNTAXES = "ldapsyntaxes";

    public static final String MATCHING_RULES = "matchingrules";

    protected String subschemasubentry = null;

    final private static Hashtable<String, String> schemaJndi2Ldap = new Hashtable<String, String>();
    static {
        schemaJndi2Ldap.put(CLASS_DEFINITION, OBJECT_CLASSES);
        schemaJndi2Ldap.put(ATTRIBUTE_DEFINITION, ATTRIBUTE_TYPES);
        schemaJndi2Ldap.put(SYNTAX_DEFINITION, LDAP_SYNTAXES);
        schemaJndi2Ldap.put(MATCHING_RULE, MATCHING_RULES);
    }

    final private static Hashtable<String, String> schemaLdap2Jndi = new Hashtable<String, String>();
    static {
        schemaLdap2Jndi.put(OBJECT_CLASSES, CLASS_DEFINITION);
        schemaLdap2Jndi.put(ATTRIBUTE_TYPES, ATTRIBUTE_DEFINITION);
        schemaLdap2Jndi.put(LDAP_SYNTAXES, SYNTAX_DEFINITION);
        schemaLdap2Jndi.put(MATCHING_RULES, MATCHING_RULE);
    }

    private LdapContextImpl parent;

    private Name rdn = null;

    public LdapSchemaContextImpl(LdapContextImpl ctx, Hashtable<Object, Object> env,
            Name dn) throws InvalidNameException {
        super(ctx, env, dn.getPrefix(0).toString());
        parent = ctx;
        rdn = dn;
    }

    public DirContext getSchema(Name name) throws NamingException {
        throw new OperationNotSupportedException();
    }

    public DirContext getSchema(String name) throws NamingException {
        throw new OperationNotSupportedException();
    }

    public DirContext getSchemaClassDefinition(Name name)
            throws NamingException {
        throw new OperationNotSupportedException();
    }

    public DirContext getSchemaClassDefinition(String name)
            throws NamingException {
        throw new OperationNotSupportedException();
    }

    public String getNameInNamespace() throws NamingException {
        throw new OperationNotSupportedException();
    }

    public DirContext createSubcontext(Name name, Attributes attributes)
            throws NamingException {
        checkName(name);

        Name schemaType = name.getPrefix(name.size() - 1);

        if (null == attributes || attributes.size() == 0) {
            throw new SchemaViolationException(Messages.getString("jndi.8D"));
        }

        String schema = schemaJndi2Ldap.get(schemaType.toString().toLowerCase());
        if (null == schema) {
            throw new SchemaViolationException(Messages.getString("jndi.8D"));
        }
        if (!LdapContextImpl.schemaTree.keySet().contains(schema)) {
            throw new SchemaViolationException(Messages.getString("jndi.8E"));
        }
        String targetDN = rdn.toString() + parent.subschemasubentry;
        StringBuilder builder = new StringBuilder("( ");
        NamingEnumeration<String> ids = attributes.getIDs();

        // FIXME what if attribute value has \' or \", or can Attributes be used
        // directly
        boolean hasNOID = false;
        while (ids.hasMoreElements()) {
            String id = ids.nextElement();
            Attribute attribute = attributes.get(id);
            if (id.equalsIgnoreCase("NUMERICOID")) {
                builder.append(attribute);
                builder.append(" ");
                hasNOID = true;
            } else {
                builder.append(id);
                builder.append(" ");
                builder.append(attribute);
                builder.append(" ");
            }
        }
        builder.append(")");
        if (!hasNOID) {
            throw new ConfigurationException(Messages.getString("jndi.8F"));
        }

        ModifyOp op = new ModifyOp(targetDN);
        BasicAttribute schemaEntry = new LdapAttribute(new BasicAttribute(
                schema, builder.toString()), parent);
        op.addModification(jndi2ldap[DirContext.ADD_ATTRIBUTE],
                new LdapAttribute(schemaEntry, parent));

        try {
            doBasicOperation(op);
        } catch (ReferralException e) {
            // TODO
        }
        return new LdapSchemaContextImpl(parent, parent.env, name);
    }

    public DirContext createSubcontext(String name, Attributes attributes)
            throws NamingException {
        Name n = convertFromStringToName(name);
        return createSubcontext(n, attributes);
    }

    public Attributes getAttributes(Name name) throws NamingException {
        Name targetDN = (rdn.size() != 0) ? name.addAll(rdn) : name;

        BasicAttributes schemaAttributes = new BasicAttributes();

        Set<String> keyset = null;
        int size = targetDN.size();
        switch (size) {
        case 0:
            break;
        case 1:
            String schemaType = schemaJndi2Ldap.get(name.get(0).toLowerCase());
            if (null == schemaType) {
                throw new NameNotFoundException(name.toString());
            }
            schemaAttributes.put(new BasicAttribute("objectclass", name.get(0)
                    .toLowerCase()));
            break;
        default:
            Hashtable<String, Object> classDef = parent.findSchemaDefInfo(
                    schemaJndi2Ldap.get(name.get(0).toLowerCase()), name.get(1));
            if (null == classDef) {
                throw new NameNotFoundException(name.toString());
            }
            schemaAttributes = new BasicAttributes();
            keyset = classDef.keySet();
            for (Iterator<String> i = keyset.iterator(); i.hasNext();) {
                String id = i.next();
                if (id.equals("orig")) {
                    continue;
                }
                Object value = classDef.get(id);
                schemaAttributes
                        .put(new BasicAttribute(id.toLowerCase(), value));
            }
        }
        return schemaAttributes;
    }

    public Attributes getAttributes(Name name, String[] as)
            throws NamingException {
        Attributes attrs = getAttributes(name);
        Attribute attr = null;
        Attributes filteredAttrs = new BasicAttributes();
        for (int i = 0; i < as.length; i++) {
            attr = attrs.get(as[i]);
            if (attr != null) {
                filteredAttrs.put(attr);
            }
        }
        return filteredAttrs;
    }

    public Attributes getAttributes(String attributeName)
            throws NamingException {
        Name name = new CompositeName(attributeName);
        return getAttributes(name);
    }

    public Attributes getAttributes(String name, String[] as)
            throws NamingException {
        return getAttributes(new CompositeName(name), as);
    }

    private void checkName(Name name) {
        if (name == null) {
            // jndi.2E=The name is null
            throw new NullPointerException(Messages.getString("jndi.2E")); //$NON-NLS-1$
        }
    }

    public void modifyAttributes(Name name, int i, Attributes attributes)
            throws NamingException {
        checkName(name);
        if (attributes == null) {
            // jndi.13=Non-null attribute is required for modification
            throw new NullPointerException(Messages.getString("jndi.13")); //$NON-NLS-1$
        }

        if (i != DirContext.ADD_ATTRIBUTE && i != DirContext.REMOVE_ATTRIBUTE
                && i != DirContext.REPLACE_ATTRIBUTE) {
            /*
             * jndi.14=Modification code {0} must be one of
             * DirContext.ADD_ATTRIBUTE, DirContext.REPLACE_ATTRIBUTE and
             * DirContext.REMOVE_ATTRIBUTE
             */
            throw new IllegalArgumentException(Messages.getString("jndi.14", i)); //$NON-NLS-1$
        }

        NamingEnumeration<? extends Attribute> enu = attributes.getAll();
        ModificationItem[] items = new ModificationItem[attributes.size()];
        int index = 0;
        while (enu.hasMore()) {
            items[index++] = new ModificationItem(i, enu.next());
        }

        modifyAttributes(name, items);

    }

    private static final int jndi2ldap[] = { -1, 0, 2, 1, };

    public void modifyAttributes(Name name, ModificationItem[] modificationItems)
            throws NamingException {
        checkName(name);

        Name targetDN = (rdn.size() != 0) ? name.addAll(rdn) : name;
        int size = targetDN.size();
        ModifyOp op = new ModifyOp(targetDN.toString());
        String oldValue = "(objectclass)";
        switch (size) {
        case 0:
            break;
        case 1:
            String schemaType = schemaJndi2Ldap.get(name.get(0).toLowerCase());
            if (null == schemaType) {
                throw new NameNotFoundException(name.toString());
            }
            if (modificationItems == null) {
                throw new NullPointerException(Messages.getString("ldap.27")); //$NON-NLS-1$
            }
            break;
        default:
            Hashtable<String, Object> classDef = parent
                    .findSchemaDefInfo(schemaJndi2Ldap.get(name.get(0)
                            .toLowerCase()), name.get(1));
            if (modificationItems == null) {
                throw new NullPointerException(Messages.getString("ldap.27")); //$NON-NLS-1$
            }
            if (null == classDef) {
                throw new NameNotFoundException(name.toString());
            }

            oldValue = (String) classDef.get("orig");
        }
        BasicAttribute oldAttr = new LdapAttribute(new BasicAttribute(
                OBJECT_CLASSES, oldValue), parent);
        StringBuilder addValue = new StringBuilder();
        for (ModificationItem item : modificationItems) {
            Attribute attr = item.getAttribute();
            addValue.append(attr.getID()).append(" ").append(attr.get());
        }
        addValue.append(" )");
        BasicAttribute newAttr = new LdapAttribute(
                new BasicAttribute(OBJECT_CLASSES, oldValue.replace(")",
                        addValue.toString())), this);
        op.addModification(jndi2ldap[DirContext.REMOVE_ATTRIBUTE],
                new LdapAttribute(oldAttr, parent));
        op.addModification(jndi2ldap[DirContext.ADD_ATTRIBUTE],
                new LdapAttribute(newAttr, parent));
       
        try {
            doBasicOperation(op);
        } catch (Exception e) {
            throw new SchemaViolationException("Cannot modify schema root");
        }

    }

    public void modifyAttributes(String s, int i, Attributes attributes)
            throws NamingException {
        Name name = convertFromStringToName(s);
        modifyAttributes(name, i, attributes);
    }

    public void modifyAttributes(String s, ModificationItem[] modificationItems)
            throws NamingException {
        Name name = convertFromStringToName(s);
        modifyAttributes(name, modificationItems);

    }

    public Context createSubcontext(Name name) throws NamingException {
        DirContext subContext = createSubcontext(name, null);
        return subContext;
    }

    public Context createSubcontext(String name) throws NamingException {
        Name n = convertFromStringToName(name);
        return createSubcontext(n);
    }

    public void destroySubcontext(Name name) throws NamingException {
        checkName(name);

        // Name schemaType = name.getPrefix(name.size() - 1);
        String targetDN = rdn.toString() + parent.subschemasubentry;
        ModifyOp op = new ModifyOp(targetDN);
        String schemaType = null;
        try {
            schemaType = schemaJndi2Ldap.get(name.getPrefix(name.size() - 1)
                    .toString().toLowerCase());
        } catch (IndexOutOfBoundsException e) {
            throw new ArrayIndexOutOfBoundsException();
        }

        Hashtable<String, Object> classDef = parent.findSchemaDefInfo(
                schemaType, name.get(1));
        if (null == classDef) {
            return;
        }
        String oldValue = (String) classDef.get("orig");
        LdapAttribute oldAttr = new LdapAttribute(new BasicAttribute(
                schemaType, oldValue), parent);
        op.addModification(jndi2ldap[DirContext.REMOVE_ATTRIBUTE], oldAttr);

        try {
            doBasicOperation(op);
        } catch (Exception e) {
            // TODO need to handle referal exception in the future
        }
    }

    public void destroySubcontext(String name) throws NamingException {
        destroySubcontext(convertFromStringToName(name));
    }

    public NamingEnumeration<NameClassPair> list(Name name)
            throws NamingException {
        Name targetDN = name.addAll(rdn);

        LdapNamingEnumeration<NameClassPair> enumeration = new LdapNamingEnumeration<NameClassPair>(
                null, null);
        Set<String> keyset = null;
        int size = targetDN.size();
        switch (size) {
        case 0:
            keyset = LdapContextImpl.schemaTree.keySet();
            for (Iterator<String> i = keyset.iterator(); i.hasNext();) {
                String schemaType = i.next();
                NameClassPair pair = new NameClassPair(schemaLdap2Jndi
                        .get(schemaType.toLowerCase()), this.getClass()
                        .getName());
                enumeration.add(pair);
            }
            break;
        case 1:
            String schemaType = schemaJndi2Ldap.get(name.get(0).toLowerCase());
            if (null == schemaType) {
                throw new NameNotFoundException(name.toString());
            }
            Hashtable<String, Hashtable<String, Object>> schemas = LdapContextImpl.schemaTree
                    .get(schemaType);
            keyset = schemas.keySet();
            for (Iterator<String> i = keyset.iterator(); i.hasNext();) {
                schemaType = i.next();
                NameClassPair pair = new NameClassPair(
                        schemaType.toLowerCase(), this.getClass().getName());
                enumeration.add(pair);
            }
            break;
        default:
            schemaType = schemaJndi2Ldap.get(name.getPrefix(1).toString()
                    .toLowerCase());
            if (null == schemaType) {
                throw new NameNotFoundException(name.toString());
            }
            list(name.getSuffix(1));
        }
        return enumeration;
    }

    public NamingEnumeration<NameClassPair> list(String name)
            throws NamingException {
        // TODO name supposed to be "" string, what about the situation when
        // name is not ""
        return list(convertFromStringToName(name));
    }

    public NamingEnumeration<Binding> listBindings(Name name)
            throws NamingException {
        Name targetDN = name.addAll(rdn);

        LdapNamingEnumeration<Binding> enumeration = new LdapNamingEnumeration<Binding>(
                null, null);
        Set<String> keyset = null;
        int size = targetDN.size();
        switch (size) {
        case 0:
            keyset = LdapContextImpl.schemaTree.keySet();
            for (Iterator<String> i = keyset.iterator(); i.hasNext();) {
                String schemaType = i.next();
                Binding binding = new Binding(schemaLdap2Jndi.get(schemaType
                        .toLowerCase()), this.getClass().getName(), null);
                enumeration.add(binding);
            }
            break;
        case 1:
            String schemaType = schemaJndi2Ldap.get(name.get(0).toLowerCase());
            if (null == schemaType) {
                throw new NameNotFoundException(name.toString());
            }
            Hashtable<String, Hashtable<String, Object>> schemas = LdapContextImpl.schemaTree
                    .get(schemaType);
            keyset = schemas.keySet();
            for (Iterator<String> i = keyset.iterator(); i.hasNext();) {
                schemaType = i.next();
                Binding binding = new Binding(schemaType.toLowerCase(), this
                        .getClass().getName(), null);
                enumeration.add(binding);
            }
            break;
        default:
            schemaType = schemaJndi2Ldap.get(name.getPrefix(1).toString()
                    .toLowerCase());
            if (null == schemaType) {
                throw new NameNotFoundException(name.toString());
            }
            list(name.getSuffix(1));
        }
        return enumeration;
    }

    public NamingEnumeration<Binding> listBindings(String name)
            throws NamingException {
        return listBindings(convertFromStringToName(name));
    }

    public Object lookup(Name n) throws NamingException {
        return new LdapSchemaContextImpl(parent, env, n.addAll(rdn));
    }

    public Object lookup(String name) throws NamingException {
        return lookup(convertFromStringToName(name));
    }

    public void rename(Name nOld, Name nNew) throws NamingException {
        throw new SchemaViolationException(Messages.getString("jndi.err.01"));
    }

    public void rename(String sOld, String sNew) throws NamingException {
        throw new SchemaViolationException(Messages.getString("jndi.err.01"));
    }

    public NamingEnumeration<SearchResult> search(Name name,
            Attributes attributes) throws NamingException {
        return search(name, attributes, null);
    }

    public NamingEnumeration<SearchResult> search(Name name,
    // Used to filter attribute value
            Attributes attributes,
            // Used to filter attribute name
            String[] as) throws NamingException {
        checkName(name);

        Name targetDN = name.addAll(rdn);

        /*
         * Formalize attributes, change all ids to lowercase, if attributes is
         * non-null
         */

        boolean hasMatchingAttributes = (null != attributes && 0 != attributes
                .size());
        boolean hasAttributes2Return = (null != as && 0 != as.length);

        // Attribute matcher
        BasicAttributes attrMatcher = new BasicAttributes();
        if (hasMatchingAttributes) {
            NamingEnumeration<? extends Attribute> attrEnum = attributes
                    .getAll();
            while (attrEnum.hasMore()) {
                Attribute old = attrEnum.next();
                BasicAttribute newAttr = new BasicAttribute(old.getID()
                        .toLowerCase());
                for (int i = 0; i < old.size(); i++) {
                    if (old.get(i) instanceof String) {
                        newAttr.add(((String) old.get(i)).toLowerCase());
                    } else {
                        newAttr.add(old.get(i));
                    }
                }
                attrMatcher.put(newAttr);
            }
        }

        // Attribute selector
        TreeSet<String> attrSel = new TreeSet<String>();

        // Construct result NamingEnumeration
        LdapNamingEnumeration<SearchResult> enumeration = new LdapNamingEnumeration<SearchResult>(
                null, null);
        String schemaType = null;

        LinkedList<String> attrValues = new LinkedList<String>();
        int size = targetDN.size();
        switch (size) {
        case 0:
            /*
             * Name is a empty string, search against root, may return schema
             * types: (classdefinition, attributedefinition, syntaxdefinition,
             * matchingrule)
             */
            attrValues.addAll(LdapContextImpl.schemaTree.keySet());
            /*
             * Filter attribute names - whether the single attribute name
             * 'objectclass' is chosen.
             */
            int objectclassIndex = -1;
            if (hasAttributes2Return) {
                for (int i = 0; i < as.length; i++) {
                    if (as[i].equalsIgnoreCase("objectclass")) {
                        objectclassIndex = i;
                        break;
                    }
                }
            }
            attrSel.add("objectclass");

            /*
             * Filter attribute values - choose from (classdefinition,
             * attributedefinition, syntaxdefinition, matchingrule)
             */
            if (hasMatchingAttributes) {
                Attribute attribute = attrMatcher.get("objectclass");
                if (null == attribute) {
                    return enumeration;
                }
                for (int i = 0; i < attrValues.size(); i++) {
                    schemaType = schemaLdap2Jndi.get(attrValues.get(i));
                    /*
                     * RI's behavior is odd here - it only retrieves the first
                     * encountered attribute value,
                     */
                    if (attribute.contains(schemaType)) {
                        BasicAttributes basicAttributes = new BasicAttributes();
                        /*
                         * if(objectclassIndex == -1), then No name was choose,
                         * which means SearchResult will have empty
                         * BasicAttributes.
                         */
                        if (objectclassIndex != -1) {
                            basicAttributes.put("objectclass", schemaType);
                        }
                        SearchResult pair = new SearchResult(schemaType, null,
                                basicAttributes);
                        enumeration.add(pair);
                        break;
                    }
                }
            } else {
                for (int i = 0; i < attrValues.size(); i++) {
                    schemaType = schemaLdap2Jndi.get(attrValues.get(i));
                    BasicAttributes basicAttributes = new BasicAttributes();
                    /*
                     * if(objectclassIndex == -1), then No name was choose,
                     * which means SearchResult will have empty BasicAttributes.
                     */
                    if (objectclassIndex != -1) {
                        basicAttributes.put("objectclass", schemaType);
                    }
                    SearchResult pair = new SearchResult(schemaType, null,
                            basicAttributes);
                    enumeration.add(pair);
                }
            }
            break;
        case 1:
            if (hasAttributes2Return) {
                attrSel.addAll(Arrays.asList(as));
            }
            schemaType = schemaJndi2Ldap.get(name.get(0).toLowerCase());
            if (null == schemaType) {
                throw new NameNotFoundException(name.toString());
            }
            Hashtable<String, Hashtable<String, Object>> schemas = LdapContextImpl.schemaTree
                    .get(schemaType);
            attrValues.addAll(schemas.keySet());
            BasicAttributes basicAttributes = null;
            if (hasMatchingAttributes) {
                for (int i = 0; i < attrValues.size(); i++) {
                    NamingEnumeration<Attribute> filters = attrMatcher.getAll();
                    String id = attrValues.get(i);
                    Hashtable<String, Object> schemaDef = schemas.get(id);
                    boolean matched = true;
                    while (filters.hasMore()) {
                        Attribute filter = filters.next();
                        Object values = schemaDef.get(filter.getID());
                        /*
                         * Attribute definition will only be retrieved when it
                         * is designated in attrFilter
                         */
                        if (values == null || !match(filter, values)) {
                            matched = false;
                            break;
                        }
                    }
                    if (matched) {
                        basicAttributes = new BasicAttributes();
                        for (Iterator<String> iterator = schemaDef.keySet()
                                .iterator(); iterator.hasNext();) {
                            String key = iterator.next();
                            if (key.equals("orig")) {
                                continue;
                            }
                            if (hasAttributes2Return && attrSel.contains(key)
                                    || !hasAttributes2Return) {
                                basicAttributes.put(key, schemaDef.get(key));
                            }
                        }
                        SearchResult pair = new SearchResult(id, null,
                                basicAttributes);
                        enumeration.add(pair);
                    }
                }
            } else {
                for (int i = 0; i < attrValues.size(); i++) {
                    Hashtable<String, Object> schemaDef = schemas
                            .get(attrValues.get(i));
                    basicAttributes = new BasicAttributes();
                    for (Iterator<String> iterator = schemaDef.keySet()
                            .iterator(); iterator.hasNext();) {
                        String key = iterator.next();
                        if (key.equals("orig")) {
                            continue;
                        }
                        if (hasAttributes2Return && attrSel.contains(key)
                                || !hasAttributes2Return) {
                            basicAttributes.put(key, schemaDef.get(key));
                        }
                    }
                    SearchResult pair = new SearchResult(attrValues.get(i),
                            null, basicAttributes);
                    enumeration.add(pair);
                }
            }
            break;

        default:
            schemaType = schemaJndi2Ldap.get(name.getPrefix(1).toString()
                    .toLowerCase());
            if (null == schemaType) {
                throw new NameNotFoundException(name.toString());
            }
            search(name.getSuffix(1), attributes, as);
        }
        return enumeration;

    }

    private boolean match(Attribute filter, Object values)
            throws NamingException {
        NamingEnumeration<?> attrValues = filter.getAll();
        ArrayList v = null;
        if (values instanceof ArrayList) {
            v = (ArrayList) values;
        } else {
            v = new ArrayList();
            v.add(values);
        }

        while (attrValues.hasMore()) {
            Object attrValue = attrValues.next();
            for (int i = 0; i < v.size(); i++) {
                if (attrValue.equals("*") || attrValue.equals(v.get(i))) {
                    return true;
                }
            }
        }
        return false;
    }

    public NamingEnumeration<SearchResult> search(Name name, String filter,
            Object[] objs, SearchControls searchControls)
            throws NamingException {

        checkName(name);

        if (filter == null) {
            throw new NullPointerException(Messages.getString("ldap.28")); //$NON-NLS-1$
        }
        if (filter.length() == 0) {
            throw new StringIndexOutOfBoundsException();
        }
        if (!filter.startsWith("(")) {
            StringBuilder filterWrapper = new StringBuilder("(");
            filterWrapper.append(filter).append(")");
            filter = filterWrapper.toString();
        }

        if (null == searchControls) {
            searchControls = new SearchControls();
        }

        FilterParser filterParser = new FilterParser(filter);
        filterParser.setArgs(objs);
        Filter f = null;
        try {
            f = filterParser.parse();
        } catch (ParseException e) {
            InvalidSearchFilterException ex = new InvalidSearchFilterException(
                    Messages.getString("ldap.29")); //$NON-NLS-1$
            ex.setRootCause(e);
            throw ex;
        }

        BasicAttributes matchingAttrs = new BasicAttributes();
        extractMatchingAttributes(f, matchingAttrs);

        return search(name, matchingAttrs, searchControls
                .getReturningAttributes());
    }

    private void extractMatchingAttributes(Filter f,
            BasicAttributes matchingAttrs) {
        if (!f.isLeaf()) {
            List<Filter> children = f.getChildren();
            for (Iterator iter = children.iterator(); iter.hasNext();) {
                extractMatchingAttributes((Filter) iter.next(), matchingAttrs);
            }
        } else {
            Object value = f.getValue();
            if (value instanceof AttributeTypeAndValuePair) {
                AttributeTypeAndValuePair pair = (AttributeTypeAndValuePair) value;
                matchingAttrs.put(pair.getType(), pair.getValue());
            } else {
                matchingAttrs.put((String) value, "*");
            }
        }
    }
}
TOP

Related Classes of org.apache.harmony.jndi.provider.ldap.LdapSchemaContextImpl

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.