1 /* NameTransformer.java -- 2 Copyright (C) 2005 Free Software Foundation, Inc. 3 4 This file is part of GNU Classpath. 5 6 GNU Classpath is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2, or (at your option) 9 any later version. 10 11 GNU Classpath is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with GNU Classpath; see the file COPYING. If not, write to the 18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 02110-1301 USA. 20 21 Linking this library statically or dynamically with other modules is 22 making a combined work based on this library. Thus, the terms and 23 conditions of the GNU General Public License cover the whole 24 combination. 25 26 As a special exception, the copyright holders of this library give you 27 permission to link this library with independent modules to produce an 28 executable, regardless of the license terms of these independent 29 modules, and to copy and distribute the resulting executable under 30 terms of your choice, provided that you also meet, for each linked 31 independent module, the terms and conditions of the license of that 32 module. An independent module is a module which is not derived from 33 or based on this library. If you modify this library, you may extend 34 this exception to your version of the library, but you are not 35 obligated to do so. If you do not wish to do so, delete this 36 exception statement from your version. */ 37 38 39 package gnu.CORBA.NamingService; 40 41 import org.omg.CORBA.IntHolder; 42 import org.omg.CosNaming.NameComponent; 43 import org.omg.CosNaming.NamingContextPackage.InvalidName; 44 45 import java.util.ArrayList; 46 import java.util.StringTokenizer; 47 48 /** 49 * This class converts between string and array representations of the 50 * multi component object names. 51 * 52 * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) 53 */ 54 public class NameTransformer 55 { 56 /** 57 * A string, indicating the escape character. 58 */ 59 public static final String ESCAPE = "\\"; 60 61 /** 62 * Convert the string name representation into the array name 63 * representation. See {@link #toString(NameComponent)} for the 64 * description of this format. 65 * 66 * @param name the string form of the name. 67 * 68 * @return the array form of the name. 69 * 70 * @throws InvalidName if the name cannot be parsed. 71 */ toName(String a_name)72 public NameComponent[] toName(String a_name) 73 throws InvalidName 74 { 75 ArrayList components = new ArrayList(); 76 StringTokenizer st = new StringTokenizer(a_name, "./\\", true); 77 78 String id; 79 String kind; 80 String next; 81 82 // Create the buffer array, reserving the last element for null. 83 String[] n = new String[ st.countTokens() + 1 ]; 84 85 int pp = 0; 86 while (st.hasMoreTokens()) 87 n [ pp++ ] = st.nextToken(); 88 89 IntHolder p = new IntHolder(); 90 91 NameComponent node = readNode(p, n); 92 93 while (node != null) 94 { 95 components.add(node); 96 node = readNode(p, n); 97 } 98 99 NameComponent[] name = new NameComponent[ components.size() ]; 100 for (int i = 0; i < name.length; i++) 101 { 102 name [ i ] = (NameComponent) components.get(i); 103 } 104 105 NameValidator.check(name); 106 107 return name; 108 } 109 110 /** 111 * Converts the name into its string representation, as defined in 112 * the specification CORBA naming service. 113 * 114 * A string representation for the name consists of the name components, 115 * separated by a slash '/' character (for example, 'a/b/c'). If the 116 * {@link NameComponent#kind} field is not empty, it is given after 117 * period ('.'), for example 'a.b/c.d/.' . 118 * The period alone represents node where part where both 119 * {@link NameComponent#kind} and {@link NameComponent#id} are empty strings. 120 * 121 * If slash or dot are part of the name, they are escaped by backslash ('\'). 122 * If the backslash itself is part of the name, it is doubled. 123 * 124 * @param a_name a name to convert. 125 * @return a string representation. 126 */ toString(NameComponent[] a_name)127 public String toString(NameComponent[] a_name) 128 throws InvalidName 129 { 130 NameValidator.check(a_name); 131 132 StringBuffer b = new StringBuffer(); 133 134 NameComponent n; 135 136 for (int ni = 0; ni < a_name.length; ni++) 137 { 138 n = a_name [ ni ]; 139 appEscaping(b, n.id); 140 if (n.kind.length() > 0) 141 { 142 b.append('.'); 143 appEscaping(b, n.kind); 144 } 145 146 if (ni < a_name.length - 1) 147 b.append('/'); 148 } 149 return b.toString(); 150 } 151 152 /** 153 * Append the contents of the string to this 154 * string buffer, inserting the escape sequences, where required. 155 * 156 * @param b a buffer to append the contents to. 157 * @param s a string to append. 158 */ appEscaping(StringBuffer b, String s)159 private void appEscaping(StringBuffer b, String s) 160 { 161 char c; 162 for (int i = 0; i < s.length(); i++) 163 { 164 c = s.charAt(i); 165 switch (c) 166 { 167 case '.' : 168 case '/' : 169 case '\\' : 170 b.append('\\'); 171 b.append(c); 172 break; 173 174 default : 175 b.append(c); 176 break; 177 } 178 } 179 } 180 181 /** 182 * Assert the end of the current name component. 183 */ assertEndOfNode(IntHolder p, String[] t)184 private void assertEndOfNode(IntHolder p, String[] t) 185 throws InvalidName 186 { 187 if (t [ p.value ] != null) 188 if (!t [ p.value ].equals("/")) 189 throw new InvalidName("End of node expected at token " + p.value); 190 } 191 192 /** 193 * Read the named component node. After reading the current positon 194 * advances to the beginning of the next node in an array. 195 * 196 * @param p the current position being wrapped inside the passed 197 * IntHolder. 198 * 199 * @param t the text buffer. 200 * 201 * @return the created node. 202 */ readNode(IntHolder p, String[] t)203 private NameComponent readNode(IntHolder p, String[] t) 204 throws InvalidName 205 { 206 // End of stream has been reached. 207 if (t [ p.value ] == null) 208 return null; 209 210 NameComponent n = new NameComponent(); 211 212 if (t [ p.value ].equals(".")) 213 { 214 // The 'id' is missing, but the 'kind' may follow. 215 n.id = ""; 216 p.value++; 217 n.kind = readPart(p, t); 218 assertEndOfNode(p, t); 219 if (t [ p.value ] != null) 220 p.value++; 221 } 222 else if (t [ p.value ].equals("/")) 223 { 224 // This is not allowed here and may happen only 225 // on two subsequent slashes. 226 throw new InvalidName("Unexpected '/' token " + p.value); 227 } 228 else 229 { 230 n.id = readPart(p, t); 231 232 // If some chars follow the id. 233 if (t [ p.value ] != null) 234 { 235 // Dot means that the kind part follows 236 if (t [ p.value ].equals(".")) 237 { 238 p.value++; 239 n.kind = readPart(p, t); 240 assertEndOfNode(p, t); 241 if (t [ p.value ] != null) 242 p.value++; 243 } 244 245 // The next name component follows - advance to 246 // the beginning of the next name component. 247 else if (t [ p.value ].equals("/")) 248 { 249 n.kind = ""; 250 p.value++; 251 } 252 else 253 throw new InvalidName("Unexpected '" + t [ p.value ] + 254 "' at token " + p.value 255 ); 256 } 257 else 258 259 // Id, and then end of sequence. 260 n.kind = ""; 261 } 262 263 return n; 264 } 265 266 /** 267 * Read the name part (id or kind). 268 * 269 * @param p the current position. After reading, advances 270 * to the beginning of the next name fragment. 271 * 272 * @param t the string buffer. 273 * 274 * @return the name part with resolved escape sequences. 275 */ readPart(IntHolder p, String[] t)276 private String readPart(IntHolder p, String[] t) 277 { 278 StringBuffer part = new StringBuffer(); 279 280 while (t [ p.value ] != null && !t [ p.value ].equals(".") && 281 !t [ p.value ].equals("/") 282 ) 283 { 284 if (t [ p.value ].equals(ESCAPE)) 285 { 286 p.value++; 287 part.append(t [ p.value ]); 288 } 289 else 290 part.append(t [ p.value ]); 291 292 p.value++; 293 } 294 295 return part.toString(); 296 } 297 main(String[] args)298 public static void main(String[] args) 299 { 300 NameComponent a = new NameComponent("a", "ak"); 301 NameComponent b = new NameComponent("b/z", "b.k"); 302 NameComponent c = new NameComponent("c", ""); 303 304 NameTransformer sn = new NameTransformer(); 305 306 try 307 { 308 String s = sn.toString(new NameComponent[] { a, b, c }); 309 System.out.println(s); 310 311 //NameComponent[] k = toName("a.k/b.k2/c/d/."); 312 //NameComponent[] k = toName("a.bc/.b/c.x"); 313 314 NameComponent[] k = sn.toName(s); 315 System.out.println("ToString"); 316 317 for (int i = 0; i < k.length; i++) 318 { 319 System.out.println(k [ i ].id + ":" + k [ i ].kind); 320 } 321 } 322 catch (InvalidName ex) 323 { 324 ex.printStackTrace(); 325 } 326 } 327 328 } 329