1. /*
  2. * @(#)CodeSetComponentInfo.java 1.31 03/12/19
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. /*
  8. * Licensed Materials - Property of IBM
  9. * RMI-IIOP v1.0
  10. * Copyright IBM Corp. 1998 1999 All Rights Reserved
  11. *
  12. * US Government Users Restricted Rights - Use, duplication or
  13. * disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
  14. */
  15. package com.sun.corba.se.impl.encoding;
  16. import java.util.StringTokenizer;
  17. import java.util.ArrayList;
  18. import java.util.Arrays;
  19. import java.util.List;
  20. import java.util.NoSuchElementException;
  21. import org.omg.CORBA.INITIALIZE;
  22. import org.omg.CORBA.CompletionStatus;
  23. import com.sun.corba.se.spi.logging.CORBALogDomains;
  24. import com.sun.corba.se.impl.logging.ORBUtilSystemException;
  25. public final class CodeSetComponentInfo {
  26. /**
  27. * CodeSetComponent is part of an IOR multi-component profile. Two
  28. * instances constitute a CodeSetComponentInfo (one for char and one
  29. * for wchar data)
  30. */
  31. public static final class CodeSetComponent {
  32. int nativeCodeSet;
  33. int[] conversionCodeSets;
  34. public boolean equals( Object obj )
  35. {
  36. if (this == obj)
  37. return true ;
  38. if (!(obj instanceof CodeSetComponent))
  39. return false ;
  40. CodeSetComponent other = (CodeSetComponent)obj ;
  41. return (nativeCodeSet == other.nativeCodeSet) &&
  42. Arrays.equals( conversionCodeSets, other.conversionCodeSets ) ;
  43. }
  44. public int hashCode()
  45. {
  46. int result = nativeCodeSet ;
  47. for (int ctr=0; ctr<conversionCodeSets.length; ctr++)
  48. result = 37*result + conversionCodeSets[ctr] ;
  49. return result ;
  50. }
  51. public CodeSetComponent() {}
  52. public CodeSetComponent(int nativeCodeSet, int[] conversionCodeSets) {
  53. this.nativeCodeSet = nativeCodeSet;
  54. if (conversionCodeSets == null)
  55. this.conversionCodeSets = new int[0];
  56. else
  57. this.conversionCodeSets = conversionCodeSets;
  58. }
  59. public void read(MarshalInputStream in) {
  60. nativeCodeSet = in.read_ulong();
  61. int len = in.read_long();
  62. conversionCodeSets = new int[len];
  63. in.read_ulong_array(conversionCodeSets, 0, len);
  64. }
  65. public void write(MarshalOutputStream out) {
  66. out.write_ulong(nativeCodeSet);
  67. out.write_long(conversionCodeSets.length);
  68. out.write_ulong_array(conversionCodeSets, 0, conversionCodeSets.length);
  69. }
  70. public String toString() {
  71. StringBuffer sbuf = new StringBuffer("CodeSetComponent(");
  72. sbuf.append("native:");
  73. sbuf.append(Integer.toHexString(nativeCodeSet));
  74. sbuf.append(" conversion:");
  75. if (conversionCodeSets == null)
  76. sbuf.append("null");
  77. else {
  78. for (int i = 0; i < conversionCodeSets.length; i++) {
  79. sbuf.append(Integer.toHexString(conversionCodeSets[i]));
  80. sbuf.append(' ');
  81. }
  82. }
  83. sbuf.append( ")" ) ;
  84. return sbuf.toString();
  85. }
  86. }
  87. private CodeSetComponent forCharData;
  88. private CodeSetComponent forWCharData;
  89. public boolean equals( Object obj )
  90. {
  91. if (this == obj)
  92. return true ;
  93. if (!(obj instanceof CodeSetComponentInfo))
  94. return false ;
  95. CodeSetComponentInfo other = (CodeSetComponentInfo)obj ;
  96. return forCharData.equals( other.forCharData ) &&
  97. forWCharData.equals( other.forWCharData ) ;
  98. }
  99. public int hashCode()
  100. {
  101. return forCharData.hashCode() ^ forWCharData.hashCode() ;
  102. }
  103. public String toString() {
  104. StringBuffer sbuf = new StringBuffer("CodeSetComponentInfo(");
  105. sbuf.append("char_data:");
  106. sbuf.append(forCharData.toString());
  107. sbuf.append(" wchar_data:");
  108. sbuf.append(forWCharData.toString());
  109. sbuf.append(")");
  110. return sbuf.toString();
  111. }
  112. public CodeSetComponentInfo() {
  113. forCharData = CodeSetComponentInfo.JAVASOFT_DEFAULT_CODESETS.forCharData;
  114. forWCharData = CodeSetComponentInfo.JAVASOFT_DEFAULT_CODESETS.forWCharData;
  115. }
  116. public CodeSetComponentInfo(CodeSetComponent charData,
  117. CodeSetComponent wcharData) {
  118. forCharData = charData;
  119. forWCharData = wcharData;
  120. }
  121. public void read(MarshalInputStream in) {
  122. forCharData = new CodeSetComponent();
  123. forCharData.read(in);
  124. forWCharData = new CodeSetComponent();
  125. forWCharData.read(in);
  126. }
  127. public void write(MarshalOutputStream out) {
  128. forCharData.write(out);
  129. forWCharData.write(out);
  130. }
  131. public CodeSetComponent getCharComponent() {
  132. return forCharData;
  133. }
  134. public CodeSetComponent getWCharComponent() {
  135. return forWCharData;
  136. }
  137. /**
  138. * CodeSetContext goes in a GIOP service context
  139. */
  140. public static final class CodeSetContext {
  141. private int char_data;
  142. private int wchar_data;
  143. public CodeSetContext() {}
  144. public CodeSetContext(int charEncoding, int wcharEncoding) {
  145. char_data = charEncoding;
  146. wchar_data = wcharEncoding;
  147. }
  148. public void read(MarshalInputStream in) {
  149. char_data = in.read_ulong();
  150. wchar_data = in.read_ulong();
  151. }
  152. public void write(MarshalOutputStream out) {
  153. out.write_ulong(char_data);
  154. out.write_ulong(wchar_data);
  155. }
  156. public int getCharCodeSet() {
  157. return char_data;
  158. }
  159. public int getWCharCodeSet() {
  160. return wchar_data;
  161. }
  162. public String toString() {
  163. StringBuffer sbuf = new StringBuffer();
  164. sbuf.append("CodeSetContext char set: ");
  165. sbuf.append(Integer.toHexString(char_data));
  166. sbuf.append(" wchar set: ");
  167. sbuf.append(Integer.toHexString(wchar_data));
  168. return sbuf.toString();
  169. }
  170. }
  171. /**
  172. * Our default code set scheme is as follows:
  173. *
  174. * char data:
  175. *
  176. * Native code set: ISO 8859-1 (8-bit)
  177. * Conversion sets: UTF-8, ISO 646 (7-bit)
  178. *
  179. * wchar data:
  180. *
  181. * Native code set: UTF-16
  182. * Conversion sets: UCS-2
  183. *
  184. * Pre-Merlin/J2EE 1.3 JavaSoft ORBs listed ISO646 for char and
  185. * UCS-2 for wchar, and provided no conversion sets. They also
  186. * didn't do correct negotiation or provide the fallback sets.
  187. * UCS-2 is still in the conversion list for backwards compatibility.
  188. *
  189. * The fallbacks are UTF-8 for char and UTF-16 for wchar.
  190. *
  191. * In GIOP 1.1, interoperability with wchar is limited to 2 byte fixed
  192. * width encodings since its wchars aren't preceded by a length.
  193. * Thus, I've chosen not to include UTF-8 in the conversion set
  194. * for wchar data.
  195. *
  196. */
  197. public static final CodeSetComponentInfo JAVASOFT_DEFAULT_CODESETS;
  198. static {
  199. CodeSetComponent charData
  200. = new CodeSetComponent(OSFCodeSetRegistry.ISO_8859_1.getNumber(),
  201. new int[] {
  202. OSFCodeSetRegistry.UTF_8.getNumber(),
  203. OSFCodeSetRegistry.ISO_646.getNumber()
  204. });
  205. CodeSetComponent wcharData
  206. = new CodeSetComponent(OSFCodeSetRegistry.UTF_16.getNumber(),
  207. new int[]
  208. {
  209. OSFCodeSetRegistry.UCS_2.getNumber()
  210. });
  211. JAVASOFT_DEFAULT_CODESETS = new CodeSetComponentInfo(charData, wcharData);
  212. }
  213. /**
  214. * Creates a CodeSetComponent from a String which contains a comma
  215. * delimited list of OSF Code Set Registry numbers. An INITIALIZE
  216. * exception is thrown if any of the numbers are not known by our
  217. * registry. Used by corba.ORB init.
  218. *
  219. * The first number in the list is taken as the native code set,
  220. * and the rest is the conversion code set list.
  221. *
  222. * The numbers can either be decimal or hex.
  223. */
  224. public static CodeSetComponent createFromString(String str) {
  225. ORBUtilSystemException wrapper = ORBUtilSystemException.get(
  226. CORBALogDomains.RPC_ENCODING ) ;
  227. if (str == null || str.length() == 0)
  228. throw wrapper.badCodeSetString() ;
  229. StringTokenizer stok = new StringTokenizer(str, ", ", false);
  230. int nativeSet = 0;
  231. int conversionInts[] = null;
  232. try {
  233. // The first value is the native code set
  234. nativeSet = Integer.decode(stok.nextToken()).intValue();
  235. if (OSFCodeSetRegistry.lookupEntry(nativeSet) == null)
  236. throw wrapper.unknownNativeCodeset( new Integer(nativeSet) ) ;
  237. List conversionList = new ArrayList(10);
  238. // Now process the other values as part of the
  239. // conversion code set list.
  240. while (stok.hasMoreTokens()) {
  241. // decode allows us to specify hex, decimal, etc
  242. Integer value = Integer.decode(stok.nextToken());
  243. if (OSFCodeSetRegistry.lookupEntry(value.intValue()) == null)
  244. throw wrapper.unknownConversionCodeSet( value ) ;
  245. conversionList.add(value);
  246. }
  247. conversionInts = new int[conversionList.size()];
  248. for (int i = 0; i < conversionInts.length; i++)
  249. conversionInts[i] = ((Integer)conversionList.get(i)).intValue();
  250. } catch (NumberFormatException nfe) {
  251. throw wrapper.invalidCodeSetNumber( nfe ) ;
  252. } catch (NoSuchElementException nsee) {
  253. throw wrapper.invalidCodeSetString( nsee, str ) ;
  254. }
  255. // Otherwise return the CodeSetComponent representing
  256. // the given values
  257. return new CodeSetComponent(nativeSet, conversionInts);
  258. }
  259. /**
  260. * Code sets for local cases without a connection.
  261. */
  262. public static final CodeSetContext LOCAL_CODE_SETS
  263. = new CodeSetContext(OSFCodeSetRegistry.ISO_8859_1.getNumber(),
  264. OSFCodeSetRegistry.UTF_16.getNumber());
  265. }