| /* |
| * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| 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 sun.corba.EncapsInputStreamFactory; |
| |
| 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.logging.OMGSystemException; |
| 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 ; |
| OMGSystemException omgWrapper ; |
| 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 ) ; |
| omgWrapper = OMGSystemException.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 = EncapsInputStreamFactory.newEncapsInputStream(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 ) ; |
| if (insURL == null) |
| throw omgWrapper.soBadSchemeName() ; |
| 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; |
| } |
| } |
| } |