<commit_before>/**
 * 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.xbean.naming.context;

import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.NotContextException;
import javax.naming.LinkRef;
import javax.naming.NameNotFoundException;
import javax.naming.InitialContext;
import javax.naming.OperationNotSupportedException;
import java.io.Serializable;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Map;

public abstract class AbstractContext implements Context, NestedContextFactory, Serializable {
    private static final long serialVersionUID = 6481918425692261483L;
    private final String nameInNamespace;
    private final Name parsedNameInNamespace;
    private final ContextAccess contextAccess;
    private final boolean modifiable;
    private final ThreadLocal inCall = new ThreadLocal();

    protected AbstractContext(String nameInNamespace) {
        this(nameInNamespace, ContextAccess.MODIFIABLE);
    }

    public AbstractContext(String nameInNamespace, ContextAccess contextAccess) {
        this.nameInNamespace = nameInNamespace;
        try {
            this.parsedNameInNamespace = getNameParser().parse(nameInNamespace);
        } catch (NamingException e) {
            throw new RuntimeException(e);
        }
        this.contextAccess = contextAccess;
        this.modifiable = contextAccess.isModifiable(getParsedNameInNamespace());
    }

    public void close() throws NamingException {
        //Ignore. Explicitly do not close the context
    }

    protected ContextAccess getContextAccess() {
        return contextAccess;
    }

    //
    //  Lookup Binding
    //

    /**
     * Gets the object bound to the name.  The name may contain slashes.
     * @param name the name
     * @return the object bound to the name, or null if not found
     */
    protected Object getDeepBinding(String name) {
        return null;
    }

    /**
     * Gets the object bound to the name.  The name will not contain slashes.
     * @param name the name
     * @return the object bound to the name, or null if not found
     */
    protected Object getBinding(String name) throws NamingException {
        Map bindings = getBindings();
        return bindings.get(name);
    }

    /**
     * Finds the specified entry.  Normally there is no need to override this method; instead you should
     * simply implement the getDeepBindings(String) and getBindings(String) method.
     *
     * This method will follow links except for the final element which is always just returned without
     * inspection.  This means this method can be used to implement lookupLink.
     *
     * @param stringName the string version of the name; maybe null
     * @param parsedName the parsed name; may be null
     * @return the value bound to the name
     * @throws NamingException if no value is bound to that name or if a problem occurs during the lookup
     */
    protected Object lookup(String stringName, Name parsedName) throws NamingException {
        if (stringName == null && parsedName == null) {
            throw new IllegalArgumentException("Both stringName and parsedName are null");
        }
        if (stringName == null) stringName = parsedName.toString();

        // try to look up the name directly (this is the fastest path)
        Object directLookup = getDeepBinding(stringName);
        if (directLookup != null) {
            return ContextUtil.resolve(stringName, directLookup);
        }

        // if the parsed name has no parts, they are asking for the current context
        if (parsedName == null) parsedName = getNameParser().parse(stringName);
        if (parsedName.isEmpty()) {
            return this;
        }

        // we didn't find an entry, pop the first element off the parsed name and attempt to
        // get a context from the bindings and delegate to that context
        Object localValue;
        String firstNameElement = parsedName.get(0);
        if (firstNameElement.length() == 0) {
            // the element is null... this is normally caused by looking up with a trailing '/' character
            localValue = this;
        } else {
            localValue = getBinding(firstNameElement);
        }

        if (localValue != null) {

            // if the name only had one part, we've looked up everything
            if (parsedName.size() == 1) {
                localValue = ContextUtil.resolve(stringName, localValue);
                return localValue;<commit_msg>When looking up a name strip off the absolute name in namespace, which avoids many extra lookups<commit_after>/**
 * 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.xbean.naming.context;

import javax.naming.CompositeName;
import javax.naming.Context;
import javax.naming.InvalidNameException;
import javax.naming.Name;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameParser;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.NotContextException;
import javax.naming.LinkRef;
import javax.naming.NameNotFoundException;
import javax.naming.InitialContext;
import javax.naming.OperationNotSupportedException;
import java.io.Serializable;
import java.util.Collections;
import java.util.Hashtable;
import java.util.Map;

public abstract class AbstractContext implements Context, NestedContextFactory, Serializable {
    private static final long serialVersionUID = 6481918425692261483L;
    private final String nameInNamespace;
    private final Name parsedNameInNamespace;
    private final ContextAccess contextAccess;
    private final boolean modifiable;
    private final ThreadLocal inCall = new ThreadLocal();

    protected AbstractContext(String nameInNamespace) {
        this(nameInNamespace, ContextAccess.MODIFIABLE);
    }

    public AbstractContext(String nameInNamespace, ContextAccess contextAccess) {
        this.nameInNamespace = nameInNamespace;
        try {
            this.parsedNameInNamespace = getNameParser().parse(nameInNamespace);
        } catch (NamingException e) {
            throw new RuntimeException(e);
        }
        this.contextAccess = contextAccess;
        this.modifiable = contextAccess.isModifiable(getParsedNameInNamespace());
    }

    public void close() throws NamingException {
        //Ignore. Explicitly do not close the context
    }

    protected ContextAccess getContextAccess() {
        return contextAccess;
    }

    //
    //  Lookup Binding
    //

    /**
     * Gets the object bound to the name.  The name may contain slashes.
     * @param name the name
     * @return the object bound to the name, or null if not found
     */
    protected Object getDeepBinding(String name) {
        return null;
    }

    /**
     * Gets the object bound to the name.  The name will not contain slashes.
     * @param name the name
     * @return the object bound to the name, or null if not found
     */
    protected Object getBinding(String name) throws NamingException {
        Map bindings = getBindings();
        return bindings.get(name);
    }

    /**
     * Finds the specified entry.  Normally there is no need to override this method; instead you should
     * simply implement the getDeepBindings(String) and getBindings(String) method.
     *
     * This method will follow links except for the final element which is always just returned without
     * inspection.  This means this method can be used to implement lookupLink.
     *
     * @param stringName the string version of the name; maybe null
     * @param parsedName the parsed name; may be null
     * @return the value bound to the name
     * @throws NamingException if no value is bound to that name or if a problem occurs during the lookup
     */
    protected Object lookup(String stringName, Name parsedName) throws NamingException {
        if (stringName == null && parsedName == null) {
            throw new IllegalArgumentException("Both stringName and parsedName are null");
        }
        if (stringName == null) stringName = parsedName.toString();

        // If the name starts with our name in namespace strip it off
        // This works because the name in namespace is assumed to be absolute
        if (stringName.startsWith(nameInNamespace)) {
            stringName = stringName.substring(nameInNamespace.length());
        }

        // try to look up the name directly (this is the fastest path)
        Object directLookup = getDeepBinding(stringName);
        if (directLookup != null) {
            return ContextUtil.resolve(stringName, directLookup);
        }

        // if the parsed name has no parts, they are asking for the current context
        if (parsedName == null) parsedName = getNameParser().parse(stringName);
        if (parsedName.isEmpty()) {
            return this;
        }

        // we didn't find an entry, pop the first element off the parsed name and attempt to
        // get a context from the bindings and delegate to that context
        Object localValue;
        String firstNameElement = parsedName.get(0);
        if (firstNameElement.length() == 0) {
            // the element is null... this is normally caused by looking up with a trailing '/' character
            localValue = this;
        } else {
            localValue = getBinding(firstNameElement);
        }

        if (localValue != null) {

            // if the name only had one part, we've looked up everything
            if (parsedName.size() == 1) {
                localValue = ContextUtil.resolve(stringName, localValue);
                return localValue;
{'fraction_non_alphanumeric': 0.06938954765041722, 'fraction_numerical': 0.004567413263065437, 'mean_word_length': 2.956219596942321, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2408033', 'n_tokens_mistral': 2843, 'n_tokens_neox': 2774, 'n_words': 1129}