Index: java/org/apache/naming/SimpleName.java =================================================================== --- java/org/apache/naming/SimpleName.java (revision 0) +++ java/org/apache/naming/SimpleName.java (working copy) @@ -0,0 +1,447 @@ +/* + * 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.naming; + +import javax.naming.InvalidNameException; +import java.util.*; + + +/** + * Simplified name parsing + * + * Around 6 times faster than the CompositeName + * + * @author Sheldon Shao (xshao@ebay.com) + */ +class SimpleName { + + private List comps; + + private static final char syntaxSeparator = '/'; + private static final char syntaxEscape = '\\'; + private static final char syntaxBeginQuote1 = '\"'; + private static final char syntaxEndQuote1 = '\"'; + private static final char syntaxBeginQuote2 = '\''; + private static final char syntaxEndQuote2 = '\''; + + private boolean isMeta(String n, int i) { + char ch = n.charAt(i); + return (ch == syntaxEscape) || + (ch == syntaxBeginQuote1) || + (ch == syntaxBeginQuote2) || + ch == syntaxSeparator; + } + + SimpleName() { + comps = new ArrayList(5); + } + + SimpleName(List comps) { + this(); + + this.comps.addAll(comps); + } + + SimpleName(String name) throws InvalidNameException { + this(); + + boolean compsAllEmpty = true; + int len = name.length(); + + int off; + + char endQuote; + boolean start; + boolean one; + StringBuilder sb = null; + + char ch; + + String comp; + for (int i = 0; i < len; ) { + off = i; + start = true; + one = false; + if (sb != null) { + sb.setLength(0); + } + while (i < len) { + ch = name.charAt(i); + + // handle quoted strings + if (start && ((one = ch == syntaxBeginQuote1)) || ch == syntaxBeginQuote2) { + // record choice of quote chars being used + endQuote = one ? syntaxEndQuote1 : syntaxEndQuote2; + + if (sb == null) { + sb = new StringBuilder(len); + } + + // consume string until matching quote + for (i += 1; ((i < len) && (ch = name.charAt(i)) != endQuote);i++) { + // skip escape character if it is escaping ending quote + // otherwise leave as is. + if (ch == syntaxEscape && (ch = name.charAt(i + 1)) == endQuote) { + i += 1; + } + sb.append(ch); // copy char + } + + // no ending quote found + if (i >= len) + throw new InvalidNameException(name + ": no close quote"); + + i += 1; + // verify that end-quote occurs at separator or end of string + if (i == len || name.charAt(i) == syntaxSeparator) { + break; + } + throw (new InvalidNameException(name + ": close quote appears before end of component")); + } else if (ch == syntaxSeparator) { + break; + } else if (ch == syntaxEscape) { + if (isMeta(name, i + 1)) { + // if escape precedes meta, consume escape and let + // meta through + if (sb == null) { + sb = new StringBuilder(len); + sb.append(name, off, i); + } + i += 1; + ch = name.charAt(i); + //The 'ch' will be appended in the following code + } else if (i + 1 >= len) { + throw (new InvalidNameException(name + ": unescaped " + syntaxEscape + " at end of component")); + } + } + + if (sb != null) { + sb.append(ch); + } + i ++; + start = false; + } + + if (sb != null) { + comp = sb.toString(); + } + else { + comp = name.substring(off, i); + } + comps.add(comp); + + if (!comp.isEmpty()) { + compsAllEmpty = false; + } + + if (i < len) { + if (name.charAt(i) == syntaxSeparator) { + i ++; + } + if ((i == len) && !compsAllEmpty) { + // Trailing separator found. Add an empty component. + comps.add(""); + } + } + } + } + + private String escape(String comp) { + int len = comp.length(); + boolean escapeSeparator = true; + char beginQuote = 0, endQuote = 0; + StringBuilder sb = new StringBuilder(len); + + // determine whether there are any separators; if so escape or quote them + if (comp.indexOf(syntaxSeparator) >= 0) { + beginQuote = syntaxBeginQuote1; + endQuote = syntaxEndQuote1; + } + + // if quoting component, + if (beginQuote != 0) { + // start string off with opening quote + sb = sb.append(beginQuote); + + // component is being quoted, so we only need to worry about + // escaping end quotes that occur in component + for (int i = 0; i < len; ) { + if (comp.charAt(i) == endQuote) { + // end-quotes must be escaped when inside a quoted string + sb.append(syntaxEscape).append(endQuote); + i += 1; + } else { + // no special treatment required + sb.append(comp.charAt(i++)); + } + } + + // end with closing quote + sb.append(endQuote); + + } else { + // When component is not quoted, add escape for: + // 1. leading quote + // 2. an escape preceding any meta char + // 3. an escape at the end of a component + // 4. separator + + // go through characters in component and escape where necessary + boolean start = true; + for (int i = 0; i < len; ) { + // leading quote must be escaped + if (start && comp.charAt(i) == syntaxBeginQuote1) { + sb.append(syntaxEscape).append(syntaxBeginQuote1); + i += 1; + } else if (start && comp.charAt(i) == syntaxBeginQuote2) { + sb.append(syntaxEscape).append(syntaxBeginQuote2); + i += 1; + } else + + // Escape an escape preceding meta characters, or at end. + // Other escapes pass through. + if (comp.charAt(i) == syntaxEscape) { + if (i + 1 >= len) { + // escape an ending escape + sb.append(syntaxEscape); + } else if (isMeta(comp, i + 1)) { + // escape meta strings + sb.append(syntaxEscape); + } + sb.append(syntaxEscape); + i += 1; + } else + + // escape unescaped separator + if (escapeSeparator && comp.charAt(i) == syntaxSeparator) { + // escape separator + sb.append(syntaxEscape).append(syntaxSeparator); + i += 1; + }else { + // no special treatment required + sb.append(comp.charAt(i++)); + } + start = false; + } + } + return (sb.toString()); + } + + + + public String toString() { + StringBuilder sb = new StringBuilder(); + String comp; + boolean compsAllEmpty = true; + int size = comps.size(); + + for (int i = 0; i < size; i++) { + comp = escape(comps.get(i)); + if ((i != 0)) + sb.append(syntaxSeparator); + if (comp.length() >= 1) + compsAllEmpty = false; + sb = sb.append(comp); + } + if (compsAllEmpty && (size >= 1)) + sb = sb.append(syntaxSeparator); + return (sb.toString()); + } + + public boolean equals(Object obj) { + if ((obj != null) && (obj instanceof SimpleName)) { + SimpleName target = (SimpleName)obj; + int size = size(); + if (target.size() == size) { + List mycomps = comps; + List comps = target.comps; + + for(int i = 0; i < size; i ++) { + // %% comps could shrink in the middle. + String my = mycomps.get(i); + String his = comps.get(i); + if (!(my.equals(his))) + return false; + } + return true; + } + } + return false; + } + + /** + * Compares obj to this SimpleName to determine ordering. + * Takes into account syntactic properties such as + * elimination of blanks, case-ignore, etc, if relevant. + * + * Note: using syntax of this NameImpl and ignoring + * that of comparison target. + */ + public int compareTo(SimpleName obj) { + if (this == obj) { + return 0; + } + + int len1 = size(); + int len2 = obj.size(); + int n = Math.min(len1, len2); + + int index1 = 0, index2 = 0; + + while (n-- != 0) { + String comp1 = get(index1++); + String comp2 = obj.get(index2++); + + // normalize according to syntax + int local = comp1.compareTo(comp2); + if (local != 0) { + return local; + } + } + + return len1 - len2; + } + + public int size() { + return (comps.size()); + } + + public List getComponents() { + return comps; + } + + public String get(int pos) { + return comps.get(pos); + } + + public List getPrefix(int pos) { + int size = size(); + if (pos < 0 || pos > size) { + throw new ArrayIndexOutOfBoundsException("Invalid position: " + pos + ", it should be [0, " + size + "]."); + } + return comps.subList(0, pos); + } + + public List getSuffix(int pos) { + int size = size(); + if (pos < 0 || pos > size) { + throw new ArrayIndexOutOfBoundsException("Invalid position: " + pos + ", it should be [0, " + size + "]."); + } + return comps.subList(pos, size); + } + + public boolean isEmpty() { + return (comps.isEmpty()); + } + + public boolean startsWith(int pos, Enumeration prefix) { + if (pos < 0 || pos > size()) { + return false; + } + try { + List myComps = getPrefix(pos); + for(String my : myComps) { + String his = prefix.nextElement(); + if (!(my.equals(his))) + return false; + } + } catch (NoSuchElementException e) { + return false; + } + return true; + } + + public boolean endsWith(int pos, Enumeration suffix) { + int size = size(); + int startIndex = size - pos; + if (startIndex < 0 || startIndex > size) { + return false; + } + try { + List myComps = getSuffix(startIndex); + for(String my: myComps) { + String his = suffix.nextElement(); + if (!(my.equals(his))) + return false; + } + } catch (NoSuchElementException e) { + return false; + } + return true; + } + + public boolean addAll(Enumeration comps) throws InvalidNameException { + boolean added = false; + while (comps.hasMoreElements()) { + try { + String comp = comps.nextElement(); + if (size() > 0) { + throw new InvalidNameException("A flat name can only have a single component"); + } + this.comps.add(comp); + added = true; + } catch (NoSuchElementException e) { + break; // "comps" has shrunk. + } + } + return added; + } + + public boolean addAll(int pos, Enumeration comps) + throws InvalidNameException { + boolean added = false; + for (int i = pos; comps.hasMoreElements(); i++) { + try { + String comp = comps.nextElement(); + if (size() > 0) { + throw new InvalidNameException("A flat name can only have a single component"); + } + this.comps.add(i, comp); + added = true; + } catch (NoSuchElementException e) { + break; // "comps" has shrunk. + } + } + return added; + } + + public void add(String comp) throws InvalidNameException { + if (size() > 0) { + throw new InvalidNameException("A flat name can only have a single component"); + } + comps.add(comp); + } + + public void add(int pos, String comp) throws InvalidNameException { + if (size() > 0) { + throw new InvalidNameException("A flat name can only zero or one component"); + } + comps.add(pos, comp); + } + + public Object remove(int pos) { + return comps.remove(pos); + } + + public int hashCode() { + int hash = 0; + for (String comp: comps) { + hash += comp.hashCode(); + } + return hash; + } +} \ No newline at end of file Property changes on: java\org\apache\naming\SimpleName.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: java/org/apache/naming/SimpleCompositeName.java =================================================================== --- java/org/apache/naming/SimpleCompositeName.java (revision 0) +++ java/org/apache/naming/SimpleCompositeName.java (working copy) @@ -0,0 +1,408 @@ +/* + * 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.naming; + +import javax.naming.InvalidNameException; +import javax.naming.Name; +import java.util.Collections; +import java.util.Enumeration; +import java.util.List; + +public class SimpleCompositeName implements Name { + + private transient SimpleName impl; + /** + * Constructs a new composite name instance using the components + * specified by 'comps'. This protected method is intended to be + * to be used by subclasses of CompositeName when they override + * methods such as clone(), getPrefix(), getSuffix(). + * + * @param comps A non-null enumeration containing the components for the new + * composite name. Each element is of class String. + * The enumeration will be consumed to extract its + * elements. + */ + protected SimpleCompositeName(List comps) { + impl = new SimpleName(comps); // null means use default syntax + } + + /** + * Constructs a new composite name instance by parsing the string n + * using the composite name syntax (left-to-right, slash separated). + * The composite name syntax is described in detail in the class + * description. + * + * @param n The non-null string to parse. + * @exception javax.naming.InvalidNameException If n has invalid composite name syntax. + */ + public SimpleCompositeName(String n) throws InvalidNameException { + impl = new SimpleName(n); // null means use default syntax + } + + /** + * Constructs a new empty composite name. Such a name returns true + * when isEmpty() is invoked on it. + */ + public SimpleCompositeName() { + impl = new SimpleName(); // null means use default syntax + } + + /** + * Generates the string representation of this composite name. + * The string representation consists of enumerating in order + * each component of the composite name and separating + * each component by a forward slash character. Quoting and + * escape characters are applied where necessary according to + * the JNDI syntax, which is described in the class description. + * An empty component is represented by an empty string. + * + * The string representation thus generated can be passed to + * the CompositeName constructor to create a new equivalent + * composite name. + * + * @return A non-null string representation of this composite name. + */ + public String toString() { + return impl.toString(); + } + + /** + * Determines whether two composite names are equal. + * If obj is null or not a composite name, false is returned. + * Two composite names are equal if each component in one is equal + * to the corresponding component in the other. This implies + * both have the same number of components, and each component's + * equals() test against the corresponding component in the other name + * returns true. + * + * @param obj The possibly null object to compare against. + * @return true if obj is equal to this composite name, false otherwise. + * @see #hashCode + */ + public boolean equals(Object obj) { + return (obj != null && + obj instanceof SimpleCompositeName && + impl.equals(((SimpleCompositeName)obj).impl)); + } + + /** + * Computes the hash code of this composite name. + * The hash code is the sum of the hash codes of individual components + * of this composite name. + * + * @return An int representing the hash code of this name. + * @see #equals + */ + public int hashCode() { + return impl.hashCode(); + } + + + /** + * Compares this CompositeName with the specified Object for order. + * Returns a + * negative integer, zero, or a positive integer as this Name is less + * than, equal to, or greater than the given Object. + *

+ * If obj is null or not an instance of CompositeName, ClassCastException + * is thrown. + *

+ * See equals() for what it means for two composite names to be equal. + * If two composite names are equal, 0 is returned. + *

+ * Ordering of composite names follows the lexicographical rules for + * string comparison, with the extension that this applies to all + * the components in the composite name. The effect is as if all the + * components were lined up in their specified ordered and the + * lexicographical rules applied over the two line-ups. + * If this composite name is "lexicographically" lesser than obj, + * a negative number is returned. + * If this composite name is "lexicographically" greater than obj, + * a positive number is returned. + * @param obj The non-null object to compare against. + * + * @return a negative integer, zero, or a positive integer as this Name + * is less than, equal to, or greater than the given Object. + * @exception ClassCastException if obj is not a CompositeName. + */ + public int compareTo(Object obj) { + if (!(obj instanceof SimpleCompositeName)) { + throw new ClassCastException("Not a SimpleCompositeName"); + } + return impl.compareTo(((SimpleCompositeName)obj).impl); + } + + /** + * Generates a copy of this composite name. + * Changes to the components of this composite name won't + * affect the new copy and vice versa. + * + * @return A non-null copy of this composite name. + */ + public Object clone() { + return (new SimpleCompositeName(impl.getComponents())); + } + + /** + * Retrieves the number of components in this composite name. + * + * @return The nonnegative number of components in this composite name. + */ + public int size() { + return (impl.size()); + } + + /** + * Determines whether this composite name is empty. A composite name + * is empty if it has zero components. + * + * @return true if this composite name is empty, false otherwise. + */ + public boolean isEmpty() { + return (impl.isEmpty()); + } + + /** + * Retrieves the components of this composite name as an enumeration + * of strings. + * The effects of updates to this composite name on this enumeration + * is undefined. + * + * @return A non-null enumeration of the components of + * this composite name. Each element of the enumeration is of + * class String. + */ + public Enumeration getAll() { + return Collections.enumeration(impl.getComponents()); + } + + /** + * Retrieves a component of this composite name. + * + * @param posn The 0-based index of the component to retrieve. + * Must be in the range [0,size()). + * @return The non-null component at index posn. + * @exception ArrayIndexOutOfBoundsException if posn is outside the + * specified range. + */ + public String get(int posn) { + return (impl.get(posn)); + } + + /** + * Creates a composite name whose components consist of a prefix of the + * components in this composite name. Subsequent changes to + * this composite name does not affect the name that is returned. + * + * @param pos The 0-based index of the component at which to stop. + * Must be in the range [0,size()]. + * @return A composite name consisting of the components at indexes in + * the range [0,posn). + * @exception ArrayIndexOutOfBoundsException + * If posn is outside the specified range. + */ + public Name getPrefix(int pos) { + List comps = impl.getPrefix(pos); + return (new SimpleCompositeName(comps)); + } + + /** + * Creates a composite name whose components consist of a suffix of the + * components in this composite name. Subsequent changes to + * this composite name does not affect the name that is returned. + * + * @param pos The 0-based index of the component at which to start. + * Must be in the range [0,size()]. + * @return A composite name consisting of the components at indexes in + * the range [posn,size()). If posn is equal to + * size(), an empty composite name is returned. + * @exception ArrayIndexOutOfBoundsException + * If posn is outside the specified range. + */ + public Name getSuffix(int pos) { + List comps = impl.getSuffix(pos); + return (new SimpleCompositeName(comps)); + } + + /** + * Determines whether a composite name is a prefix of this composite name. + * A composite name 'n' is a prefix if it is equal to + * getPrefix(n.size())--in other words, this composite name + * starts with 'n'. If 'n' is null or not a composite name, false is returned. + * + * @param n The possibly null name to check. + * @return true if n is a CompositeName and + * is a prefix of this composite name, false otherwise. + */ + public boolean startsWith(Name n) { + if (n instanceof SimpleCompositeName) { + return (impl.startsWith(n.size(), n.getAll())); + } else { + return false; + } + } + + /** + * Determines whether a composite name is a suffix of this composite name. + * A composite name 'n' is a suffix if it it is equal to + * getSuffix(size()-n.size())--in other words, this + * composite name ends with 'n'. + * If n is null or not a composite name, false is returned. + * + * @param n The possibly null name to check. + * @return true if n is a CompositeName and + * is a suffix of this composite name, false otherwise. + */ + public boolean endsWith(Name n) { + if (n instanceof SimpleCompositeName) { + return (impl.endsWith(n.size(), n.getAll())); + } else { + return false; + } + } + + /** + * Adds the components of a composite name -- in order -- to the end of + * this composite name. + * + * @param suffix The non-null components to add. + * @return The updated CompositeName, not a new one. Cannot be null. + * @exception InvalidNameException If suffix is not a composite name. + */ + public Name addAll(Name suffix) + throws InvalidNameException + { + if (suffix instanceof SimpleCompositeName) { + impl.addAll(suffix.getAll()); + return this; + } else { + throw new InvalidNameException("Not a composite name: " + suffix.toString()); + } + } + + /** + * Adds the components of a composite name -- in order -- at a specified + * position within this composite name. + * Components of this composite name at or after the index of the first + * new component are shifted up (away from index 0) + * to accommodate the new components. + * + * @param n The non-null components to add. + * @param posn The index in this name at which to add the new + * components. Must be in the range [0,size()]. + * @return The updated CompositeName, not a new one. Cannot be null. + * @exception InvalidNameException If n is not a composite name. + * @exception ArrayIndexOutOfBoundsException + * If posn is outside the specified range. + */ + public Name addAll(int posn, Name n) + throws InvalidNameException + { + if (n instanceof SimpleCompositeName) { + impl.addAll(posn, n.getAll()); + return this; + } else { + throw new InvalidNameException("Not a composite name: " + + n.toString()); + } + } + + /** + * Adds a single component to the end of this composite name. + * + * @param comp The non-null component to add. + * @return The updated CompositeName, not a new one. Cannot be null. + * @exception InvalidNameException If adding comp at end of the name + * would violate the name's syntax. + */ + public Name add(String comp) throws InvalidNameException { + impl.add(comp); + return this; + } + + /** + * Adds a single component at a specified position within this + * composite name. + * Components of this composite name at or after the index of the new + * component are shifted up by one (away from index 0) to accommodate + * the new component. + * + * @param comp The non-null component to add. + * @param posn The index at which to add the new component. + * Must be in the range [0,size()]. + * @return The updated CompositeName, not a new one. Cannot be null. + * @exception ArrayIndexOutOfBoundsException + * If posn is outside the specified range. + * @exception InvalidNameException If adding comp at the specified position + * would violate the name's syntax. + */ + public Name add(int posn, String comp) + throws InvalidNameException + { + impl.add(posn, comp); + return this; + } + + /** + * Deletes a component from this composite name. + * The component of this composite name at position 'posn' is removed, + * and components at indices greater than 'posn' + * are shifted down (towards index 0) by one. + * + * @param posn The index of the component to delete. + * Must be in the range [0,size()). + * @return The component removed (a String). + * @exception ArrayIndexOutOfBoundsException + * If posn is outside the specified range (includes case where + * composite name is empty). + * @exception InvalidNameException If deleting the component + * would violate the name's syntax. + */ + public Object remove(int posn) throws InvalidNameException{ + return impl.remove(posn); + } + + /** + * Overridden to avoid implementation dependency. + * @serialData The number of components (an int) followed by + * the individual components (each a String). + */ + private void writeObject(java.io.ObjectOutputStream s) + throws java.io.IOException { + s.writeInt(size()); + Enumeration comps = getAll(); + while (comps.hasMoreElements()) { + s.writeObject(comps.nextElement()); + } + } + + /** + * Overridden to avoid implementation dependency. + */ + private void readObject(java.io.ObjectInputStream s) + throws java.io.IOException, ClassNotFoundException { + impl = new SimpleName(); // null means use default syntax + int n = s.readInt(); // number of components + try { + while (--n >= 0) { + add((String)s.readObject()); + } + } catch (InvalidNameException e) { + throw (new java.io.StreamCorruptedException("Invalid name")); + } + } +} \ No newline at end of file Property changes on: java\org\apache\naming\SimpleCompositeName.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: test/org/apache/naming/TestSimpleName.java =================================================================== --- test/org/apache/naming/TestSimpleName.java (revision 0) +++ test/org/apache/naming/TestSimpleName.java (working copy) @@ -0,0 +1,292 @@ +/* + * 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.naming; + +import org.junit.Test; + +import javax.naming.CompositeName; +import javax.naming.InvalidNameException; +import javax.naming.Name; +import javax.naming.NamingException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +/** + * Test case for SimpleName + */ +public class TestSimpleName { + + @Test + public void testSimpleName() throws NamingException { + + CompositeName cn = new CompositeName("/META-INF/javax.naming.Name"); + + assertEquals(cn.size(), 3); + assertEquals(cn.get(0), ""); + assertEquals(cn.get(1), "META-INF"); + assertEquals(cn.get(2), "javax.naming.Name"); + + SimpleName name = new SimpleName("/META-INF/javax.naming.Name"); + + assertEquals(name.size(), 3); + assertEquals(name.get(0), ""); + assertEquals(name.get(1), "META-INF"); + assertEquals(name.get(2), "javax.naming.Name"); + + } + + @Test + public void testAB() throws NamingException { + + int warmupTimes = 1000; + + for(int i = 0; i < warmupTimes; i ++) { + CompositeName cn = new CompositeName("/META-INF/javax.naming.Name"); + SimpleName name = new SimpleName("/META-INF/javax.naming.Name"); + } + + int invocation = 1000000; + + long start = System.currentTimeMillis(); + for(int i = 0; i < invocation; i ++) { + CompositeName cn = new CompositeName("/META-INF/javax.naming.Name"); + } + long end = System.currentTimeMillis(); + System.out.println("CompositeName:" + (end-start)); + start = System.currentTimeMillis(); + for(int i = 0; i < invocation; i ++) { + SimpleCompositeName cn = new SimpleCompositeName("/META-INF/javax.naming.Name"); + } + end = System.currentTimeMillis(); + System.out.println("SimpleCompositeName:" + (end-start)); + + start = System.currentTimeMillis(); + for(int i = 0; i < invocation; i ++) { + SimpleCompositeName cn = new SimpleCompositeName("/META-INF/javax.naming.Name"); + } + end = System.currentTimeMillis(); + System.out.println("SimpleCompositeName:" + (end-start)); + start = System.currentTimeMillis(); + for(int i = 0; i < invocation; i ++) { + CompositeName cn = new CompositeName("/META-INF/javax.naming.Name"); + } + end = System.currentTimeMillis(); + System.out.println("CompositeName:" + (end-start)); + + } + + + @Test + public void testEscape1() throws Exception { + CompositeName cn = new CompositeName("/META-INF/'javax\\'.naming.Name'"); + + assertEquals(cn.size(), 3); + assertEquals(cn.get(0), ""); + assertEquals(cn.get(1), "META-INF"); + assertEquals(cn.get(2), "javax'.naming.Name"); + + SimpleName name = new SimpleName("/META-INF/'javax\\'.naming.Name'"); + + assertEquals(name.size(), 3); + assertEquals(name.get(0), ""); + assertEquals(name.get(1), "META-INF"); + assertEquals(name.get(2), "javax'.naming.Name"); + } + + @Test + public void testEscape2() throws Exception { + CompositeName cn = new CompositeName("/\"META'-INF\\\"\"/'javax\\'.naming.Name'"); + + assertEquals(cn.size(), 3); + assertEquals(cn.get(0), ""); + assertEquals(cn.get(1), "META'-INF\""); + assertEquals(cn.get(2), "javax'.naming.Name"); + + SimpleName name = new SimpleName("/\"META'-INF\\\"\"/'javax\\'.naming.Name'"); + + assertEquals(name.size(), 3); + assertEquals(name.get(0), ""); + assertEquals(name.get(1), "META'-INF\""); + assertEquals(name.get(2), "javax'.naming.Name"); + } + + @Test + public void testEscape3() throws Exception { + CompositeName cn = new CompositeName("/META\\'-INF\\\"/'javax\\'.naming.Name'"); + + assertEquals(cn.size(), 3); + assertEquals(cn.get(0), ""); + assertEquals(cn.get(1), "META'-INF\""); + assertEquals(cn.get(2), "javax'.naming.Name"); + + SimpleName name = new SimpleName("/META\\'-INF\\\"/'javax\\'.naming.Name'"); + + assertEquals(name.size(), 3); + assertEquals(name.get(0), ""); + assertEquals(name.get(1), "META'-INF\""); + assertEquals(name.get(2), "javax'.naming.Name"); + } + + @Test + public void testEscape4() throws Exception { + CompositeName cn = new CompositeName("/\\/META\\'-INF\\\"/'javax\\'.naming.Name'"); + + assertEquals(cn.size(), 3); + assertEquals(cn.get(0), ""); + assertEquals(cn.get(1), "/META'-INF\""); + assertEquals(cn.get(2), "javax'.naming.Name"); + + SimpleName name = new SimpleName("/\\/META\\'-INF\\\"/'javax\\'.naming.Name'"); + + assertEquals(name.size(), 3); + assertEquals(name.get(0), ""); + assertEquals(name.get(1), "/META'-INF\""); + assertEquals(name.get(2), "javax'.naming.Name"); + } + + @Test + public void testToString() throws Exception { + CompositeName cn = new CompositeName("/\\/META\\'-INF\\\"/'javax\\'.naming.Name'"); + + assertEquals(cn.size(), 3); + assertEquals(cn.get(0), ""); + assertEquals(cn.get(1), "/META'-INF\""); + assertEquals(cn.get(2), "javax'.naming.Name"); + + assertEquals("/\"/META'-INF\\\"\"/javax'.naming.Name", cn.toString()); + + SimpleName name = new SimpleName("/\\/META\\'-INF\\\"/'javax\\'.naming.Name'"); + + assertEquals(name.size(), 3); + assertEquals(name.get(0), ""); + assertEquals(name.get(1), "/META'-INF\""); + assertEquals(name.get(2), "javax'.naming.Name"); + assertEquals("/\"/META'-INF\\\"\"/javax'.naming.Name", name.toString()); + + //Make sure the result is same as CompositeName + assertEquals(cn.toString(), name.toString()); + } + + @Test + public void testEscape5() throws Exception { + CompositeName cn = new CompositeName("/\\/META\\'-INF\\\"//'javax\\'.naming.Name'"); + + assertEquals(cn.size(), 4); + assertEquals(cn.get(0), ""); + assertEquals(cn.get(1), "/META'-INF\""); + assertEquals(cn.get(2), ""); + assertEquals(cn.get(3), "javax'.naming.Name"); + + SimpleName name = new SimpleName("/\\/META\\'-INF\\\"//'javax\\'.naming.Name'"); + + assertEquals(name.size(), 4); + assertEquals(name.get(0), ""); + assertEquals(name.get(1), "/META'-INF\""); + assertEquals(name.get(2), ""); + assertEquals(name.get(3), "javax'.naming.Name"); + } + + + private void testPrefix(Name name) { + + assertEquals(name.size(), 4); + + Name prefix1 = name.getPrefix(4); + assertEquals(prefix1.get(0), ""); + assertEquals(prefix1.get(1), "/META'-INF\""); + assertEquals(prefix1.get(2), ""); + assertEquals(prefix1.get(3), "javax'.naming.Name"); + + Name prefix2 = name.getPrefix(3); + assertEquals(prefix2.get(0), ""); + assertEquals(prefix2.get(1), "/META'-INF\""); + assertEquals(prefix2.get(2), ""); + + + Name prefix3 = name.getPrefix(2); + assertEquals(prefix3.get(0), ""); + assertEquals(prefix3.get(1), "/META'-INF\""); + + Name prefix4 = name.getPrefix(1); + assertEquals(prefix4.get(0), ""); + + Name prefix5 = name.getPrefix(0); + assertEquals(prefix5.size(), 0); + } + + @Test + public void testPrefix() throws Exception { + Name name = new CompositeName("/\\/META\\'-INF\\\"//'javax\\'.naming.Name'"); + testPrefix(name); + + name = new SimpleCompositeName("/\\/META\\'-INF\\\"//'javax\\'.naming.Name'"); + testPrefix(name); + } + + private void testSuffix(Name name) { + assertEquals(name.size(), 4); + + Name suffix1 = name.getSuffix(0); + assertEquals(suffix1.get(0), ""); + assertEquals(suffix1.get(1), "/META'-INF\""); + assertEquals(suffix1.get(2), ""); + assertEquals(suffix1.get(3), "javax'.naming.Name"); + + Name suffix2 = name.getSuffix(1); + assertEquals(suffix2.get(0), "/META'-INF\""); + assertEquals(suffix2.get(1), ""); + assertEquals(suffix2.get(2), "javax'.naming.Name"); + + + Name suffix3 = name.getSuffix(2); + assertEquals(suffix3.get(0), ""); + assertEquals(suffix3.get(1), "javax'.naming.Name"); + + Name suffix4 = name.getSuffix(3); + assertEquals(suffix4.get(0), "javax'.naming.Name"); + + Name suffix5 = name.getSuffix(4); + assertEquals(suffix5.size(), 0); + } + + @Test + public void testSuffix() throws Exception { + Name name = new CompositeName("/\\/META\\'-INF\\\"//'javax\\'.naming.Name'"); + testSuffix(name); + + name = new SimpleCompositeName("/\\/META\\'-INF\\\"//'javax\\'.naming.Name'"); + testSuffix(name); + } + + @Test + public void testException() throws Exception { + try { + new CompositeName("/\\/META\\'-INF\\\"//'javax\\'.naming.Name"); + fail("Invalid name parsing"); + } + catch(InvalidNameException ine) { + } + + try { + new SimpleCompositeName("/\\/META\\'-INF\\\"//'javax\\'.naming.Name"); + fail("Invalid name parsing"); + } + catch(InvalidNameException ine) { + } + } +} Property changes on: test\org\apache\naming\TestSimpleName.java ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: java/org/apache/naming/NameParserImpl.java =================================================================== --- java/org/apache/naming/NameParserImpl.java (revision 1613338) +++ java/org/apache/naming/NameParserImpl.java (working copy) @@ -18,7 +18,6 @@ package org.apache.naming; -import javax.naming.CompositeName; import javax.naming.Name; import javax.naming.NameParser; import javax.naming.NamingException; @@ -48,7 +47,7 @@ @Override public Name parse(String name) throws NamingException { - return new CompositeName(name); + return new SimpleCompositeName(name); } Index: java/org/apache/naming/NamingContext.java =================================================================== --- java/org/apache/naming/NamingContext.java (revision 1613338) +++ java/org/apache/naming/NamingContext.java (working copy) @@ -23,7 +23,6 @@ import java.util.Hashtable; import javax.naming.Binding; -import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.LinkRef; @@ -164,7 +163,7 @@ @Override public Object lookup(String name) throws NamingException { - return lookup(new CompositeName(name), true); + return lookup(new SimpleCompositeName(name), true); } @@ -200,7 +199,7 @@ @Override public void bind(String name, Object obj) throws NamingException { - bind(new CompositeName(name), obj); + bind(new SimpleCompositeName(name), obj); } @@ -238,7 +237,7 @@ @Override public void rebind(String name, Object obj) throws NamingException { - rebind(new CompositeName(name), obj); + rebind(new SimpleCompositeName(name), obj); } @@ -301,7 +300,7 @@ @Override public void unbind(String name) throws NamingException { - unbind(new CompositeName(name)); + unbind(new SimpleCompositeName(name)); } @@ -337,7 +336,7 @@ @Override public void rename(String oldName, String newName) throws NamingException { - rename(new CompositeName(oldName), new CompositeName(newName)); + rename(new SimpleCompositeName(oldName), new SimpleCompositeName(newName)); } @@ -391,7 +390,7 @@ @Override public NamingEnumeration list(String name) throws NamingException { - return list(new CompositeName(name)); + return list(new SimpleCompositeName(name)); } @@ -445,7 +444,7 @@ @Override public NamingEnumeration listBindings(String name) throws NamingException { - return listBindings(new CompositeName(name)); + return listBindings(new SimpleCompositeName(name)); } @@ -526,7 +525,7 @@ @Override public void destroySubcontext(String name) throws NamingException { - destroySubcontext(new CompositeName(name)); + destroySubcontext(new SimpleCompositeName(name)); } @@ -571,7 +570,7 @@ @Override public Context createSubcontext(String name) throws NamingException { - return createSubcontext(new CompositeName(name)); + return createSubcontext(new SimpleCompositeName(name)); } @@ -604,7 +603,7 @@ @Override public Object lookupLink(String name) throws NamingException { - return lookup(new CompositeName(name), false); + return lookup(new SimpleCompositeName(name), false); } @@ -657,7 +656,7 @@ @Override public NameParser getNameParser(String name) throws NamingException { - return getNameParser(new CompositeName(name)); + return getNameParser(new SimpleCompositeName(name)); } Index: java/org/apache/naming/NamingContextBindingsEnumeration.java =================================================================== --- java/org/apache/naming/NamingContextBindingsEnumeration.java (revision 1613338) +++ java/org/apache/naming/NamingContextBindingsEnumeration.java (working copy) @@ -21,7 +21,6 @@ import java.util.Iterator; import javax.naming.Binding; -import javax.naming.CompositeName; import javax.naming.Context; import javax.naming.NamingEnumeration; import javax.naming.NamingException; @@ -114,7 +113,7 @@ if (entry.type == NamingEntry.REFERENCE || entry.type == NamingEntry.LINK_REF) { try { - value = ctx.lookup(new CompositeName(entry.name)); + value = ctx.lookup(new SimpleCompositeName(entry.name)); } catch (NamingException e) { throw e; } catch (Exception e) {