View Javadoc
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  
26  package com.sun.corba.se.impl.naming.namingutil;
27  
28  import java.util.*;
29  
30  import com.sun.corba.se.spi.logging.CORBALogDomains ;
31  import 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   */
40  public 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 }