Path: blob/jdk8u272-b10-aarch32-20201026/jdk/src/share/classes/com/sun/jndi/cosnaming/CNNameParser.java
83410 views
/*1* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package com.sun.jndi.cosnaming;2627import javax.naming.*;28import java.util.Properties;29import java.util.Vector;30import java.util.Enumeration;3132import org.omg.CosNaming.NameComponent;3334/**35* Parsing routines for NameParser as well as COS Naming stringified names.36* This is used by CNCtx to create a NameComponent[] object and vice versa.37* It follows Section 4.5 of Interoperable Naming Service (INS) 98-10-11.38* In summary, the stringified form is a left-to-right, forward-slash39* separated name. id and kinds are separated by '.'. backslash is the40* escape character.41*42* @author Rosanna Lee43*/4445final public class CNNameParser implements NameParser {4647private static final Properties mySyntax = new Properties();48private static final char kindSeparator = '.';49private static final char compSeparator = '/';50private static final char escapeChar = '\\';51static {52mySyntax.put("jndi.syntax.direction", "left_to_right");53mySyntax.put("jndi.syntax.separator", ""+compSeparator);54mySyntax.put("jndi.syntax.escape", ""+escapeChar);55};5657/**58* Constructs a new name parser for parsing names in INS syntax.59*/60public CNNameParser() {61}6263/**64* Returns a CompoundName given a string in INS syntax.65* @param name The non-null string representation of the name.66* @return a non-null CompoundName67*/68public Name parse(String name) throws NamingException {69Vector<String> comps = insStringToStringifiedComps(name);70return new CNCompoundName(comps.elements());71}7273/**74* Creates a NameComponent[] from a Name structure.75* Used by CNCtx to convert the input Name arg into a NameComponent[].76* @param a CompoundName or a CompositeName;77* each component must be the stringified form of a NameComponent.78*/79static NameComponent[] nameToCosName(Name name)80throws InvalidNameException {81int len = name.size();82if (len == 0) {83return new NameComponent[0];84}8586NameComponent[] answer = new NameComponent[len];87for (int i = 0; i < len; i++) {88answer[i] = parseComponent(name.get(i));89}90return answer;91}9293/**94* Returns the INS stringified form of a NameComponent[].95* Used by CNCtx.getNameInNamespace(), CNCompoundName.toString().96*/97static String cosNameToInsString(NameComponent[] cname) {98StringBuffer str = new StringBuffer();99for ( int i = 0; i < cname.length; i++) {100if ( i > 0) {101str.append(compSeparator);102}103str.append(stringifyComponent(cname[i]));104}105return str.toString();106}107108/**109* Creates a CompositeName from a NameComponent[].110* Used by ExceptionMapper and CNBindingEnumeration to convert111* a NameComponent[] into a composite name.112*/113static Name cosNameToName(NameComponent[] cname) {114Name nm = new CompositeName();115for ( int i = 0; cname != null && i < cname.length; i++) {116try {117nm.add(stringifyComponent(cname[i]));118} catch (InvalidNameException e) {119// ignore120}121}122return nm;123}124125/**126* Converts an INS-syntax string name into a Vector in which127* each element of the vector contains a stringified form of128* a NameComponent.129*/130private static Vector<String> insStringToStringifiedComps(String str)131throws InvalidNameException {132133int len = str.length();134Vector<String> components = new Vector<>(10);135char[] id = new char[len];136char[] kind = new char[len];137int idCount, kindCount;138boolean idMode;139for (int i = 0; i < len; ) {140idCount = kindCount = 0; // reset for new component141idMode = true; // always start off parsing id142while (i < len) {143if (str.charAt(i) == compSeparator) {144break;145146} else if (str.charAt(i) == escapeChar) {147if (i + 1 >= len) {148throw new InvalidNameException(str +149": unescaped \\ at end of component");150} else if (isMeta(str.charAt(i+1))) {151++i; // skip escape and let meta through152if (idMode) {153id[idCount++] = str.charAt(i++);154} else {155kind[kindCount++] = str.charAt(i++);156}157} else {158throw new InvalidNameException(str +159": invalid character being escaped");160}161162} else if (idMode && str.charAt(i) == kindSeparator) {163// just look for the first kindSeparator164++i; // skip kind separator165idMode = false;166167} else {168if (idMode) {169id[idCount++] = str.charAt(i++);170} else {171kind[kindCount++] = str.charAt(i++);172}173}174}175components.addElement(stringifyComponent(176new NameComponent(new String(id, 0, idCount),177new String(kind, 0, kindCount))));178179if (i < len) {180++i; // skip separator181}182}183184return components;185}186187/**188* Return a NameComponent given its stringified form.189*/190private static NameComponent parseComponent(String compStr)191throws InvalidNameException {192NameComponent comp = new NameComponent();193int kindSep = -1;194int len = compStr.length();195196int j = 0;197char[] newStr = new char[len];198boolean escaped = false;199200// Find the kind separator201for (int i = 0; i < len && kindSep < 0; i++) {202if (escaped) {203newStr[j++] = compStr.charAt(i);204escaped = false;205} else if (compStr.charAt(i) == escapeChar) {206if (i + 1 >= len) {207throw new InvalidNameException(compStr +208": unescaped \\ at end of component");209} else if (isMeta(compStr.charAt(i+1))) {210escaped = true;211} else {212throw new InvalidNameException(compStr +213": invalid character being escaped");214}215} else if (compStr.charAt(i) == kindSeparator) {216kindSep = i;217} else {218newStr[j++] = compStr.charAt(i);219}220}221222// Set id223comp.id = new String(newStr, 0, j);224225// Set kind226if (kindSep < 0) {227comp.kind = ""; // no kind separator228} else {229// unescape kind230j = 0;231escaped = false;232for (int i = kindSep+1; i < len; i++) {233if (escaped) {234newStr[j++] = compStr.charAt(i);235escaped = false;236} else if (compStr.charAt(i) == escapeChar) {237if (i + 1 >= len) {238throw new InvalidNameException(compStr +239": unescaped \\ at end of component");240} else if (isMeta(compStr.charAt(i+1))) {241escaped = true;242} else {243throw new InvalidNameException(compStr +244": invalid character being escaped");245}246} else {247newStr[j++] = compStr.charAt(i);248}249}250comp.kind = new String(newStr, 0, j);251}252return comp;253}254255private static String stringifyComponent(NameComponent comp) {256StringBuffer one = new StringBuffer(escape(comp.id));257if (comp.kind != null && !comp.kind.equals("")) {258one.append(kindSeparator + escape(comp.kind));259}260if (one.length() == 0) {261return ""+kindSeparator; // if neither id nor kind specified262} else {263return one.toString();264}265}266267/**268* Returns a string with '.', '\', '/' escaped. Used when269* stringifying the name into its INS stringified form.270*/271private static String escape(String str) {272if (str.indexOf(kindSeparator) < 0 &&273str.indexOf(compSeparator) < 0 &&274str.indexOf(escapeChar) < 0) {275return str; // no meta characters to escape276} else {277int len = str.length();278int j = 0;279char[] newStr = new char[len+len];280for (int i = 0; i < len; i++) {281if (isMeta(str.charAt(i))) {282newStr[j++] = escapeChar; // escape meta character283}284newStr[j++] = str.charAt(i);285}286return new String(newStr, 0, j);287}288}289290/**291* In INS, there are three meta characters: '.', '/' and '\'.292*/293private static boolean isMeta(char ch) {294switch (ch) {295case kindSeparator:296case compSeparator:297case escapeChar:298return true;299}300return false;301}302303/**304* An implementation of CompoundName that bypasses the parsing305* and stringifying code of the default CompoundName.306*/307static final class CNCompoundName extends CompoundName {308CNCompoundName(Enumeration<String> enum_) {309super(enum_, CNNameParser.mySyntax);310}311312public Object clone() {313return new CNCompoundName(getAll());314}315316public Name getPrefix(int posn) {317Enumeration<String> comps = super.getPrefix(posn).getAll();318return new CNCompoundName(comps);319}320321public Name getSuffix(int posn) {322Enumeration<String> comps = super.getSuffix(posn).getAll();323return new CNCompoundName(comps);324}325326public String toString() {327try {328// Convert Name to NameComponent[] then stringify329return cosNameToInsString(nameToCosName(this));330} catch (InvalidNameException e) {331return super.toString();332}333}334335private static final long serialVersionUID = -6599252802678482317L;336}337338// for testing only339/*340private static void print(String input) {341try {342System.out.println("\n >>>>>> input: " + input);343344System.out.println("--Compound Name: ");345NameParser parser = new CNNameParser();346Name name = parser.parse(input);347for (int i = 0; i < name.size(); i++) {348System.out.println("\t" + i + ": " + name.get(i));349NameComponent cp = parseComponent(name.get(i));350System.out.println("\t\t" + "id: " + cp.id + ";kind: " + cp.kind);351}352System.out.println("\t" + name.toString());353354System.out.println("--Composite Name: ");355Name composite = new CompositeName(input);356for (int i = 0; i < composite.size(); i++) {357System.out.println("\t" + i+": " + composite.get(i));358}359System.out.println("\t" + composite.toString());360361System.out.println("--Composite To NameComponent");362NameComponent[] names = nameToCosName(composite);363for (int i = 0; i < composite.size(); i++) {364System.out.println("\t" + i+": id: " + names[i].id + "; kind: " + names[i].kind);365}366System.out.println("\t" + cosNameToInsString(names));367} catch (NamingException e) {368System.out.println(e);369}370}371372private static void checkName(Name name, String[] comps) throws Exception {373if (name.size() != comps.length) {374throw new Exception(375"test failed; incorrect component count in " + name + "; " +376"expecting " + comps.length + " got " + name.size());377}378for (int i = 0; i < name.size(); i++) {379if (!comps[i].equals(name.get(i))) {380throw new Exception (381"test failed; invalid component in " + name + "; " +382"expecting '" + comps[i] + "' got '" + name.get(i) + "'");383}384}385}386387private static void checkCompound(NameParser parser,388String input, String[] comps) throws Exception {389checkName(parser.parse(input), comps);390}391392private static void checkComposite(String input, String[] comps)393throws Exception {394checkName(new CompositeName(input), comps);395}396397private static String[] compounds = {398"a/b/c",399"a.b/c.d",400"a",401".",402"a.",403"c.d",404".e",405"a/x\\/y\\/z/b",406"a\\.b.c\\.d/e.f",407"a/b\\\\/c",408"x\\\\.y",409"x\\.y",410"x.\\\\y",411"x.y\\\\",412"\\\\x.y",413"a.b\\.c/d"414};415private static String[][] compoundComps = {416{"a", "b", "c"},417{"a.b", "c.d"},418{"a"},419{"."},420{"a"},421{"c.d"},422{".e"},423{"a", "x\\/y\\/z", "b"},424{"a\\.b.c\\.d", "e.f"},425{"a", "b\\\\", "c"},426{"x\\\\.y"},427{"x\\.y"},428{"x.\\\\y"},429{"x.y\\\\"},430{"\\\\x.y"},431{"a.b\\.c", "d"},432};433434private static String[] composites = {435"a/b/c",436"a.b/c.d",437"a",438".",439"a.",440"c.d",441".e",442"a/x\\\\\\/y\\\\\\/z/b",443"a\\\\.b.c\\\\.d/e.f",444"a/b\\\\\\\\/c",445"x\\\\\\.y",446"x\\\\.y",447"x.\\\\\\\\y",448"x.y\\\\\\\\",449"\\\\\\\\x.y"450};451452private static String[][] compositeComps = {453{"a", "b", "c"},454{"a.b", "c.d"},455{"a"},456{"."},457{"a."}, // unlike compound, kind sep is not consumed458{"c.d"},459{".e"},460{"a", "x\\/y\\/z", "b"},461{"a\\.b.c\\.d", "e.f"},462{"a", "b\\\\", "c"},463{"x\\\\.y"},464{"x\\.y"},465{"x.\\\\y"},466{"x.y\\\\"},467{"\\\\x.y"}468};469470public static void main(String[] args) throws Exception {471if (args.length > 0) {472for (int i = 0; i < args.length; i++) {473print(args[0]);474}475} else {476print("x\\\\.y");477print("x\\.y");478print("x.\\\\y");479print("x.y\\\\");480print("\\\\x.y");481}482483NameParser parser = new com.sun.jndi.cosnaming.CNNameParser();484for (int i = 0; i < compounds.length; i++) {485checkCompound(parser, compounds[i], compoundComps[i]);486}487for (int i = 0; i < composites.length; i++) {488checkComposite(composites[i], compositeComps[i]);489}490491System.out.println("hardwire");492NameComponent[] foo = new NameComponent[1];493foo[0] = new NameComponent("foo\\", "bar");494495System.out.println(cosNameToInsString(foo));496System.out.println(cosNameToName(foo));497}498*/499}500501502