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