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