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