1. /*
  2. * @(#)INSURLOperationImpl.java 1.86 04/06/21
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package com.sun.corba.se.impl.resolver;
  8. import java.util.List ;
  9. import java.util.Map ;
  10. import java.util.Comparator ;
  11. import java.util.Iterator ;
  12. import java.util.HashMap ;
  13. import java.util.ArrayList ;
  14. import java.util.Collections ;
  15. import org.omg.CosNaming.NamingContextExt ;
  16. import org.omg.CosNaming.NamingContextExtHelper ;
  17. import com.sun.corba.se.spi.ior.IOR;
  18. import com.sun.corba.se.spi.ior.IORTemplate;
  19. import com.sun.corba.se.spi.ior.ObjectKey;
  20. import com.sun.corba.se.spi.ior.IORFactories;
  21. import com.sun.corba.se.spi.ior.ObjectKeyFactory ;
  22. import com.sun.corba.se.spi.ior.iiop.IIOPAddress;
  23. import com.sun.corba.se.spi.ior.iiop.IIOPProfile ;
  24. import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate ;
  25. import com.sun.corba.se.spi.ior.iiop.IIOPFactories ;
  26. import com.sun.corba.se.spi.ior.iiop.GIOPVersion;
  27. import com.sun.corba.se.spi.ior.iiop.AlternateIIOPAddressComponent;
  28. import com.sun.corba.se.spi.logging.CORBALogDomains ;
  29. import com.sun.corba.se.spi.orb.Operation;
  30. import com.sun.corba.se.spi.orb.ORB;
  31. import com.sun.corba.se.spi.resolver.Resolver;
  32. import com.sun.corba.se.impl.encoding.EncapsInputStream;
  33. import com.sun.corba.se.impl.logging.ORBUtilSystemException ;
  34. import com.sun.corba.se.impl.naming.namingutil.INSURLHandler;
  35. import com.sun.corba.se.impl.naming.namingutil.IIOPEndpointInfo;
  36. import com.sun.corba.se.impl.naming.namingutil.INSURL;
  37. import com.sun.corba.se.impl.naming.namingutil.CorbalocURL;
  38. import com.sun.corba.se.impl.naming.namingutil.CorbanameURL;
  39. import com.sun.corba.se.impl.orbutil.ORBConstants;
  40. import com.sun.corba.se.impl.orbutil.ORBUtility;
  41. /**
  42. * This class provides an Operation that converts from CORBA INS URL strings into
  43. * CORBA object references. It will eventually become extensible, but for now it
  44. * simply encapsulates the existing implementation. Once the full extensibility
  45. * is in place, we want this operation to convert string to INSURL, which has mainly
  46. * a public resolver method that returns an object reference.
  47. *
  48. * @author Hemanth
  49. * @author Ken
  50. */
  51. public class INSURLOperationImpl implements Operation
  52. {
  53. ORB orb;
  54. ORBUtilSystemException wrapper ;
  55. Resolver bootstrapResolver ;
  56. // Root Naming Context for default resolution of names.
  57. private NamingContextExt rootNamingContextExt;
  58. private Object rootContextCacheLock = new Object() ;
  59. // The URLHandler to parse INS URL's
  60. private INSURLHandler insURLHandler = INSURLHandler.getINSURLHandler() ;
  61. public INSURLOperationImpl( ORB orb, Resolver bootstrapResolver )
  62. {
  63. this.orb = orb ;
  64. wrapper = ORBUtilSystemException.get( orb,
  65. CORBALogDomains.ORB_RESOLVER ) ;
  66. this.bootstrapResolver = bootstrapResolver ;
  67. }
  68. private static final int NIBBLES_PER_BYTE = 2 ;
  69. private static final int UN_SHIFT = 4 ; // "UPPER NIBBLE" shift factor for <<
  70. /** This static method takes a Stringified IOR and converts it into IOR object.
  71. * It is the caller's responsibility to only pass strings that start with "IOR:".
  72. */
  73. private org.omg.CORBA.Object getIORFromString( String str )
  74. {
  75. // Length must be even for str to be valid
  76. if ( (str.length() & 1) == 1 )
  77. throw wrapper.badStringifiedIorLen() ;
  78. byte[] buf = new byte[(str.length() - ORBConstants.STRINGIFY_PREFIX.length()) / NIBBLES_PER_BYTE];
  79. for (int i=ORBConstants.STRINGIFY_PREFIX.length(), j=0; i < str.length(); i +=NIBBLES_PER_BYTE, j++) {
  80. buf[j] = (byte)((ORBUtility.hexOf(str.charAt(i)) << UN_SHIFT) & 0xF0);
  81. buf[j] |= (byte)(ORBUtility.hexOf(str.charAt(i+1)) & 0x0F);
  82. }
  83. EncapsInputStream s = new EncapsInputStream(orb, buf, buf.length,
  84. orb.getORBData().getGIOPVersion());
  85. s.consumeEndian();
  86. return s.read_Object() ;
  87. }
  88. public Object operate( Object arg )
  89. {
  90. if (arg instanceof String) {
  91. String str = (String)arg ;
  92. if (str.startsWith( ORBConstants.STRINGIFY_PREFIX ))
  93. // XXX handle this as just another URL scheme
  94. return getIORFromString( str ) ;
  95. else {
  96. INSURL insURL = insURLHandler.parseURL( str ) ;
  97. return resolveINSURL( insURL ) ;
  98. }
  99. }
  100. throw wrapper.stringExpected() ;
  101. }
  102. private org.omg.CORBA.Object resolveINSURL( INSURL theURLObject ) {
  103. // XXX resolve should be a method on INSURL
  104. if( theURLObject.isCorbanameURL() ) {
  105. return resolveCorbaname( (CorbanameURL)theURLObject );
  106. } else {
  107. return resolveCorbaloc( (CorbalocURL)theURLObject );
  108. }
  109. }
  110. /**
  111. * resolves a corbaloc: url that is encapsulated in a CorbalocURL object.
  112. *
  113. * @return the CORBA.Object if resolution is successful
  114. */
  115. private org.omg.CORBA.Object resolveCorbaloc(
  116. CorbalocURL theCorbaLocObject )
  117. {
  118. org.omg.CORBA.Object result = null;
  119. // If RIR flag is true use the Bootstrap protocol
  120. if( theCorbaLocObject.getRIRFlag( ) ) {
  121. result = bootstrapResolver.resolve(theCorbaLocObject.getKeyString());
  122. } else {
  123. result = getIORUsingCorbaloc( theCorbaLocObject );
  124. }
  125. return result;
  126. }
  127. /**
  128. * resolves a corbaname: url that is encapsulated in a CorbanameURL object.
  129. *
  130. * @return the CORBA.Object if resolution is successful
  131. */
  132. private org.omg.CORBA.Object resolveCorbaname( CorbanameURL theCorbaName ) {
  133. org.omg.CORBA.Object result = null;
  134. try {
  135. NamingContextExt theNamingContext = null;
  136. if( theCorbaName.getRIRFlag( ) ) {
  137. // Case 1 of corbaname: rir#
  138. theNamingContext = getDefaultRootNamingContext( );
  139. } else {
  140. // Case 2 of corbaname: ::hostname#
  141. org.omg.CORBA.Object corbalocResult =
  142. getIORUsingCorbaloc( theCorbaName );
  143. if( corbalocResult == null ) {
  144. return null;
  145. }
  146. theNamingContext =
  147. NamingContextExtHelper.narrow( corbalocResult );
  148. }
  149. String StringifiedName = theCorbaName.getStringifiedName( );
  150. if( StringifiedName == null ) {
  151. // This means return the Root Naming context
  152. return theNamingContext;
  153. } else {
  154. return theNamingContext.resolve_str( StringifiedName );
  155. }
  156. } catch( Exception e ) {
  157. clearRootNamingContextCache( );
  158. return null;
  159. }
  160. }
  161. /**
  162. * This is an internal method to get the IOR from the CorbalocURL object.
  163. *
  164. * @return the CORBA.Object if resolution is successful
  165. */
  166. private org.omg.CORBA.Object getIORUsingCorbaloc( INSURL corbalocObject )
  167. {
  168. Map profileMap = new HashMap();
  169. List profileList1_0 = new ArrayList();
  170. // corbalocObject cannot be null, because it's validated during
  171. // parsing. So no null check is required.
  172. java.util.List theEndpointInfo = corbalocObject.getEndpointInfo();
  173. String theKeyString = corbalocObject.getKeyString();
  174. // If there is no KeyString then it's invalid
  175. if( theKeyString == null ) {
  176. return null;
  177. }
  178. ObjectKey key = orb.getObjectKeyFactory().create(
  179. theKeyString.getBytes() );
  180. IORTemplate iortemp = IORFactories.makeIORTemplate( key.getTemplate() );
  181. java.util.Iterator iterator = theEndpointInfo.iterator( );
  182. while( iterator.hasNext( ) ) {
  183. IIOPEndpointInfo element =
  184. (IIOPEndpointInfo) iterator.next( );
  185. IIOPAddress addr = IIOPFactories.makeIIOPAddress( orb, element.getHost(),
  186. element.getPort() );
  187. GIOPVersion giopVersion = GIOPVersion.getInstance( (byte)element.getMajor(),
  188. (byte)element.getMinor());
  189. IIOPProfileTemplate profileTemplate = null;
  190. if (giopVersion.equals(GIOPVersion.V1_0)) {
  191. profileTemplate = IIOPFactories.makeIIOPProfileTemplate(
  192. orb, giopVersion, addr);
  193. profileList1_0.add(profileTemplate);
  194. } else {
  195. if (profileMap.get(giopVersion) == null) {
  196. profileTemplate = IIOPFactories.makeIIOPProfileTemplate(
  197. orb, giopVersion, addr);
  198. profileMap.put(giopVersion, profileTemplate);
  199. } else {
  200. profileTemplate = (IIOPProfileTemplate)profileMap.get(giopVersion);
  201. AlternateIIOPAddressComponent iiopAddressComponent =
  202. IIOPFactories.makeAlternateIIOPAddressComponent(addr);
  203. profileTemplate.add(iiopAddressComponent);
  204. }
  205. }
  206. }
  207. GIOPVersion giopVersion = orb.getORBData().getGIOPVersion();
  208. IIOPProfileTemplate pTemplate = (IIOPProfileTemplate)profileMap.get(giopVersion);
  209. if (pTemplate != null) {
  210. iortemp.add(pTemplate); // Add profile for GIOP version used by this ORB
  211. profileMap.remove(giopVersion); // Now remove this value from the map
  212. }
  213. // Create a comparator that can sort in decending order (1.2, 1.1, ...)
  214. Comparator comp = new Comparator() {
  215. public int compare(Object o1, Object o2) {
  216. GIOPVersion gv1 = (GIOPVersion)o1;
  217. GIOPVersion gv2 = (GIOPVersion)o2;
  218. return (gv1.lessThan(gv2) ? 1 : (gv1.equals(gv2) ? 0 : -1));
  219. };
  220. };
  221. // Now sort using the above comparator
  222. List list = new ArrayList(profileMap.keySet());
  223. Collections.sort(list, comp);
  224. // Add the profiles in the sorted order
  225. Iterator iter = list.iterator();
  226. while (iter.hasNext()) {
  227. IIOPProfileTemplate pt = (IIOPProfileTemplate)profileMap.get(iter.next());
  228. iortemp.add(pt);
  229. }
  230. // Finally add the 1.0 profiles
  231. iortemp.addAll(profileList1_0);
  232. IOR ior = iortemp.makeIOR( orb, "", key.getId() ) ;
  233. return ORBUtility.makeObjectReference( ior ) ;
  234. }
  235. /**
  236. * This is required for corbaname: resolution. Currently we
  237. * are not caching RootNamingContext as the reference to rootNamingContext
  238. * may not be Persistent in all the implementations.
  239. * _REVISIT_ to clear the rootNamingContext in case of COMM_FAILURE.
  240. *
  241. * @return the org.omg.COSNaming.NamingContextExt if resolution is
  242. * successful
  243. *
  244. */
  245. private NamingContextExt getDefaultRootNamingContext( ) {
  246. synchronized( rootContextCacheLock ) {
  247. if( rootNamingContextExt == null ) {
  248. try {
  249. rootNamingContextExt =
  250. NamingContextExtHelper.narrow(
  251. orb.getLocalResolver().resolve( "NameService" ) );
  252. } catch( Exception e ) {
  253. rootNamingContextExt = null;
  254. }
  255. }
  256. }
  257. return rootNamingContextExt;
  258. }
  259. /**
  260. * A utility method to clear the RootNamingContext, if there is an
  261. * exception in resolving CosNaming:Name from the RootNamingContext,
  262. */
  263. private void clearRootNamingContextCache( ) {
  264. synchronized( rootContextCacheLock ) {
  265. rootNamingContextExt = null;
  266. }
  267. }
  268. }