Path: blob/master/src/java.naming/share/classes/javax/naming/CompositeName.java
41152 views
/*1* Copyright (c) 1999, 2020, 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 javax.naming;2627import java.util.Enumeration;28import java.util.Properties;2930/**31* This class represents a composite name -- a sequence of32* component names spanning multiple namespaces.33* Each component is a string name from the namespace of a34* naming system. If the component comes from a hierarchical35* namespace, that component can be further parsed into36* its atomic parts by using the CompoundName class.37*<p>38* The components of a composite name are numbered. The indexes of a39* composite name with N components range from 0 up to, but not including, N.40* This range may be written as [0,N).41* The most significant component is at index 0.42* An empty composite name has no components.43*44* <h2>JNDI Composite Name Syntax</h2>45* JNDI defines a standard string representation for composite names. This46* representation is the concatenation of the components of a composite name47* from left to right using the component separator (a forward48* slash character (/)) to separate each component.49* The JNDI syntax defines the following meta characters:50* <ul>51* <li>escape (backward slash \),52* <li>quote characters (single (') and double quotes (")), and53* <li>component separator (forward slash character (/)).54* </ul>55* Any occurrence of a leading quote, an escape preceding any meta character,56* an escape at the end of a component, or a component separator character57* in an unquoted component must be preceded by an escape character when58* that component is being composed into a composite name string.59* Alternatively, to avoid adding escape characters as described,60* the entire component can be quoted using matching single quotes61* or matching double quotes. A single quote occurring within a double-quoted62* component is not considered a meta character (and need not be escaped),63* and vice versa.64*<p>65* When two composite names are compared, the case of the characters66* is significant.67*<p>68* A leading component separator (the composite name string begins with69* a separator) denotes a leading empty component (a component consisting70* of an empty string).71* A trailing component separator (the composite name string ends with72* a separator) denotes a trailing empty component.73* Adjacent component separators denote an empty component.74*75*<h2>Composite Name Examples</h2>76*This table shows examples of some composite names. Each row shows77*the string form of a composite name and its corresponding structural form78*({@code CompositeName}).79*80<table class="striped"><caption style="display:none">examples showing string81form of composite name and its corresponding structural form (CompositeName)</caption>82<thead>83<tr>84<th scope="col">String Name</th>85<th scope="col">CompositeName</th>86</tr>87</thead>88<tbody style="text-align:left">89<tr>90<th scope="row">91""92</th>93<td>{} (the empty name == new CompositeName("") == new CompositeName())94</td>95</tr>9697<tr>98<th scope="row">99"x"100</th>101<td>{"x"}102</td>103</tr>104105<tr>106<th scope="row">107"x/y"108</th>109<td>{"x", "y"}</td>110</tr>111112<tr>113<th scope="row">"x/"</th>114<td>{"x", ""}</td>115</tr>116117<tr>118<th scope="row">"/x"</th>119<td>{"", "x"}</td>120</tr>121122<tr>123<th scope="row">"/"</th>124<td>{""}</td>125</tr>126127<tr>128<th scope="row">"//"</th>129<td>{"", ""}</td>130</tr>131132<tr><th scope="row">"/x/"</th>133<td>{"", "x", ""}</td>134</tr>135136<tr><th scope="row">"x//y"</th>137<td>{"x", "", "y"}</td>138</tr>139</tbody>140</table>141*142*<h2>Composition Examples</h2>143* Here are some composition examples. The right column shows composing144* string composite names while the left column shows composing the145* corresponding {@code CompositeName}s. Notice that composing the146* string forms of two composite names simply involves concatenating147* their string forms together.148149<table class="striped"><caption style="display:none">composition examples150showing string names and composite names</caption>151<thead>152<tr>153<th scope="col">String Names</th>154<th scope="col">CompositeNames</th>155</tr>156</thead>157158<tbody style="text-align:left">159<tr>160<th scope="row">161"x/y" + "/" = x/y/162</th>163<td>164{"x", "y"} + {""} = {"x", "y", ""}165</td>166</tr>167168<tr>169<th scope="row">170"" + "x" = "x"171</th>172<td>173{} + {"x"} = {"x"}174</td>175</tr>176177<tr>178<th scope="row">179"/" + "x" = "/x"180</th>181<td>182{""} + {"x"} = {"", "x"}183</td>184</tr>185186<tr>187<th scope="row">188"x" + "" + "" = "x"189</th>190<td>191{"x"} + {} + {} = {"x"}192</td>193</tr>194</tbody>195</table>196*197*<h2>Multithreaded Access</h2>198* A {@code CompositeName} instance is not synchronized against concurrent199* multithreaded access. Multiple threads trying to access and modify a200* {@code CompositeName} should lock the object.201*202* @author Rosanna Lee203* @author Scott Seligman204* @since 1.3205*/206207208public class CompositeName implements Name {209210private transient NameImpl impl;211/**212* Constructs a new composite name instance using the components213* specified by 'comps'. This protected method is intended214* to be used by subclasses of CompositeName when they override215* methods such as clone(), getPrefix(), getSuffix().216*217* @param comps A non-null enumeration containing the components for the new218* composite name. Each element is of class String.219* The enumeration will be consumed to extract its220* elements.221*/222protected CompositeName(Enumeration<String> comps) {223impl = new NameImpl(null, comps); // null means use default syntax224}225226/**227* Constructs a new composite name instance by parsing the string n228* using the composite name syntax (left-to-right, slash separated).229* The composite name syntax is described in detail in the class230* description.231*232* @param n The non-null string to parse.233* @throws InvalidNameException If n has invalid composite name syntax.234*/235public CompositeName(String n) throws InvalidNameException {236impl = new NameImpl(null, n); // null means use default syntax237}238239/**240* Constructs a new empty composite name. Such a name returns true241* when <code>isEmpty()</code> is invoked on it.242*/243public CompositeName() {244impl = new NameImpl(null); // null means use default syntax245}246247/**248* Generates the string representation of this composite name.249* The string representation consists of enumerating in order250* each component of the composite name and separating251* each component by a forward slash character. Quoting and252* escape characters are applied where necessary according to253* the JNDI syntax, which is described in the class description.254* An empty component is represented by an empty string.255*256* The string representation thus generated can be passed to257* the CompositeName constructor to create a new equivalent258* composite name.259*260* @return A non-null string representation of this composite name.261*/262public String toString() {263return impl.toString();264}265266/**267* Determines whether two composite names are equal.268* If obj is null or not a composite name, false is returned.269* Two composite names are equal if each component in one is equal270* to the corresponding component in the other. This implies271* both have the same number of components, and each component's272* equals() test against the corresponding component in the other name273* returns true.274*275* @param obj The possibly null object to compare against.276* @return true if obj is equal to this composite name, false otherwise.277* @see #hashCode278*/279public boolean equals(Object obj) {280return (obj != null &&281obj instanceof CompositeName &&282impl.equals(((CompositeName)obj).impl));283}284285/**286* Computes the hash code of this composite name.287* The hash code is the sum of the hash codes of individual components288* of this composite name.289*290* @return An int representing the hash code of this name.291* @see #equals292*/293public int hashCode() {294return impl.hashCode();295}296297298/**299* Compares this CompositeName with the specified Object for order.300* Returns a301* negative integer, zero, or a positive integer as this Name is less302* than, equal to, or greater than the given Object.303* <p>304* If obj is null or not an instance of CompositeName, ClassCastException305* is thrown.306* <p>307* See equals() for what it means for two composite names to be equal.308* If two composite names are equal, 0 is returned.309* <p>310* Ordering of composite names follows the lexicographical rules for311* string comparison, with the extension that this applies to all312* the components in the composite name. The effect is as if all the313* components were lined up in their specified ordered and the314* lexicographical rules applied over the two line-ups.315* If this composite name is "lexicographically" lesser than obj,316* a negative number is returned.317* If this composite name is "lexicographically" greater than obj,318* a positive number is returned.319* @param obj The non-null object to compare against.320*321* @return a negative integer, zero, or a positive integer as this Name322* is less than, equal to, or greater than the given Object.323* @throws ClassCastException if obj is not a CompositeName.324*/325public int compareTo(Object obj) {326if (!(obj instanceof CompositeName)) {327throw new ClassCastException("Not a CompositeName");328}329return impl.compareTo(((CompositeName)obj).impl);330}331332/**333* Generates a copy of this composite name.334* Changes to the components of this composite name won't335* affect the new copy and vice versa.336*337* @return A non-null copy of this composite name.338*/339public Object clone() {340return (new CompositeName(getAll()));341}342343/**344* Retrieves the number of components in this composite name.345*346* @return The nonnegative number of components in this composite name.347*/348public int size() {349return (impl.size());350}351352/**353* Determines whether this composite name is empty. A composite name354* is empty if it has zero components.355*356* @return true if this composite name is empty, false otherwise.357*/358public boolean isEmpty() {359return (impl.isEmpty());360}361362/**363* Retrieves the components of this composite name as an enumeration364* of strings.365* The effects of updates to this composite name on this enumeration366* is undefined.367*368* @return A non-null enumeration of the components of369* this composite name. Each element of the enumeration is of370* class String.371*/372public Enumeration<String> getAll() {373return (impl.getAll());374}375376/**377* Retrieves a component of this composite name.378*379* @param posn The 0-based index of the component to retrieve.380* Must be in the range [0,size()).381* @return The non-null component at index posn.382* @throws ArrayIndexOutOfBoundsException if posn is outside the383* specified range.384*/385public String get(int posn) {386return (impl.get(posn));387}388389/**390* Creates a composite name whose components consist of a prefix of the391* components in this composite name. Subsequent changes to392* this composite name does not affect the name that is returned.393*394* @param posn The 0-based index of the component at which to stop.395* Must be in the range [0,size()].396* @return A composite name consisting of the components at indexes in397* the range [0,posn).398* @throws ArrayIndexOutOfBoundsException399* If posn is outside the specified range.400*/401public Name getPrefix(int posn) {402Enumeration<String> comps = impl.getPrefix(posn);403return (new CompositeName(comps));404}405406/**407* Creates a composite name whose components consist of a suffix of the408* components in this composite name. Subsequent changes to409* this composite name does not affect the name that is returned.410*411* @param posn The 0-based index of the component at which to start.412* Must be in the range [0,size()].413* @return A composite name consisting of the components at indexes in414* the range [posn,size()). If posn is equal to415* size(), an empty composite name is returned.416* @throws ArrayIndexOutOfBoundsException417* If posn is outside the specified range.418*/419public Name getSuffix(int posn) {420Enumeration<String> comps = impl.getSuffix(posn);421return (new CompositeName(comps));422}423424/**425* Determines whether a composite name is a prefix of this composite name.426* A composite name 'n' is a prefix if it is equal to427* getPrefix(n.size())--in other words, this composite name428* starts with 'n'. If 'n' is null or not a composite name, false is returned.429*430* @param n The possibly null name to check.431* @return true if n is a CompositeName and432* is a prefix of this composite name, false otherwise.433*/434public boolean startsWith(Name n) {435if (n instanceof CompositeName) {436return (impl.startsWith(n.size(), n.getAll()));437} else {438return false;439}440}441442/**443* Determines whether a composite name is a suffix of this composite name.444* A composite name 'n' is a suffix if it is equal to445* getSuffix(size()-n.size())--in other words, this446* composite name ends with 'n'.447* If n is null or not a composite name, false is returned.448*449* @param n The possibly null name to check.450* @return true if n is a CompositeName and451* is a suffix of this composite name, false otherwise.452*/453public boolean endsWith(Name n) {454if (n instanceof CompositeName) {455return (impl.endsWith(n.size(), n.getAll()));456} else {457return false;458}459}460461/**462* Adds the components of a composite name -- in order -- to the end of463* this composite name.464*465* @param suffix The non-null components to add.466* @return The updated CompositeName, not a new one. Cannot be null.467* @throws InvalidNameException If suffix is not a composite name.468*/469public Name addAll(Name suffix)470throws InvalidNameException471{472if (suffix instanceof CompositeName) {473impl.addAll(suffix.getAll());474return this;475} else {476throw new InvalidNameException("Not a composite name: " +477suffix.toString());478}479}480481/**482* Adds the components of a composite name -- in order -- at a specified483* position within this composite name.484* Components of this composite name at or after the index of the first485* new component are shifted up (away from index 0)486* to accommodate the new components.487*488* @param n The non-null components to add.489* @param posn The index in this name at which to add the new490* components. Must be in the range [0,size()].491* @return The updated CompositeName, not a new one. Cannot be null.492* @throws InvalidNameException If n is not a composite name.493* @throws ArrayIndexOutOfBoundsException494* If posn is outside the specified range.495*/496public Name addAll(int posn, Name n)497throws InvalidNameException498{499if (n instanceof CompositeName) {500impl.addAll(posn, n.getAll());501return this;502} else {503throw new InvalidNameException("Not a composite name: " +504n.toString());505}506}507508/**509* Adds a single component to the end of this composite name.510*511* @param comp The non-null component to add.512* @return The updated CompositeName, not a new one. Cannot be null.513* @throws InvalidNameException If adding comp at end of the name514* would violate the name's syntax.515*/516public Name add(String comp) throws InvalidNameException {517impl.add(comp);518return this;519}520521/**522* Adds a single component at a specified position within this523* composite name.524* Components of this composite name at or after the index of the new525* component are shifted up by one (away from index 0) to accommodate526* the new component.527*528* @param comp The non-null component to add.529* @param posn The index at which to add the new component.530* Must be in the range [0,size()].531* @return The updated CompositeName, not a new one. Cannot be null.532* @throws ArrayIndexOutOfBoundsException533* If posn is outside the specified range.534* @throws InvalidNameException If adding comp at the specified position535* would violate the name's syntax.536*/537public Name add(int posn, String comp)538throws InvalidNameException539{540impl.add(posn, comp);541return this;542}543544/**545* Deletes a component from this composite name.546* The component of this composite name at position 'posn' is removed,547* and components at indices greater than 'posn'548* are shifted down (towards index 0) by one.549*550* @param posn The index of the component to delete.551* Must be in the range [0,size()).552* @return The component removed (a String).553* @throws ArrayIndexOutOfBoundsException554* If posn is outside the specified range (includes case where555* composite name is empty).556* @throws InvalidNameException If deleting the component557* would violate the name's syntax.558*/559public Object remove(int posn) throws InvalidNameException{560return impl.remove(posn);561}562563/**564* The writeObject method is called to save the state of the565* {@code CompositeName} to a stream.566*567* @serialData The number of components (an {@code int}) followed by568* the individual components (each a {@code String}).569*570* @param s the {@code ObjectOutputStream} to write to571* @throws java.io.IOException if an I/O error occurs572*/573@java.io.Serial574private void writeObject(java.io.ObjectOutputStream s)575throws java.io.IOException {576// Overridden to avoid implementation dependency577s.writeInt(size());578Enumeration<String> comps = getAll();579while (comps.hasMoreElements()) {580s.writeObject(comps.nextElement());581}582}583584/**585* The readObject method is called to restore the state of586* the {@code CompositeName} from a stream.587*588* See {@code writeObject} for a description of the serial form.589*590* @param s the {@code ObjectInputStream} to read from591* @throws java.io.IOException if an I/O error occurs592* @throws ClassNotFoundException if the class of a serialized object593* could not be found594*/595@java.io.Serial596private void readObject(java.io.ObjectInputStream s)597throws java.io.IOException, ClassNotFoundException {598// Overridden to avoid implementation dependency599impl = new NameImpl(null); // null means use default syntax600int n = s.readInt(); // number of components601try {602while (--n >= 0) {603add((String)s.readObject());604}605} catch (InvalidNameException e) {606throw (new java.io.StreamCorruptedException("Invalid name"));607}608}609610/**611* Use serialVersionUID from JNDI 1.1.1 for interoperability612*/613@java.io.Serial614private static final long serialVersionUID = 1667768148915813118L;615616/*617// %%% Test code for serialization.618public static void main(String[] args) throws Exception {619CompositeName c = new CompositeName("aaa/bbb");620java.io.FileOutputStream f1 = new java.io.FileOutputStream("/tmp/ser");621java.io.ObjectOutputStream s1 = new java.io.ObjectOutputStream(f1);622s1.writeObject(c);623s1.close();624java.io.FileInputStream f2 = new java.io.FileInputStream("/tmp/ser");625java.io.ObjectInputStream s2 = new java.io.ObjectInputStream(f2);626c = (CompositeName)s2.readObject();627628System.out.println("Size: " + c.size());629System.out.println("Size: " + c.snit);630}631*/632633/*634%%% Testing code635public static void main(String[] args) {636try {637for (int i = 0; i < args.length; i++) {638Name name;639Enumeration e;640System.out.println("Given name: " + args[i]);641name = new CompositeName(args[i]);642e = name.getComponents();643while (e.hasMoreElements()) {644System.out.println("Element: " + e.nextElement());645}646System.out.println("Constructed name: " + name.toString());647}648} catch (Exception ne) {649ne.printStackTrace();650}651}652*/653}654655656