CodeSetComponentInfo.java revision 608:7e06bf1dcb09
1/*
2 * Copyright (c) 1998, 2003, 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 */
31
32package com.sun.corba.se.impl.encoding;
33
34import java.util.StringTokenizer;
35import java.util.ArrayList;
36import java.util.Arrays;
37import java.util.List;
38import java.util.NoSuchElementException;
39import org.omg.CORBA.INITIALIZE;
40import org.omg.CORBA.CompletionStatus;
41
42import com.sun.corba.se.spi.logging.CORBALogDomains;
43import com.sun.corba.se.impl.logging.ORBUtilSystemException;
44
45public final class CodeSetComponentInfo {
46
47    /**
48     * CodeSetComponent is part of an IOR multi-component profile.  Two
49     * instances constitute a CodeSetComponentInfo (one for char and one
50     * for wchar data)
51     */
52    public static final class CodeSetComponent {
53        int nativeCodeSet;
54        int[] conversionCodeSets;
55
56        public boolean equals( Object obj )
57        {
58            if (this == obj)
59                return true ;
60
61            if (!(obj instanceof CodeSetComponent))
62                return false ;
63
64            CodeSetComponent other = (CodeSetComponent)obj ;
65
66            return (nativeCodeSet == other.nativeCodeSet) &&
67                Arrays.equals( conversionCodeSets, other.conversionCodeSets ) ;
68        }
69
70        public int hashCode()
71        {
72            int result = nativeCodeSet ;
73            for (int ctr=0; ctr<conversionCodeSets.length; ctr++)
74                result = 37*result + conversionCodeSets[ctr] ;
75            return result ;
76        }
77
78        public CodeSetComponent() {}
79
80        public CodeSetComponent(int nativeCodeSet, int[] conversionCodeSets) {
81            this.nativeCodeSet = nativeCodeSet;
82            if (conversionCodeSets == null)
83                this.conversionCodeSets = new int[0];
84            else
85                this.conversionCodeSets = conversionCodeSets;
86        }
87
88        public void read(MarshalInputStream in) {
89            nativeCodeSet = in.read_ulong();
90            int len = in.read_long();
91            conversionCodeSets = new int[len];
92            in.read_ulong_array(conversionCodeSets, 0, len);
93
94        }
95
96        public void write(MarshalOutputStream out) {
97            out.write_ulong(nativeCodeSet);
98            out.write_long(conversionCodeSets.length);
99            out.write_ulong_array(conversionCodeSets, 0, conversionCodeSets.length);
100        }
101
102        public String toString() {
103            StringBuffer sbuf = new StringBuffer("CodeSetComponent(");
104
105            sbuf.append("native:");
106            sbuf.append(Integer.toHexString(nativeCodeSet));
107            sbuf.append(" conversion:");
108            if (conversionCodeSets == null)
109                sbuf.append("null");
110            else {
111                for (int i = 0; i < conversionCodeSets.length; i++) {
112                    sbuf.append(Integer.toHexString(conversionCodeSets[i]));
113                    sbuf.append(' ');
114                }
115            }
116            sbuf.append( ")" ) ;
117
118            return sbuf.toString();
119        }
120    }
121
122    private CodeSetComponent forCharData;
123    private CodeSetComponent forWCharData;
124
125    public boolean equals( Object obj )
126    {
127        if (this == obj)
128            return true ;
129
130        if (!(obj instanceof CodeSetComponentInfo))
131            return false ;
132
133        CodeSetComponentInfo other = (CodeSetComponentInfo)obj ;
134        return forCharData.equals( other.forCharData ) &&
135            forWCharData.equals( other.forWCharData ) ;
136    }
137
138    public int hashCode()
139    {
140        return forCharData.hashCode() ^ forWCharData.hashCode() ;
141    }
142
143    public String toString() {
144        StringBuffer sbuf = new StringBuffer("CodeSetComponentInfo(");
145
146        sbuf.append("char_data:");
147        sbuf.append(forCharData.toString());
148        sbuf.append(" wchar_data:");
149        sbuf.append(forWCharData.toString());
150        sbuf.append(")");
151
152        return sbuf.toString();
153    }
154
155    public CodeSetComponentInfo() {
156        forCharData = CodeSetComponentInfo.JAVASOFT_DEFAULT_CODESETS.forCharData;
157        forWCharData = CodeSetComponentInfo.JAVASOFT_DEFAULT_CODESETS.forWCharData;
158    }
159
160    public CodeSetComponentInfo(CodeSetComponent charData,
161                                CodeSetComponent wcharData) {
162        forCharData = charData;
163        forWCharData = wcharData;
164    }
165
166    public void read(MarshalInputStream in) {
167        forCharData = new CodeSetComponent();
168        forCharData.read(in);
169        forWCharData = new CodeSetComponent();
170        forWCharData.read(in);
171    }
172
173    public void write(MarshalOutputStream out) {
174        forCharData.write(out);
175        forWCharData.write(out);
176    }
177
178    public CodeSetComponent getCharComponent() {
179        return forCharData;
180    }
181
182    public CodeSetComponent getWCharComponent() {
183        return forWCharData;
184    }
185
186    /**
187     * CodeSetContext goes in a GIOP service context
188     */
189    public static final class CodeSetContext {
190        private int char_data;
191        private int wchar_data;
192
193        public CodeSetContext() {}
194
195        public CodeSetContext(int charEncoding, int wcharEncoding) {
196            char_data = charEncoding;
197            wchar_data = wcharEncoding;
198        }
199
200        public void read(MarshalInputStream in) {
201            char_data = in.read_ulong();
202            wchar_data = in.read_ulong();
203        }
204
205        public void write(MarshalOutputStream out) {
206            out.write_ulong(char_data);
207            out.write_ulong(wchar_data);
208        }
209
210        public int getCharCodeSet() {
211            return char_data;
212        }
213
214        public int getWCharCodeSet() {
215            return wchar_data;
216        }
217
218        public String toString() {
219            StringBuffer sbuf = new StringBuffer();
220            sbuf.append("CodeSetContext char set: ");
221            sbuf.append(Integer.toHexString(char_data));
222            sbuf.append(" wchar set: ");
223            sbuf.append(Integer.toHexString(wchar_data));
224            return sbuf.toString();
225        }
226    }
227
228    /**
229     * Our default code set scheme is as follows:
230     *
231     * char data:
232     *
233     * Native code set:  ISO 8859-1 (8-bit)
234     * Conversion sets:  UTF-8, ISO 646 (7-bit)
235     *
236     * wchar data:
237     *
238     * Native code set:  UTF-16
239     * Conversion sets:  UCS-2
240     *
241     * Pre-Merlin/J2EE 1.3 JavaSoft ORBs listed ISO646 for char and
242     * UCS-2 for wchar, and provided no conversion sets.  They also
243     * didn't do correct negotiation or provide the fallback sets.
244     * UCS-2 is still in the conversion list for backwards compatibility.
245     *
246     * The fallbacks are UTF-8 for char and UTF-16 for wchar.
247     *
248     * In GIOP 1.1, interoperability with wchar is limited to 2 byte fixed
249     * width encodings since its wchars aren't preceded by a length.
250     * Thus, I've chosen not to include UTF-8 in the conversion set
251     * for wchar data.
252     *
253     */
254    public static final CodeSetComponentInfo JAVASOFT_DEFAULT_CODESETS;
255    static {
256        CodeSetComponent charData
257            = new CodeSetComponent(OSFCodeSetRegistry.ISO_8859_1.getNumber(),
258                                   new int[] {
259                                       OSFCodeSetRegistry.UTF_8.getNumber(),
260                                       OSFCodeSetRegistry.ISO_646.getNumber()
261                                   });
262
263        CodeSetComponent wcharData
264            = new CodeSetComponent(OSFCodeSetRegistry.UTF_16.getNumber(),
265                                   new int[]
266                                   {
267                                       OSFCodeSetRegistry.UCS_2.getNumber()
268                                   });
269
270        JAVASOFT_DEFAULT_CODESETS = new CodeSetComponentInfo(charData, wcharData);
271    }
272
273    /**
274     * Creates a CodeSetComponent from a String which contains a comma
275     * delimited list of OSF Code Set Registry numbers.  An INITIALIZE
276     * exception is thrown if any of the numbers are not known by our
277     * registry.  Used by corba.ORB init.
278     *
279     * The first number in the list is taken as the native code set,
280     * and the rest is the conversion code set list.
281     *
282     * The numbers can either be decimal or hex.
283     */
284    public static CodeSetComponent createFromString(String str) {
285        ORBUtilSystemException wrapper = ORBUtilSystemException.get(
286            CORBALogDomains.RPC_ENCODING ) ;
287
288        if (str == null || str.length() == 0)
289            throw wrapper.badCodeSetString() ;
290
291        StringTokenizer stok = new StringTokenizer(str, ", ", false);
292        int nativeSet = 0;
293        int conversionInts[] = null;
294
295        try {
296
297            // The first value is the native code set
298            nativeSet = Integer.decode(stok.nextToken()).intValue();
299
300            if (OSFCodeSetRegistry.lookupEntry(nativeSet) == null)
301                throw wrapper.unknownNativeCodeset( new Integer(nativeSet) ) ;
302
303            List conversionList = new ArrayList(10);
304
305            // Now process the other values as part of the
306            // conversion code set list.
307            while (stok.hasMoreTokens()) {
308
309                // decode allows us to specify hex, decimal, etc
310                Integer value = Integer.decode(stok.nextToken());
311
312                if (OSFCodeSetRegistry.lookupEntry(value.intValue()) == null)
313                    throw wrapper.unknownConversionCodeSet( value ) ;
314
315                conversionList.add(value);
316            }
317
318            conversionInts = new int[conversionList.size()];
319
320            for (int i = 0; i < conversionInts.length; i++)
321                conversionInts[i] = ((Integer)conversionList.get(i)).intValue();
322
323        } catch (NumberFormatException nfe) {
324            throw wrapper.invalidCodeSetNumber( nfe ) ;
325        } catch (NoSuchElementException nsee) {
326            throw wrapper.invalidCodeSetString( nsee, str ) ;
327        }
328
329        // Otherwise return the CodeSetComponent representing
330        // the given values
331        return new CodeSetComponent(nativeSet, conversionInts);
332    }
333
334    /**
335     * Code sets for local cases without a connection.
336     */
337    public static final CodeSetContext LOCAL_CODE_SETS
338        = new CodeSetContext(OSFCodeSetRegistry.ISO_8859_1.getNumber(),
339                             OSFCodeSetRegistry.UTF_16.getNumber());
340}
341