1. /*
  2. * @(#)InitialNamingClient.java 1.50 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. /*
  8. * Licensed Materials - Property of IBM
  9. * RMI-IIOP v1.0
  10. * Copyright IBM Corp. 1998 1999 All Rights Reserved
  11. *
  12. * US Government Users Restricted Rights - Use, duplication or
  13. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  14. */
  15. package com.sun.corba.se.internal.corba;
  16. import java.net.*;
  17. import java.util.*;
  18. import java.io.StringWriter;
  19. import org.omg.CORBA.CompletionStatus;
  20. import org.omg.CORBA.DATA_CONVERSION;
  21. import org.omg.CORBA.INTERNAL;
  22. import org.omg.CORBA.ORBPackage.InvalidName;
  23. import org.omg.CORBA.portable.ApplicationException;
  24. import org.omg.CORBA.portable.Delegate;
  25. import org.omg.CORBA.portable.InputStream;
  26. import org.omg.CORBA.portable.OutputStream;
  27. import org.omg.CORBA.portable.RemarshalException;
  28. import com.sun.corba.se.internal.core.*;
  29. import com.sun.corba.se.internal.CosNaming.MinorCodes;
  30. import com.sun.corba.se.internal.orbutil.SubcontractList;
  31. import com.sun.corba.se.internal.orbutil.ORBConstants;
  32. import com.sun.corba.se.internal.core.GIOPVersion;
  33. import com.sun.corba.se.internal.core.IOR;
  34. import com.sun.corba.se.internal.orbutil.ORBUtility;
  35. import com.sun.corba.se.internal.iiop.messages.MessageBase;
  36. import com.sun.corba.se.internal.iiop.messages.LocateRequestMessage;
  37. import com.sun.corba.se.internal.iiop.messages.LocateReplyMessage;
  38. import com.sun.corba.se.internal.ior.ObjectKeyFactory ;
  39. import org.omg.CosNaming.*;
  40. import com.sun.corba.se.internal.iiop.*;
  41. /** This class encapsulates all the state and logic for listing and
  42. * resolving services that are published in the initial naming (bootstrap)
  43. * service. It is only called through list_initial_services() and
  44. * resolve_initial_references() in ORB.java. Also, INS grammer parsing
  45. * routines are in this class.
  46. */
  47. public class InitialNamingClient
  48. {
  49. static private final int defaultInitialServicesPort =
  50. ORBConstants.DEFAULT_INITIAL_PORT;
  51. // State for the initial services: a URL if specified by a URL,
  52. // otherwise a representation to invoke on,
  53. // a port and its default value for the endpoint, a list of
  54. // initial services (a cache), and a list of resolved services (a cache).
  55. private URL servicesURL = null;
  56. protected int initialServicesPort = defaultInitialServicesPort;
  57. private String[] listOfInitialServices;
  58. private java.util.Properties resolvedInitialReferences = null;
  59. // ORBInitRefList contains a list of corbaloc and corbaname objects
  60. // defined with -ORBInitRef definition.
  61. private java.util.Hashtable orbInitRefList;
  62. // contains the -ORBDefaultInitRef definition.
  63. private String orbDefaultInitRef;
  64. com.sun.corba.se.internal.corba.ORB orb;
  65. // Root Naming Context for default resolution of names.
  66. private NamingContextExt rootNamingContextExt;
  67. public InitialNamingClient(com.sun.corba.se.internal.corba.ORB orb) {
  68. this.orb = orb;
  69. orbInitRefList = new java.util.Hashtable();
  70. orbDefaultInitRef = null;
  71. }
  72. void setServicesURL(URL url) {
  73. servicesURL = url;
  74. }
  75. void setInitialServicesPort(int port) {
  76. initialServicesPort = port;
  77. }
  78. /** sets the -ORBInitRef definitions in the vector.
  79. */
  80. boolean setORBInitRefList( java.util.Vector theList ) {
  81. boolean status = true;
  82. if( theList == null ) {
  83. status = false;
  84. } else {
  85. for( int i = 0; (i < theList.size()) && (status == true); i++ ) {
  86. status = parseORBInitRef( (String) theList.elementAt(i) );
  87. }
  88. }
  89. return status;
  90. }
  91. /** adds the -ORBInitRef definitions in the vector.
  92. */
  93. boolean addORBInitRef( String initRefProperty ) {
  94. return parseORBInitRef( initRefProperty );
  95. }
  96. /** There will be one -ORBDefaultInitRef definition, which will be set here. */
  97. boolean setORBDefaultInitRef( String theOrbDefaultInitRef ) {
  98. orbDefaultInitRef = theOrbDefaultInitRef;
  99. return true;
  100. }
  101. /** This method parses all -ORBInitRef definitions and returns true or
  102. * false based on the correct syntax according to INS specifications.
  103. */
  104. private boolean parseORBInitRef( String theOrbInitRef )
  105. throws org.omg.CORBA.BAD_PARAM
  106. {
  107. boolean status = true;
  108. if( (theOrbInitRef == null ) || (theOrbInitRef.length() == 0 ) )
  109. {
  110. // If the string after -ORBInitRef is null then return false.
  111. status = false;
  112. } else {
  113. String name = null;
  114. String value = null;
  115. int equalToIndex = 0;
  116. equalToIndex = theOrbInitRef.indexOf( '=' );
  117. if( equalToIndex == -1 ) {
  118. // If '=' is missing in the -ORBInitRef then it is wrong.
  119. status = false;
  120. } else {
  121. name = theOrbInitRef.substring( 0, equalToIndex );
  122. value = theOrbInitRef.substring( equalToIndex + 1 );
  123. if( value == null || value.length() == 0 ) {
  124. // If there is no string after '=' then it is wrong.
  125. status = false;
  126. } else {
  127. Object theValue = null;
  128. if ( value.startsWith( "corbaloc:" ) == true ) {
  129. // -ORBInitRef String starts with corbaloc:.
  130. // So check the corbaloc: grammer.
  131. CorbaLoc theCorbaLocObject =
  132. checkcorbalocGrammer( value );
  133. if( theCorbaLocObject != null ) {
  134. theValue = theCorbaLocObject;
  135. } else {
  136. // Could not build CorbaLoc object which means
  137. // there is a syntax error.
  138. status = false;
  139. }
  140. }
  141. else if ( value.startsWith( "corbaname:" ) == true ) {
  142. // -ORBInitRef String starts with corbaname:.
  143. // So check the corbaname: grammer.
  144. CorbaName theCorbaNameObject =
  145. checkcorbanameGrammer( value );
  146. if( theCorbaNameObject != null ) {
  147. theValue = theCorbaNameObject;
  148. } else {
  149. // Could not build CorbaName object which means
  150. // there is a syntax error.
  151. status = false;
  152. }
  153. }
  154. else if ( value.startsWith(
  155. IOR.STRINGIFY_PREFIX ) == true ) {
  156. // If it is IOR Object store it as it is.
  157. theValue = value;
  158. status = true;
  159. } else {
  160. // If it does not start with corbaloc: or corbaname: or
  161. // IOR: then it is worng.
  162. status = false;
  163. }
  164. if( status == true ) {
  165. try {
  166. // If the CorbaLoc or CorbaName or IOR object is
  167. // built successfully then add that to the list.
  168. orbInitRefList.put( name, theValue );
  169. } catch( Exception e ) {
  170. status = false;
  171. }
  172. } else {
  173. throw new org.omg.CORBA.BAD_PARAM(
  174. MinorCodes.INS_BAD_SCHEME_NAME,
  175. CompletionStatus.COMPLETED_NO);
  176. }
  177. }
  178. }
  179. }
  180. return status;
  181. }
  182. /** Check whether the given 'corbaloc' is valid according to INS
  183. * specification.
  184. * returns CorbaLoc object which contains endpointinfo and objectKey.
  185. * _REVISIT_ : Cleanup for Tiger
  186. */
  187. public CorbaLoc checkcorbalocGrammer( String value )
  188. throws org.omg.CORBA.BAD_PARAM
  189. {
  190. CorbaLoc theCorbaLocObject = new CorbaLoc( );
  191. // Get the substring after corbaloc:
  192. if( value != null ) {
  193. try {
  194. // First Clean the URL Escapes if there are any
  195. value = decode( value );
  196. } catch( Exception e ) {
  197. // There is something wrong with the URL escapes
  198. // and hence throw the exception
  199. throw new org.omg.CORBA.BAD_PARAM(
  200. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  201. CompletionStatus.COMPLETED_NO);
  202. }
  203. // String length of corbaloc: is 9
  204. int startIndex = 9;
  205. int endIndex = value.indexOf( '/' );
  206. // BUG FIX for 4336809
  207. if( endIndex == -1 ) {
  208. // If there is no '/' then the endIndex is at the end of the URL
  209. endIndex = value.length();
  210. }
  211. if( endIndex == 1 ) {
  212. // There are no characters after corbaloc: then it is an error.
  213. throw new org.omg.CORBA.BAD_PARAM(
  214. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  215. CompletionStatus.COMPLETED_NO);
  216. }
  217. else {
  218. // Anything between corbaloc: and / are the host information
  219. // of the server where the Service Object is located
  220. java.util.Vector hostNames = getHostNamesFromURL(
  221. value.substring( startIndex, endIndex ) );
  222. if( ( hostNames == null )
  223. ||( hostNames.size() == 0 ) )
  224. {
  225. // hostName is null which means the address portion
  226. // of the url is incorrect
  227. throw new org.omg.CORBA.BAD_PARAM(
  228. MinorCodes.INS_BAD_ADDRESS,
  229. CompletionStatus.COMPLETED_NO);
  230. }
  231. for( int i = 0;
  232. (i < hostNames.size()) && (theCorbaLocObject != null) ; i++ )
  233. {
  234. String hostName = (String)hostNames.elementAt( i );
  235. String host = null;
  236. // 2089 is the default port number according to INS spec.
  237. // GIOP 1.2 is the default version.
  238. int port = 2089;
  239. int major = 1;
  240. int minor = 2;
  241. if( hostName.startsWith( "iiop:" ) ) {
  242. // Check the iiop syntax
  243. int at = hostName.indexOf( '@' );
  244. if( at == -1 ) {
  245. // There is no Major and Minor number
  246. try {
  247. host = hostName.substring( 5 );
  248. if( ( host == null )
  249. ||( host.length() == 0 ) )
  250. {
  251. // _REVISIT_ Add a new method to throw
  252. // BAD_PARAM exception and then invoke
  253. // that method to throw BAD_PARAM exception
  254. // hostName is null which means the address
  255. // portion of the url is incorrect
  256. throw new org.omg.CORBA.BAD_PARAM(
  257. MinorCodes.INS_BAD_ADDRESS,
  258. CompletionStatus.COMPLETED_NO);
  259. } else {
  260. // A Hack to differentiate IPV6 address
  261. // from IPV4 address, Current Resolution
  262. // is to use [ ] to differentiate ipv6 host
  263. int squareBracketBeginIndex =
  264. host.indexOf ( '[' );
  265. if( squareBracketBeginIndex != -1 ) {
  266. // ipv6Host should be enclosed in
  267. // [ ], if not it will result in a
  268. // BAD_PARAM exception
  269. String ipv6Port = getIPV6Port( host );
  270. if( ipv6Port != null ) {
  271. port = Integer.parseInt( ipv6Port );
  272. }
  273. host = getIPV6Host( host );
  274. } else {
  275. // If there is a colon, Make sure what
  276. // follows after colon is indeed a
  277. // Integer If it is not then we have an
  278. // invalid port number
  279. int colon = host.indexOf( ':' );
  280. if( colon != -1 ) {
  281. port = Integer.parseInt(
  282. host.substring( colon+1) );
  283. host = host.substring( 0, colon );
  284. }
  285. }
  286. }
  287. } catch( Exception e ) {
  288. // Any kind of Exception is bad here.
  289. org.omg.CORBA.BAD_PARAM exception =
  290. new org.omg.CORBA.BAD_PARAM(
  291. MinorCodes.INS_BAD_ADDRESS,
  292. CompletionStatus.COMPLETED_NO);
  293. exception.initCause(e);
  294. throw exception;
  295. }
  296. } else {
  297. try {
  298. String version = hostName.substring( 5, at );
  299. int dot = version.indexOf('.');
  300. // There is a version without ., which means
  301. // Malformed list
  302. if (dot < 0) {
  303. theCorbaLocObject = null;
  304. } else {
  305. // Substring after iiop: and before . which
  306. // will be a major number (IIOP version).
  307. major = Integer.parseInt(
  308. version.substring(0, dot));
  309. minor = Integer.parseInt(
  310. version.substring(dot+1));
  311. validateGIOPVersion(major, minor);
  312. // A Hack to differentiate IPV6 address
  313. // from IPV4 address, Current Resolution
  314. // is to use [ ] to differentiate ipv6 host
  315. int squareBracketBeginIndex =
  316. hostName.indexOf ( '[' );
  317. if( squareBracketBeginIndex != -1 ) {
  318. // hostName info conatins iiop version,
  319. // get the hostinfo using the '[' token
  320. host = hostName.substring(
  321. squareBracketBeginIndex );
  322. // ipv6Host should be enclosed in
  323. // [ ], if not it will result in a
  324. // BAD_PARAM exception
  325. String ipv6Port = getIPV6Port( host );
  326. if( ipv6Port != null ) {
  327. port = Integer.parseInt( ipv6Port );
  328. }
  329. host = getIPV6Host( host );
  330. } else {
  331. host = hostName.substring( at+1 );
  332. int colon = host.indexOf( ':' );
  333. if( colon != -1 ) {
  334. port = Integer.parseInt(
  335. host.substring( colon+1) );
  336. host = host.substring( 0, colon );
  337. }
  338. }
  339. }
  340. }
  341. // Any kind of exception is bad here, It could be
  342. // number format exception or Null String exception
  343. catch( Exception e ) {
  344. org.omg.CORBA.BAD_PARAM exception =
  345. new org.omg.CORBA.BAD_PARAM(
  346. MinorCodes.INS_BAD_ADDRESS,
  347. CompletionStatus.COMPLETED_NO);
  348. exception.initCause(e);
  349. throw exception;
  350. }
  351. }
  352. }
  353. else if( hostName.startsWith( "rir:" ) ) {
  354. //Check the rir syntax
  355. try {
  356. String afterRIR = hostName.substring( 4 );
  357. // There should not be anything after rir:, If
  358. // there is something.
  359. // Then we have an invalid URL
  360. if( afterRIR.length() != 0 ) {
  361. throw new org.omg.CORBA.BAD_PARAM(
  362. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  363. CompletionStatus.COMPLETED_NO);
  364. } else {
  365. theCorbaLocObject.setRIRFlag( );
  366. }
  367. } catch( Exception e ) {
  368. // Any exception is bad here
  369. org.omg.CORBA.BAD_PARAM exception =
  370. new org.omg.CORBA.BAD_PARAM(
  371. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  372. CompletionStatus.COMPLETED_NO);
  373. exception.initCause(e);
  374. throw exception;
  375. }
  376. } else if( hostName.startsWith( ":" ) ) {
  377. // Check the default iiop syntax
  378. try {
  379. // String after :
  380. host = hostName.substring( 1 );
  381. // It is invalid to have a url in the form
  382. // corbaloc::rir:,:/<ObjectKey>
  383. // Bug Fix: 4404982
  384. if( ( host == null )
  385. ||( host.length() == 0 ) ) {
  386. throw new org.omg.CORBA.BAD_PARAM(
  387. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  388. CompletionStatus.COMPLETED_NO);
  389. }
  390. // @ in Hostname is invalid
  391. int at = host.indexOf( '@' );
  392. if( at != -1 ) {
  393. try {
  394. // GIOP Version number like 1.2
  395. // will be decoded as major = 1 and
  396. // minor 2.
  397. major = Integer.parseInt(
  398. host.substring(0, 1));
  399. minor = Integer.parseInt(
  400. host.substring(2, 3));
  401. validateGIOPVersion( major, minor );
  402. // Host Info will be after @
  403. host = hostName.substring( at + 2 );
  404. }
  405. catch( Exception e ) {
  406. // Any Exception is bad here, Possible cause
  407. // could be a malformed GIOP Version.
  408. org.omg.CORBA.BAD_PARAM exception =
  409. new org.omg.CORBA.BAD_PARAM(
  410. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  411. CompletionStatus.COMPLETED_NO);
  412. exception.initCause(e);
  413. throw exception;
  414. }
  415. }
  416. // If there is a colon, Make sure to check
  417. // that the string after : is indeed number
  418. // So that we can use it as Port Number
  419. int colon = host.indexOf( ':' );
  420. if( colon != -1 ) {
  421. port = Integer.parseInt(
  422. host.substring( colon+1) );
  423. host = host.substring( 0, colon );
  424. }
  425. } catch( Exception e ) {
  426. org.omg.CORBA.BAD_PARAM exception =
  427. new org.omg.CORBA.BAD_PARAM(
  428. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  429. CompletionStatus.COMPLETED_NO);
  430. exception.initCause(e);
  431. throw exception;
  432. }
  433. } else {
  434. // Right now we are not allowing any other protocol
  435. // other than iiop:, rir: so raise exception indicating
  436. // that the URL is malformed
  437. throw new org.omg.CORBA.BAD_PARAM(
  438. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  439. CompletionStatus.COMPLETED_NO);
  440. }
  441. if( ( theCorbaLocObject != null )
  442. &&( theCorbaLocObject.getRIRFlag() == false ) )
  443. {
  444. // Add the Host information if RIR flag is set,
  445. // If RIR is set then it means use the internal Boot
  446. // Strap protocol for Key String resolution
  447. HostInfo newHostInfo = new HostInfo( );
  448. newHostInfo.setVersion( major, minor );
  449. newHostInfo.setHostName( host );
  450. newHostInfo.setPortNumber( port );
  451. theCorbaLocObject.addHostInfo( newHostInfo );
  452. }
  453. }
  454. if( theCorbaLocObject != null ) {
  455. try {
  456. String keyString = null;
  457. // _REVISIT_ Clean up the logic here to make it
  458. // more readable.
  459. // If there is nothing after corbaloc:hostinfo/
  460. // then NameService is the default KeyString
  461. if( value.length() <= (endIndex + 1) ) {
  462. keyString = "NameService";
  463. }
  464. else {
  465. keyString = value.substring( endIndex + 1 );
  466. }
  467. theCorbaLocObject.setKeyString( keyString );
  468. } catch( Exception e ) {
  469. org.omg.CORBA.BAD_PARAM exception =
  470. new org.omg.CORBA.BAD_PARAM(
  471. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  472. CompletionStatus.COMPLETED_NO);
  473. exception.initCause(e);
  474. throw exception;
  475. }
  476. } else {
  477. // The URL doesn't have a Slash after corbaloc or has a
  478. // slash at the wrong place.
  479. throw new org.omg.CORBA.BAD_PARAM(
  480. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  481. CompletionStatus.COMPLETED_NO);
  482. }
  483. }
  484. }
  485. return theCorbaLocObject;
  486. }
  487. /**
  488. * Returns an IPV6 Host that is inside [ ] tokens. There is no validation
  489. * done here, if it is an incorrect IPV6 address then the request through
  490. * this URL results in a COMM_FAILURE, otherwise malformed list will
  491. * result in BAD_PARAM exception thrown in checkcorbalocGrammer.
  492. */
  493. private String getIPV6Host( String endpointInfo ) {
  494. // ipv6Host should be enclosed in
  495. // [ ], if not it will result in a
  496. // BAD_PARAM exception
  497. int squareBracketEndIndex = endpointInfo.indexOf ( ']' );
  498. // get the host between [ ]
  499. String ipv6Host = endpointInfo.substring( 1, squareBracketEndIndex );
  500. return ipv6Host;
  501. }
  502. /**
  503. * Returns an IPV6 Port that is after [<ipv6>]:. There is no validation
  504. * done here, if it is an incorrect port then the request through
  505. * this URL results in a COMM_FAILURE, otherwise malformed list will
  506. * result in BAD_PARAM exception thrown in checkcorbalocGrammer.
  507. */
  508. private String getIPV6Port( String endpointInfo )
  509. {
  510. int squareBracketEndIndex = endpointInfo.indexOf ( ']' );
  511. // If there is port information, then it has to be after ] bracket
  512. // indexOf returns the count from the index of zero as the base, so
  513. // equality check requires squareBracketEndIndex + 1.
  514. if( (squareBracketEndIndex + 1) != (endpointInfo.length( )) ) {
  515. if( endpointInfo.charAt( squareBracketEndIndex + 1 ) != ':' ) {
  516. throw new RuntimeException(
  517. "Host and Port is not separated by ':'" );
  518. }
  519. // PortInformation should be after ']:' delimiter
  520. // If there is an exception then it will be caught in
  521. // checkcorbaGrammer method and rethrown as BAD_PARAM
  522. return endpointInfo.substring( squareBracketEndIndex + 2 );
  523. }
  524. return null;
  525. }
  526. /** Quickly check whether the given corbaname is valid
  527. * return true if it is and false otherwise
  528. */
  529. public CorbaName checkcorbanameGrammer( String value )
  530. throws org.omg.CORBA.BAD_PARAM
  531. {
  532. CorbaName theCorbaNameObject = null;
  533. // First Clean the URL Escapes if there are any
  534. try {
  535. value = decode( value );
  536. } catch( Exception e ) {
  537. throw new org.omg.CORBA.BAD_PARAM(
  538. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  539. CompletionStatus.COMPLETED_NO);
  540. }
  541. int index = value.indexOf( '#' );
  542. if( index != -1 ) {
  543. try {
  544. // Append corbaloc: for Grammer check, Get the string between
  545. // corbaname: and # which forms the corbaloc string
  546. String corbalocString = "corbaloc:" +
  547. value.substring( 10, index ) + "/";
  548. // Check the corbaloc grammer and set the returned corbaloc
  549. // object to the CorbaName Object
  550. CorbaLoc theCorbaLocObject = checkcorbalocGrammer(
  551. corbalocString );
  552. if( theCorbaLocObject != null ) {
  553. theCorbaNameObject = new CorbaName( );
  554. theCorbaNameObject.setCorbaLoc( theCorbaLocObject );
  555. // String after '#' is the Stringified name used to resolve
  556. // the Object reference from the rootnaming context. If
  557. // the String is null then the Root Naming context is passed
  558. // back
  559. String StringifiedName = value.substring( index + 1 );
  560. if(( StringifiedName != null )
  561. && ( StringifiedName.length() != 0 ) )
  562. {
  563. theCorbaNameObject.setStringifiedName(StringifiedName);
  564. }
  565. }
  566. } catch( Exception e ) {
  567. // Any kind of exception is bad here
  568. throw new org.omg.CORBA.BAD_PARAM(
  569. MinorCodes.INS_BAD_SCHEME_SPECIFIC_PART,
  570. CompletionStatus.COMPLETED_NO);
  571. }
  572. }
  573. // This is the case with no # in the string
  574. else {
  575. // Build a corbaloc string to check the grammer.
  576. // 10 is the length of corbaname:
  577. String corbalocString = "corbaloc:" +
  578. value.substring( 10, value.length() );
  579. // If the string doesnot end with a / then add one to end the
  580. // URL correctly
  581. if( corbalocString.endsWith( "/" ) != true ) {
  582. corbalocString = corbalocString + "/";
  583. }
  584. // Check the corbaloc grammer and set the returned corbaloc
  585. // object to the CorbaName Object
  586. CorbaLoc theCorbaLocObject = checkcorbalocGrammer(
  587. corbalocString );
  588. if( theCorbaLocObject != null ) {
  589. theCorbaNameObject = new CorbaName( );
  590. theCorbaNameObject.setCorbaLoc( theCorbaLocObject );
  591. // If the Key String is null then the Root Naming context
  592. // is passed back
  593. //theCorbaNameObject.setStringifiedName(null);
  594. }
  595. }
  596. return theCorbaNameObject;
  597. }
  598. /** resolveUsingORBInitRef is called first when ever
  599. * resolve_initial_reference is called.
  600. * This method, checks to see if there is an entry for the requested
  601. * service name (identifier) under -ORBInitRef.
  602. * If there is one, It parses and tries to resolve the reference with
  603. * the given ORBInitDef definition.
  604. * returns the Stringified Object reference if successful in resolving,
  605. * Null is returned otherwise.
  606. */
  607. private String resolveUsingORBInitRef( String identifier ) {
  608. String sresult = null;
  609. org.omg.CORBA.Object result = null;
  610. Object URLValue = orbInitRefList.get( identifier );
  611. if( URLValue != null ) {
  612. CorbaLoc CorbaLocInstance = new CorbaLoc( );
  613. CorbaName CorbaNameInstance = new CorbaName( );
  614. // Check whether the URLValue is a CorbaLoc object
  615. if( URLValue.getClass().isInstance((Object) CorbaLocInstance ) ) {
  616. sresult = resolveCorbaloc( (CorbaLoc) URLValue );
  617. } else if( URLValue.getClass().isInstance((Object)
  618. CorbaNameInstance ) )
  619. {
  620. // Check whether the URLValue is a CorbaName object
  621. org.omg.CORBA.Object theObject =
  622. resolveCorbaname( (CorbaName) URLValue );
  623. try {
  624. sresult = orb.object_to_string( theObject );
  625. } catch( Exception e ) {
  626. sresult = null;
  627. }
  628. } else {
  629. // It has to be IOR otherwise
  630. sresult = (String) URLValue;
  631. }
  632. }
  633. return sresult;
  634. }
  635. String resolveCorbaloc( CorbaLoc theCorbaLocObject ) {
  636. String sresult = null;
  637. // If RIR flag is true use the Bootstrap protocol
  638. if( theCorbaLocObject.getRIRFlag( ) == true ) {
  639. sresult =
  640. resolveUsingBootstrapProtocol(theCorbaLocObject.getKeyString());
  641. } else {
  642. sresult = getIORUsingHostInfo( theCorbaLocObject.getHostInfo(),
  643. theCorbaLocObject.getKeyString() );
  644. }
  645. return sresult;
  646. }
  647. private String getIORUsingHostInfo( java.util.Vector theHostInfo,
  648. String theKeyString )
  649. {
  650. // If there is no KeyString then it's invalid
  651. if( theKeyString == null ) {
  652. return null;
  653. }
  654. String sresult = null;
  655. IOR theIOR = null;
  656. for( int i = 0; (i < theHostInfo.size()) && (theIOR == null ); i++ ) {
  657. HostInfo element = (HostInfo) theHostInfo.elementAt( i );
  658. theIOR = new IOR( orb, "", element.getHostName(),
  659. element.getPortNumber(), element.getMajorNumber(),
  660. element.getMinorNumber(), theKeyString, null );
  661. //First check whether there is a server listening for Locate Request
  662. //for the given key at Host and Port specified in the URL
  663. //If there is a server, then decide whether the IOR is valid or
  664. //not
  665. theIOR = locateObject( theIOR, theKeyString.getBytes());
  666. if( theIOR != null ) {
  667. sresult = theIOR.stringify();
  668. }
  669. }
  670. return sresult;
  671. }
  672. org.omg.CORBA.Object resolveCorbaname( CorbaName theCorbaName ) {
  673. org.omg.CORBA.Object result = null;
  674. CorbaLoc theCorbaLoc = theCorbaName.getCorbaLoc( );
  675. if( theCorbaLoc == null ) {
  676. return null;
  677. }
  678. // Case 1 of corbaname: rir#
  679. if( theCorbaLoc.getRIRFlag( ) == true ) {
  680. try {
  681. NamingContextExt theNamingContext =
  682. getDefaultRootNamingContext( );
  683. String StringifiedName = theCorbaName.getStringifiedName( );
  684. if( StringifiedName == null ) {
  685. // This means return the Root Naming context
  686. result = theNamingContext;
  687. } else {
  688. result = theNamingContext.resolve_str( StringifiedName );
  689. }
  690. } catch( Exception e ) {
  691. result = null;
  692. }
  693. } else {
  694. // Case 2 of corbaname: ::hostname#
  695. try {
  696. String sresult = getIORUsingHostInfo( theCorbaLoc.getHostInfo(), theCorbaLoc.getKeyString() );
  697. if( sresult != null ) {
  698. org.omg.CORBA.Object theObject =
  699. orb.string_to_object( sresult );
  700. if( theObject != null ) {
  701. NamingContextExt theNamingContext =
  702. NamingContextExtHelper.narrow( theObject );
  703. if( theNamingContext != null ) {
  704. String StringifiedName =
  705. theCorbaName.getStringifiedName( );
  706. //Return Root Naming Context if the Stringified Name
  707. // is null.
  708. result = theNamingContext;
  709. if( StringifiedName != null ) {
  710. result =
  711. theNamingContext.resolve_str(
  712. StringifiedName );
  713. }
  714. }
  715. }
  716. }
  717. } catch( Exception e ) {
  718. result = null;
  719. }
  720. }
  721. return result;
  722. }
  723. private java.util.Vector getHostNamesFromURL(String theHostPartOfURLString)
  724. {
  725. java.util.Vector theHosts = new java.util.Vector();
  726. boolean nomoreCommas = false;
  727. int index = 0;
  728. for( int i = 0; (i < theHostPartOfURLString.length())
  729. && (nomoreCommas == false); )
  730. {
  731. int theCommaIndex = theHostPartOfURLString.indexOf( ',', index );
  732. if( theCommaIndex == -1 ) {
  733. // There are no more Hostnames and hence set the flag to true
  734. // also get the Hostname and add it into the list.
  735. nomoreCommas = true;
  736. String temp = theHostPartOfURLString.substring( index );
  737. theHosts.addElement( temp );
  738. } else {
  739. // Found a comma, which means there is a hostname after comma
  740. // hence get the substring mapping to one of the hostname and
  741. // port number.
  742. String temp = theHostPartOfURLString.substring( index,
  743. theCommaIndex );
  744. theHosts.addElement( temp );
  745. index = theCommaIndex + 1;
  746. }
  747. }
  748. return theHosts;
  749. }
  750. private String resolveUsingBootstrapProtocol( String identifier ) {
  751. String stringifiedReference = null;
  752. // Use bootstrap protocol
  753. org.omg.CORBA.Object result =
  754. resolve(identifier, orb.getORBInitialHost(), initialServicesPort);
  755. if (result != null) {
  756. stringifiedReference = orb.object_to_string( result );
  757. }
  758. return stringifiedReference;
  759. }
  760. private org.omg.CORBA.Object resolveIOR( String URLValue ) {
  761. return null;
  762. }
  763. private NamingContextExt getDefaultRootNamingContext( ) {
  764. if( rootNamingContextExt == null ) {
  765. try {
  766. rootNamingContextExt =
  767. NamingContextExtHelper.narrow(
  768. this.resolve_initial_references( "NameService" ) );
  769. } catch( Exception e ) {
  770. rootNamingContextExt = null;
  771. }
  772. }
  773. return rootNamingContextExt;
  774. }
  775. private String resolveUsingORBDefaultInitRef( String identifier ) {
  776. // If the ORBDefaultInitDef is not defined simply return null
  777. if( orbDefaultInitRef == null ) {
  778. return null;
  779. }
  780. // If the ORBDefaultInitDef is defined as corbaloc: then create the
  781. // corbaloc String in the format
  782. // <ORBInitDefaultInitDef Param>/<Identifier>
  783. // and resolve it using resolveCorbaloc method
  784. if( orbDefaultInitRef.startsWith( "corbaloc:" ) ) {
  785. String theCorbaLocString = orbDefaultInitRef + "/" + identifier;
  786. CorbaLoc theCorbaLoc = checkcorbalocGrammer( theCorbaLocString );
  787. if( theCorbaLoc != null ) {
  788. // We are just passing the string after 'corbaloc:'
  789. // for resolution
  790. return resolveCorbaloc( theCorbaLoc );
  791. } else {
  792. return null;
  793. }
  794. }
  795. // If the ORBDefaultInitDef is defined as corbaname: then create the
  796. // corbaloc String in the format
  797. // <ORBInitDefaultInitDef Param>#<Identifier>
  798. // and resolve it using resolveCorbaname method
  799. if( orbDefaultInitRef.startsWith( "corbaname:" ) ) {
  800. String theCorbaNameString = orbDefaultInitRef + "#" + identifier;
  801. CorbaName theCorbaName = checkcorbanameGrammer(theCorbaNameString);
  802. if( theCorbaName != null ) {
  803. org.omg.CORBA.Object theObject =
  804. resolveCorbaname(theCorbaName );
  805. if( theObject != null ) {
  806. return orb.object_to_string( theObject );
  807. }
  808. } else {
  809. return null;
  810. }
  811. }
  812. return null;
  813. }
  814. /** Locate Object returns true, If there is a Server listening at Host and
  815. * Port specified in the IOR and ObjectKey is valid. If not, then the
  816. * locate request will result in GIOPLocateReplyUnknownObject, in which
  817. * case a false is returned resulting in null IOR being returned.
  818. */
  819. private IOR locateObject( IOR ior, byte[] theObjectKey ) {
  820. IOR theNewIOR = null;
  821. LocateRequestMessage msg;
  822. com.sun.corba.se.internal.iiop.IIOPOutputStream os;
  823. com.sun.corba.se.internal.iiop.IIOPInputStream is;
  824. try {
  825. ClientGIOP giop = orb.getClientGIOP();
  826. Connection conn = giop.getConnection( ior );
  827. int id = giop.allocateRequestId() ;
  828. GIOPVersion requestVersion =
  829. GIOPVersion.chooseRequestVersion(orb, ior);
  830. msg = MessageBase.createLocateRequest(
  831. (com.sun.corba.se.internal.iiop.ORB) orb, requestVersion,
  832. id, theObjectKey);
  833. // This chooses the right buffering strategy for the locate msg.
  834. // locate msgs 1.0 & 1.1 :=> grow, 1.2 :=> stream
  835. os = com.sun.corba.se.internal.iiop.IIOPOutputStream.
  836. createIIOPOutputStreamForLocateMsg(
  837. requestVersion,
  838. (com.sun.corba.se.internal.iiop.ORB) orb, conn);
  839. os.setMessage(msg);
  840. msg.write(os);
  841. is = conn.send(os, false);
  842. LocateReplyMessage reply;
  843. reply = (LocateReplyMessage) is.getMessage();
  844. switch(reply.getReplyStatus()) {
  845. case LocateReplyMessage.UNKNOWN_OBJECT :
  846. theNewIOR = null;
  847. break;
  848. case LocateReplyMessage.OBJECT_FORWARD :
  849. case LocateReplyMessage.OBJECT_FORWARD_PERM :
  850. theNewIOR = reply.getIOR();
  851. break;
  852. case LocateReplyMessage.OBJECT_HERE :
  853. theNewIOR = ior;
  854. break;
  855. default:
  856. theNewIOR = null;
  857. break;
  858. }
  859. } catch( Exception e ) {
  860. theNewIOR = null;
  861. }
  862. return theNewIOR;
  863. }
  864. /**
  865. * Get a list of the initially available CORBA services.
  866. * This does not work unless an ORBInitialHost is specified during
  867. * initialization
  868. * (or unless there is an ORB running on the AppletHost) since the
  869. * localhostname is inaccessible to applets. If a service properties URL
  870. * was specified then it is used, otherwise the bootstrapping protocol is
  871. * used.
  872. * @return A list of the initial services available.
  873. */
  874. String[] list_initial_services () {
  875. // Call real function
  876. return this.cachedServices();
  877. }
  878. private Properties getServicesFromURL() {
  879. if ( resolvedInitialReferences == null ) {
  880. try {
  881. // Open connection
  882. URLConnection urlc = servicesURL.openConnection();
  883. java.io.InputStream is = urlc.getInputStream();
  884. // Create and load properties
  885. Properties serviceProps = new Properties();
  886. serviceProps.load(is);
  887. resolvedInitialReferences = serviceProps;
  888. is.close();
  889. } catch (java.io.IOException ex) {
  890. throw new org.omg.CORBA.COMM_FAILURE(ex.toString(),
  891. com.sun.corba.se.internal.orbutil.MinorCodes.GET_PROPERTIES_ERROR,
  892. CompletionStatus.COMPLETED_NO);
  893. }
  894. }
  895. return resolvedInitialReferences;
  896. }
  897. private synchronized String[] cachedServices() {
  898. if ( listOfInitialServices == null ) {
  899. String[] list = null;
  900. if (( listOfInitialServices==null) && (servicesURL != null)) {
  901. // A URL was given, so use it.
  902. Properties serviceProps = getServicesFromURL();
  903. // Create a list of strings (the keys) and copy entries
  904. list = new String[serviceProps.size()];
  905. Enumeration theKeys = serviceProps.keys();
  906. for (int index=0;theKeys.hasMoreElements();index++) {
  907. list[index] = (String)theKeys.nextElement();
  908. }
  909. }
  910. else {
  911. list = getInitialServices(orb.getORBInitialHost(),
  912. initialServicesPort);
  913. }
  914. listOfInitialServices = list;
  915. }
  916. return listOfInitialServices;
  917. }
  918. String[] getInitialServices(String host, int port)
  919. {
  920. // REVISIT - this should be implemented using DII to avoid
  921. // duplicating unnecessary exception handling code.
  922. boolean remarshal = true;
  923. // Create a delegate (subcontract) to invoke on
  924. ClientDelegate sc = this.getInitialRep(host, port);
  925. // Invoke.
  926. InputStream is = null;
  927. // If there is a location forward then you will need
  928. // to invoke again on the updated information.
  929. // Just calling this same routine with the same host/port
  930. // does not take the location forward info into account.
  931. while (remarshal) {
  932. remarshal = false;
  933. OutputStream os = (OutputStream) sc.createRequest("list", false);
  934. try {
  935. // The only reason null is passed is to get the version of
  936. // invoke used by streams. Otherwise the PortableInterceptor
  937. // call stack will become unbalanced since the version of
  938. // invoke which only takes the stream does not call
  939. // PortableInterceptor ending points.
  940. // Note that the first parameter is ignored inside invoke.
  941. is = sc.invoke((org.omg.CORBA.Object)null, os);
  942. } catch (ApplicationException e) {
  943. throw new INTERNAL("InitialNamingClient.getInitialServices: Caught an ApplicationException. This should never happen.");
  944. } catch (RemarshalException e) {
  945. remarshal = true;
  946. }
  947. }
  948. // Unmarshal String[].
  949. int length = is.read_long();
  950. String[] ret = new String[length];
  951. for (int i=0; i<length; i++)
  952. ret[i] = is.read_string();
  953. // List all the Services registered in the Bootstrap Registry
  954. // + All the Services registered using ORBInitInfo
  955. java.util.Set orbInitKeySet = orbInitRefList.keySet();
  956. if( orbInitKeySet != null ) {
  957. String[] newList = new String[ret.length +
  958. orbInitKeySet.size() ];
  959. int i;
  960. for( i = 0; i < length; i++ ) {
  961. newList[i] = ret[i];
  962. }
  963. Object[] temp = orbInitKeySet.toArray();
  964. for( i = length; i < (length + orbInitKeySet.size()); i++ ) {
  965. newList[i] = (String) temp[i];
  966. }
  967. return newList;
  968. }
  969. return ret;
  970. }
  971. /**
  972. * This creates a GIOP 1.0 IOR.
  973. * Used to bootstrap request as a GIOP 1.0 request.
  974. * This is to inter-operate with old Name Service
  975. * implementations from SUN.
  976. */
  977. private ClientDelegate getInitialRep(String host, int port) {
  978. // Create a representation (delegate) for the initial name server.
  979. // Create a new IOR
  980. byte[] initialKey = new byte[4];
  981. initialKey[0] = 0x49; initialKey[1] = 0x4e;
  982. initialKey[2] = 0x49; initialKey[3] = 0x54;
  983. IOR initialIOR = new IOR(orb, "", host, port,
  984. GIOPVersion.V1_0.getMajor(),
  985. GIOPVersion.V1_0.getMinor(),
  986. ObjectKeyFactory.get().create(orb,initialKey),
  987. null);
  988. // Create a subcontract
  989. ClientDelegate rep = new ClientDelegate(orb, initialIOR,
  990. SubcontractList.defaultSubcontract);
  991. return rep;
  992. }
  993. /**
  994. * Resolve the stringified reference of one of the initially
  995. * available CORBA services.
  996. * @param identifier The stringified object reference of the
  997. * desired service.
  998. * @return An object reference for the desired service.
  999. * @exception InvalidName The supplied identifier is not associated
  1000. * with a known service.
  1001. * @exception SystemException One of a fixed set of Corba system exceptions.
  1002. */
  1003. org.omg.CORBA.Object resolve_initial_references(String identifier)
  1004. throws InvalidName
  1005. {
  1006. return cachedInitialReferences(identifier);
  1007. }
  1008. private org.omg.CORBA.Object resolve(String identifier, String host,
  1009. int port)
  1010. {
  1011. // REVISIT - this should be implemented using DII to avoid
  1012. // duplicating unnecessary exception handling code.
  1013. boolean remarshal = true;
  1014. // URL not specified: do bootstrapping
  1015. ClientDelegate sc = this.getInitialRep(host, port);
  1016. // Invoke.
  1017. InputStream is = null;
  1018. // If there is a location forward then you will need
  1019. // to invoke again on the updated information.
  1020. // Just calling this same routine with the same host/port
  1021. // does not take the location forward info into account.
  1022. while (remarshal) {
  1023. remarshal = false;
  1024. OutputStream os = (OutputStream) sc.createRequest("get", false);
  1025. os.write_string(identifier);
  1026. try {
  1027. // The only reason null is passed is to get the version of
  1028. // invoke used by streams. Otherwise the PortableInterceptor
  1029. // call stack will become unbalanced since the version of
  1030. // invoke which only takes the stream does not call
  1031. // PortableInterceptor ending points.
  1032. // Note that the first parameter is ignored inside invoke.
  1033. is = sc.invoke((org.omg.CORBA.Object)null, os);
  1034. } catch (ApplicationException e) {
  1035. throw new INTERNAL("InitialNamingClient.resolve: Caught an ApplicationException. This should never happen.");
  1036. } catch (RemarshalException e) {
  1037. remarshal = true;
  1038. }
  1039. }
  1040. return is.read_Object();
  1041. }
  1042. org.omg.CORBA.Object resolve_initial_references(String identifier,
  1043. String modifier)
  1044. throws InvalidName
  1045. {
  1046. int ind = modifier.indexOf(":");
  1047. if (ind <= 0)
  1048. throw new DATA_CONVERSION(
  1049. com.sun.corba.se.internal.orbutil.MinorCodes.BAD_MODIFIER,
  1050. CompletionStatus.COMPLETED_NO);
  1051. try {
  1052. String hostName = modifier.substring(0,ind);
  1053. int port = java.lang.Integer.parseInt(modifier.substring(ind+1,
  1054. modifier.length()));
  1055. return resolve_initial_references(identifier, hostName, port);
  1056. } catch (Exception e) {
  1057. throw new DATA_CONVERSION(
  1058. com.sun.corba.se.internal.orbutil.MinorCodes.BAD_MODIFIER,
  1059. CompletionStatus.COMPLETED_NO);
  1060. }
  1061. }
  1062. org.omg.CORBA.Object resolve_initial_references(String identifier,
  1063. String host, int port)
  1064. throws InvalidName
  1065. {
  1066. org.omg.CORBA.Object result = resolve(identifier, host, port);
  1067. if (result == null)
  1068. throw new InvalidName();
  1069. return result;
  1070. }
  1071. private synchronized org.omg.CORBA.Object cachedInitialReferences(
  1072. String identifier)
  1073. throws InvalidName
  1074. {
  1075. org.omg.CORBA.Object result = null;
  1076. String sresult = null;
  1077. // Check cache
  1078. if (resolvedInitialReferences != null)
  1079. sresult = resolvedInitialReferences.getProperty(identifier);
  1080. // Found it?
  1081. if (sresult == null) {
  1082. // First try to resolve the identifier using -ORBInitDef definition
  1083. sresult = resolveUsingORBInitRef( identifier );
  1084. if( sresult == null ) {
  1085. // Second try to resolve the identifier using
  1086. // -ORBDefaultInitDef definition
  1087. sresult = resolveUsingORBDefaultInitRef( identifier );
  1088. }
  1089. if( sresult == null ) {
  1090. // Last try to resolve the identifier using BootStrap protocol
  1091. sresult = resolveUsingBootstrapProtocol( identifier );
  1092. if( sresult == null ) {
  1093. // If all three paths fail, Throw an InvalidName exception
  1094. throw new InvalidName();
  1095. }
  1096. }
  1097. try {
  1098. result = orb.string_to_object(sresult);
  1099. } catch( Exception e ) {
  1100. result = null;
  1101. }
  1102. if (resolvedInitialReferences == null)
  1103. resolvedInitialReferences = new java.util.Properties();
  1104. // Add to cached properties
  1105. if (sresult != null && sresult.length() > 0)
  1106. resolvedInitialReferences.put(identifier,sresult);
  1107. } else {
  1108. // Get from cache
  1109. result = orb.string_to_object(sresult);
  1110. }
  1111. return result;
  1112. }
  1113. /** If GIOP Version is not correct, This method throws a BAD_PARAM
  1114. * Exception.
  1115. */
  1116. private void validateGIOPVersion( int major, int minor ) {
  1117. if((major>ORBConstants.MAJORNUMBER_SUPPORTED)
  1118. ||(minor>ORBConstants.MINORNUMBERMAX ) )
  1119. {
  1120. // Bad Version Number for IIOP
  1121. throw new org.omg.CORBA.BAD_PARAM(
  1122. MinorCodes.INS_BAD_ADDRESS,
  1123. CompletionStatus.COMPLETED_NO);
  1124. }
  1125. }
  1126. /** Decode method removes URL escapes as per IETF 2386 RFP.
  1127. */
  1128. private String decode( String stringToDecode ) {
  1129. StringWriter theStringWithoutEscape = new StringWriter();
  1130. for( int i = 0; i < stringToDecode.length(); i++ )
  1131. {
  1132. char c = stringToDecode.charAt( i ) ;
  1133. if( c != '%' ) {
  1134. theStringWithoutEscape.write( c );
  1135. } else {
  1136. // Get the two hexadecimal digits and convert that into int
  1137. i++;
  1138. int Hex1 = ORBUtility.hexOf( stringToDecode.charAt(i) );
  1139. i++;
  1140. int Hex2 = ORBUtility.hexOf( stringToDecode.charAt(i) );
  1141. int value = (Hex1 * 16) + Hex2;
  1142. // Convert the integer to ASCII
  1143. theStringWithoutEscape.write( (char) value );
  1144. }
  1145. }
  1146. return theStringWithoutEscape.toString();
  1147. }
  1148. }