/* * @(#)INSURLOperationImpl.java 1.86 04/06/21 * * Copyright 2004 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. */ package com.sun.corba.se.impl.resolver; import java.util.List ; import java.util.Map ; import java.util.Comparator ; import java.util.Iterator ; import java.util.HashMap ; import java.util.ArrayList ; import java.util.Collections ; import org.omg.CosNaming.NamingContextExt ; import org.omg.CosNaming.NamingContextExtHelper ; import com.sun.corba.se.spi.ior.IOR; import com.sun.corba.se.spi.ior.IORTemplate; import com.sun.corba.se.spi.ior.ObjectKey; import com.sun.corba.se.spi.ior.IORFactories; import com.sun.corba.se.spi.ior.ObjectKeyFactory ; import com.sun.corba.se.spi.ior.iiop.IIOPAddress; import com.sun.corba.se.spi.ior.iiop.IIOPProfile ; import com.sun.corba.se.spi.ior.iiop.IIOPProfileTemplate ; import com.sun.corba.se.spi.ior.iiop.IIOPFactories ; import com.sun.corba.se.spi.ior.iiop.GIOPVersion; import com.sun.corba.se.spi.ior.iiop.AlternateIIOPAddressComponent; import com.sun.corba.se.spi.logging.CORBALogDomains ; import com.sun.corba.se.spi.orb.Operation; import com.sun.corba.se.spi.orb.ORB; import com.sun.corba.se.spi.resolver.Resolver; import com.sun.corba.se.impl.encoding.EncapsInputStream; import com.sun.corba.se.impl.logging.ORBUtilSystemException ; import com.sun.corba.se.impl.naming.namingutil.INSURLHandler; import com.sun.corba.se.impl.naming.namingutil.IIOPEndpointInfo; import com.sun.corba.se.impl.naming.namingutil.INSURL; import com.sun.corba.se.impl.naming.namingutil.CorbalocURL; import com.sun.corba.se.impl.naming.namingutil.CorbanameURL; import com.sun.corba.se.impl.orbutil.ORBConstants; import com.sun.corba.se.impl.orbutil.ORBUtility; /** * This class provides an Operation that converts from CORBA INS URL strings into * CORBA object references. It will eventually become extensible, but for now it * simply encapsulates the existing implementation. Once the full extensibility * is in place, we want this operation to convert string to INSURL, which has mainly * a public resolver method that returns an object reference. * * @author Hemanth * @author Ken */ public class INSURLOperationImpl implements Operation { ORB orb; ORBUtilSystemException wrapper ; Resolver bootstrapResolver ; // Root Naming Context for default resolution of names. private NamingContextExt rootNamingContextExt; private Object rootContextCacheLock = new Object() ; // The URLHandler to parse INS URL's private INSURLHandler insURLHandler = INSURLHandler.getINSURLHandler() ; public INSURLOperationImpl( ORB orb, Resolver bootstrapResolver ) { this.orb = orb ; wrapper = ORBUtilSystemException.get( orb, CORBALogDomains.ORB_RESOLVER ) ; this.bootstrapResolver = bootstrapResolver ; } private static final int NIBBLES_PER_BYTE = 2 ; private static final int UN_SHIFT = 4 ; // "UPPER NIBBLE" shift factor for << /** This static method takes a Stringified IOR and converts it into IOR object. * It is the caller's responsibility to only pass strings that start with "IOR:". */ private org.omg.CORBA.Object getIORFromString( String str ) { // Length must be even for str to be valid if ( (str.length() & 1) == 1 ) throw wrapper.badStringifiedIorLen() ; byte[] buf = new byte[(str.length() - ORBConstants.STRINGIFY_PREFIX.length()) / NIBBLES_PER_BYTE]; for (int i=ORBConstants.STRINGIFY_PREFIX.length(), j=0; i < str.length(); i +=NIBBLES_PER_BYTE, j++) { buf[j] = (byte)((ORBUtility.hexOf(str.charAt(i)) << UN_SHIFT) & 0xF0); buf[j] |= (byte)(ORBUtility.hexOf(str.charAt(i+1)) & 0x0F); } EncapsInputStream s = new EncapsInputStream(orb, buf, buf.length, orb.getORBData().getGIOPVersion()); s.consumeEndian(); return s.read_Object() ; } public Object operate( Object arg ) { if (arg instanceof String) { String str = (String)arg ; if (str.startsWith( ORBConstants.STRINGIFY_PREFIX )) // XXX handle this as just another URL scheme return getIORFromString( str ) ; else { INSURL insURL = insURLHandler.parseURL( str ) ; return resolveINSURL( insURL ) ; } } throw wrapper.stringExpected() ; } private org.omg.CORBA.Object resolveINSURL( INSURL theURLObject ) { // XXX resolve should be a method on INSURL if( theURLObject.isCorbanameURL() ) { return resolveCorbaname( (CorbanameURL)theURLObject ); } else { return resolveCorbaloc( (CorbalocURL)theURLObject ); } } /** * resolves a corbaloc: url that is encapsulated in a CorbalocURL object. * * @return the CORBA.Object if resolution is successful */ private org.omg.CORBA.Object resolveCorbaloc( CorbalocURL theCorbaLocObject ) { org.omg.CORBA.Object result = null; // If RIR flag is true use the Bootstrap protocol if( theCorbaLocObject.getRIRFlag( ) ) { result = bootstrapResolver.resolve(theCorbaLocObject.getKeyString()); } else { result = getIORUsingCorbaloc( theCorbaLocObject ); } return result; } /** * resolves a corbaname: url that is encapsulated in a CorbanameURL object. * * @return the CORBA.Object if resolution is successful */ private org.omg.CORBA.Object resolveCorbaname( CorbanameURL theCorbaName ) { org.omg.CORBA.Object result = null; try { NamingContextExt theNamingContext = null; if( theCorbaName.getRIRFlag( ) ) { // Case 1 of corbaname: rir# theNamingContext = getDefaultRootNamingContext( ); } else { // Case 2 of corbaname: ::hostname# org.omg.CORBA.Object corbalocResult = getIORUsingCorbaloc( theCorbaName ); if( corbalocResult == null ) { return null; } theNamingContext = NamingContextExtHelper.narrow( corbalocResult ); } String StringifiedName = theCorbaName.getStringifiedName( ); if( StringifiedName == null ) { // This means return the Root Naming context return theNamingContext; } else { return theNamingContext.resolve_str( StringifiedName ); } } catch( Exception e ) { clearRootNamingContextCache( ); return null; } } /** * This is an internal method to get the IOR from the CorbalocURL object. * * @return the CORBA.Object if resolution is successful */ private org.omg.CORBA.Object getIORUsingCorbaloc( INSURL corbalocObject ) { Map profileMap = new HashMap(); List profileList1_0 = new ArrayList(); // corbalocObject cannot be null, because it's validated during // parsing. So no null check is required. java.util.List theEndpointInfo = corbalocObject.getEndpointInfo(); String theKeyString = corbalocObject.getKeyString(); // If there is no KeyString then it's invalid if( theKeyString == null ) { return null; } ObjectKey key = orb.getObjectKeyFactory().create( theKeyString.getBytes() ); IORTemplate iortemp = IORFactories.makeIORTemplate( key.getTemplate() ); java.util.Iterator iterator = theEndpointInfo.iterator( ); while( iterator.hasNext( ) ) { IIOPEndpointInfo element = (IIOPEndpointInfo) iterator.next( ); IIOPAddress addr = IIOPFactories.makeIIOPAddress( orb, element.getHost(), element.getPort() ); GIOPVersion giopVersion = GIOPVersion.getInstance( (byte)element.getMajor(), (byte)element.getMinor()); IIOPProfileTemplate profileTemplate = null; if (giopVersion.equals(GIOPVersion.V1_0)) { profileTemplate = IIOPFactories.makeIIOPProfileTemplate( orb, giopVersion, addr); profileList1_0.add(profileTemplate); } else { if (profileMap.get(giopVersion) == null) { profileTemplate = IIOPFactories.makeIIOPProfileTemplate( orb, giopVersion, addr); profileMap.put(giopVersion, profileTemplate); } else { profileTemplate = (IIOPProfileTemplate)profileMap.get(giopVersion); AlternateIIOPAddressComponent iiopAddressComponent = IIOPFactories.makeAlternateIIOPAddressComponent(addr); profileTemplate.add(iiopAddressComponent); } } } GIOPVersion giopVersion = orb.getORBData().getGIOPVersion(); IIOPProfileTemplate pTemplate = (IIOPProfileTemplate)profileMap.get(giopVersion); if (pTemplate != null) { iortemp.add(pTemplate); // Add profile for GIOP version used by this ORB profileMap.remove(giopVersion); // Now remove this value from the map } // Create a comparator that can sort in decending order (1.2, 1.1, ...) Comparator comp = new Comparator() { public int compare(Object o1, Object o2) { GIOPVersion gv1 = (GIOPVersion)o1; GIOPVersion gv2 = (GIOPVersion)o2; return (gv1.lessThan(gv2) ? 1 : (gv1.equals(gv2) ? 0 : -1)); }; }; // Now sort using the above comparator List list = new ArrayList(profileMap.keySet()); Collections.sort(list, comp); // Add the profiles in the sorted order Iterator iter = list.iterator(); while (iter.hasNext()) { IIOPProfileTemplate pt = (IIOPProfileTemplate)profileMap.get(iter.next()); iortemp.add(pt); } // Finally add the 1.0 profiles iortemp.addAll(profileList1_0); IOR ior = iortemp.makeIOR( orb, "", key.getId() ) ; return ORBUtility.makeObjectReference( ior ) ; } /** * This is required for corbaname: resolution. Currently we * are not caching RootNamingContext as the reference to rootNamingContext * may not be Persistent in all the implementations. * _REVISIT_ to clear the rootNamingContext in case of COMM_FAILURE. * * @return the org.omg.COSNaming.NamingContextExt if resolution is * successful * */ private NamingContextExt getDefaultRootNamingContext( ) { synchronized( rootContextCacheLock ) { if( rootNamingContextExt == null ) { try { rootNamingContextExt = NamingContextExtHelper.narrow( orb.getLocalResolver().resolve( "NameService" ) ); } catch( Exception e ) { rootNamingContextExt = null; } } } return rootNamingContextExt; } /** * A utility method to clear the RootNamingContext, if there is an * exception in resolving CosNaming:Name from the RootNamingContext, */ private void clearRootNamingContextCache( ) { synchronized( rootContextCacheLock ) { rootNamingContextExt = null; } } }