1 /* ArrayValueHelper.java --
2    Copyright (C) 2005 Free Software Foundation, Inc.
3 
4 This file is part of GNU Classpath.
5 
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10 
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING.  If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
20 
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library.  Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
25 
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module.  An independent module is a module which is not derived from
33 or based on this library.  If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so.  If you do not wish to do so, delete this
36 exception statement from your version. */
37 
38 
39 package gnu.CORBA.CDR;
40 
41 import gnu.CORBA.ObjectCreator;
42 
43 import org.omg.CORBA.BooleanSeqHelper;
44 import org.omg.CORBA.CharSeqHelper;
45 import org.omg.CORBA.DoubleSeqHelper;
46 import org.omg.CORBA.FloatSeqHelper;
47 import org.omg.CORBA.LongLongSeqHelper;
48 import org.omg.CORBA.LongSeqHelper;
49 import org.omg.CORBA.OctetSeqHelper;
50 import org.omg.CORBA.ShortSeqHelper;
51 import org.omg.CORBA.portable.BoxedValueHelper;
52 import org.omg.CORBA.portable.InputStream;
53 import org.omg.CORBA.portable.OutputStream;
54 
55 import java.io.Serializable;
56 import java.lang.reflect.Array;
57 import java.rmi.Remote;
58 
59 import javax.rmi.CORBA.Util;
60 import javax.rmi.CORBA.ValueHandler;
61 
62 /**
63  * Writes arrays as a boxed value types. A single instance is used to write a
64  * single array. This class is only used with RMI/IIOP, to handle array boxed
65  * values.
66  *
67  * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org)
68  */
69 class ArrayValueHelper
70   implements BoxedValueHelper
71 {
72   /**
73    * The value handler (one for all instances).
74    */
75   static ValueHandler handler = Util.createValueHandler();
76 
77   /**
78    * A class of the array being written.
79    */
80   Class arrayClass;
81 
82   /**
83    * The array component class.
84    */
85   Class component;
86 
87   /**
88    * The array component repository Id.
89    */
90   String componentId;
91 
92   /**
93    * If true, the array members are written as objects rather than as values.
94    * True for Remotes and CORBA objects.
95    */
written_as_object()96   boolean written_as_object()
97   {
98     return org.omg.CORBA.Object.class.isAssignableFrom(component)
99       || Remote.class.isAssignableFrom(component);
100   }
101 
102   /**
103    * Creates the instance of the helper to write this specific array class.
104    */
ArrayValueHelper(Class an_arrayClass)105   ArrayValueHelper(Class an_arrayClass)
106   {
107     arrayClass = an_arrayClass;
108   }
109 
110   /**
111    * Get the array repository Id that will be the RMI repository id.
112    */
get_id()113   public String get_id()
114   {
115     return ObjectCreator.getRepositoryId(arrayClass);
116   }
117 
118   /**
119    * Read the array from the input stream.
120    */
read_value(InputStream input)121   public Serializable read_value(InputStream input)
122   {
123     if (input instanceof HeadlessInput)
124       {
125         ((HeadlessInput) input).subsequentCalls = true;
126       }
127 
128     component = arrayClass.getComponentType();
129 
130     if (component.equals(byte.class))
131       return OctetSeqHelper.read(input);
132     else if (component.equals(String.class))
133       {
134         // String array is optimized because this may be frequent.
135         String[] s = new String[input.read_long()];
136 
137         for (int i = 0; i < s.length; i++)
138           s[i] = (String) Vio.read(input, Vio.m_StringValueHelper);
139         return s;
140       }
141     else if (component.equals(int.class))
142       return LongSeqHelper.read(input);
143     else if (component.equals(long.class))
144       return LongLongSeqHelper.read(input);
145     else if (component.equals(double.class))
146       return DoubleSeqHelper.read(input);
147     else if (component.equals(float.class))
148       return FloatSeqHelper.read(input);
149     else if (component.equals(boolean.class))
150       return BooleanSeqHelper.read(input);
151     else if (component.equals(short.class))
152       return ShortSeqHelper.read(input);
153     else if (component.equals(char.class))
154       return CharSeqHelper.read(input);
155     else
156       {
157         // Read others, use reflection.
158         int n = input.read_long();
159 
160         gnuValueStream s = null;
161 
162         Serializable array = (Serializable) Array.newInstance(component, n);
163         if (written_as_object())
164           for (int i = 0; i < n; i++)
165             {
166               gnuRuntime g;
167               int position;
168               if (input instanceof gnuValueStream)
169                 {
170                   s = (gnuValueStream) input;
171                   g = s.getRunTime();
172                   position = s.getPosition();
173                 }
174               else
175                 {
176                   g = null;
177                   position = -1;
178                 }
179 
180               if (input instanceof HeadlessInput)
181                 ((HeadlessInput) input).subsequentCalls = true;
182 
183               Object o = handler.readValue(input, position, component, null, g);
184               Array.set(array, i, o);
185             }
186         else
187           for (int i = 0; i < n; i++)
188             Array.set(array, i, Vio.read(input, component));
189         return array;
190       }
191   }
192 
193   /**
194    * Write the array to the input stream.
195    */
write_value(OutputStream output, Serializable value)196   public void write_value(OutputStream output, Serializable value)
197   {
198     if (output instanceof gnuValueStream)
199       {
200         gnuRuntime r = ((gnuValueStream) output).getRunTime();
201         if (r != null)
202           r.target = null;
203       }
204 
205     if (value instanceof byte[])
206       OctetSeqHelper.write(output, (byte[]) value);
207     else if (value instanceof String[])
208       {
209         String[] s = (String[]) value;
210         output.write_long(s.length);
211         for (int i = 0; i < s.length; i++)
212           Vio.write(output, s[i], Vio.m_StringValueHelper);
213       }
214     else if (value instanceof int[])
215       LongSeqHelper.write(output, (int[]) value);
216     else if (value instanceof long[])
217       LongLongSeqHelper.write(output, (long[]) value);
218     else if (value instanceof double[])
219       DoubleSeqHelper.write(output, (double[]) value);
220     else if (value instanceof float[])
221       FloatSeqHelper.write(output, (float[]) value);
222     else if (value instanceof boolean[])
223       BooleanSeqHelper.write(output, (boolean[]) value);
224     else if (value instanceof short[])
225       ShortSeqHelper.write(output, (short[]) value);
226     else if (value instanceof char[])
227       CharSeqHelper.write(output, (char[]) value);
228     else
229       {
230         // Write others, use reflection.
231         component = arrayClass.getComponentType();
232 
233         int n = Array.getLength(value);
234         output.write_long(n);
235         if (written_as_object())
236           for (int i = 0; i < n; i++)
237             {
238               Object o = Array.get(value, i);
239               if (o == null)
240                 output.write_Object(null);
241               else
242                 // CORBA objects have another notation.
243                 handler.writeValue(output, (Serializable) o);
244             }
245         else
246           {
247             for (int i = 0; i < n; i++)
248               Vio.write(output, (Serializable) Array.get(value, i),
249                 component);
250           }
251 
252       }
253   }
254 }
255