1. /*
  2. * @(#)SQLOutputImpl.java 1.5 04/05/05
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.sql.rowset.serial;
  8. import java.sql.*;
  9. import javax.sql.*;
  10. import java.io.*;
  11. import java.lang.String;
  12. import java.math.*;
  13. import java.util.Map;
  14. import java.util.Vector;
  15. /**
  16. * The output stream for writing the attributes of a
  17. * custom-mapped user-defined type (UDT) back to the database.
  18. * The driver uses this interface internally, and its
  19. * methods are never directly invoked by an application programmer.
  20. * <p>
  21. * When an application calls the
  22. * method <code>PreparedStatement.setObject</code>, the driver
  23. * checks to see whether the value to be written is a UDT with
  24. * a custom mapping. If it is, there will be an entry in a
  25. * type map containing the <code>Class</code> object for the
  26. * class that implements <code>SQLData</code> for this UDT.
  27. * If the value to be written is an instance of <code>SQLData</code>,
  28. * the driver will create an instance of <code>SQLOutputImpl</code>
  29. * and pass it to the method <code>SQLData.writeSQL</code>.
  30. * The method <code>writeSQL</code> in turn calls the
  31. * appropriate <code>SQLOutputImpl.writeXXX</code> methods
  32. * to write data from the <code>SQLData</code> object to
  33. * the <code>SQLOutputImpl</code> output stream as the
  34. * representation of an SQL user-defined type.
  35. */
  36. public class SQLOutputImpl implements SQLOutput {
  37. /**
  38. * A reference to an existing vector that
  39. * contains the attributes of a <code>Struct</code> object.
  40. */
  41. private Vector attribs;
  42. /**
  43. * The type map the driver supplies to a newly created
  44. * <code>SQLOutputImpl</code> object. This type map
  45. * indicates the <code>SQLData</code> class whose
  46. * <code>writeSQL</code> method will be called. This
  47. * method will in turn call the appropriate
  48. * <code>SQLOutputImpl/code> writer methods.
  49. */
  50. private Map map;
  51. /**
  52. * Creates a new <code>SQLOutputImpl</code> object
  53. * initialized with the given vector of attributes and
  54. * type map. The driver will use the type map to determine
  55. * which <code>SQLData.writeSQL</code> method to invoke.
  56. * This method will then call the appropriate
  57. * <code>SQLOutputImpl</code> writer methods in order and
  58. * thereby write the attributes to the new output stream.
  59. *
  60. * @param attributes a <code>Vector</code> object containing the attributes of
  61. * the UDT to be mapped to one or more objects in the Java
  62. * programming language
  63. *
  64. * @param map a <code>java.util.Map</code> object containing zero or
  65. * more entries, with each entry consisting of 1) a <code>String</code>
  66. * giving the fully qualified name of a UDT and 2) the
  67. * <code>Class</code> object for the <code>SQLData</code> implementation
  68. * that defines how the UDT is to be mapped
  69. * @throws SQLException if the <code>attributes</code> or the <code>map</code>
  70. * is a <code>null</code> value
  71. */
  72. public SQLOutputImpl(Vector<?> attributes, Map<String,?> map)
  73. throws SQLException
  74. {
  75. if ((attributes == null) || (map == null)) {
  76. throw new SQLException("Cannot instantiate a SQLOutputImpl " +
  77. "instance with null parameters");
  78. }
  79. this.attribs = attributes;
  80. this.map = map;
  81. }
  82. //================================================================
  83. // Methods for writing attributes to the stream of SQL data.
  84. // These methods correspond to the column-accessor methods of
  85. // java.sql.ResultSet.
  86. //================================================================
  87. /**
  88. * Writes a <code>String</code> in the Java programming language
  89. * to this <code>SQLOutputImpl</code> object. The driver converts
  90. * it to an SQL <code>CHAR</code>, <code>VARCHAR</code>, or
  91. * <code>LONGVARCHAR</code> before returning it to the database.
  92. *
  93. * @param x the value to pass to the database
  94. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  95. * use by a <code>SQLData</code> object attempting to write the attribute
  96. * values of a UDT to the database.
  97. */
  98. public void writeString(String x) throws SQLException {
  99. //System.out.println("Adding :"+x);
  100. attribs.add(x);
  101. }
  102. /**
  103. * Writes a <code>boolean</code> in the Java programming language
  104. * to this <code>SQLOutputImpl</code> object. The driver converts
  105. * it to an SQL <code>BIT</code> before returning it to the database.
  106. *
  107. * @param x the value to pass to the database
  108. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  109. * use by a <code>SQLData</code> object attempting to write the attribute
  110. * values of a UDT to the database.
  111. */
  112. public void writeBoolean(boolean x) throws SQLException {
  113. attribs.add(new Boolean(x));
  114. }
  115. /**
  116. * Writes a <code>byte</code> in the Java programming language
  117. * to this <code>SQLOutputImpl</code> object. The driver converts
  118. * it to an SQL <code>BIT</code> before returning it to the database.
  119. *
  120. * @param x the value to pass to the database
  121. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  122. * use by a <code>SQLData</code> object attempting to write the attribute
  123. * values of a UDT to the database.
  124. */
  125. public void writeByte(byte x) throws SQLException {
  126. attribs.add(new Byte(x));
  127. }
  128. /**
  129. * Writes a <code>short</code> in the Java programming language
  130. * to this <code>SQLOutputImpl</code> object. The driver converts
  131. * it to an SQL <code>SMALLINT</code> before returning it to the database.
  132. *
  133. * @param x the value to pass to the database
  134. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  135. * use by a <code>SQLData</code> object attempting to write the attribute
  136. * values of a UDT to the database.
  137. */
  138. public void writeShort(short x) throws SQLException {
  139. attribs.add(new Short(x));
  140. }
  141. /**
  142. * Writes an <code>int</code> in the Java programming language
  143. * to this <code>SQLOutputImpl</code> object. The driver converts
  144. * it to an SQL <code>INTEGER</code> before returning it to the database.
  145. *
  146. * @param x the value to pass to the database
  147. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  148. * use by a <code>SQLData</code> object attempting to write the attribute
  149. * values of a UDT to the database.
  150. */
  151. public void writeInt(int x) throws SQLException {
  152. attribs.add(new Integer(x));
  153. }
  154. /**
  155. * Writes a <code>long</code> in the Java programming language
  156. * to this <code>SQLOutputImpl</code> object. The driver converts
  157. * it to an SQL <code>BIGINT</code> before returning it to the database.
  158. *
  159. * @param x the value to pass to the database
  160. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  161. * use by a <code>SQLData</code> object attempting to write the attribute
  162. * values of a UDT to the database.
  163. */
  164. public void writeLong(long x) throws SQLException {
  165. attribs.add(new Long(x));
  166. }
  167. /**
  168. * Writes a <code>float</code> in the Java programming language
  169. * to this <code><code>SQLOutputImpl</code></code> object. The driver converts
  170. * it to an SQL <code>REAL</code> before returning it to the database.
  171. *
  172. * @param x the value to pass to the database
  173. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  174. * use by a <code>SQLData</code> object attempting to write the attribute
  175. * values of a UDT to the database.
  176. */
  177. public void writeFloat(float x) throws SQLException {
  178. attribs.add(new Float(x));
  179. }
  180. /**
  181. * Writes a <code>double</code> in the Java programming language
  182. * to this <code>SQLOutputImpl</code> object. The driver converts
  183. * it to an SQL <code>DOUBLE</code> before returning it to the database.
  184. *
  185. * @param x the value to pass to the database
  186. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  187. * use by a <code>SQLData</code> object attempting to write the attribute
  188. * values of a UDT to the database.
  189. */
  190. public void writeDouble(double x) throws SQLException{
  191. attribs.add(new Double(x));
  192. }
  193. /**
  194. * Writes a <code>java.math.BigDecimal</code> object in the Java programming
  195. * language to this <code>SQLOutputImpl</code> object. The driver converts
  196. * it to an SQL <code>NUMERIC</code> before returning it to the database.
  197. *
  198. * @param x the value to pass to the database
  199. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  200. * use by a <code>SQLData</code> object attempting to write the attribute
  201. * values of a UDT to the database.
  202. */
  203. public void writeBigDecimal(java.math.BigDecimal x) throws SQLException{
  204. attribs.add(x);
  205. }
  206. /**
  207. * Writes an array of <code>bytes</code> in the Java programming language
  208. * to this <code>SQLOutputImpl</code> object. The driver converts
  209. * it to an SQL <code>VARBINARY</code> or <code>LONGVARBINARY</code>
  210. * before returning it to the database.
  211. *
  212. * @param x the value to pass to the database
  213. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  214. * use by a <code>SQLData</code> object attempting to write the attribute
  215. * values of a UDT to the database.
  216. */
  217. public void writeBytes(byte[] x) throws SQLException {
  218. attribs.add(x);
  219. }
  220. /**
  221. * Writes a <code>java.sql.Date</code> object in the Java programming
  222. * language to this <code>SQLOutputImpl</code> object. The driver converts
  223. * it to an SQL <code>DATE</code> before returning it to the database.
  224. *
  225. * @param x the value to pass to the database
  226. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  227. * use by a <code>SQLData</code> object attempting to write the attribute
  228. * values of a UDT to the database.
  229. */
  230. public void writeDate(java.sql.Date x) throws SQLException {
  231. attribs.add(x);
  232. }
  233. /**
  234. * Writes a <code>java.sql.Time</code> object in the Java programming
  235. * language to this <code>SQLOutputImpl</code> object. The driver converts
  236. * it to an SQL <code>TIME</code> before returning it to the database.
  237. *
  238. * @param x the value to pass to the database
  239. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  240. * use by a <code>SQLData</code> object attempting to write the attribute
  241. * values of a UDT to the database.
  242. */
  243. public void writeTime(java.sql.Time x) throws SQLException {
  244. attribs.add(x);
  245. }
  246. /**
  247. * Writes a <code>java.sql.Timestamp</code> object in the Java programming
  248. * language to this <code>SQLOutputImpl</code> object. The driver converts
  249. * it to an SQL <code>TIMESTAMP</code> before returning it to the database.
  250. *
  251. * @param x the value to pass to the database
  252. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  253. * use by a <code>SQLData</code> object attempting to write the attribute
  254. * values of a UDT to the database.
  255. */
  256. public void writeTimestamp(java.sql.Timestamp x) throws SQLException {
  257. attribs.add(x);
  258. }
  259. /**
  260. * Writes a stream of Unicode characters to this
  261. * <code>SQLOutputImpl</code> object. The driver will do any necessary
  262. * conversion from Unicode to the database <code>CHAR</code> format.
  263. *
  264. * @param x the value to pass to the database
  265. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  266. * use by a <code>SQLData</code> object attempting to write the attribute
  267. * values of a UDT to the database.
  268. */
  269. public void writeCharacterStream(java.io.Reader x) throws SQLException {
  270. BufferedReader bufReader = new BufferedReader(x);
  271. try {
  272. int i;
  273. while( (i = bufReader.read()) != -1 ) {
  274. char ch = (char)i;
  275. StringBuffer strBuf = new StringBuffer();
  276. strBuf.append(ch);
  277. String str = new String(strBuf);
  278. String strLine = bufReader.readLine();
  279. writeString(str.concat(strLine));
  280. }
  281. } catch(IOException ioe) {
  282. }
  283. }
  284. /**
  285. * Writes a stream of ASCII characters to this
  286. * <code>SQLOutputImpl</code> object. The driver will do any necessary
  287. * conversion from ASCII to the database <code>CHAR</code> format.
  288. *
  289. * @param x the value to pass to the database
  290. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  291. * use by a <code>SQLData</code> object attempting to write the attribute
  292. * values of a UDT to the database.
  293. */
  294. public void writeAsciiStream(java.io.InputStream x) throws SQLException {
  295. BufferedReader bufReader = new BufferedReader(new InputStreamReader(x));
  296. try {
  297. int i;
  298. while( (i=bufReader.read()) != -1 ) {
  299. char ch = (char)i;
  300. StringBuffer strBuf = new StringBuffer();
  301. strBuf.append(ch);
  302. String str = new String(strBuf);
  303. String strLine = bufReader.readLine();
  304. writeString(str.concat(strLine));
  305. }
  306. }catch(IOException ioe) {
  307. throw new SQLException(ioe.getMessage());
  308. }
  309. }
  310. /**
  311. * Writes a stream of uninterpreted bytes to this <code>SQLOutputImpl</code>
  312. * object.
  313. *
  314. * @param x the value to pass to the database
  315. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  316. * use by a <code>SQLData</code> object attempting to write the attribute
  317. * values of a UDT to the database.
  318. */
  319. public void writeBinaryStream(java.io.InputStream x) throws SQLException {
  320. BufferedReader bufReader = new BufferedReader(new InputStreamReader(x));
  321. try {
  322. int i;
  323. while( (i=bufReader.read()) != -1 ) {
  324. char ch = (char)i;
  325. StringBuffer strBuf = new StringBuffer();
  326. strBuf.append(ch);
  327. String str = new String(strBuf);
  328. String strLine = bufReader.readLine();
  329. writeString(str.concat(strLine));
  330. }
  331. } catch(IOException ioe) {
  332. throw new SQLException(ioe.getMessage());
  333. }
  334. }
  335. //================================================================
  336. // Methods for writing items of SQL user-defined types to the stream.
  337. // These methods pass objects to the database as values of SQL
  338. // Structured Types, Distinct Types, Constructed Types, and Locator
  339. // Types. They decompose the Java object(s) and write leaf data
  340. // items using the methods above.
  341. //================================================================
  342. /**
  343. * Writes to the stream the data contained in the given
  344. * <code>SQLData</code> object.
  345. * When the <code>SQLData</code> object is <code>null</code>, this
  346. * method writes an SQL <code>NULL</code> to the stream.
  347. * Otherwise, it calls the <code>SQLData.writeSQL</code>
  348. * method of the given object, which
  349. * writes the object's attributes to the stream.
  350. * <P>
  351. * The implementation of the method <code>SQLData.writeSQ</code>
  352. * calls the appropriate <code>SQLOutputImpl.writeXXX</code> method(s)
  353. * for writing each of the object's attributes in order.
  354. * The attributes must be read from an <code>SQLInput</code>
  355. * input stream and written to an <code>SQLOutputImpl</code>
  356. * output stream in the same order in which they were
  357. * listed in the SQL definition of the user-defined type.
  358. *
  359. * @param x the object representing data of an SQL structured or
  360. * distinct type
  361. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  362. * use by a <code>SQLData</code> object attempting to write the attribute
  363. * values of a UDT to the database.
  364. */
  365. public void writeObject(SQLData x) throws SQLException {
  366. /*
  367. * Except for the types that are passed as objects
  368. * this seems to be the only way for an object to
  369. * get a null value for a field in a structure.
  370. *
  371. * Note: this means that the class defining SQLData
  372. * will need to track if a field is SQL null for itself
  373. */
  374. if (x == null) {
  375. attribs.add(x);
  376. return;
  377. }
  378. /*
  379. * We have to write out a SerialStruct that contains
  380. * the name of this class otherwise we don't know
  381. * what to re-instantiate during readSQL()
  382. */
  383. attribs.add(new SerialStruct((SQLData)x, map));
  384. }
  385. /**
  386. * Writes a <code>Ref</code> object in the Java programming language
  387. * to this <code>SQLOutputImpl</code> object. The driver converts
  388. * it to a serializable <code>SerialRef</code> SQL <code>REF</code> value
  389. * before returning it to the database.
  390. *
  391. * @param x an object representing an SQL <code>REF</code> value
  392. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  393. * use by a <code>SQLData</code> object attempting to write the attribute
  394. * values of a UDT to the database.
  395. */
  396. public void writeRef(Ref x) throws SQLException {
  397. if (x == null) {
  398. attribs.add(x);
  399. return;
  400. }
  401. attribs.add(new SerialRef(x));
  402. }
  403. /**
  404. * Writes a <code>Blob</code> object in the Java programming language
  405. * to this <code>SQLOutputImpl</code> object. The driver converts
  406. * it to a serializable <code>SerialBlob</code> SQL <code>BLOB</code> value
  407. * before returning it to the database.
  408. *
  409. * @param x an object representing an SQL <code>BLOB</code> value
  410. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  411. * use by a <code>SQLData</code> object attempting to write the attribute
  412. * values of a UDT to the database.
  413. */
  414. public void writeBlob(Blob x) throws SQLException {
  415. if (x == null) {
  416. attribs.add(x);
  417. return;
  418. }
  419. attribs.add(new SerialBlob(x));
  420. }
  421. /**
  422. * Writes a <code>Clob</code> object in the Java programming language
  423. * to this <code>SQLOutputImpl</code> object. The driver converts
  424. * it to a serializable <code>SerialClob</code> SQL <code>CLOB</code> value
  425. * before returning it to the database.
  426. *
  427. * @param x an object representing an SQL <code>CLOB</code> value
  428. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  429. * use by a <code>SQLData</code> object attempting to write the attribute
  430. * values of a UDT to the database.
  431. */
  432. public void writeClob(Clob x) throws SQLException {
  433. if (x == null) {
  434. attribs.add(x);
  435. return;
  436. }
  437. attribs.add(new SerialClob(x));
  438. }
  439. /**
  440. * Writes a <code>Struct</code> object in the Java
  441. * programming language to this <code>SQLOutputImpl</code>
  442. * object. The driver converts this value to an SQL structured type
  443. * before returning it to the database.
  444. * <P>
  445. * This method should be used when an SQL structured type has been
  446. * mapped to a <code>Struct</code> object in the Java programming
  447. * language (the standard mapping). The method
  448. * <code>writeObject</code> should be used if an SQL structured type
  449. * has been custom mapped to a class in the Java programming language.
  450. *
  451. * @param x an object representing the attributes of an SQL structured type
  452. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  453. * use by a <code>SQLData</code> object attempting to write the attribute
  454. * values of a UDT to the database.
  455. */
  456. public void writeStruct(Struct x) throws SQLException {
  457. SerialStruct s = new SerialStruct(x,map);;
  458. attribs.add(s);
  459. }
  460. /**
  461. * Writes an <code>Array</code> object in the Java
  462. * programming language to this <code>SQLOutputImpl</code>
  463. * object. The driver converts this value to a serializable
  464. * <code>SerialArray</code> SQL <code>ARRAY</code>
  465. * value before returning it to the database.
  466. *
  467. * @param x an object representing an SQL <code>ARRAY</code> value
  468. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  469. * use by a <code>SQLData</code> object attempting to write the attribute
  470. * values of a UDT to the database.
  471. */
  472. public void writeArray(Array x) throws SQLException {
  473. if (x == null) {
  474. attribs.add(x);
  475. return;
  476. }
  477. attribs.add(new SerialArray(x, map));
  478. }
  479. /**
  480. * Writes an <code>java.sql.Type.DATALINK</code> object in the Java
  481. * programming language to this <code>SQLOutputImpl</code> object. The
  482. * driver converts this value to a serializable <code>SerialDatalink</code>
  483. * SQL <code>DATALINK</code> value before return it to the database.
  484. *
  485. * @param url an object representing a SQL <code>DATALINK</code> value
  486. * @throws SQLException if the <code>SQLOutputImpl</code> object is in
  487. * use by a <code>SQLData</code> object attempting to write the attribute
  488. * values of a UDT to the database.
  489. */
  490. public void writeURL(java.net.URL url) throws SQLException {
  491. if (url == null) {
  492. attribs.add(url);
  493. return;
  494. }
  495. attribs.add(new SerialDatalink(url));
  496. }
  497. }