0N/A/*
2362N/A * Copyright (c) 1999, 2003, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage com.sun.jndi.cosnaming;
0N/A
0N/Aimport javax.naming.*;
0N/Aimport java.util.Properties;
0N/Aimport java.util.Vector;
0N/Aimport java.util.Enumeration;
0N/A
0N/Aimport org.omg.CosNaming.NameComponent;
0N/A
0N/A/**
0N/A * Parsing routines for NameParser as well as COS Naming stringified names.
0N/A * This is used by CNCtx to create a NameComponent[] object and vice versa.
0N/A * It follows Section 4.5 of Interoperable Naming Service (INS) 98-10-11.
0N/A * In summary, the stringified form is a left-to-right, forward-slash
0N/A * separated name. id and kinds are separated by '.'. backslash is the
0N/A * escape character.
0N/A *
0N/A * @author Rosanna Lee
0N/A */
0N/A
0N/Afinal public class CNNameParser implements NameParser {
0N/A
0N/A private static final Properties mySyntax = new Properties();
0N/A private static final char kindSeparator = '.';
0N/A private static final char compSeparator = '/';
0N/A private static final char escapeChar = '\\';
0N/A static {
0N/A mySyntax.put("jndi.syntax.direction", "left_to_right");
0N/A mySyntax.put("jndi.syntax.separator", ""+compSeparator);
0N/A mySyntax.put("jndi.syntax.escape", ""+escapeChar);
0N/A };
0N/A
0N/A /**
0N/A * Constructs a new name parser for parsing names in INS syntax.
0N/A */
0N/A public CNNameParser() {
0N/A }
0N/A
0N/A /**
0N/A * Returns a CompoundName given a string in INS syntax.
0N/A * @param name The non-null string representation of the name.
0N/A * @return a non-null CompoundName
0N/A */
0N/A public Name parse(String name) throws NamingException {
0N/A Vector comps = insStringToStringifiedComps(name);
0N/A return new CNCompoundName(comps.elements());
0N/A }
0N/A
0N/A /**
0N/A * Creates a NameComponent[] from a Name structure.
0N/A * Used by CNCtx to convert the input Name arg into a NameComponent[].
0N/A * @param a CompoundName or a CompositeName;
0N/A * each component must be the stringified form of a NameComponent.
0N/A */
0N/A static NameComponent[] nameToCosName(Name name)
0N/A throws InvalidNameException {
0N/A int len = name.size();
0N/A if (len == 0) {
0N/A return new NameComponent[0];
0N/A }
0N/A
0N/A NameComponent[] answer = new NameComponent[len];
0N/A for (int i = 0; i < len; i++) {
0N/A answer[i] = parseComponent(name.get(i));
0N/A }
0N/A return answer;
0N/A }
0N/A
0N/A /**
0N/A * Returns the INS stringified form of a NameComponent[].
0N/A * Used by CNCtx.getNameInNamespace(), CNCompoundName.toString().
0N/A */
0N/A static String cosNameToInsString(NameComponent[] cname) {
0N/A StringBuffer str = new StringBuffer();
0N/A for ( int i = 0; i < cname.length; i++) {
0N/A if ( i > 0) {
0N/A str.append(compSeparator);
0N/A }
0N/A str.append(stringifyComponent(cname[i]));
0N/A }
0N/A return str.toString();
0N/A }
0N/A
0N/A /**
0N/A * Creates a CompositeName from a NameComponent[].
0N/A * Used by ExceptionMapper and CNBindingEnumeration to convert
0N/A * a NameComponent[] into a composite name.
0N/A */
0N/A static Name cosNameToName(NameComponent[] cname) {
0N/A Name nm = new CompositeName();
0N/A for ( int i = 0; cname != null && i < cname.length; i++) {
0N/A try {
0N/A nm.add(stringifyComponent(cname[i]));
0N/A } catch (InvalidNameException e) {
0N/A // ignore
0N/A }
0N/A }
0N/A return nm;
0N/A }
0N/A
0N/A /**
0N/A * Converts an INS-syntax string name into a Vector in which
0N/A * each element of the vector contains a stringified form of
0N/A * a NameComponent.
0N/A */
0N/A private static Vector insStringToStringifiedComps(String str)
0N/A throws InvalidNameException {
0N/A
0N/A int len = str.length();
0N/A Vector components = new Vector(10);
0N/A char[] id = new char[len];
0N/A char[] kind = new char[len];
0N/A int idCount, kindCount;
0N/A boolean idMode;
0N/A for (int i = 0; i < len; ) {
0N/A idCount = kindCount = 0; // reset for new component
0N/A idMode = true; // always start off parsing id
0N/A while (i < len) {
0N/A if (str.charAt(i) == compSeparator) {
0N/A break;
0N/A
0N/A } else if (str.charAt(i) == escapeChar) {
0N/A if (i + 1 >= len) {
0N/A throw new InvalidNameException(str +
0N/A ": unescaped \\ at end of component");
0N/A } else if (isMeta(str.charAt(i+1))) {
0N/A ++i; // skip escape and let meta through
0N/A if (idMode) {
0N/A id[idCount++] = str.charAt(i++);
0N/A } else {
0N/A kind[kindCount++] = str.charAt(i++);
0N/A }
0N/A } else {
0N/A throw new InvalidNameException(str +
0N/A ": invalid character being escaped");
0N/A }
0N/A
0N/A } else if (idMode && str.charAt(i) == kindSeparator) {
0N/A // just look for the first kindSeparator
0N/A ++i; // skip kind separator
0N/A idMode = false;
0N/A
0N/A } else {
0N/A if (idMode) {
0N/A id[idCount++] = str.charAt(i++);
0N/A } else {
0N/A kind[kindCount++] = str.charAt(i++);
0N/A }
0N/A }
0N/A }
0N/A components.addElement(stringifyComponent(
0N/A new NameComponent(new String(id, 0, idCount),
0N/A new String(kind, 0, kindCount))));
0N/A
0N/A if (i < len) {
0N/A ++i; // skip separator
0N/A }
0N/A }
0N/A
0N/A return components;
0N/A }
0N/A
0N/A /**
0N/A * Return a NameComponent given its stringified form.
0N/A */
0N/A private static NameComponent parseComponent(String compStr)
0N/A throws InvalidNameException {
0N/A NameComponent comp = new NameComponent();
0N/A int kindSep = -1;
0N/A int len = compStr.length();
0N/A
0N/A int j = 0;
0N/A char[] newStr = new char[len];
0N/A boolean escaped = false;
0N/A
0N/A // Find the kind separator
0N/A for (int i = 0; i < len && kindSep < 0; i++) {
0N/A if (escaped) {
0N/A newStr[j++] = compStr.charAt(i);
0N/A escaped = false;
0N/A } else if (compStr.charAt(i) == escapeChar) {
0N/A if (i + 1 >= len) {
0N/A throw new InvalidNameException(compStr +
0N/A ": unescaped \\ at end of component");
0N/A } else if (isMeta(compStr.charAt(i+1))) {
0N/A escaped = true;
0N/A } else {
0N/A throw new InvalidNameException(compStr +
0N/A ": invalid character being escaped");
0N/A }
0N/A } else if (compStr.charAt(i) == kindSeparator) {
0N/A kindSep = i;
0N/A } else {
0N/A newStr[j++] = compStr.charAt(i);
0N/A }
0N/A }
0N/A
0N/A // Set id
0N/A comp.id = new String(newStr, 0, j);
0N/A
0N/A // Set kind
0N/A if (kindSep < 0) {
0N/A comp.kind = ""; // no kind separator
0N/A } else {
0N/A // unescape kind
0N/A j = 0;
0N/A escaped = false;
0N/A for (int i = kindSep+1; i < len; i++) {
0N/A if (escaped) {
0N/A newStr[j++] = compStr.charAt(i);
0N/A escaped = false;
0N/A } else if (compStr.charAt(i) == escapeChar) {
0N/A if (i + 1 >= len) {
0N/A throw new InvalidNameException(compStr +
0N/A ": unescaped \\ at end of component");
0N/A } else if (isMeta(compStr.charAt(i+1))) {
0N/A escaped = true;
0N/A } else {
0N/A throw new InvalidNameException(compStr +
0N/A ": invalid character being escaped");
0N/A }
0N/A } else {
0N/A newStr[j++] = compStr.charAt(i);
0N/A }
0N/A }
0N/A comp.kind = new String(newStr, 0, j);
0N/A }
0N/A return comp;
0N/A }
0N/A
0N/A private static String stringifyComponent(NameComponent comp) {
0N/A StringBuffer one = new StringBuffer(escape(comp.id));
0N/A if (comp.kind != null && !comp.kind.equals("")) {
0N/A one.append(kindSeparator + escape(comp.kind));
0N/A }
0N/A if (one.length() == 0) {
0N/A return ""+kindSeparator; // if neither id nor kind specified
0N/A } else {
0N/A return one.toString();
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Returns a string with '.', '\', '/' escaped. Used when
0N/A * stringifying the name into its INS stringified form.
0N/A */
0N/A private static String escape(String str) {
0N/A if (str.indexOf(kindSeparator) < 0 &&
0N/A str.indexOf(compSeparator) < 0 &&
0N/A str.indexOf(escapeChar) < 0) {
0N/A return str; // no meta characters to escape
0N/A } else {
0N/A int len = str.length();
0N/A int j = 0;
0N/A char[] newStr = new char[len+len];
0N/A for (int i = 0; i < len; i++) {
0N/A if (isMeta(str.charAt(i))) {
0N/A newStr[j++] = escapeChar; // escape meta character
0N/A }
0N/A newStr[j++] = str.charAt(i);
0N/A }
0N/A return new String(newStr, 0, j);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * In INS, there are three meta characters: '.', '/' and '\'.
0N/A */
0N/A private static boolean isMeta(char ch) {
0N/A switch (ch) {
0N/A case kindSeparator:
0N/A case compSeparator:
0N/A case escapeChar:
0N/A return true;
0N/A }
0N/A return false;
0N/A }
0N/A
0N/A /**
0N/A * An implementation of CompoundName that bypasses the parsing
0N/A * and stringifying code of the default CompoundName.
0N/A */
0N/A static final class CNCompoundName extends CompoundName {
0N/A CNCompoundName(Enumeration enum_) {
0N/A super(enum_, CNNameParser.mySyntax);
0N/A }
0N/A
0N/A public Object clone() {
0N/A return new CNCompoundName(getAll());
0N/A }
0N/A
0N/A public Name getPrefix(int posn) {
0N/A Enumeration comps = super.getPrefix(posn).getAll();
0N/A return new CNCompoundName(comps);
0N/A }
0N/A
0N/A public Name getSuffix(int posn) {
0N/A Enumeration comps = super.getSuffix(posn).getAll();
0N/A return new CNCompoundName(comps);
0N/A }
0N/A
0N/A public String toString() {
0N/A try {
0N/A // Convert Name to NameComponent[] then stringify
0N/A return cosNameToInsString(nameToCosName(this));
0N/A } catch (InvalidNameException e) {
0N/A return super.toString();
0N/A }
0N/A }
0N/A
0N/A private static final long serialVersionUID = -6599252802678482317L;
0N/A }
0N/A
0N/A// for testing only
0N/A/*
0N/A private static void print(String input) {
0N/A try {
0N/A System.out.println("\n >>>>>> input: " + input);
0N/A
0N/A System.out.println("--Compound Name: ");
0N/A NameParser parser = new CNNameParser();
0N/A Name name = parser.parse(input);
0N/A for (int i = 0; i < name.size(); i++) {
0N/A System.out.println("\t" + i + ": " + name.get(i));
0N/A NameComponent cp = parseComponent(name.get(i));
0N/A System.out.println("\t\t" + "id: " + cp.id + ";kind: " + cp.kind);
0N/A }
0N/A System.out.println("\t" + name.toString());
0N/A
0N/A System.out.println("--Composite Name: ");
0N/A Name composite = new CompositeName(input);
0N/A for (int i = 0; i < composite.size(); i++) {
0N/A System.out.println("\t" + i+": " + composite.get(i));
0N/A }
0N/A System.out.println("\t" + composite.toString());
0N/A
0N/A System.out.println("--Composite To NameComponent");
0N/A NameComponent[] names = nameToCosName(composite);
0N/A for (int i = 0; i < composite.size(); i++) {
0N/A System.out.println("\t" + i+": id: " + names[i].id + "; kind: " + names[i].kind);
0N/A }
0N/A System.out.println("\t" + cosNameToInsString(names));
0N/A } catch (NamingException e) {
0N/A System.out.println(e);
0N/A }
0N/A }
0N/A
0N/A private static void checkName(Name name, String[] comps) throws Exception {
0N/A if (name.size() != comps.length) {
0N/A throw new Exception(
0N/A "test failed; incorrect component count in " + name + "; " +
0N/A "expecting " + comps.length + " got " + name.size());
0N/A }
0N/A for (int i = 0; i < name.size(); i++) {
0N/A if (!comps[i].equals(name.get(i))) {
0N/A throw new Exception (
0N/A "test failed; invalid component in " + name + "; " +
0N/A "expecting '" + comps[i] + "' got '" + name.get(i) + "'");
0N/A }
0N/A }
0N/A }
0N/A
0N/A private static void checkCompound(NameParser parser,
0N/A String input, String[] comps) throws Exception {
0N/A checkName(parser.parse(input), comps);
0N/A }
0N/A
0N/A private static void checkComposite(String input, String[] comps)
0N/A throws Exception {
0N/A checkName(new CompositeName(input), comps);
0N/A }
0N/A
0N/A private static String[] compounds = {
0N/A "a/b/c",
0N/A "a.b/c.d",
0N/A "a",
0N/A ".",
0N/A "a.",
0N/A "c.d",
0N/A ".e",
0N/A "a/x\\/y\\/z/b",
0N/A "a\\.b.c\\.d/e.f",
0N/A "a/b\\\\/c",
0N/A "x\\\\.y",
0N/A "x\\.y",
0N/A "x.\\\\y",
0N/A "x.y\\\\",
0N/A "\\\\x.y",
0N/A "a.b\\.c/d"
0N/A };
0N/A private static String[][] compoundComps = {
0N/A {"a", "b", "c"},
0N/A {"a.b", "c.d"},
0N/A {"a"},
0N/A {"."},
0N/A {"a"},
0N/A {"c.d"},
0N/A {".e"},
0N/A {"a", "x\\/y\\/z", "b"},
0N/A {"a\\.b.c\\.d", "e.f"},
0N/A {"a", "b\\\\", "c"},
0N/A {"x\\\\.y"},
0N/A {"x\\.y"},
0N/A {"x.\\\\y"},
0N/A {"x.y\\\\"},
0N/A {"\\\\x.y"},
0N/A {"a.b\\.c", "d"},
0N/A };
0N/A
0N/A private static String[] composites = {
0N/A "a/b/c",
0N/A "a.b/c.d",
0N/A "a",
0N/A ".",
0N/A "a.",
0N/A "c.d",
0N/A ".e",
0N/A "a/x\\\\\\/y\\\\\\/z/b",
0N/A "a\\\\.b.c\\\\.d/e.f",
0N/A "a/b\\\\\\\\/c",
0N/A "x\\\\\\.y",
0N/A "x\\\\.y",
0N/A "x.\\\\\\\\y",
0N/A "x.y\\\\\\\\",
0N/A "\\\\\\\\x.y"
0N/A };
0N/A
0N/A private static String[][] compositeComps = {
0N/A {"a", "b", "c"},
0N/A {"a.b", "c.d"},
0N/A {"a"},
0N/A {"."},
0N/A {"a."}, // unlike compound, kind sep is not consumed
0N/A {"c.d"},
0N/A {".e"},
0N/A {"a", "x\\/y\\/z", "b"},
0N/A {"a\\.b.c\\.d", "e.f"},
0N/A {"a", "b\\\\", "c"},
0N/A {"x\\\\.y"},
0N/A {"x\\.y"},
0N/A {"x.\\\\y"},
0N/A {"x.y\\\\"},
0N/A {"\\\\x.y"}
0N/A };
0N/A
0N/A public static void main(String[] args) throws Exception {
0N/A if (args.length > 0) {
0N/A for (int i = 0; i < args.length; i++) {
0N/A print(args[0]);
0N/A }
0N/A } else {
0N/A print("x\\\\.y");
0N/A print("x\\.y");
0N/A print("x.\\\\y");
0N/A print("x.y\\\\");
0N/A print("\\\\x.y");
0N/A }
0N/A
0N/A NameParser parser = new com.sun.jndi.cosnaming.CNNameParser();
0N/A for (int i = 0; i < compounds.length; i++) {
0N/A checkCompound(parser, compounds[i], compoundComps[i]);
0N/A }
0N/A for (int i = 0; i < composites.length; i++) {
0N/A checkComposite(composites[i], compositeComps[i]);
0N/A }
0N/A
0N/A System.out.println("hardwire");
0N/A NameComponent[] foo = new NameComponent[1];
0N/A foo[0] = new NameComponent("foo\\", "bar");
0N/A
0N/A System.out.println(cosNameToInsString(foo));
0N/A System.out.println(cosNameToName(foo));
0N/A }
0N/A*/
0N/A}