Source Code Cross Referenced for RMIConnectorServer.java in  » 6.0-JDK-Core » management » javax » management » remote » rmi » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Home
Java Source Code / Java Documentation
1.6.0 JDK Core
2.6.0 JDK Modules
3.6.0 JDK Modules com.sun
4.6.0 JDK Modules com.sun.java
5.6.0 JDK Modules sun
6.6.0 JDK Platform
7.Ajax
8.Apache Harmony Java SE
9.Aspect oriented
10.Authentication Authorization
11.Blogger System
12.Build
13.Byte Code
14.Cache
15.Chart
16.Chat
17.Code Analyzer
18.Collaboration
19.Content Management System
20.Database Client
21.Database DBMS
22.Database JDBC Connection Pool
23.Database ORM
24.Development
25.EJB Server
26.ERP CRM Financial
27.ESB
28.Forum
29.Game
30.GIS
31.Graphic 3D
32.Graphic Library
33.Groupware
34.HTML Parser
35.IDE
36.IDE Eclipse
37.IDE Netbeans
38.Installer
39.Internationalization Localization
40.Inversion of Control
41.Issue Tracking
42.J2EE
43.J2ME
44.JBoss
45.JMS
46.JMX
47.Library
48.Mail Clients
49.Music
50.Net
51.Parser
52.PDF
53.Portal
54.Profiler
55.Project Management
56.Report
57.RSS RDF
58.Rule Engine
59.Science
60.Scripting
61.Search Engine
62.Security
63.Sevlet Container
64.Source Control
65.Swing Library
66.Template Engine
67.Test Coverage
68.Testing
69.UML
70.Web Crawler
71.Web Framework
72.Web Mail
73.Web Server
74.Web Services
75.Web Services apache cxf 2.2.6
76.Web Services AXIS2
77.Wiki Engine
78.Workflow Engines
79.XML
80.XML UI
Java Source Code / Java Documentation » 6.0 JDK Core » management » javax.management.remote.rmi 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001        /*
002         * Copyright 2002-2007 Sun Microsystems, Inc.  All Rights Reserved.
003         * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004         *
005         * This code is free software; you can redistribute it and/or modify it
006         * under the terms of the GNU General Public License version 2 only, as
007         * published by the Free Software Foundation.  Sun designates this
008         * particular file as subject to the "Classpath" exception as provided
009         * by Sun in the LICENSE file that accompanied this code.
010         *
011         * This code is distributed in the hope that it will be useful, but WITHOUT
012         * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013         * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014         * version 2 for more details (a copy is included in the LICENSE file that
015         * accompanied this code).
016         *
017         * You should have received a copy of the GNU General Public License version
018         * 2 along with this work; if not, write to the Free Software Foundation,
019         * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020         *
021         * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022         * CA 95054 USA or visit www.sun.com if you need additional information or
023         * have any questions.
024         */
025
026        package javax.management.remote.rmi;
027
028        import com.sun.jmx.remote.security.MBeanServerFileAccessController;
029        import com.sun.jmx.remote.util.ClassLogger;
030        import com.sun.jmx.remote.util.EnvHelp;
031
032        import java.io.ByteArrayOutputStream;
033        import java.io.IOException;
034        import java.io.ObjectOutputStream;
035        import java.net.MalformedURLException;
036        import java.rmi.server.RMIClientSocketFactory;
037        import java.rmi.server.RMIServerSocketFactory;
038        import java.util.Collections;
039        import java.util.HashMap;
040        import java.util.HashSet;
041        import java.util.Hashtable;
042        import java.util.Map;
043        import java.util.Set;
044
045        import javax.management.InstanceNotFoundException;
046        import javax.management.MBeanServer;
047
048        import javax.management.remote.JMXConnectionNotification;
049        import javax.management.remote.JMXConnector;
050        import javax.management.remote.JMXConnectorServer;
051        import javax.management.remote.JMXServiceURL;
052        import javax.management.remote.MBeanServerForwarder;
053
054        import javax.naming.InitialContext;
055        import javax.naming.NamingException;
056
057        /**
058         * <p>A JMX API connector server that creates RMI-based connections
059         * from remote clients.  Usually, such connector servers are made
060         * using {@link javax.management.remote.JMXConnectorServerFactory
061         * JMXConnectorServerFactory}.  However, specialized applications can
062         * use this class directly, for example with an {@link RMIServerImpl}
063         * object.</p>
064         *
065         * @since 1.5
066         */
067        public class RMIConnectorServer extends JMXConnectorServer {
068            /**
069             * <p>Name of the attribute that specifies whether the {@link
070             * RMIServer} stub that represents an RMI connector server should
071             * override an existing stub at the same address.  The value
072             * associated with this attribute, if any, should be a string that
073             * is equal, ignoring case, to <code>"true"</code> or
074             * <code>"false"</code>.  The default value is false.</p>
075             */
076            public static final String JNDI_REBIND_ATTRIBUTE = "jmx.remote.jndi.rebind";
077
078            /**
079             * <p>Name of the attribute that specifies the {@link
080             * RMIClientSocketFactory} for the RMI objects created in
081             * conjunction with this connector. The value associated with this
082             * attribute must be of type <code>RMIClientSocketFactory</code> and can
083             * only be specified in the <code>Map</code> argument supplied when
084             * creating a connector server.</p>
085             */
086            public static final String RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE = "jmx.remote.rmi.client.socket.factory";
087
088            /**
089             * <p>Name of the attribute that specifies the {@link
090             * RMIServerSocketFactory} for the RMI objects created in
091             * conjunction with this connector. The value associated with this
092             * attribute must be of type <code>RMIServerSocketFactory</code> and can
093             * only be specified in the <code>Map</code> argument supplied when
094             * creating a connector server.</p>
095             */
096            public static final String RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE = "jmx.remote.rmi.server.socket.factory";
097
098            /**
099             * <p>Makes an <code>RMIConnectorServer</code>.
100             * This is equivalent to calling {@link #RMIConnectorServer(
101             * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
102             * RMIConnectorServer(directoryURL,environment,null,null)}</p>
103             *
104             * @param url the URL defining how to create the connector server.
105             * Cannot be null.
106             *
107             * @param environment attributes governing the creation and
108             * storing of the RMI object.  Can be null, which is equivalent to
109             * an empty Map.
110             *
111             * @exception IllegalArgumentException if <code>url</code> is null.
112             *
113             * @exception MalformedURLException if <code>url</code> does not
114             * conform to the syntax for an RMI connector, or if its protocol
115             * is not recognized by this implementation. Only "rmi" and "iiop"
116             * are valid when this constructor is used.
117             *
118             * @exception IOException if the connector server cannot be created
119             * for some reason or if it is inevitable that its {@link #start()
120             * start} method will fail.
121             */
122            public RMIConnectorServer(JMXServiceURL url,
123                    Map<String, ?> environment) throws IOException {
124                this (url, environment, (MBeanServer) null);
125            }
126
127            /**
128             * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
129             * server.
130             * This is equivalent to calling {@link #RMIConnectorServer(
131             * JMXServiceURL,Map,RMIServerImpl,MBeanServer)
132             * RMIConnectorServer(directoryURL,environment,null,mbeanServer)}</p>
133             *
134             * @param url the URL defining how to create the connector server.
135             * Cannot be null.
136             *
137             * @param environment attributes governing the creation and
138             * storing of the RMI object.  Can be null, which is equivalent to
139             * an empty Map.
140             *
141             * @param mbeanServer the MBean server to which the new connector
142             * server is attached, or null if it will be attached by being
143             * registered as an MBean in the MBean server.
144             *
145             * @exception IllegalArgumentException if <code>url</code> is null.
146             *
147             * @exception MalformedURLException if <code>url</code> does not
148             * conform to the syntax for an RMI connector, or if its protocol
149             * is not recognized by this implementation. Only "rmi" and "iiop"
150             * are valid when this constructor is used.
151             *
152             * @exception IOException if the connector server cannot be created
153             * for some reason or if it is inevitable that its {@link #start()
154             * start} method will fail.
155             */
156            public RMIConnectorServer(JMXServiceURL url,
157                    Map<String, ?> environment, MBeanServer mbeanServer)
158                    throws IOException {
159                this (url, environment, (RMIServerImpl) null, mbeanServer);
160            }
161
162            /**
163             * <p>Makes an <code>RMIConnectorServer</code> for the given MBean
164             * server.</p>
165             *
166             * @param url the URL defining how to create the connector server.
167             * Cannot be null.
168             *
169             * @param environment attributes governing the creation and
170             * storing of the RMI object.  Can be null, which is equivalent to
171             * an empty Map.
172             *
173             * @param rmiServerImpl An implementation of the RMIServer interface,
174             *  consistent with the protocol type specified in <var>url</var>.
175             *  If this parameter is non null, the protocol type specified by
176             *  <var>url</var> is not constrained, and is assumed to be valid.
177             *  Otherwise, only "rmi" and "iiop" will be recognized.
178             *
179             * @param mbeanServer the MBean server to which the new connector
180             * server is attached, or null if it will be attached by being
181             * registered as an MBean in the MBean server.
182             *
183             * @exception IllegalArgumentException if <code>url</code> is null.
184             *
185             * @exception MalformedURLException if <code>url</code> does not
186             * conform to the syntax for an RMI connector, or if its protocol
187             * is not recognized by this implementation. Only "rmi" and "iiop"
188             * are recognized when <var>rmiServerImpl</var> is null.
189             *
190             * @exception IOException if the connector server cannot be created
191             * for some reason or if it is inevitable that its {@link #start()
192             * start} method will fail.
193             *
194             * @see #start
195             */
196            public RMIConnectorServer(JMXServiceURL url,
197                    Map<String, ?> environment, RMIServerImpl rmiServerImpl,
198                    MBeanServer mbeanServer) throws IOException {
199                super (mbeanServer);
200
201                if (url == null)
202                    throw new IllegalArgumentException("Null JMXServiceURL");
203                if (rmiServerImpl == null) {
204                    final String prt = url.getProtocol();
205                    if (prt == null
206                            || !(prt.equals("rmi") || prt.equals("iiop"))) {
207                        final String msg = "Invalid protocol type: " + prt;
208                        throw new MalformedURLException(msg);
209                    }
210                    final String urlPath = url.getURLPath();
211                    if (!urlPath.equals("") && !urlPath.equals("/")
212                            && !urlPath.startsWith("/jndi/")) {
213                        final String msg = "URL path must be empty or start with "
214                                + "/jndi/";
215                        throw new MalformedURLException(msg);
216                    }
217                }
218
219                if (environment == null)
220                    this .attributes = Collections.emptyMap();
221                else {
222                    EnvHelp.checkAttributes(environment);
223                    this .attributes = Collections.unmodifiableMap(environment);
224                }
225
226                this .address = url;
227                this .rmiServerImpl = rmiServerImpl;
228            }
229
230            /**
231             * <p>Returns a client stub for this connector server.  A client
232             * stub is a serializable object whose {@link
233             * JMXConnector#connect(Map) connect} method can be used to make
234             * one new connection to this connector server.</p>
235             *
236             * @param env client connection parameters of the same sort that
237             * could be provided to {@link JMXConnector#connect(Map)
238             * JMXConnector.connect(Map)}.  Can be null, which is equivalent
239             * to an empty map.
240             *
241             * @return a client stub that can be used to make a new connection
242             * to this connector server.
243             *
244             * @exception UnsupportedOperationException if this connector
245             * server does not support the generation of client stubs.
246             *
247             * @exception IllegalStateException if the JMXConnectorServer is
248             * not started (see {@link #isActive()}).
249             *
250             * @exception IOException if a communications problem means that a
251             * stub cannot be created.
252             **/
253            public JMXConnector toJMXConnector(Map<String, ?> env)
254                    throws IOException {
255                // The serialized for of rmiServerImpl is automatically
256                // a RMI server stub.
257                if (!isActive())
258                    throw new IllegalStateException("Connector is not active");
259
260                // Merge maps
261                Map<String, Object> usemap = new HashMap<String, Object>(
262                        (this .attributes == null) ? Collections
263                                .<String, Object> emptyMap() : this .attributes);
264
265                if (env != null) {
266                    EnvHelp.checkAttributes(env);
267                    usemap.putAll(env);
268                }
269
270                usemap = EnvHelp.filterAttributes(usemap);
271
272                final RMIServer stub = (RMIServer) rmiServerImpl.toStub();
273
274                return new RMIConnector(stub, usemap);
275            }
276
277            /**
278             * <p>Activates the connector server, that is starts listening for
279             * client connections.  Calling this method when the connector
280             * server is already active has no effect.  Calling this method
281             * when the connector server has been stopped will generate an
282             * <code>IOException</code>.</p>
283             *
284             * <p>The behavior of this method when called for the first time
285             * depends on the parameters that were supplied at construction,
286             * as described below.</p>
287             *
288             * <p>First, an object of a subclass of {@link RMIServerImpl} is
289             * required, to export the connector server through RMI:</p>
290             *
291             * <ul>
292             *
293             * <li>If an <code>RMIServerImpl</code> was supplied to the
294             * constructor, it is used.
295             *
296             * <li>Otherwise, if the protocol part of the
297             * <code>JMXServiceURL</code> supplied to the constructor was
298             * <code>iiop</code>, an object of type {@link RMIIIOPServerImpl}
299             * is created.
300             *
301             * <li>Otherwise, if the <code>JMXServiceURL</code>
302             * was null, or its protocol part was <code>rmi</code>, an object
303             * of type {@link RMIJRMPServerImpl} is created.
304             *
305             * <li>Otherwise, the implementation can create an
306             * implementation-specific {@link RMIServerImpl} or it can throw
307             * {@link MalformedURLException}.
308             *
309             * </ul>
310             *
311             * <p>If the given address includes a JNDI directory URL as
312             * specified in the package documentation for {@link
313             * javax.management.remote.rmi}, then this
314             * <code>RMIConnectorServer</code> will bootstrap by binding the
315             * <code>RMIServerImpl</code> to the given address.</p>
316             *
317             * <p>If the URL path part of the <code>JMXServiceURL</code> was
318             * empty or a single slash (<code>/</code>), then the RMI object
319             * will not be bound to a directory.  Instead, a reference to it
320             * will be encoded in the URL path of the RMIConnectorServer
321             * address (returned by {@link #getAddress()}).  The encodings for
322             * <code>rmi</code> and <code>iiop</code> are described in the
323             * package documentation for {@link
324             * javax.management.remote.rmi}.</p>
325             *
326             * <p>The behavior when the URL path is neither empty nor a JNDI
327             * directory URL, or when the protocol is neither <code>rmi</code>
328             * nor <code>iiop</code>, is implementation defined, and may
329             * include throwing {@link MalformedURLException} when the
330             * connector server is created or when it is started.</p>
331             *
332             * @exception IllegalStateException if the connector server has
333             * not been attached to an MBean server.
334             * @exception IOException if the connector server cannot be
335             * started.
336             */
337            public synchronized void start() throws IOException {
338                final boolean tracing = logger.traceOn();
339
340                if (state == STARTED) {
341                    if (tracing)
342                        logger.trace("start", "already started");
343                    return;
344                } else if (state == STOPPED) {
345                    if (tracing)
346                        logger.trace("start", "already stopped");
347                    throw new IOException("The server has been stopped.");
348                }
349
350                if (getMBeanServer() == null)
351                    throw new IllegalStateException(
352                            "This connector server is not "
353                                    + "attached to an MBean server");
354
355                // Check the internal access file property to see
356                // if an MBeanServerForwarder is to be provided
357                //
358                if (attributes != null) {
359                    // Check if access file property is specified
360                    //
361                    String accessFile = (String) attributes
362                            .get("jmx.remote.x.access.file");
363                    if (accessFile != null) {
364                        // Access file property specified, create an instance
365                        // of the MBeanServerFileAccessController class
366                        //
367                        MBeanServerForwarder mbsf = null;
368                        try {
369                            mbsf = new MBeanServerFileAccessController(
370                                    accessFile);
371                        } catch (IOException e) {
372                            throw EnvHelp
373                                    .initCause(new IllegalArgumentException(e
374                                            .getMessage()), e);
375                        }
376                        // Set the MBeanServerForwarder
377                        //
378                        setMBeanServerForwarder(mbsf);
379                    }
380                }
381
382                try {
383                    if (tracing)
384                        logger.trace("start", "setting default class loader");
385                    defaultClassLoader = EnvHelp.resolveServerClassLoader(
386                            attributes, getMBeanServer());
387                } catch (InstanceNotFoundException infc) {
388                    IllegalArgumentException x = new IllegalArgumentException(
389                            "ClassLoader not found: " + infc);
390                    throw EnvHelp.initCause(x, infc);
391                }
392
393                if (tracing)
394                    logger.trace("start", "setting RMIServer object");
395                final RMIServerImpl rmiServer;
396
397                if (rmiServerImpl != null)
398                    rmiServer = rmiServerImpl;
399                else
400                    rmiServer = newServer();
401
402                rmiServer.setMBeanServer(getMBeanServer());
403                rmiServer.setDefaultClassLoader(defaultClassLoader);
404                rmiServer.setRMIConnectorServer(this );
405                rmiServer.export();
406
407                try {
408                    if (tracing)
409                        logger.trace("start",
410                                "getting RMIServer object to export");
411                    final RMIServer objref = objectToBind(rmiServer, attributes);
412
413                    if (address != null
414                            && address.getURLPath().startsWith("/jndi/")) {
415                        final String jndiUrl = address.getURLPath()
416                                .substring(6);
417
418                        if (tracing)
419                            logger.trace("start", "Using external directory: "
420                                    + jndiUrl);
421
422                        final boolean rebind = EnvHelp
423                                .computeBooleanFromString(attributes,
424                                        JNDI_REBIND_ATTRIBUTE);
425
426                        if (tracing)
427                            logger.trace("start", JNDI_REBIND_ATTRIBUTE + "="
428                                    + rebind);
429
430                        try {
431                            if (tracing)
432                                logger.trace("start", "binding to " + jndiUrl);
433
434                            final Hashtable usemap = EnvHelp
435                                    .mapToHashtable(attributes);
436
437                            bind(jndiUrl, usemap, objref, rebind);
438
439                            boundJndiUrl = jndiUrl;
440                        } catch (NamingException e) {
441                            // fit e in the nested exception if we are on 1.4
442                            throw newIOException("Cannot bind to URL ["
443                                    + jndiUrl + "]: " + e, e);
444                        }
445                    } else {
446                        // if jndiURL is null, we must encode the stub into the URL.
447                        if (tracing)
448                            logger.trace("start", "Encoding URL");
449
450                        encodeStubInAddress(objref, attributes);
451
452                        if (tracing)
453                            logger.trace("start", "Encoded URL: "
454                                    + this .address);
455                    }
456                } catch (Exception e) {
457                    try {
458                        rmiServer.close();
459                    } catch (Exception x) {
460                        // OK: we are already throwing another exception
461                    }
462                    if (e instanceof  RuntimeException)
463                        throw (RuntimeException) e;
464                    else if (e instanceof  IOException)
465                        throw (IOException) e;
466                    else
467                        throw newIOException("Got unexpected exception while "
468                                + "starting the connector server: " + e, e);
469                }
470
471                rmiServerImpl = rmiServer;
472
473                synchronized (openedServers) {
474                    openedServers.add(this );
475                }
476
477                state = STARTED;
478
479                if (tracing) {
480                    logger.trace("start", "Connector Server Address = "
481                            + address);
482                    logger.trace("start", "started.");
483                }
484            }
485
486            /**
487             * <p>Deactivates the connector server, that is, stops listening for
488             * client connections.  Calling this method will also close all
489             * client connections that were made by this server.  After this
490             * method returns, whether normally or with an exception, the
491             * connector server will not create any new client
492             * connections.</p>
493             *
494             * <p>Once a connector server has been stopped, it cannot be started
495             * again.</p>
496             *
497             * <p>Calling this method when the connector server has already
498             * been stopped has no effect.  Calling this method when the
499             * connector server has not yet been started will disable the
500             * connector server object permanently.</p>
501             *
502             * <p>If closing a client connection produces an exception, that
503             * exception is not thrown from this method.  A {@link
504             * JMXConnectionNotification} is emitted from this MBean with the
505             * connection ID of the connection that could not be closed.</p>
506             *
507             * <p>Closing a connector server is a potentially slow operation.
508             * For example, if a client machine with an open connection has
509             * crashed, the close operation might have to wait for a network
510             * protocol timeout.  Callers that do not want to block in a close
511             * operation should do it in a separate thread.</p>
512             *
513             * <p>This method calls the method {@link RMIServerImpl#close()
514             * close} on the connector server's <code>RMIServerImpl</code>
515             * object.</p>
516             *
517             * <p>If the <code>RMIServerImpl</code> was bound to a JNDI
518             * directory by the {@link #start() start} method, it is unbound
519             * from the directory by this method.</p>
520             *
521             * @exception IOException if the server cannot be closed cleanly,
522             * or if the <code>RMIServerImpl</code> cannot be unbound from the
523             * directory.  When this exception is thrown, the server has
524             * already attempted to close all client connections, if
525             * appropriate; to call {@link RMIServerImpl#close()}; and to
526             * unbind the <code>RMIServerImpl</code> from its directory, if
527             * appropriate.  All client connections are closed except possibly
528             * those that generated exceptions when the server attempted to
529             * close them.
530             */
531            public void stop() throws IOException {
532                final boolean tracing = logger.traceOn();
533
534                synchronized (this ) {
535                    if (state == STOPPED) {
536                        if (tracing)
537                            logger.trace("stop", "already stopped.");
538                        return;
539                    } else if (state == CREATED) {
540                        if (tracing)
541                            logger.trace("stop", "not started yet.");
542                    }
543
544                    if (tracing)
545                        logger.trace("stop", "stopping.");
546                    state = STOPPED;
547                }
548
549                synchronized (openedServers) {
550                    openedServers.remove(this );
551                }
552
553                IOException exception = null;
554
555                // rmiServerImpl can be null if stop() called without start()
556                if (rmiServerImpl != null) {
557                    try {
558                        if (tracing)
559                            logger.trace("stop", "closing RMI server.");
560                        rmiServerImpl.close();
561                    } catch (IOException e) {
562                        if (tracing)
563                            logger.trace("stop", "failed to close RMI server: "
564                                    + e);
565                        if (logger.debugOn())
566                            logger.debug("stop", e);
567                        exception = e;
568                    }
569                }
570
571                if (boundJndiUrl != null) {
572                    try {
573                        if (tracing)
574                            logger.trace("stop",
575                                    "unbind from external directory: "
576                                            + boundJndiUrl);
577
578                        final Hashtable usemap = EnvHelp
579                                .mapToHashtable(attributes);
580
581                        InitialContext ctx = new InitialContext(usemap);
582
583                        ctx.unbind(boundJndiUrl);
584
585                        ctx.close();
586                    } catch (NamingException e) {
587                        if (tracing)
588                            logger.trace("stop",
589                                    "failed to unbind RMI server: " + e);
590                        if (logger.debugOn())
591                            logger.debug("stop", e);
592                        // fit e in as the nested exception if we are on 1.4
593                        if (exception == null)
594                            exception = newIOException("Cannot bind to URL: "
595                                    + e, e);
596                    }
597                }
598
599                if (exception != null)
600                    throw exception;
601
602                if (tracing)
603                    logger.trace("stop", "stopped");
604            }
605
606            public synchronized boolean isActive() {
607                return (state == STARTED);
608            }
609
610            public JMXServiceURL getAddress() {
611                if (!isActive())
612                    return null;
613                return address;
614            }
615
616            public Map<String, ?> getAttributes() {
617                Map<String, ?> map = EnvHelp.filterAttributes(attributes);
618                return Collections.unmodifiableMap(map);
619            }
620
621            public synchronized void setMBeanServerForwarder(
622                    MBeanServerForwarder mbsf) {
623                super .setMBeanServerForwarder(mbsf);
624                if (rmiServerImpl != null)
625                    rmiServerImpl.setMBeanServer(getMBeanServer());
626            }
627
628            /* We repeat the definitions of connection{Opened,Closed,Failed}
629               here so that they are accessible to other classes in this package
630               even though they have protected access.  */
631
632            protected void connectionOpened(String connectionId,
633                    String message, Object userData) {
634                super .connectionOpened(connectionId, message, userData);
635            }
636
637            protected void connectionClosed(String connectionId,
638                    String message, Object userData) {
639                super .connectionClosed(connectionId, message, userData);
640            }
641
642            protected void connectionFailed(String connectionId,
643                    String message, Object userData) {
644                super .connectionFailed(connectionId, message, userData);
645            }
646
647            /**
648             * Bind a stub to a registry.
649             * @param jndiUrl URL of the stub in the registry, extracted
650             *        from the <code>JMXServiceURL</code>.
651             * @param attributes A Hashtable containing environment parameters,
652             *        built from the Map specified at this object creation.
653             * @param rmiServer The object to bind in the registry
654             * @param rebind true if the object must be rebound.
655             **/
656            void bind(String jndiUrl, Hashtable attributes,
657                    RMIServer rmiServer, boolean rebind)
658                    throws NamingException, MalformedURLException {
659                // if jndiURL is not null, we nust bind the stub to a
660                // directory.
661                InitialContext ctx = new InitialContext(attributes);
662
663                if (rebind)
664                    ctx.rebind(jndiUrl, rmiServer);
665                else
666                    ctx.bind(jndiUrl, rmiServer);
667                ctx.close();
668            }
669
670            /**
671             * Creates a new RMIServerImpl.
672             **/
673            RMIServerImpl newServer() throws IOException {
674                final boolean iiop = isIiopURL(address, true);
675                final int port;
676                if (address == null)
677                    port = 0;
678                else
679                    port = address.getPort();
680                if (iiop)
681                    return newIIOPServer(attributes);
682                else
683                    return newJRMPServer(attributes, port);
684            }
685
686            /**
687             * Encode a stub into the JMXServiceURL.
688             * @param rmiServer The stub object to encode in the URL
689             * @param attributes A Map containing environment parameters,
690             *        built from the Map specified at this object creation.
691             **/
692            private void encodeStubInAddress(RMIServer rmiServer, Map attributes)
693                    throws IOException {
694
695                final String protocol, host;
696                final int port;
697
698                if (address == null) {
699                    if (rmiServer instanceof  javax.rmi.CORBA.Stub)
700                        protocol = "iiop";
701                    else
702                        protocol = "rmi";
703                    host = null; // will default to local host name
704                    port = 0;
705                } else {
706                    protocol = address.getProtocol();
707                    host = (address.getHost().equals("")) ? null : address
708                            .getHost();
709                    port = address.getPort();
710                }
711
712                final String urlPath = encodeStub(rmiServer, attributes);
713
714                address = new JMXServiceURL(protocol, host, port, urlPath);
715            }
716
717            static boolean isIiopURL(JMXServiceURL directoryURL, boolean strict)
718                    throws MalformedURLException {
719                String protocol = directoryURL.getProtocol();
720                if (protocol.equals("rmi"))
721                    return false;
722                else if (protocol.equals("iiop"))
723                    return true;
724                else if (strict) {
725
726                    throw new MalformedURLException("URL must have protocol "
727                            + "\"rmi\" or \"iiop\": \"" + protocol + "\"");
728                }
729                return false;
730            }
731
732            /**
733             * Returns the IOR of the given rmiServer.
734             **/
735            static String encodeStub(RMIServer rmiServer, Map env)
736                    throws IOException {
737                if (rmiServer instanceof  javax.rmi.CORBA.Stub)
738                    return "/ior/" + encodeIIOPStub(rmiServer, env);
739                else
740                    return "/stub/" + encodeJRMPStub(rmiServer, env);
741            }
742
743            static String encodeJRMPStub(RMIServer rmiServer, Map env)
744                    throws IOException {
745                ByteArrayOutputStream bout = new ByteArrayOutputStream();
746                ObjectOutputStream oout = new ObjectOutputStream(bout);
747                oout.writeObject(rmiServer);
748                oout.close();
749                byte[] bytes = bout.toByteArray();
750                return byteArrayToBase64(bytes);
751            }
752
753            static String encodeIIOPStub(RMIServer rmiServer, Map env)
754                    throws IOException {
755                try {
756                    javax.rmi.CORBA.Stub stub = (javax.rmi.CORBA.Stub) rmiServer;
757                    return stub._orb().object_to_string(stub);
758                } catch (org.omg.CORBA.BAD_OPERATION x) {
759                    throw newIOException(x.getMessage(), x);
760                }
761            }
762
763            /**
764             * Object that we will bind to the registry.
765             * This object is a stub connected to our RMIServerImpl.
766             **/
767            private static RMIServer objectToBind(RMIServerImpl rmiServer,
768                    Map env) throws IOException {
769                return RMIConnector.connectStub((RMIServer) rmiServer.toStub(),
770                        env);
771            }
772
773            private static RMIServerImpl newJRMPServer(Map<String, ?> env,
774                    int port) throws IOException {
775                RMIClientSocketFactory csf = (RMIClientSocketFactory) env
776                        .get(RMI_CLIENT_SOCKET_FACTORY_ATTRIBUTE);
777                RMIServerSocketFactory ssf = (RMIServerSocketFactory) env
778                        .get(RMI_SERVER_SOCKET_FACTORY_ATTRIBUTE);
779                return new RMIJRMPServerImpl(port, csf, ssf, env);
780            }
781
782            private static RMIServerImpl newIIOPServer(Map<String, ?> env)
783                    throws IOException {
784                return new RMIIIOPServerImpl(env);
785            }
786
787            private static String byteArrayToBase64(byte[] a) {
788                int aLen = a.length;
789                int numFullGroups = aLen / 3;
790                int numBytesInPartialGroup = aLen - 3 * numFullGroups;
791                int resultLen = 4 * ((aLen + 2) / 3);
792                final StringBuilder result = new StringBuilder(resultLen);
793
794                // Translate all full groups from byte array elements to Base64
795                int inCursor = 0;
796                for (int i = 0; i < numFullGroups; i++) {
797                    int byte0 = a[inCursor++] & 0xff;
798                    int byte1 = a[inCursor++] & 0xff;
799                    int byte2 = a[inCursor++] & 0xff;
800                    result.append(intToAlpha[byte0 >> 2]);
801                    result
802                            .append(intToAlpha[(byte0 << 4) & 0x3f
803                                    | (byte1 >> 4)]);
804                    result
805                            .append(intToAlpha[(byte1 << 2) & 0x3f
806                                    | (byte2 >> 6)]);
807                    result.append(intToAlpha[byte2 & 0x3f]);
808                }
809
810                // Translate partial group if present
811                if (numBytesInPartialGroup != 0) {
812                    int byte0 = a[inCursor++] & 0xff;
813                    result.append(intToAlpha[byte0 >> 2]);
814                    if (numBytesInPartialGroup == 1) {
815                        result.append(intToAlpha[(byte0 << 4) & 0x3f]);
816                        result.append("==");
817                    } else {
818                        // assert numBytesInPartialGroup == 2;
819                        int byte1 = a[inCursor++] & 0xff;
820                        result.append(intToAlpha[(byte0 << 4) & 0x3f
821                                | (byte1 >> 4)]);
822                        result.append(intToAlpha[(byte1 << 2) & 0x3f]);
823                        result.append('=');
824                    }
825                }
826                // assert inCursor == a.length;
827                // assert result.length() == resultLen;
828                return result.toString();
829            }
830
831            /**
832             * This array is a lookup table that translates 6-bit positive integer
833             * index values into their "Base64 Alphabet" equivalents as specified
834             * in Table 1 of RFC 2045.
835             */
836            private static final char intToAlpha[] = { 'A', 'B', 'C', 'D', 'E',
837                    'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
838                    'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c',
839                    'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
840                    'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0',
841                    '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '/' };
842
843            /**
844             * Construct a new IOException with a nested exception.
845             * The nested exception is set only if JDK >= 1.4
846             */
847            private static IOException newIOException(String message,
848                    Throwable cause) {
849                final IOException x = new IOException(message);
850                return EnvHelp.initCause(x, cause);
851            }
852
853            // Private variables
854            // -----------------
855
856            private static ClassLogger logger = new ClassLogger(
857                    "javax.management.remote.rmi", "RMIConnectorServer");
858
859            private JMXServiceURL address;
860            private RMIServerImpl rmiServerImpl;
861            private final Map<String, ?> attributes;
862            private ClassLoader defaultClassLoader = null;
863
864            private String boundJndiUrl;
865
866            // state
867            private static final int CREATED = 0;
868            private static final int STARTED = 1;
869            private static final int STOPPED = 2;
870
871            private int state = CREATED;
872            private final static Set<RMIConnectorServer> openedServers = new HashSet<RMIConnectorServer>();
873        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.