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