src/share/classes/com/sun/corba/se/impl/io/OutputStreamHook.java

Tue, 19 May 2015 21:51:03 +0100

author
msheppar
date
Tue, 19 May 2015 21:51:03 +0100
changeset 940
303fd9eb7e21
parent 754
20e2e121586b
child 1022
6081f57a0021
permissions
-rw-r--r--

8068721: RMI-IIOP communication fails when ConcurrentHashMap is passed to remote method
Reviewed-by: chegar, alanb

     1 /*
     2  * Copyright (c) 1999, 2015, Oracle and/or its affiliates. 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.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    25 /*
    26  * Licensed Materials - Property of IBM
    27  * RMI-IIOP v1.0
    28  * Copyright IBM Corp. 1998 1999  All Rights Reserved
    29  *
    30  */
    32 package com.sun.corba.se.impl.io;
    34 import java.io.IOException;
    35 import java.io.NotActiveException;
    36 import java.io.OutputStream;
    37 import java.io.ObjectOutputStream;
    38 import java.io.ObjectOutput;
    39 import java.util.Map;
    40 import java.util.HashMap;
    42 import org.omg.CORBA.INTERNAL;
    44 public abstract class OutputStreamHook extends ObjectOutputStream
    45 {
    46     private HookPutFields putFields = null;
    48     /**
    49      * Since ObjectOutputStream.PutField methods specify no exceptions,
    50      * we are not checking for null parameters on put methods.
    51      */
    52     private class HookPutFields extends ObjectOutputStream.PutField
    53     {
    54         private Map<String,Object> fields = new HashMap<>();
    56         /**
    57          * Put the value of the named boolean field into the persistent field.
    58          */
    59         public void put(String name, boolean value){
    60             fields.put(name, new Boolean(value));
    61         }
    63         /**
    64          * Put the value of the named char field into the persistent fields.
    65          */
    66         public void put(String name, char value){
    67             fields.put(name, new Character(value));
    68         }
    70         /**
    71          * Put the value of the named byte field into the persistent fields.
    72          */
    73         public void put(String name, byte value){
    74             fields.put(name, new Byte(value));
    75         }
    77         /**
    78          * Put the value of the named short field into the persistent fields.
    79          */
    80         public void put(String name, short value){
    81             fields.put(name, new Short(value));
    82         }
    84         /**
    85          * Put the value of the named int field into the persistent fields.
    86          */
    87         public void put(String name, int value){
    88             fields.put(name, new Integer(value));
    89         }
    91         /**
    92          * Put the value of the named long field into the persistent fields.
    93          */
    94         public void put(String name, long value){
    95             fields.put(name, new Long(value));
    96         }
    98         /**
    99          * Put the value of the named float field into the persistent fields.
   100          *
   101          */
   102         public void put(String name, float value){
   103             fields.put(name, new Float(value));
   104         }
   106         /**
   107          * Put the value of the named double field into the persistent field.
   108          */
   109         public void put(String name, double value){
   110             fields.put(name, new Double(value));
   111         }
   113         /**
   114          * Put the value of the named Object field into the persistent field.
   115          */
   116         public void put(String name, Object value){
   117             fields.put(name, value);
   118         }
   120         /**
   121          * Write the data and fields to the specified ObjectOutput stream.
   122          */
   123         public void write(ObjectOutput out) throws IOException {
   124             OutputStreamHook hook = (OutputStreamHook)out;
   126             ObjectStreamField[] osfields = hook.getFieldsNoCopy();
   128             // Write the fields to the stream in the order
   129             // provided by the ObjectStreamClass.  (They should
   130             // be sorted appropriately already.)
   131             for (int i = 0; i < osfields.length; i++) {
   133                 Object value = fields.get(osfields[i].getName());
   135                 hook.writeField(osfields[i], value);
   136             }
   137         }
   138     }
   140     abstract void writeField(ObjectStreamField field, Object value) throws IOException;
   142     public OutputStreamHook()
   143         throws java.io.IOException {
   144         super();
   145     }
   147     public void defaultWriteObject() throws IOException {
   149         writeObjectState.defaultWriteObject(this);
   151         defaultWriteObjectDelegate();
   152     }
   154     public abstract void defaultWriteObjectDelegate();
   156     public ObjectOutputStream.PutField putFields()
   157         throws IOException {
   158         if (putFields == null) {
   159             putFields = new HookPutFields();
   160         }
   161         return putFields;
   162     }
   164     // Stream format version, saved/restored during recursive calls
   165     protected byte streamFormatVersion = 1;
   167     // Return the stream format version currently being used
   168     // to serialize an object
   169     public byte getStreamFormatVersion() {
   170         return streamFormatVersion;
   171     }
   173     abstract ObjectStreamField[] getFieldsNoCopy();
   175     // User uses PutFields to simulate default data.
   176     // See java.io.ObjectOutputStream.PutFields
   177     public void writeFields()
   178         throws IOException {
   180         writeObjectState.defaultWriteObject(this);
   181         if (putFields != null) {
   182             putFields.write(this);
   183         } else {
   184             throw new NotActiveException("no current PutField object");
   185         }
   186     }
   188     abstract org.omg.CORBA_2_3.portable.OutputStream getOrbStream();
   190     protected abstract void beginOptionalCustomData();
   193     // The following is a State pattern implementation of what
   194     // should be done when a Serializable has a
   195     // writeObject method.  This was especially necessary for
   196     // RMI-IIOP stream format version 2.  Please see the
   197     // state diagrams in the docs directory of the workspace.
   199     protected WriteObjectState writeObjectState = NOT_IN_WRITE_OBJECT;
   201     protected void setState(WriteObjectState newState) {
   202         writeObjectState = newState;
   203     }
   205     // Description of possible actions
   206     protected static class WriteObjectState {
   207         public void enterWriteObject(OutputStreamHook stream) throws IOException {}
   208         public void exitWriteObject(OutputStreamHook stream) throws IOException {}
   209         public void defaultWriteObject(OutputStreamHook stream) throws IOException {}
   210         public void writeData(OutputStreamHook stream) throws IOException {}
   211     }
   213     protected static class DefaultState extends WriteObjectState {
   214         public void enterWriteObject(OutputStreamHook stream) throws IOException {
   215             stream.setState(IN_WRITE_OBJECT);
   216         }
   217     }
   219     protected static final WriteObjectState NOT_IN_WRITE_OBJECT = new DefaultState();
   220     protected static final WriteObjectState IN_WRITE_OBJECT = new InWriteObjectState();
   221     protected static final WriteObjectState WROTE_DEFAULT_DATA = new WroteDefaultDataState();
   222     protected static final WriteObjectState WROTE_CUSTOM_DATA = new WroteCustomDataState();
   224     protected static class InWriteObjectState extends WriteObjectState {
   226         public void enterWriteObject(OutputStreamHook stream) throws IOException {
   227             // XXX I18N, logging needed.
   228             throw new IOException("Internal state failure: Entered writeObject twice");
   229         }
   231         public void exitWriteObject(OutputStreamHook stream) throws IOException {
   233             // We didn't write any data, so write the
   234             // called defaultWriteObject indicator as false
   235             stream.getOrbStream().write_boolean(false);
   237             // If we're in stream format verison 2, we must
   238             // put the "null" marker to say that there isn't
   239             // any optional data
   240             if (stream.getStreamFormatVersion() == 2)
   241                 stream.getOrbStream().write_long(0);
   243             stream.setState(NOT_IN_WRITE_OBJECT);
   244         }
   246         public void defaultWriteObject(OutputStreamHook stream) throws IOException {
   248             // The writeObject method called defaultWriteObject
   249             // or writeFields, so put the called defaultWriteObject
   250             // indicator as true
   251             stream.getOrbStream().write_boolean(true);
   253             stream.setState(WROTE_DEFAULT_DATA);
   254         }
   256         public void writeData(OutputStreamHook stream) throws IOException {
   258             // The writeObject method first called a direct
   259             // write operation.  Write the called defaultWriteObject
   260             // indicator as false, put the special stream format
   261             // version 2 header (if stream format version 2, of course),
   262             // and write the data
   263             stream.getOrbStream().write_boolean(false);
   264             stream.beginOptionalCustomData();
   265             stream.setState(WROTE_CUSTOM_DATA);
   266         }
   267     }
   269     protected static class WroteDefaultDataState extends InWriteObjectState {
   271         public void exitWriteObject(OutputStreamHook stream) throws IOException {
   273             // We only wrote default data, so if in stream format
   274             // version 2, put the null indicator to say that there
   275             // is no optional data
   276             if (stream.getStreamFormatVersion() == 2)
   277                 stream.getOrbStream().write_long(0);
   279             stream.setState(NOT_IN_WRITE_OBJECT);
   280         }
   282         public void defaultWriteObject(OutputStreamHook stream) throws IOException {
   283             // XXX I18N, logging needed.
   284             throw new IOException("Called defaultWriteObject/writeFields twice");
   285         }
   287         public void writeData(OutputStreamHook stream) throws IOException {
   289             // The writeObject method called a direct write operation.
   290             // If in stream format version 2, put the fake valuetype
   291             // header.
   292             stream.beginOptionalCustomData();
   294             stream.setState(WROTE_CUSTOM_DATA);
   295         }
   296     }
   298     protected static class WroteCustomDataState extends InWriteObjectState {
   300         public void exitWriteObject(OutputStreamHook stream) throws IOException {
   301             // In stream format version 2, we must tell the ORB
   302             // stream to close the fake custom valuetype.
   303             if (stream.getStreamFormatVersion() == 2)
   304                 ((org.omg.CORBA.portable.ValueOutputStream)stream.getOrbStream()).end_value();
   306             stream.setState(NOT_IN_WRITE_OBJECT);
   307         }
   309         public void defaultWriteObject(OutputStreamHook stream) throws IOException {
   310             // XXX I18N, logging needed.
   311             throw new IOException("Cannot call defaultWriteObject/writeFields after writing custom data in RMI-IIOP");
   312         }
   314         // We don't have to do anything special here, just let
   315         // the stream write the data.
   316         public void writeData(OutputStreamHook stream) throws IOException {}
   317     }
   318 }

mercurial