InterOperableNamingImpl.java revision 608:7e06bf1dcb09
1/* 2 * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.corba.se.impl.naming.cosnaming; 27 28import org.omg.CosNaming.NamingContextExtPackage.*; 29import java.io.StringWriter; 30 31// Import general CORBA classes 32import org.omg.CORBA.SystemException; 33import org.omg.CORBA.Object; 34 35// Import org.omg.CosNaming types 36import org.omg.CosNaming.NameComponent; 37import org.omg.CosNaming.NamingContext; 38 39 40/** 41 * Class InteroperableNamingImpl implements the methods defined 42 * for NamingContextExt which is part of Interoperable Naming 43 * Service specifications. This class is added for doing more 44 * of Parsing and Building of Stringified names according to INS 45 * Spec. 46 */ 47public class InterOperableNamingImpl 48{ 49 /** 50 * Method which stringifies the Name Components given as the input 51 * parameter. 52 * 53 * @param n Array of Name Components (Simple or Compound Names) 54 * @return string which is the stringified reference. 55 */ 56 public String convertToString( org.omg.CosNaming.NameComponent[] 57 theNameComponents ) 58 { 59 String theConvertedString = 60 convertNameComponentToString( theNameComponents[0] ); 61 String temp; 62 for( int i = 1; i < theNameComponents.length; i++ ) { 63 temp = convertNameComponentToString( theNameComponents[i] ); 64 if( temp != null ) { 65 theConvertedString = 66 theConvertedString + "/" + convertNameComponentToString( 67 theNameComponents[i] ); 68 } 69 } 70 return theConvertedString; 71 } 72 73 /** This method converts a single Namecomponent to String, By adding Escapes 74 * If neccessary. 75 */ 76 private String convertNameComponentToString( 77 org.omg.CosNaming.NameComponent theNameComponent ) 78 { 79 if( ( ( theNameComponent.id == null ) 80 ||( theNameComponent.id.length() == 0 ) ) 81 &&( ( theNameComponent.kind == null ) 82 ||( theNameComponent.kind.length() == 0 ) ) ) 83 { 84 return "."; 85 } 86 else if( ( theNameComponent.id == null ) 87 ||( theNameComponent.id.length() == 0 ) ) 88 { 89 String kind = addEscape( theNameComponent.kind ); 90 return "." + kind; 91 } 92 else if( ( theNameComponent.kind == null ) 93 ||( theNameComponent.kind.length() == 0 ) ) 94 { 95 String id = addEscape( theNameComponent.id ); 96 return id; 97 } 98 else { 99 String id = addEscape( theNameComponent.id ); 100 String kind = addEscape( theNameComponent.kind ); 101 return (id + "." + kind); 102 } 103 } 104 105 106 /** This method adds escape '\' for the Namecomponent if neccessary 107 */ 108 private String addEscape( String value ) 109 { 110 StringBuffer theNewValue; 111 if( (value != null) && ( (value.indexOf('.') != -1 ) || 112 (value.indexOf('/') != -1))) 113 { 114 char c; 115 theNewValue = new StringBuffer( ); 116 for( int i = 0; i < value.length( ); i++ ) { 117 c = value.charAt( i ); 118 if( ( c != '.' ) && (c != '/' ) ) 119 { 120 theNewValue.append( c ); 121 } 122 else { 123 // Adding escape for the "." 124 theNewValue.append( '\\' ); 125 theNewValue.append( c ); 126 } 127 } 128 } 129 else { 130 return value; 131 } 132 return new String( theNewValue ); 133 } 134 135 /** 136 * Method which converts the Stringified name into Array of Name Components. 137 * 138 * @param string which is the stringified name. 139 * @return Array of Name Components (Simple or Compound Names) 140 */ 141 public org.omg.CosNaming.NameComponent[] convertToNameComponent( 142 String theStringifiedName ) 143 throws org.omg.CosNaming.NamingContextPackage.InvalidName 144 { 145 String[] theStringifiedNameComponents = 146 breakStringToNameComponents( theStringifiedName ); 147 if( ( theStringifiedNameComponents == null ) 148 || (theStringifiedNameComponents.length == 0 ) ) 149 { 150 return null; 151 } 152 NameComponent[] theNameComponents = 153 new NameComponent[theStringifiedNameComponents.length]; 154 for( int i = 0; i < theStringifiedNameComponents.length; i++ ) { 155 theNameComponents[i] = createNameComponentFromString( 156 theStringifiedNameComponents[i] ); 157 } 158 return theNameComponents; 159 } 160 161 /** Step1 in converting Stringified name into array of Name Component 162 * is breaking the String into multiple name components 163 */ 164 private String[] breakStringToNameComponents( String theStringifiedName ) { 165 int[] theIndices = new int[100]; 166 int theIndicesIndex = 0; 167 168 for(int index = 0; index <= theStringifiedName.length(); ) { 169 theIndices[theIndicesIndex] = theStringifiedName.indexOf( '/', 170 index ); 171 if( theIndices[theIndicesIndex] == -1 ) { 172 // This is the end of all the occurence of '/' and hence come 173 // out of the loop 174 index = theStringifiedName.length()+1; 175 } 176 else { 177 // If the '/' is found, first check whether it is 178 // preceded by escape '\' 179 // If not then set theIndices and increment theIndicesIndex 180 // and also set the index else just ignore the '/' 181 if( (theIndices[theIndicesIndex] > 0 ) 182 && (theStringifiedName.charAt( 183 theIndices[theIndicesIndex]-1) == '\\') ) 184 { 185 index = theIndices[theIndicesIndex] + 1; 186 theIndices[theIndicesIndex] = -1; 187 } 188 else { 189 index = theIndices[theIndicesIndex] + 1; 190 theIndicesIndex++; 191 } 192 } 193 } 194 if( theIndicesIndex == 0 ) { 195 String[] tempString = new String[1]; 196 tempString[0] = theStringifiedName; 197 return tempString; 198 } 199 if( theIndicesIndex != 0 ) { 200 theIndicesIndex++; 201 } 202 return StringComponentsFromIndices( theIndices, theIndicesIndex, 203 theStringifiedName ); 204 } 205 206 /** This method breaks one big String into multiple substrings based 207 * on the array of index passed in. 208 */ 209 private String[] StringComponentsFromIndices( int[] theIndices, 210 int indicesCount, String theStringifiedName ) 211 { 212 String[] theStringComponents = new String[indicesCount]; 213 int firstIndex = 0; 214 int lastIndex = theIndices[0]; 215 for( int i = 0; i < indicesCount; i++ ) { 216 theStringComponents[i] = theStringifiedName.substring( firstIndex, 217 lastIndex ); 218 if( ( theIndices[i] < theStringifiedName.length() - 1 ) 219 &&( theIndices[i] != -1 ) ) 220 { 221 firstIndex = theIndices[i]+1; 222 } 223 else { 224 firstIndex = 0; 225 i = indicesCount; 226 } 227 if( (i+1 < theIndices.length) 228 && (theIndices[i+1] < (theStringifiedName.length() - 1)) 229 && (theIndices[i+1] != -1) ) 230 { 231 lastIndex = theIndices[i+1]; 232 } 233 else { 234 i = indicesCount; 235 } 236 // This is done for the last component 237 if( firstIndex != 0 && i == indicesCount ) { 238 theStringComponents[indicesCount-1] = 239 theStringifiedName.substring( firstIndex ); 240 } 241 } 242 return theStringComponents; 243 } 244 245 /** Step 2: After Breaking the Stringified name into set of NameComponent 246 * Strings, The next step is to create Namecomponents from the substring 247 * by removing the escapes if there are any. 248 */ 249 private NameComponent createNameComponentFromString( 250 String theStringifiedNameComponent ) 251 throws org.omg.CosNaming.NamingContextPackage.InvalidName 252 253 { 254 String id = null; 255 String kind = null; 256 if( ( theStringifiedNameComponent == null ) 257 || ( theStringifiedNameComponent.length( ) == 0) 258 || ( theStringifiedNameComponent.endsWith(".") ) ) 259 { 260 // If any of the above is true, then we create an invalid Name 261 // Component to indicate that it is an invalid name. 262 throw new org.omg.CosNaming.NamingContextPackage.InvalidName( ); 263 } 264 265 int index = theStringifiedNameComponent.indexOf( '.', 0 ); 266 // The format could be XYZ (Without kind) 267 if( index == -1 ) { 268 id = theStringifiedNameComponent; 269 } 270 // The format is .XYZ (Without ID) 271 else if( index == 0 ) { 272 // This check is for the Namecomponent which is just "." meaning Id 273 // and Kinds are null 274 if( theStringifiedNameComponent.length( ) != 1 ) { 275 kind = theStringifiedNameComponent.substring(1); 276 } 277 } 278 else 279 { 280 if( theStringifiedNameComponent.charAt(index-1) != '\\' ) { 281 id = theStringifiedNameComponent.substring( 0, index); 282 kind = theStringifiedNameComponent.substring( index + 1 ); 283 } 284 else { 285 boolean kindfound = false; 286 while( (index < theStringifiedNameComponent.length() ) 287 &&( kindfound != true ) ) 288 { 289 index = theStringifiedNameComponent.indexOf( '.',index + 1); 290 if( index > 0 ) { 291 if( theStringifiedNameComponent.charAt( 292 index - 1 ) != '\\' ) 293 { 294 kindfound = true; 295 } 296 } 297 else 298 { 299 // No more '.', which means there is no Kind 300 index = theStringifiedNameComponent.length(); 301 } 302 } 303 if( kindfound == true ) { 304 id = theStringifiedNameComponent.substring( 0, index); 305 kind = theStringifiedNameComponent.substring(index + 1 ); 306 } 307 else { 308 id = theStringifiedNameComponent; 309 } 310 } 311 } 312 id = cleanEscapeCharacter( id ); 313 kind = cleanEscapeCharacter( kind ); 314 if( id == null ) { 315 id = ""; 316 } 317 if( kind == null ) { 318 kind = ""; 319 } 320 return new NameComponent( id, kind ); 321 } 322 323 324 /** This method cleans the escapes in the Stringified name and returns the 325 * correct String 326 */ 327 private String cleanEscapeCharacter( String theString ) 328 { 329 if( ( theString == null ) || (theString.length() == 0 ) ) { 330 return theString; 331 } 332 int index = theString.indexOf( '\\' ); 333 if( index == 0 ) { 334 return theString; 335 } 336 else { 337 StringBuffer src = new StringBuffer( theString ); 338 StringBuffer dest = new StringBuffer( ); 339 char c; 340 for( int i = 0; i < theString.length( ); i++ ) { 341 c = src.charAt( i ); 342 if( c != '\\' ) { 343 dest.append( c ); 344 } else { 345 if( i+1 < theString.length() ) { 346 char d = src.charAt( i + 1 ); 347 // If there is a AlphaNumeric character after a \ 348 // then include slash, as it is not intended as an 349 // escape character. 350 if( Character.isLetterOrDigit(d) ) { 351 dest.append( c ); 352 } 353 } 354 } 355 } 356 return new String(dest); 357 } 358 } 359 360 /** 361 * Method which converts the Stringified name and Host Name Address into 362 * a URL based Name 363 * 364 * @param address which is ip based host name 365 * @param name which is the stringified name. 366 * @return url based Name. 367 */ 368 public String createURLBasedAddress( String address, String name ) 369 throws InvalidAddress 370 { 371 String theurl = null; 372 if( ( address == null ) 373 ||( address.length() == 0 ) ) { 374 throw new InvalidAddress(); 375 } 376 else { 377 theurl = "corbaname:" + address + "#" + encode( name ); 378 } 379 return theurl; 380 } 381 382 /** Encodes the string according to RFC 2396 IETF spec required by INS. 383 */ 384 private String encode( String stringToEncode ) { 385 StringWriter theStringAfterEscape = new StringWriter(); 386 int byteCount = 0; 387 for( int i = 0; i < stringToEncode.length(); i++ ) 388 { 389 char c = stringToEncode.charAt( i ) ; 390 if( Character.isLetterOrDigit( c ) ) { 391 theStringAfterEscape.write( c ); 392 } 393 // Do no Escape for characters in this list 394 // RFC 2396 395 else if((c == ';') || (c == '/') || (c == '?') 396 || (c == ':') || (c == '@') || (c == '&') || (c == '=') 397 || (c == '+') || (c == '$') || (c == ';') || (c == '-') 398 || (c == '_') || (c == '.') || (c == '!') || (c == '~') 399 || (c == '*') || (c == ' ') || (c == '(') || (c == ')') ) 400 { 401 theStringAfterEscape.write( c ); 402 } 403 else { 404 // Add escape 405 theStringAfterEscape.write( '%' ); 406 String hexString = Integer.toHexString( (int) c ); 407 theStringAfterEscape.write( hexString ); 408 } 409 } 410 return theStringAfterEscape.toString(); 411 } 412 413} 414