CorbalocURL.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 2002, 2003, 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.naming.namingutil;
27
28import java.util.*;
29
30import com.sun.corba.se.spi.logging.CORBALogDomains ;
31import com.sun.corba.se.impl.logging.NamingSystemException ;
32
33/**
34 *  The corbaloc: URL definitions from the -ORBInitDef and -ORBDefaultInitDef's
35 *  will be parsed and converted to  this object. This object is capable of
36 *  storing multiple  Host profiles as defined in the CorbaLoc grammer.
37 *
38 *  @author  Hemanth
39 */
40public class CorbalocURL extends INSURLBase
41{
42    static NamingSystemException wrapper = NamingSystemException.get(
43        CORBALogDomains.NAMING_READ ) ;
44
45    /**
46     * This constructor parses the URL and initializes all the variables. Once
47     * the URL Object is constructed it is immutable. URL parameter is a
48     * corbaloc: URL string with 'corbaloc:' prefix stripped.
49     */
50    public CorbalocURL( String aURL ) {
51        String url = aURL;
52
53        if( url != null ) {
54            try {
55                // First Clean the URL Escapes if there are any
56                url = Utility.cleanEscapes( url );
57            } catch( Exception e ) {
58                // There is something wrong with the URL escapes used
59                // so throw an exception
60                badAddress( e );
61            }
62            int endIndex = url.indexOf( '/' );
63            if( endIndex == -1 ) {
64                // If there is no '/' then the endIndex is at the end of the URL
65                endIndex = url.length();
66            }
67            // _REVISIT_: Add a testcase to check 'corbaloc:/'
68            if( endIndex == 0 )  {
69                // The url starts with a '/', it's an error
70                badAddress( null );
71            }
72            // Anything between corbaloc: and / is the host,port information
73            // of the server where the Service Object is located
74            StringTokenizer endpoints = new StringTokenizer(
75                url.substring( 0, endIndex ), "," );
76            // NOTE:
77            // There should be atleast one token, because there are checks
78            // to make sure that there is host information before the
79            // delimiter '/'. So no need to explicitly check for number of
80            // tokens != 0
81            while( endpoints.hasMoreTokens( ) ) {
82                String endpointInfo = endpoints.nextToken();
83                IIOPEndpointInfo iiopEndpointInfo = null;
84                if( endpointInfo.startsWith( "iiop:" ) ) {
85                    iiopEndpointInfo = handleIIOPColon( endpointInfo );
86                } else if( endpointInfo.startsWith( "rir:" ) ) {
87                    handleRIRColon( endpointInfo );
88                    rirFlag = true;
89                } else if( endpointInfo.startsWith( ":" ) ) {
90                    iiopEndpointInfo = handleColon( endpointInfo );
91                } else {
92                    // Right now we are not allowing any other protocol
93                    // other than iiop:, rir: so raise exception indicating
94                    // that the URL is malformed
95                    badAddress( null );
96                }
97                if ( rirFlag == false ) {
98                    // Add the Host information if RIR flag is set,
99                    // If RIR is set then it means use the internal Boot
100                    // Strap protocol for Key String resolution
101                    if( theEndpointInfo == null ) {
102                        theEndpointInfo = new java.util.ArrayList( );
103                    }
104                    theEndpointInfo.add( iiopEndpointInfo );
105                }
106            }
107            // If there is something after corbaloc:endpointInfo/
108            // then that is the keyString
109            if( url.length() > (endIndex + 1) ) {
110                theKeyString = url.substring( endIndex + 1 );
111            }
112        }
113    }
114
115
116    /**
117     *  A Utility method to throw BAD_PARAM exception to signal malformed
118     *  INS URL.
119     */
120    private void badAddress( java.lang.Throwable e )
121    {
122        throw wrapper.insBadAddress( e ) ;
123    }
124
125    /**
126     *  If there is 'iiop:' token in the URL, this method will parses
127     *  and  validates that host and port information.
128     */
129    private IIOPEndpointInfo handleIIOPColon( String iiopInfo )
130    {
131         // Check the iiop syntax
132         iiopInfo = iiopInfo.substring( NamingConstants.IIOP_LENGTH  );
133         return handleColon( iiopInfo );
134    }
135
136
137    /**
138     * This is to handle the case of host information with no 'iiop:' prefix.
139     * instead if ':' is specified then iiop is assumed.
140     */
141    private IIOPEndpointInfo handleColon( String iiopInfo ) {
142         // String after ":"
143         iiopInfo = iiopInfo.substring( 1 );
144         String hostandport = iiopInfo;
145         // The format can be 1.2@<host>:<port>
146         StringTokenizer tokenizer = new StringTokenizer( iiopInfo, "@" );
147         IIOPEndpointInfo iiopEndpointInfo = new IIOPEndpointInfo( );
148         int tokenCount = tokenizer.countTokens( );
149         // There can be 1 or 2 tokens with '@' as the delimiter
150         //  - if there is only 1 token then there is no GIOP version
151         //    information.  A Default GIOP version of 1.2 is used.
152         //  - if there are 2 tokens then there is GIOP version is specified
153         //  - if there are no tokens or more than 2 tokens, then that's an
154         //    error
155         if( ( tokenCount == 0 )
156           ||( tokenCount > 2 ))
157         {
158             badAddress( null );
159         }
160         if( tokenCount == 2 ) {
161            // There is VersionInformation after iiop:
162            String version     = tokenizer.nextToken( );
163            int dot = version.indexOf('.');
164            // There is a version without ., which means
165            // Malformed list
166            if (dot == -1) {
167                badAddress( null );
168            }
169            try {
170                iiopEndpointInfo.setVersion(
171                    Integer.parseInt( version.substring( 0, dot )),
172                    Integer.parseInt( version.substring(dot+1)) );
173                hostandport = tokenizer.nextToken( );
174            } catch( Throwable e ) {
175                badAddress( e );
176            }
177         }
178         try {
179           // A Hack to differentiate IPV6 address
180           // from IPV4 address, Current Resolution
181           // is to use [ ] to differentiate ipv6 host
182           int squareBracketBeginIndex = hostandport.indexOf ( '[' );
183           if( squareBracketBeginIndex != -1 ) {
184               // ipv6Host should be enclosed in
185               // [ ], if not it will result in a
186               // BAD_PARAM exception
187               String ipv6Port = getIPV6Port( hostandport );
188               if( ipv6Port != null ) {
189                   iiopEndpointInfo.setPort( Integer.parseInt( ipv6Port ));
190               }
191               iiopEndpointInfo.setHost( getIPV6Host( hostandport ));
192               return iiopEndpointInfo;
193           }
194           tokenizer = new StringTokenizer( hostandport, ":" );
195           // There are three possible cases here
196           // 1. Host and Port is explicitly specified by using ":" as a
197           //    a separator
198           // 2. Only Host is specified without the port
199           // 3. HostAndPort info is null
200           if( tokenizer.countTokens( ) == 2 ) {
201               // Case 1: There is Host and Port Info
202               iiopEndpointInfo.setHost( tokenizer.nextToken( ) );
203               iiopEndpointInfo.setPort( Integer.parseInt(
204                   tokenizer.nextToken( )));
205           } else {
206               if( ( hostandport != null )
207                 &&( hostandport.length() != 0 ) )
208               {
209                   // Case 2: Only Host is specified. iiopEndpointInfo is
210                   // initialized to use the default INS port, if no port is
211                   // specified
212                   iiopEndpointInfo.setHost( hostandport );
213               }
214               // Case 3: If no Host and Port info is provided then we use the
215               // the default LocalHost and INSPort. iiopEndpointInfo is
216               // already initialized with this info.
217           }
218       } catch( Throwable e ) {
219           // Any kind of Exception is bad here.
220           // Possible causes: A Number Format exception because port info is
221           // malformed
222           badAddress( e );
223       }
224       Utility.validateGIOPVersion( iiopEndpointInfo );
225       return iiopEndpointInfo;
226    }
227
228    /**
229     *  Validate 'rir:' case.
230     */
231    private void handleRIRColon( String rirInfo )
232    {
233        if( rirInfo.length() != NamingConstants.RIRCOLON_LENGTH ) {
234            badAddress( null );
235        }
236    }
237
238    /**
239      * Returns an IPV6 Port that is after [<ipv6>]:. There is no validation
240      * done here, if it is an incorrect port then the request through
241      * this URL results in a COMM_FAILURE, otherwise malformed list will
242      * result in BAD_PARAM exception thrown in checkcorbalocGrammer.
243      */
244     private String getIPV6Port( String endpointInfo )
245     {
246         int squareBracketEndIndex = endpointInfo.indexOf ( ']' );
247         // If there is port information, then it has to be after ] bracket
248         // indexOf returns the count from the index of zero as the base, so
249         // equality check requires squareBracketEndIndex + 1.
250         if( (squareBracketEndIndex + 1) != (endpointInfo.length( )) ) {
251             if( endpointInfo.charAt( squareBracketEndIndex + 1 ) != ':' ) {
252                  throw new RuntimeException(
253                      "Host and Port is not separated by ':'" );
254             }
255             // PortInformation  should be after ']:' delimiter
256             // If there is an exception then it will be caught in
257             // checkcorbaGrammer method and rethrown as BAD_PARAM
258             return endpointInfo.substring( squareBracketEndIndex + 2 );
259         }
260         return null;
261     }
262
263
264     /**
265      * Returns an IPV6 Host that is inside [ ] tokens. There is no validation
266      * done here, if it is an incorrect IPV6 address then the request through
267      * this URL results in a COMM_FAILURE, otherwise malformed list will
268      * result in BAD_PARAM exception thrown in checkcorbalocGrammer.
269      */
270     private String getIPV6Host( String endpointInfo ) {
271          // ipv6Host should be enclosed in
272          // [ ], if not it will result in a
273          // BAD_PARAM exception
274          int squareBracketEndIndex = endpointInfo.indexOf ( ']' );
275          // get the host between [ ]
276          String ipv6Host = endpointInfo.substring( 1, squareBracketEndIndex  );
277          return ipv6Host;
278    }
279
280    /**
281     * Will be true only in CorbanameURL class.
282     */
283    public boolean isCorbanameURL( ) {
284        return false;
285    }
286
287
288}
289