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 2001-2004 (C) Exoffice Technologies Inc. All Rights Reserved.
42   *
43   * $Id: HttpJndiInitialContextFactory.java,v 1.20 2004/01/29 12:14:14 tanderson Exp $
44   */
45  package org.exolab.jms.jndi.http;
46  
47  import java.util.Hashtable;
48  
49  import javax.naming.ConfigurationException;
50  import javax.naming.Context;
51  import javax.naming.NameParser;
52  import javax.naming.NamingException;
53  import javax.naming.ServiceUnavailableException;
54  import javax.naming.spi.InitialContextFactory;
55  
56  import org.apache.avalon.excalibur.naming.DefaultNamespace;
57  import org.apache.avalon.excalibur.naming.RemoteContext;
58  import org.apache.commons.logging.Log;
59  import org.apache.commons.logging.LogFactory;
60  
61  import org.exolab.core.http.HttpClient;
62  import org.exolab.core.util.URI;
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.20 $ $Date: 2004/01/29 12:14:14 $
72   * @author      <a href="mailto:mourikis@exolab.org">Jim Mourikis</a>
73   * @author      <a href="mailto:tima@intalio.com">Tim Anderson</a>
74   */
75  public class HttpJndiInitialContextFactory implements InitialContextFactory {
76  
77      /***
78       * The JNDI servlet name
79       */
80      protected static final String SERVLET = "openjms/OpenJMSJndi";
81  
82      /***
83       * The allowed scheme names for the provider URL
84       */
85      private static final String HTTP_SCHEME = "http";
86  
87      /***
88       * The logger
89       */
90      private static final Log _log =
91          LogFactory.getLog(HttpJndiInitialContextFactory.class);
92  
93  
94      /***
95       * Default constructor
96       */
97      public HttpJndiInitialContextFactory() {
98      }
99  
100     /***
101      * Creates an initial context for beginning name resolution.
102      *
103      * @param environment the environment specifying information to be used in
104      * the creation of the initial context.
105      * @return the initial context
106      * @throws NamingException if the initial context cannot be created
107      */
108     public Context getInitialContext(Hashtable environment)
109         throws NamingException {
110         Context context = null;
111         String url = getProviderURL(environment);
112 
113         HttpClient connection = openConnection(url);
114         NameServiceProxy provider = new NameServiceProxy(connection);
115         NameParser parser;
116         try {
117             parser = provider.getNameParser();
118         } catch (NamingException exception) {
119             throw exception;
120         } catch (Exception exception) {
121             NamingException error = new ServiceUnavailableException(
122                 exception.getMessage());
123             error.setRootCause(exception);
124             throw error;
125         }
126         DefaultNamespace namespace = new DefaultNamespace(parser);
127         Hashtable env = new Hashtable(environment);
128         env.put(RemoteContext.NAMING_PROVIDER, provider);
129         env.put(RemoteContext.NAMESPACE, namespace);
130         return new RemoteContext(env, parser.parse(""));
131     }
132 
133     /***
134      * Returns the JNDI provider URL
135      *
136      * @return the JNDI provider URL
137      * @throws NamingException if the URL cannot be determined
138      */
139     protected String getProviderURL(Hashtable environment)
140         throws NamingException {
141 
142         if (environment == null) {
143             throw new ConfigurationException(
144                 "Cannot connect to JNDI provider - environment not set");
145         }
146         String url = (String) environment.get(Context.PROVIDER_URL);
147         if (url != null) {
148             URI uri;
149             try {
150                 uri = new URI(url);
151             } catch (URI.MalformedURIException exception) {
152                 throw new ConfigurationException(
153                     "Malformed JNDI provider URL: " + url);
154             }
155             if (!HTTP_SCHEME.equals(uri.getScheme())) {
156                 throw new ConfigurationException(
157                     "URL=" + url + " has an invalid scheme");
158             }
159             String path = uri.getPath();
160             if (path == null || path.length() == 0) {
161                 url += "/" + SERVLET;
162             } else if (path.equals("/")) {
163                 url += SERVLET;
164             }
165         } else {
166             url = getDeprecatedEnvironment(environment);
167         }
168 
169         return url;
170     }
171 
172     /***
173      * Get a connection to the JNDI provider
174      *
175      * @param url the JNDI provider URL
176      * @return a connection to the JNDI provider
177      * @throws NamingException if a connection cannot be established
178      */
179     protected HttpClient openConnection(String url) throws NamingException {
180         HttpClient client;
181         try {
182             client = new HttpClient(url, "HttpJndiInitialContextFactory");
183         } catch (Exception exception) {
184             NamingException error = new NamingException(
185                 "Failed to connect to JNDI provider");
186             error.setRootCause(exception);
187             throw error;
188         }
189         return client;
190     }
191 
192     /***
193      * Returns the http url using the old environment properties, logging a
194      * warning. This method will be removed in future releases
195      */
196     private String getDeprecatedEnvironment(Hashtable environment) {
197         _log.warn(getClass().getName() +
198             ": using deprecated environment. Use Context.PROVIDER_URL");
199 
200         StringBuffer url = new StringBuffer(HTTP_SCHEME);
201         String host = (String) environment.get(JndiConstants.HOST_PROPERTY);
202         Integer port = (Integer) environment.get(
203             JndiConstants.PORT_NUMBER_PROPERTY);
204 
205         // if the host is specified then use it, otherwise use localhost
206         if (host != null) {
207             url.append(host);
208         } else {
209             url.append("localhost");
210         }
211 
212         // if the port has been specified then use it
213         if (port != null) {
214             url.append(":");
215             url.append(port.toString());
216         }
217 
218         url.append("/");
219         url.append(SERVLET);
220 
221         return url.toString();
222     }
223 
224 } //-- HttpJndiInitialContextFactory