View Javadoc

1   /***
2    * Redistribution and use of this software and associated documentation
3    * ("Software"), with or without modification, are permitted provided
4    * that the following conditions are met:
5    *
6    * 1. Redistributions of source code must retain copyright
7    *    statements and notices.  Redistributions must also contain a
8    *    copy of this document.
9    *
10   * 2. Redistributions in binary form must reproduce the
11   *    above copyright notice, this list of conditions and the
12   *    following disclaimer in the documentation and/or other
13   *    materials provided with the distribution.
14   *
15   * 3. The name "Exolab" must not be used to endorse or promote
16   *    products derived from this Software without prior written
17   *    permission of Exoffice Technologies.  For written permission,
18   *    please contact info@exolab.org.
19   *
20   * 4. Products derived from this Software may not be called "Exolab"
21   *    nor may "Exolab" appear in their names without prior written
22   *    permission of Exoffice Technologies. Exolab is a registered
23   *    trademark of Exoffice Technologies.
24   *
25   * 5. Due credit should be given to the Exolab Project
26   *    (http://www.exolab.org/).
27   *
28   * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
29   * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
30   * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
31   * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL
32   * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
33   * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
34   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
35   * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
37   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
38   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
39   * OF THE POSSIBILITY OF SUCH DAMAGE.
40   *
41   * Copyright 2000-2001,2003 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: IpcJndiInitialContextFactory.java,v 1.22.2.1 2004/05/01 06:10:04 tanderson Exp $
44   */
45  
46  package org.exolab.jms.jndi.mipc;
47  
48  import java.util.Hashtable;
49  
50  import javax.naming.ConfigurationException;
51  import javax.naming.Context;
52  import javax.naming.NameParser;
53  import javax.naming.NamingException;
54  import javax.naming.ServiceUnavailableException;
55  import javax.naming.spi.InitialContextFactory;
56  
57  import org.apache.avalon.excalibur.naming.DefaultNamespace;
58  import org.apache.avalon.excalibur.naming.RemoteContext;
59  import org.apache.commons.logging.Log;
60  import org.apache.commons.logging.LogFactory;
61  
62  import org.exolab.core.ipc.Client;
63  import org.exolab.jms.jndi.JndiConstants;
64  
65  
66  /***
67   * This is the client side helper class that retrieves the root context
68   * of the JNDI server. This class implements the InitialContextFactory
69   * interface.
70   *
71   * @version     $Revision: 1.22.2.1 $ $Date: 2004/05/01 06:10:04 $
72   * @author      <a href="mailto:mourikis@intalio.com">Jim Mourikis</a>
73   * @see         org.exolab.jms.server.mipc.IpcJndiServer
74   */
75  public class IpcJndiInitialContextFactory implements InitialContextFactory {
76  
77      /***
78       * The allowed scheme names for the provider URL
79       */
80      private static final String TCP_SCHEME = "tcp://";
81      private static final String TCPS_SCHEME = "tcps://";
82  
83      /***
84       * The url scheme separator
85       */
86      private final static String SCHEME_SEPARATOR = "://";
87  
88      /***
89       * The host/port separator
90       */
91      private final static String HOST_PORT_SEPARATOR = ":";
92  
93      /***
94       * The end separator
95       */
96      private final static String URL_TERMINATOR = "/";
97  
98      /***
99       * The server host address
100      */
101     private String _host;
102 
103     /***
104      * The port number the server is on
105      */
106     private int _port;
107 
108     /***
109      * The logger
110      */
111     private static final Log _log =
112         LogFactory.getLog(IpcJndiInitialContextFactory.class);
113 
114 
115     /***
116      * Default constructor
117      */
118     public IpcJndiInitialContextFactory() {
119     }
120 
121     /***
122      * Creates an initial context for beginning name resolution, based on
123      * the {@link Context#PROVIDER_URL} attribute.
124      *
125      * @param environment the environment specifying information to be used in
126      * the creation of the initial context.
127      * @return an initial context
128      * @throws NamingException if the initial context cannot be created
129      */
130     public Context getInitialContext(Hashtable environment)
131         throws NamingException {
132         Context context = null;
133 
134         String url = (String) environment.get(Context.PROVIDER_URL);
135         if (url == null || url.length() == 0) {
136             url = getDeprecatedEnvironment(environment);
137         }
138         parseURL(url);
139 
140         Client connection = openConnection();
141         NameServiceProxy provider = new NameServiceProxy(connection);
142         NameParser parser;
143         try {
144             parser = provider.getNameParser();
145         } catch (NamingException exception) {
146             throw exception;
147         } catch (Exception exception) {
148             NamingException error = new ServiceUnavailableException(
149                 exception.getMessage());
150             error.setRootCause(exception);
151             throw error;
152         }
153         DefaultNamespace namespace = new DefaultNamespace(parser);
154         Hashtable env = new Hashtable(environment);
155         env.put(RemoteContext.NAMING_PROVIDER, provider);
156         env.put(RemoteContext.NAMESPACE, namespace);
157         return new RemoteContext(env, parser.parse(""));
158     }
159 
160     private void parseURL(String url) throws NamingException {
161         if (url.startsWith("mipc://")) {
162             // TODO: remove this when removing getDeprecatedEnvironment
163             _log.warn(getClass().getName() +
164                 ": using deprecated Context.PROVIDER_URL=" + url);
165             url = TCP_SCHEME + url.substring(7);
166         } else if (!url.startsWith(TCP_SCHEME) &&
167             !url.startsWith(TCPS_SCHEME)) {
168             throw new ConfigurationException(
169                 "URL=" + url + " has an invalid scheme");
170         }
171 
172         int schemeIndex = url.indexOf("://");
173         int hostIndex = url.indexOf(HOST_PORT_SEPARATOR, schemeIndex +
174             SCHEME_SEPARATOR.length());
175         if (hostIndex == -1) {
176             throw new ConfigurationException("URL=" + url + " is invalid");
177         }
178 
179         int endIndex = url.indexOf(URL_TERMINATOR, hostIndex +
180             HOST_PORT_SEPARATOR.length());
181         if (endIndex != -1 && endIndex != (url.length() - 1)) {
182             // url can have trailing '/', but nothing after it
183             throw new ConfigurationException("URL=" + url + " is invalid");
184         }
185 
186         // get the server address
187         _host = url.substring(schemeIndex + SCHEME_SEPARATOR.length(),
188             hostIndex);
189 
190         // get the port address
191         try {
192             int start = hostIndex + HOST_PORT_SEPARATOR.length();
193             String port = (endIndex == -1) ? url.substring(start) :
194                 url.substring(start, endIndex);
195             _port = Integer.parseInt(port);
196         } catch (Exception exception) {
197             throw new ConfigurationException("URL=" + url + " is invalid");
198         }
199     }
200 
201     /***
202      * Get a connection to the specified host and port.
203      *
204      * @return the client connection to the specified host and port
205      * @throws NamingException if a connection cannot be established
206      */
207     private Client openConnection() throws NamingException {
208         Client client;
209         try {
210             client = new Client(_host, _port);
211         } catch (Exception exception) {
212             NamingException error = new NamingException(
213                 "Failed to connect to JNDI provider");
214             error.setRootCause(exception);
215             throw error;
216         }
217         return client;
218     }
219 
220     /***
221      * Returns the tcp url using the old environment properties, logging a
222      * warning. This method will be removed in future releases
223      */
224     private String getDeprecatedEnvironment(Hashtable environment) {
225         _log.warn(getClass().getName() +
226             ": using deprecated environment. Use Context.PROVIDER_URL");
227 
228         StringBuffer url = new StringBuffer("tcp://");
229         String host = (String) environment.get(JndiConstants.HOST_PROPERTY);
230         Integer port = (Integer) environment.get(
231             JndiConstants.PORT_NUMBER_PROPERTY);
232 
233         // if the host is specified then use it, otherwise use localhost
234         if (host != null) {
235             url.append(host);
236             url.append(":");
237         } else {
238             url.append("localhost:");
239         }
240 
241         // if the port has been specified then use it otherwise use
242         // the default port
243         if (port != null) {
244             url.append(port.toString());
245         } else {
246             url.append("3035");
247         }
248 
249         return url.toString();
250     }
251 
252 } //-- IpcJndiInitialContextFactory