blob: eb911cd83ce8bc17742eb44fb9b61f1e43bb1068 [file] [log] [blame]
/*
* Copyright (c) 2002, 2003, 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.naming.namingutil;
import java.util.*;
import com.sun.corba.se.spi.logging.CORBALogDomains ;
import com.sun.corba.se.impl.logging.NamingSystemException ;
/**
* The corbaloc: URL definitions from the -ORBInitDef and -ORBDefaultInitDef's
* will be parsed and converted to this object. This object is capable of
* storing multiple Host profiles as defined in the CorbaLoc grammer.
*
* @author Hemanth
*/
public class CorbalocURL extends INSURLBase
{
static NamingSystemException wrapper = NamingSystemException.get(
CORBALogDomains.NAMING_READ ) ;
/**
* This constructor parses the URL and initializes all the variables. Once
* the URL Object is constructed it is immutable. URL parameter is a
* corbaloc: URL string with 'corbaloc:' prefix stripped.
*/
public CorbalocURL( String aURL ) {
String url = aURL;
if( url != null ) {
try {
// First Clean the URL Escapes if there are any
url = Utility.cleanEscapes( url );
} catch( Exception e ) {
// There is something wrong with the URL escapes used
// so throw an exception
badAddress( e );
}
int endIndex = url.indexOf( '/' );
if( endIndex == -1 ) {
// If there is no '/' then the endIndex is at the end of the URL
endIndex = url.length();
}
// _REVISIT_: Add a testcase to check 'corbaloc:/'
if( endIndex == 0 ) {
// The url starts with a '/', it's an error
badAddress( null );
}
// Anything between corbaloc: and / is the host,port information
// of the server where the Service Object is located
StringTokenizer endpoints = new StringTokenizer(
url.substring( 0, endIndex ), "," );
// NOTE:
// There should be atleast one token, because there are checks
// to make sure that there is host information before the
// delimiter '/'. So no need to explicitly check for number of
// tokens != 0
while( endpoints.hasMoreTokens( ) ) {
String endpointInfo = endpoints.nextToken();
IIOPEndpointInfo iiopEndpointInfo = null;
if( endpointInfo.startsWith( "iiop:" ) ) {
iiopEndpointInfo = handleIIOPColon( endpointInfo );
} else if( endpointInfo.startsWith( "rir:" ) ) {
handleRIRColon( endpointInfo );
rirFlag = true;
} else if( endpointInfo.startsWith( ":" ) ) {
iiopEndpointInfo = handleColon( endpointInfo );
} else {
// Right now we are not allowing any other protocol
// other than iiop:, rir: so raise exception indicating
// that the URL is malformed
badAddress( null );
}
if ( rirFlag == false ) {
// Add the Host information if RIR flag is set,
// If RIR is set then it means use the internal Boot
// Strap protocol for Key String resolution
if( theEndpointInfo == null ) {
theEndpointInfo = new java.util.ArrayList( );
}
theEndpointInfo.add( iiopEndpointInfo );
}
}
// If there is something after corbaloc:endpointInfo/
// then that is the keyString
if( url.length() > (endIndex + 1) ) {
theKeyString = url.substring( endIndex + 1 );
}
}
}
/**
* A Utility method to throw BAD_PARAM exception to signal malformed
* INS URL.
*/
private void badAddress( java.lang.Throwable e )
{
throw wrapper.insBadAddress( e ) ;
}
/**
* If there is 'iiop:' token in the URL, this method will parses
* and validates that host and port information.
*/
private IIOPEndpointInfo handleIIOPColon( String iiopInfo )
{
// Check the iiop syntax
iiopInfo = iiopInfo.substring( NamingConstants.IIOP_LENGTH );
return handleColon( iiopInfo );
}
/**
* This is to handle the case of host information with no 'iiop:' prefix.
* instead if ':' is specified then iiop is assumed.
*/
private IIOPEndpointInfo handleColon( String iiopInfo ) {
// String after ":"
iiopInfo = iiopInfo.substring( 1 );
String hostandport = iiopInfo;
// The format can be 1.2@<host>:<port>
StringTokenizer tokenizer = new StringTokenizer( iiopInfo, "@" );
IIOPEndpointInfo iiopEndpointInfo = new IIOPEndpointInfo( );
int tokenCount = tokenizer.countTokens( );
// There can be 1 or 2 tokens with '@' as the delimiter
// - if there is only 1 token then there is no GIOP version
// information. A Default GIOP version of 1.2 is used.
// - if there are 2 tokens then there is GIOP version is specified
// - if there are no tokens or more than 2 tokens, then that's an
// error
if( ( tokenCount == 0 )
||( tokenCount > 2 ))
{
badAddress( null );
}
if( tokenCount == 2 ) {
// There is VersionInformation after iiop:
String version = tokenizer.nextToken( );
int dot = version.indexOf('.');
// There is a version without ., which means
// Malformed list
if (dot == -1) {
badAddress( null );
}
try {
iiopEndpointInfo.setVersion(
Integer.parseInt( version.substring( 0, dot )),
Integer.parseInt( version.substring(dot+1)) );
hostandport = tokenizer.nextToken( );
} catch( Throwable e ) {
badAddress( e );
}
}
try {
// A Hack to differentiate IPV6 address
// from IPV4 address, Current Resolution
// is to use [ ] to differentiate ipv6 host
int squareBracketBeginIndex = hostandport.indexOf ( '[' );
if( squareBracketBeginIndex != -1 ) {
// ipv6Host should be enclosed in
// [ ], if not it will result in a
// BAD_PARAM exception
String ipv6Port = getIPV6Port( hostandport );
if( ipv6Port != null ) {
iiopEndpointInfo.setPort( Integer.parseInt( ipv6Port ));
}
iiopEndpointInfo.setHost( getIPV6Host( hostandport ));
return iiopEndpointInfo;
}
tokenizer = new StringTokenizer( hostandport, ":" );
// There are three possible cases here
// 1. Host and Port is explicitly specified by using ":" as a
// a separator
// 2. Only Host is specified without the port
// 3. HostAndPort info is null
if( tokenizer.countTokens( ) == 2 ) {
// Case 1: There is Host and Port Info
iiopEndpointInfo.setHost( tokenizer.nextToken( ) );
iiopEndpointInfo.setPort( Integer.parseInt(
tokenizer.nextToken( )));
} else {
if( ( hostandport != null )
&&( hostandport.length() != 0 ) )
{
// Case 2: Only Host is specified. iiopEndpointInfo is
// initialized to use the default INS port, if no port is
// specified
iiopEndpointInfo.setHost( hostandport );
}
// Case 3: If no Host and Port info is provided then we use the
// the default LocalHost and INSPort. iiopEndpointInfo is
// already initialized with this info.
}
} catch( Throwable e ) {
// Any kind of Exception is bad here.
// Possible causes: A Number Format exception because port info is
// malformed
badAddress( e );
}
Utility.validateGIOPVersion( iiopEndpointInfo );
return iiopEndpointInfo;
}
/**
* Validate 'rir:' case.
*/
private void handleRIRColon( String rirInfo )
{
if( rirInfo.length() != NamingConstants.RIRCOLON_LENGTH ) {
badAddress( null );
}
}
/**
* Returns an IPV6 Port that is after [<ipv6>]:. There is no validation
* done here, if it is an incorrect port then the request through
* this URL results in a COMM_FAILURE, otherwise malformed list will
* result in BAD_PARAM exception thrown in checkcorbalocGrammer.
*/
private String getIPV6Port( String endpointInfo )
{
int squareBracketEndIndex = endpointInfo.indexOf ( ']' );
// If there is port information, then it has to be after ] bracket
// indexOf returns the count from the index of zero as the base, so
// equality check requires squareBracketEndIndex + 1.
if( (squareBracketEndIndex + 1) != (endpointInfo.length( )) ) {
if( endpointInfo.charAt( squareBracketEndIndex + 1 ) != ':' ) {
throw new RuntimeException(
"Host and Port is not separated by ':'" );
}
// PortInformation should be after ']:' delimiter
// If there is an exception then it will be caught in
// checkcorbaGrammer method and rethrown as BAD_PARAM
return endpointInfo.substring( squareBracketEndIndex + 2 );
}
return null;
}
/**
* Returns an IPV6 Host that is inside [ ] tokens. There is no validation
* done here, if it is an incorrect IPV6 address then the request through
* this URL results in a COMM_FAILURE, otherwise malformed list will
* result in BAD_PARAM exception thrown in checkcorbalocGrammer.
*/
private String getIPV6Host( String endpointInfo ) {
// ipv6Host should be enclosed in
// [ ], if not it will result in a
// BAD_PARAM exception
int squareBracketEndIndex = endpointInfo.indexOf ( ']' );
// get the host between [ ]
String ipv6Host = endpointInfo.substring( 1, squareBracketEndIndex );
return ipv6Host;
}
/**
* Will be true only in CorbanameURL class.
*/
public boolean isCorbanameURL( ) {
return false;
}
}