KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > appserv > management > client > AppserverConnectionSource


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23  
24 /*
25  * $Header: /cvs/glassfish/admin-core/mbeanapi/src/java/com/sun/appserv/management/client/AppserverConnectionSource.java,v 1.8 2006/03/09 20:30:21 llc Exp $
26  * $Revision: 1.8 $
27  * $Date: 2006/03/09 20:30:21 $
28  */

29
30 package com.sun.appserv.management.client;
31
32 import java.util.HashMap JavaDoc;
33 import java.util.Map JavaDoc;
34 import java.util.logging.Logger JavaDoc;
35
36 import java.io.IOException JavaDoc;
37 import java.io.File JavaDoc;
38
39 import java.net.MalformedURLException JavaDoc;
40
41 import java.security.KeyStore JavaDoc;
42 import javax.net.ssl.X509TrustManager;
43 import javax.net.ssl.HandshakeCompletedListener;
44
45 import javax.management.MBeanServerConnection JavaDoc;
46 import javax.management.remote.JMXConnector JavaDoc;
47 import javax.management.remote.JMXServiceURL JavaDoc;
48 import javax.management.remote.JMXConnectorFactory JavaDoc;
49 import javax.management.remote.JMXConnectionNotification JavaDoc;
50 import javax.management.Notification JavaDoc;
51 import javax.management.NotificationListener JavaDoc;
52
53
54 import com.sun.appserv.management.client.ConnectionSource;
55 import com.sun.appserv.management.util.jmx.JMXConnectorConnectionSource;
56 import com.sun.appserv.management.util.misc.MapUtil;
57
58 import com.sun.appserv.management.DomainRoot;
59
60
61 /**
62     Supports connectivity to Sun Appserver 8.1 and later (not available
63     prior to 8.1).
64     This is the only official way
65     to get a connection to the appserver.
66     <p>
67     Helper methods to simplify connecting are available in
68     {@link com.sun.appserv.management.helper.Connect}.
69     <p>
70     If the server is running with TLS enabled, then you must use the constructor
71     that includes TLSParams. Here is an example of how to connect using TLS:
72 <pre>
73 final File trustStore = new File( "~/.keystore" );
74     final char[] trustStorePassword = "changeme".toCharArray(); // or whatever it is
75 final HandshakeCompletedListener listener = new HandshakeCompletedListenerImpl();
76 final TrustStoreTrustManager trustMgr = new TrustStoreTrustManager( trustStore, trustStorePassword);
77 trustMgr.setPrompt( true );
78
79 final TLSParams tlsParams = new TLSParams( new X509TrustManager[] { trustMgr }, listener );
80 final AppserverConnectionSource src =
81     new AppserverConnectionSource( AppserverConnectionSource.PROTOCOL_RMI,
82         "localhost", 8686, "admin", "admin123",
83         tlsParams,
84         null );
85 final DomainRoot domainRoot = src.getDomainRoot();
86 </pre>
87     If security is not an issue, it is recommended to simply disable TLS on the
88     server. However, you can also connect using TLS whereby the
89     server certificate is blindly trusted:
90 <pre>
91 final TLSParams tlsParams = new TLSParams( TrustAnyTrustManager.getInstanceArray(), null );
92 final AppserverConnectionSource src =
93     new AppserverConnectionSource( AppserverConnectionSource.PROTOCOL_RMI,
94         "localhost", 8686, "admin", "admin123",
95         tlsParams,
96         null );
97 final DomainRoot domainRoot = src.getDomainRoot();
98 </pre>
99     
100     
101     @see com.sun.appserv.management.client.TrustStoreTrustManager
102     @see com.sun.appserv.management.client.TrustAnyTrustManager
103     @see com.sun.appserv.management.client.HandshakeCompletedListenerImpl
104     @see com.sun.appserv.management.client.TLSParams
105  */

106 public final class AppserverConnectionSource
107     implements NotificationListener JavaDoc, ConnectionSource
108 {
109     private final String JavaDoc mHost;
110     private final int mPort;
111     private final String JavaDoc mProtocol;
112     private final String JavaDoc mUser;
113     private final String JavaDoc mPassword;
114     private final TLSParams mTLSParams;
115     private final Map JavaDoc<String JavaDoc,String JavaDoc> mReserved;
116     
117     protected JMXConnector JavaDoc mJMXConnector;
118     
119     /**
120         FIXME FIXME FIXME
121         This should be removed after the http connector supports the HandshakeCompletedListener
122      */

123     private static final boolean DISABLE_HANDSHAKE_COMPLETED_CHECK = true;
124
125         private boolean
126     disableHandShakeCompletedCheck()
127     {
128         return( DISABLE_HANDSHAKE_COMPLETED_CHECK && mProtocol.equals( PROTOCOL_HTTP ) );
129     }
130     
131     
132     /**
133         @return true if the specified protocol is supported.
134      */

135         public static boolean
136     isSupportedProtocol( final String JavaDoc protocol )
137     {
138         return( protocol != null &&
139                 (
140                     protocol.equals( PROTOCOL_HTTP ) ||
141                     protocol.equals( PROTOCOL_RMI )
142                 )
143             );
144     }
145     
146     
147     /**
148         [used internally]
149      */

150     public final static String JavaDoc TRUST_MANAGERS_KEY = "TRUST_MANAGER_KEY";
151     
152     /**
153         [used internally]
154      */

155     public final static String JavaDoc HANDSHAKE_COMPLETED_LISTENER_KEY = "HandshakeCompletedListener";
156     
157     
158     private static final String JavaDoc PROTOCOL_PREFIX = "sun-as-";
159     
160     /**
161         RMI protocol to the Appserver.
162         <b>Do not use the literal value of this constant in your code;
163         it is subject to change</b>
164      */

165     public final static String JavaDoc PROTOCOL_RMI = PROTOCOL_PREFIX + "rmi";
166     /**
167         Default protocol to the Appserver eg PROTOCOL_RMI.
168      */

169     public final static String JavaDoc DEFAULT_PROTOCOL = PROTOCOL_RMI;
170     
171     /**
172         Internal unsupported protocol. Not supported for external use.
173         <b>Do not use the literal value of this constant in your code;
174         it is subject to change</b>
175      */

176     public final static String JavaDoc PROTOCOL_HTTP = PROTOCOL_PREFIX + "http";
177     
178     private static final String JavaDoc INTERNAL_HTTP = "s1ashttp";
179     private static final String JavaDoc INTERNAL_HTTPS = "s1ashttps";
180     
181     /**
182         Packages for http(s) JMXConnectorProvider.
183      */

184     private final static String JavaDoc HTTP_FACTORY_PACKAGES =
185         "com.sun.enterprise.admin.jmx.remote.protocol";
186     
187     /**
188         Name of the default TrustStore file, located in the client's
189         home directory.
190         
191       */

192     public static final String JavaDoc DEFAULT_TRUST_STORE_NAME = ".asadmintruststore";
193     
194     /**
195         The default pasword for {@link #DEFAULT_TRUST_STORE_NAME}.
196      */

197     public static final String JavaDoc DEFAULT_TRUST_STORE_PASSWORD = "changeit";
198     
199     /**
200         Create a new instance using the default protocol without TLS.
201         
202         @param host hostname or IP address
203         @param port port to which to connect
204         @param user username
205         @param userPassword password for specified username
206         @param reserved reserved for future use
207      */

208         public
209     AppserverConnectionSource(
210         String JavaDoc host,
211         int port,
212         String JavaDoc user,
213         String JavaDoc userPassword,
214         final Map JavaDoc<String JavaDoc,String JavaDoc> reserved)
215     {
216         this( DEFAULT_PROTOCOL, host, port, user, userPassword, reserved);
217     }
218
219
220     /**
221         Create a new instance connecting to the specified host/port with
222         the specified protocol without TLS.
223         <p>
224         <b>Note:</b>The only supported protocol is {@link #PROTOCOL_RMI}.
225         Use of any other protocol is not supported and these protocols are
226         subject to change or removal at any time.
227         
228         @param protocol protocol to use eg PROTOCOL_RMI
229         @param host hostname or IP address
230         @param port port to which to connect
231         @param user username
232         @param userPassword password for specified username
233         @param reserved reserved for future use
234      */

235         public
236     AppserverConnectionSource(
237         final String JavaDoc protocol,
238         final String JavaDoc host,
239         final int port,
240         final String JavaDoc user,
241         final String JavaDoc userPassword,
242         final Map JavaDoc<String JavaDoc,String JavaDoc> reserved )
243     {
244         this ( protocol, host, port, user, userPassword, null, reserved );
245     }
246     
247     /**
248         Create a new instance which will use TLS for security if specified.
249         
250         @param protocol protocol to use eg PROTOCOL_RMI
251         @param host hostname or IP address
252         @param port port to which to connect
253         @param user username
254         @param userPassword password for specified username
255         @param tlsParams (may be null if TLS is not desired)
256         @param reserved reserved for future use
257         
258         @see com.sun.appserv.management.client.TLSParams
259      */

260         public
261     AppserverConnectionSource(
262         final String JavaDoc protocol,
263         final String JavaDoc host,
264         final int port,
265         final String JavaDoc user,
266         final String JavaDoc userPassword,
267         final TLSParams tlsParams,
268         final Map JavaDoc<String JavaDoc,String JavaDoc> reserved )
269     {
270         if ( reserved != null && reserved.keySet().size() != 0 )
271         {
272             throw new IllegalArgumentException JavaDoc( "No parameters may be passed in 'reserved' Map" );
273         }
274         
275         if ( isSupportedProtocol( protocol ) )
276         {
277             mHost = host;
278             mPort = port;
279             mProtocol = protocol;
280             mUser = user;
281             mPassword = userPassword;
282             mTLSParams = tlsParams;
283             mReserved = reserved;
284         }
285         else
286         {
287             throw new IllegalArgumentException JavaDoc( "unsupported protocol: " + protocol +
288                 ", use either PROTOCOL_RMI or PROTOCOL_HTTP" );
289         }
290     }
291     
292         private Object JavaDoc
293     envGet( final String JavaDoc key )
294     {
295         return( mReserved == null ? null : mReserved.get( key ) );
296     }
297     
298         private final boolean
299     useTLS()
300     {
301         return( mTLSParams != null );
302     }
303     
304         private final X509TrustManager[]
305     getTrustManagers()
306     {
307         return( mTLSParams == null ? null : mTLSParams.getTrustManagers() );
308     }
309     
310         private final HandshakeCompletedListener
311     getSuppliedHandshakeCompletedListener()
312     {
313         return( mTLSParams == null ? null : mTLSParams.getHandshakeCompletedListener() );
314     }
315     
316     
317         private Map JavaDoc<String JavaDoc,Object JavaDoc>
318     getCredentialsEnv(
319         final String JavaDoc user,
320         final String JavaDoc password )
321     {
322         final HashMap JavaDoc<String JavaDoc,Object JavaDoc> env = new HashMap JavaDoc<String JavaDoc,Object JavaDoc>();
323             
324         final String JavaDoc[] credentials = new String JavaDoc[] { mUser, mPassword };
325         
326         env.put( JMXConnector.CREDENTIALS, credentials );
327         
328         return( env );
329     }
330     
331     private static final String JavaDoc APPSERVER_JNDI_NAME = "/management/rmi-jmx-connector";
332
333         private void
334     warning( final String JavaDoc msg )
335     {
336         System.out.println( "\n***\nWARNING: " + msg );
337     }
338     
339         private JMXConnector JavaDoc
340     createNew()
341         throws MalformedURLException JavaDoc, IOException JavaDoc
342     {
343         final Map JavaDoc<String JavaDoc,Object JavaDoc> env = getCredentialsEnv( mUser, mPassword );
344         
345         // NetBeans fix; classloader must be more than system classloader
346
env.put("jmx.remote.protocol.provider.class.loader",
347             this.getClass().getClassLoader());
348
349         final HandshakeCompletedListenerImpl hcListener =
350             new HandshakeCompletedListenerImpl( getSuppliedHandshakeCompletedListener() );
351         
352         JMXServiceURL JavaDoc url = null;
353         if ( mProtocol.equals( PROTOCOL_HTTP ) )
354         {
355             if ( useTLS() )
356             {
357                 //env.put( TRUST_MANAGERS_KEY, getTrustManagers() );
358
final X509TrustManager[] tms = getTrustManagers();
359                                 if (tms != null && tms.length >= 1) {
360                                     env.put( TRUST_MANAGERS_KEY, tms[0]);
361                                 }
362                 env.put( HANDSHAKE_COMPLETED_LISTENER_KEY, hcListener );
363             }
364             
365             env.put( "com.sun.enterprise.as.http.auth", "BASIC" );
366             env.put( "USER", mUser );
367             env.put( "PASSWORD", mPassword );
368             // so our JMXConnectorProvider may be found
369
env.put( JMXConnectorFactory.PROTOCOL_PROVIDER_PACKAGES, HTTP_FACTORY_PACKAGES );
370             
371             final String JavaDoc internalProtocol = useTLS() ? INTERNAL_HTTPS : INTERNAL_HTTP;
372             url = new JMXServiceURL JavaDoc( internalProtocol, mHost, mPort);
373         }
374         else if ( mProtocol.equals( PROTOCOL_RMI ) )
375         {
376             if ( useTLS() )
377             {
378                 // the only way we can communicate with/control the RMI stub is through
379
// this special singleton class
380
final AdminRMISSLClientSocketFactoryEnvImpl rmiEnv =
381                     AdminRMISSLClientSocketFactoryEnvImpl.getInstance();
382                 rmiEnv.setHandshakeCompletedListener( hcListener );
383                 rmiEnv.setTrustManagers( getTrustManagers() );
384             }
385             
386             final String JavaDoc s = "service:jmx:rmi:///jndi/rmi://" +
387                 mHost + ":" + mPort + APPSERVER_JNDI_NAME;
388                          
389             url = new JMXServiceURL JavaDoc( s );
390         }
391         else
392         {
393             assert( false );
394         }
395         
396         final JMXConnector JavaDoc conn = JMXConnectorFactory.connect( url, env );
397         
398         /*
399             If the connection was established with RMI, it could have been an insecure
400             connection if a on-TLS stub was downloaded. Verify that the
401             a TLS Handshake was actually completed.
402          */

403         if ( ! disableHandShakeCompletedCheck() )
404         {
405             if ( useTLS() && hcListener.getLastEvent() == null )
406             {
407                 conn.close();
408                 throw new IOException JavaDoc( "Connection could not be established using TLS; server is not using TLS" );
409             }
410         }
411         else
412         {
413             //warning( "HandshakeCompletedCheck is temporarily disabled for PROTOCOL_HTTP" );
414
/* This has been commented out -- See CR: 6172198. HTTPS/JMX Connector Implementation
415             does not have to accept HandshakeCompletedListener for 8.1*/

416         }
417         
418         conn.addConnectionNotificationListener( this, null, conn );
419         
420         return( conn );
421     }
422     
423     /**
424         Used internally as callback for {@link javax.management.NotificationListener}.
425         <b>DO NOT CALL THIS METHOD</b>.
426      */

427         public void
428     handleNotification(
429         final Notification JavaDoc notifIn,
430         final Object JavaDoc handback)
431     {
432         if ( notifIn instanceof JMXConnectionNotification JavaDoc )
433         {
434             final JMXConnectionNotification JavaDoc notif = (JMXConnectionNotification JavaDoc)notifIn;
435             
436             final String JavaDoc type = notif.getType();
437         
438             if ( type.equals( JMXConnectionNotification.FAILED) ||
439                 type.equals( JMXConnectionNotification.CLOSED ) )
440             {
441                 mJMXConnector = null;
442             }
443         }
444     }
445     
446     /**
447         If the connection has already been created, return the existing JMXConnector
448         unless 'forceNew' is true or the connection is currently null.
449         
450         @param forceNew if a new connection should be created
451         @return JMXConnector
452      */

453         public JMXConnector JavaDoc
454     getJMXConnector( final boolean forceNew )
455         throws IOException JavaDoc
456     {
457         if ( forceNew || mJMXConnector == null )
458         {
459             mJMXConnector = createNew();
460             getMBeanServerConnection( false ); // make sure it works...
461
}
462         
463         return( mJMXConnector );
464     }
465     
466     
467         public MBeanServerConnection JavaDoc
468     getExistingMBeanServerConnection( )
469     {
470         try
471         {
472             return( getJMXConnector( false ).getMBeanServerConnection() );
473         }
474         catch( IOException JavaDoc e )
475         {
476         }
477         return( null );
478     }
479     
480     
481     /**
482         @return getJMXConnector( forceNew ).getMBeanServerConnection()
483      */

484         public MBeanServerConnection JavaDoc
485     getMBeanServerConnection( final boolean forceNew )
486         throws IOException JavaDoc
487     {
488         return( getJMXConnector( forceNew ).getMBeanServerConnection() );
489     }
490     
491     /**
492         {@link DomainRoot} will be returned. Upon return, AMX is
493         ready for use. If the server has just been started, there
494         may be a slight delay until AMX is ready for use; this method
495         returns only once AMX is ready for use.
496        
497         @return a DomainRoot
498      */

499         public DomainRoot
500     getDomainRoot()
501         throws IOException JavaDoc
502     {
503         final DomainRoot domainRoot =
504             ProxyFactory.getInstance( this ).getDomainRoot( true );
505         
506         return domainRoot;
507     }
508     
509         public String JavaDoc
510     toString()
511     {
512         return(
513             "protocol=" + mProtocol +
514             ", host=" + mHost +
515             ", port=" + mPort +
516             ", user=" + mUser +
517             ", useTLS={" + useTLS() + "}" +
518             ", mReserved=" + (mReserved == null ? "null" : MapUtil.toString( mReserved )) );
519     }
520     
521
522     
523 }
524
525
Popular Tags