Save This Page
Home » openjdk-7 » sun.rmi » transport » [javadoc | source]
    1   /*
    2    * Copyright 1996-2005 Sun Microsystems, Inc.  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.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package sun.rmi.transport;
   27   
   28   import java.io.IOException;
   29   import java.io.ObjectOutput;
   30   import java.rmi.MarshalException;
   31   import java.rmi.NoSuchObjectException;
   32   import java.rmi.Remote;
   33   import java.rmi.RemoteException;
   34   import java.rmi.server.LogStream;
   35   import java.rmi.server.ObjID;
   36   import java.rmi.server.RemoteCall;
   37   import java.rmi.server.RemoteServer;
   38   import java.rmi.server.ServerNotActiveException;
   39   import java.security.AccessControlContext;
   40   import sun.rmi.runtime.Log;
   41   import sun.rmi.server.Dispatcher;
   42   import sun.rmi.server.UnicastServerRef;
   43   
   44   /**
   45    * Transport abstraction for enabling communication between different
   46    * VMs.
   47    *
   48    * @author Ann Wollrath
   49    */
   50   public abstract class Transport {
   51   
   52       /** "transport" package log level */
   53       static final int logLevel = LogStream.parseLevel(getLogLevel());
   54   
   55       private static String getLogLevel() {
   56           return java.security.AccessController.doPrivileged(
   57               new sun.security.action.GetPropertyAction("sun.rmi.transport.logLevel"));
   58       }
   59   
   60       /* transport package log */
   61       static final Log transportLog =
   62           Log.getLog("sun.rmi.transport.misc", "transport", Transport.logLevel);
   63   
   64       /** References the current transport when a call is being serviced */
   65       private static final ThreadLocal currentTransport = new ThreadLocal();
   66   
   67       /** ObjID for DGCImpl */
   68       private static final ObjID dgcID = new ObjID(ObjID.DGC_ID);
   69   
   70       /**
   71        * Returns a <I>Channel</I> that generates connections to the
   72        * endpoint <I>ep</I>. A Channel is an object that creates and
   73        * manages connections of a particular type to some particular
   74        * address space.
   75        * @param ep the endpoint to which connections will be generated.
   76        * @return the channel or null if the transport cannot
   77        * generate connections to this endpoint
   78        */
   79       public abstract Channel getChannel(Endpoint ep);
   80   
   81       /**
   82        * Removes the <I>Channel</I> that generates connections to the
   83        * endpoint <I>ep</I>.
   84        */
   85       public abstract void free(Endpoint ep);
   86   
   87       /**
   88        * Export the object so that it can accept incoming calls.
   89        */
   90       public void exportObject(Target target) throws RemoteException {
   91           target.setExportedTransport(this);
   92           ObjectTable.putTarget(target);
   93       }
   94   
   95       /**
   96        * Invoked when an object that was exported on this transport has
   97        * become unexported, either by being garbage collected or by
   98        * being explicitly unexported.
   99        **/
  100       protected void targetUnexported() { }
  101   
  102       /**
  103        * Returns the current transport if a call is being serviced, otherwise
  104        * returns null.
  105        **/
  106       static Transport currentTransport() {
  107           return (Transport) currentTransport.get();
  108       }
  109   
  110       /**
  111        * Verify that the current access control context has permission to accept
  112        * the connection being dispatched by the current thread.  The current
  113        * access control context is passed as a parameter to avoid the overhead of
  114        * an additional call to AccessController.getContext.
  115        */
  116       protected abstract void checkAcceptPermission(AccessControlContext acc);
  117   
  118       /**
  119        * Service an incoming remote call. When a message arrives on the
  120        * connection indicating the beginning of a remote call, the
  121        * threads are required to call the <I>serviceCall</I> method of
  122        * their transport.  The default implementation of this method
  123        * locates and calls the dispatcher object.  Ordinarily a
  124        * transport implementation will not need to override this method.
  125        * At the entry to <I>tr.serviceCall(conn)</I>, the connection's
  126        * input stream is positioned at the start of the incoming
  127        * message.  The <I>serviceCall</I> method processes the incoming
  128        * remote invocation and sends the result on the connection's
  129        * output stream.  If it returns "true", then the remote
  130        * invocation was processed without error and the transport can
  131        * cache the connection.  If it returns "false", a protocol error
  132        * occurred during the call, and the transport should destroy the
  133        * connection.
  134        */
  135       public boolean serviceCall(final RemoteCall call) {
  136           try {
  137               /* read object id */
  138               final Remote impl;
  139               ObjID id;
  140   
  141               try {
  142                   id = ObjID.read(call.getInputStream());
  143               } catch (java.io.IOException e) {
  144                   throw new MarshalException("unable to read objID", e);
  145               }
  146   
  147               /* get the remote object */
  148               Transport transport = id.equals(dgcID) ? null : this;
  149               Target target =
  150                   ObjectTable.getTarget(new ObjectEndpoint(id, transport));
  151   
  152               if (target == null || (impl = target.getImpl()) == null) {
  153                   throw new NoSuchObjectException("no such object in table");
  154               }
  155   
  156               final Dispatcher disp = target.getDispatcher();
  157               target.incrementCallCount();
  158               try {
  159                   /* call the dispatcher */
  160                   transportLog.log(Log.VERBOSE, "call dispatcher");
  161   
  162                   final AccessControlContext acc =
  163                       target.getAccessControlContext();
  164                   ClassLoader ccl = target.getContextClassLoader();
  165   
  166                   Thread t = Thread.currentThread();
  167                   ClassLoader savedCcl = t.getContextClassLoader();
  168   
  169                   try {
  170                       t.setContextClassLoader(ccl);
  171                       currentTransport.set(this);
  172                       try {
  173                           java.security.AccessController.doPrivileged(
  174                               new java.security.PrivilegedExceptionAction<Void>() {
  175                               public Void run() throws IOException {
  176                                   checkAcceptPermission(acc);
  177                                   disp.dispatch(impl, call);
  178                                   return null;
  179                               }
  180                           }, acc);
  181                       } catch (java.security.PrivilegedActionException pae) {
  182                           throw (IOException) pae.getException();
  183                       }
  184                   } finally {
  185                       t.setContextClassLoader(savedCcl);
  186                       currentTransport.set(null);
  187                   }
  188   
  189               } catch (IOException ex) {
  190                   transportLog.log(Log.BRIEF,
  191                                    "exception thrown by dispatcher: ", ex);
  192                   return false;
  193               } finally {
  194                   target.decrementCallCount();
  195               }
  196   
  197           } catch (RemoteException e) {
  198   
  199               // if calls are being logged, write out exception
  200               if (UnicastServerRef.callLog.isLoggable(Log.BRIEF)) {
  201                   // include client host name if possible
  202                   String clientHost = "";
  203                   try {
  204                       clientHost = "[" +
  205                           RemoteServer.getClientHost() + "] ";
  206                   } catch (ServerNotActiveException ex) {
  207                   }
  208                   String message = clientHost + "exception: ";
  209                   UnicastServerRef.callLog.log(Log.BRIEF, message, e);
  210               }
  211   
  212               /* We will get a RemoteException if either a) the objID is
  213                * not readable, b) the target is not in the object table, or
  214                * c) the object is in the midst of being unexported (note:
  215                * NoSuchObjectException is thrown by the incrementCallCount
  216                * method if the object is being unexported).  Here it is
  217                * relatively safe to marshal an exception to the client
  218                * since the client will not have seen a return value yet.
  219                */
  220               try {
  221                   ObjectOutput out = call.getResultStream(false);
  222                   UnicastServerRef.clearStackTraces(e);
  223                   out.writeObject(e);
  224                   call.releaseOutputStream();
  225   
  226               } catch (IOException ie) {
  227                   transportLog.log(Log.BRIEF,
  228                       "exception thrown marshalling exception: ", ie);
  229                   return false;
  230               }
  231           }
  232   
  233           return true;
  234       }
  235   }

Save This Page
Home » openjdk-7 » sun.rmi » transport » [javadoc | source]