001 /*
002 * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package javax.sql.rowset.serial;
027
028 import java.sql.*;
029 import javax.sql.*;
030 import java.io.*;
031 import java.lang.String;
032 import java.math.*;
033 import java.util.Map;
034 import java.util.Vector;
035
036 /**
037 * The output stream for writing the attributes of a
038 * custom-mapped user-defined type (UDT) back to the database.
039 * The driver uses this interface internally, and its
040 * methods are never directly invoked by an application programmer.
041 * <p>
042 * When an application calls the
043 * method <code>PreparedStatement.setObject</code>, the driver
044 * checks to see whether the value to be written is a UDT with
045 * a custom mapping. If it is, there will be an entry in a
046 * type map containing the <code>Class</code> object for the
047 * class that implements <code>SQLData</code> for this UDT.
048 * If the value to be written is an instance of <code>SQLData</code>,
049 * the driver will create an instance of <code>SQLOutputImpl</code>
050 * and pass it to the method <code>SQLData.writeSQL</code>.
051 * The method <code>writeSQL</code> in turn calls the
052 * appropriate <code>SQLOutputImpl.writeXXX</code> methods
053 * to write data from the <code>SQLData</code> object to
054 * the <code>SQLOutputImpl</code> output stream as the
055 * representation of an SQL user-defined type.
056 */
057 public class SQLOutputImpl implements SQLOutput {
058
059 /**
060 * A reference to an existing vector that
061 * contains the attributes of a <code>Struct</code> object.
062 */
063 private Vector attribs;
064
065 /**
066 * The type map the driver supplies to a newly created
067 * <code>SQLOutputImpl</code> object. This type map
068 * indicates the <code>SQLData</code> class whose
069 * <code>writeSQL</code> method will be called. This
070 * method will in turn call the appropriate
071 * <code>SQLOutputImpl</code> writer methods.
072 */
073 private Map map;
074
075 /**
076 * Creates a new <code>SQLOutputImpl</code> object
077 * initialized with the given vector of attributes and
078 * type map. The driver will use the type map to determine
079 * which <code>SQLData.writeSQL</code> method to invoke.
080 * This method will then call the appropriate
081 * <code>SQLOutputImpl</code> writer methods in order and
082 * thereby write the attributes to the new output stream.
083 *
084 * @param attributes a <code>Vector</code> object containing the attributes of
085 * the UDT to be mapped to one or more objects in the Java
086 * programming language
087 *
088 * @param map a <code>java.util.Map</code> object containing zero or
089 * more entries, with each entry consisting of 1) a <code>String</code>
090 * giving the fully qualified name of a UDT and 2) the
091 * <code>Class</code> object for the <code>SQLData</code> implementation
092 * that defines how the UDT is to be mapped
093 * @throws SQLException if the <code>attributes</code> or the <code>map</code>
094 * is a <code>null</code> value
095 */
096 public SQLOutputImpl(Vector<?> attributes, Map<String, ?> map)
097 throws SQLException {
098 if ((attributes == null) || (map == null)) {
099 throw new SQLException(
100 "Cannot instantiate a SQLOutputImpl "
101 + "instance with null parameters");
102 }
103 this .attribs = attributes;
104 this .map = map;
105 }
106
107 //================================================================
108 // Methods for writing attributes to the stream of SQL data.
109 // These methods correspond to the column-accessor methods of
110 // java.sql.ResultSet.
111 //================================================================
112
113 /**
114 * Writes a <code>String</code> in the Java programming language
115 * to this <code>SQLOutputImpl</code> object. The driver converts
116 * it to an SQL <code>CHAR</code>, <code>VARCHAR</code>, or
117 * <code>LONGVARCHAR</code> before returning it to the database.
118 *
119 * @param x the value to pass to the database
120 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
121 * use by a <code>SQLData</code> object attempting to write the attribute
122 * values of a UDT to the database.
123 */
124 public void writeString(String x) throws SQLException {
125 //System.out.println("Adding :"+x);
126 attribs.add(x);
127 }
128
129 /**
130 * Writes a <code>boolean</code> in the Java programming language
131 * to this <code>SQLOutputImpl</code> object. The driver converts
132 * it to an SQL <code>BIT</code> before returning it to the database.
133 *
134 * @param x the value to pass to the database
135 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
136 * use by a <code>SQLData</code> object attempting to write the attribute
137 * values of a UDT to the database.
138 */
139 public void writeBoolean(boolean x) throws SQLException {
140 attribs.add(new Boolean(x));
141 }
142
143 /**
144 * Writes a <code>byte</code> in the Java programming language
145 * to this <code>SQLOutputImpl</code> object. The driver converts
146 * it to an SQL <code>BIT</code> before returning it to the database.
147 *
148 * @param x the value to pass to the database
149 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
150 * use by a <code>SQLData</code> object attempting to write the attribute
151 * values of a UDT to the database.
152 */
153 public void writeByte(byte x) throws SQLException {
154 attribs.add(new Byte(x));
155 }
156
157 /**
158 * Writes a <code>short</code> in the Java programming language
159 * to this <code>SQLOutputImpl</code> object. The driver converts
160 * it to an SQL <code>SMALLINT</code> before returning it to the database.
161 *
162 * @param x the value to pass to the database
163 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
164 * use by a <code>SQLData</code> object attempting to write the attribute
165 * values of a UDT to the database.
166 */
167 public void writeShort(short x) throws SQLException {
168 attribs.add(new Short(x));
169 }
170
171 /**
172 * Writes an <code>int</code> in the Java programming language
173 * to this <code>SQLOutputImpl</code> object. The driver converts
174 * it to an SQL <code>INTEGER</code> before returning it to the database.
175 *
176 * @param x the value to pass to the database
177 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
178 * use by a <code>SQLData</code> object attempting to write the attribute
179 * values of a UDT to the database.
180 */
181 public void writeInt(int x) throws SQLException {
182 attribs.add(new Integer(x));
183 }
184
185 /**
186 * Writes a <code>long</code> in the Java programming language
187 * to this <code>SQLOutputImpl</code> object. The driver converts
188 * it to an SQL <code>BIGINT</code> before returning it to the database.
189 *
190 * @param x the value to pass to the database
191 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
192 * use by a <code>SQLData</code> object attempting to write the attribute
193 * values of a UDT to the database.
194 */
195 public void writeLong(long x) throws SQLException {
196 attribs.add(new Long(x));
197 }
198
199 /**
200 * Writes a <code>float</code> in the Java programming language
201 * to this <code>SQLOutputImpl</code> object. The driver converts
202 * it to an SQL <code>REAL</code> before returning it to the database.
203 *
204 * @param x the value to pass to the database
205 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
206 * use by a <code>SQLData</code> object attempting to write the attribute
207 * values of a UDT to the database.
208 */
209 public void writeFloat(float x) throws SQLException {
210 attribs.add(new Float(x));
211 }
212
213 /**
214 * Writes a <code>double</code> in the Java programming language
215 * to this <code>SQLOutputImpl</code> object. The driver converts
216 * it to an SQL <code>DOUBLE</code> before returning it to the database.
217 *
218 * @param x the value to pass to the database
219 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
220 * use by a <code>SQLData</code> object attempting to write the attribute
221 * values of a UDT to the database.
222 */
223 public void writeDouble(double x) throws SQLException {
224 attribs.add(new Double(x));
225 }
226
227 /**
228 * Writes a <code>java.math.BigDecimal</code> object in the Java programming
229 * language to this <code>SQLOutputImpl</code> object. The driver converts
230 * it to an SQL <code>NUMERIC</code> before returning it to the database.
231 *
232 * @param x the value to pass to the database
233 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
234 * use by a <code>SQLData</code> object attempting to write the attribute
235 * values of a UDT to the database.
236 */
237 public void writeBigDecimal(java.math.BigDecimal x)
238 throws SQLException {
239 attribs.add(x);
240 }
241
242 /**
243 * Writes an array of <code>bytes</code> in the Java programming language
244 * to this <code>SQLOutputImpl</code> object. The driver converts
245 * it to an SQL <code>VARBINARY</code> or <code>LONGVARBINARY</code>
246 * before returning it to the database.
247 *
248 * @param x the value to pass to the database
249 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
250 * use by a <code>SQLData</code> object attempting to write the attribute
251 * values of a UDT to the database.
252 */
253 public void writeBytes(byte[] x) throws SQLException {
254 attribs.add(x);
255 }
256
257 /**
258 * Writes a <code>java.sql.Date</code> object in the Java programming
259 * language to this <code>SQLOutputImpl</code> object. The driver converts
260 * it to an SQL <code>DATE</code> before returning it to the database.
261 *
262 * @param x the value to pass to the database
263 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
264 * use by a <code>SQLData</code> object attempting to write the attribute
265 * values of a UDT to the database.
266 */
267 public void writeDate(java.sql.Date x) throws SQLException {
268 attribs.add(x);
269 }
270
271 /**
272 * Writes a <code>java.sql.Time</code> object in the Java programming
273 * language to this <code>SQLOutputImpl</code> object. The driver converts
274 * it to an SQL <code>TIME</code> before returning it to the database.
275 *
276 * @param x the value to pass to the database
277 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
278 * use by a <code>SQLData</code> object attempting to write the attribute
279 * values of a UDT to the database.
280 */
281 public void writeTime(java.sql.Time x) throws SQLException {
282 attribs.add(x);
283 }
284
285 /**
286 * Writes a <code>java.sql.Timestamp</code> object in the Java programming
287 * language to this <code>SQLOutputImpl</code> object. The driver converts
288 * it to an SQL <code>TIMESTAMP</code> before returning it to the database.
289 *
290 * @param x the value to pass to the database
291 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
292 * use by a <code>SQLData</code> object attempting to write the attribute
293 * values of a UDT to the database.
294 */
295 public void writeTimestamp(java.sql.Timestamp x)
296 throws SQLException {
297 attribs.add(x);
298 }
299
300 /**
301 * Writes a stream of Unicode characters to this
302 * <code>SQLOutputImpl</code> object. The driver will do any necessary
303 * conversion from Unicode to the database <code>CHAR</code> format.
304 *
305 * @param x the value to pass to the database
306 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
307 * use by a <code>SQLData</code> object attempting to write the attribute
308 * values of a UDT to the database.
309 */
310 public void writeCharacterStream(java.io.Reader x)
311 throws SQLException {
312 BufferedReader bufReader = new BufferedReader(x);
313 try {
314 int i;
315 while ((i = bufReader.read()) != -1) {
316 char ch = (char) i;
317 StringBuffer strBuf = new StringBuffer();
318 strBuf.append(ch);
319
320 String str = new String(strBuf);
321 String strLine = bufReader.readLine();
322
323 writeString(str.concat(strLine));
324 }
325 } catch (IOException ioe) {
326
327 }
328 }
329
330 /**
331 * Writes a stream of ASCII characters to this
332 * <code>SQLOutputImpl</code> object. The driver will do any necessary
333 * conversion from ASCII to the database <code>CHAR</code> format.
334 *
335 * @param x the value to pass to the database
336 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
337 * use by a <code>SQLData</code> object attempting to write the attribute
338 * values of a UDT to the database.
339 */
340 public void writeAsciiStream(java.io.InputStream x)
341 throws SQLException {
342 BufferedReader bufReader = new BufferedReader(
343 new InputStreamReader(x));
344 try {
345 int i;
346 while ((i = bufReader.read()) != -1) {
347 char ch = (char) i;
348
349 StringBuffer strBuf = new StringBuffer();
350 strBuf.append(ch);
351
352 String str = new String(strBuf);
353 String strLine = bufReader.readLine();
354
355 writeString(str.concat(strLine));
356 }
357 } catch (IOException ioe) {
358 throw new SQLException(ioe.getMessage());
359 }
360 }
361
362 /**
363 * Writes a stream of uninterpreted bytes to this <code>SQLOutputImpl</code>
364 * object.
365 *
366 * @param x the value to pass to the database
367 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
368 * use by a <code>SQLData</code> object attempting to write the attribute
369 * values of a UDT to the database.
370 */
371 public void writeBinaryStream(java.io.InputStream x)
372 throws SQLException {
373 BufferedReader bufReader = new BufferedReader(
374 new InputStreamReader(x));
375 try {
376 int i;
377 while ((i = bufReader.read()) != -1) {
378 char ch = (char) i;
379
380 StringBuffer strBuf = new StringBuffer();
381 strBuf.append(ch);
382
383 String str = new String(strBuf);
384 String strLine = bufReader.readLine();
385
386 writeString(str.concat(strLine));
387 }
388 } catch (IOException ioe) {
389 throw new SQLException(ioe.getMessage());
390 }
391 }
392
393 //================================================================
394 // Methods for writing items of SQL user-defined types to the stream.
395 // These methods pass objects to the database as values of SQL
396 // Structured Types, Distinct Types, Constructed Types, and Locator
397 // Types. They decompose the Java object(s) and write leaf data
398 // items using the methods above.
399 //================================================================
400
401 /**
402 * Writes to the stream the data contained in the given
403 * <code>SQLData</code> object.
404 * When the <code>SQLData</code> object is <code>null</code>, this
405 * method writes an SQL <code>NULL</code> to the stream.
406 * Otherwise, it calls the <code>SQLData.writeSQL</code>
407 * method of the given object, which
408 * writes the object's attributes to the stream.
409 * <P>
410 * The implementation of the method <code>SQLData.writeSQ</code>
411 * calls the appropriate <code>SQLOutputImpl.writeXXX</code> method(s)
412 * for writing each of the object's attributes in order.
413 * The attributes must be read from an <code>SQLInput</code>
414 * input stream and written to an <code>SQLOutputImpl</code>
415 * output stream in the same order in which they were
416 * listed in the SQL definition of the user-defined type.
417 *
418 * @param x the object representing data of an SQL structured or
419 * distinct type
420 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
421 * use by a <code>SQLData</code> object attempting to write the attribute
422 * values of a UDT to the database.
423 */
424 public void writeObject(SQLData x) throws SQLException {
425
426 /*
427 * Except for the types that are passed as objects
428 * this seems to be the only way for an object to
429 * get a null value for a field in a structure.
430 *
431 * Note: this means that the class defining SQLData
432 * will need to track if a field is SQL null for itself
433 */
434 if (x == null) {
435 attribs.add(x);
436 return;
437 }
438
439 /*
440 * We have to write out a SerialStruct that contains
441 * the name of this class otherwise we don't know
442 * what to re-instantiate during readSQL()
443 */
444 attribs.add(new SerialStruct((SQLData) x, map));
445 }
446
447 /**
448 * Writes a <code>Ref</code> object in the Java programming language
449 * to this <code>SQLOutputImpl</code> object. The driver converts
450 * it to a serializable <code>SerialRef</code> SQL <code>REF</code> value
451 * before returning it to the database.
452 *
453 * @param x an object representing an SQL <code>REF</code> value
454 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
455 * use by a <code>SQLData</code> object attempting to write the attribute
456 * values of a UDT to the database.
457 */
458 public void writeRef(Ref x) throws SQLException {
459 if (x == null) {
460 attribs.add(x);
461 return;
462 }
463 attribs.add(new SerialRef(x));
464 }
465
466 /**
467 * Writes a <code>Blob</code> object in the Java programming language
468 * to this <code>SQLOutputImpl</code> object. The driver converts
469 * it to a serializable <code>SerialBlob</code> SQL <code>BLOB</code> value
470 * before returning it to the database.
471 *
472 * @param x an object representing an SQL <code>BLOB</code> value
473 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
474 * use by a <code>SQLData</code> object attempting to write the attribute
475 * values of a UDT to the database.
476 */
477 public void writeBlob(Blob x) throws SQLException {
478 if (x == null) {
479 attribs.add(x);
480 return;
481 }
482 attribs.add(new SerialBlob(x));
483 }
484
485 /**
486 * Writes a <code>Clob</code> object in the Java programming language
487 * to this <code>SQLOutputImpl</code> object. The driver converts
488 * it to a serializable <code>SerialClob</code> SQL <code>CLOB</code> value
489 * before returning it to the database.
490 *
491 * @param x an object representing an SQL <code>CLOB</code> value
492 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
493 * use by a <code>SQLData</code> object attempting to write the attribute
494 * values of a UDT to the database.
495 */
496 public void writeClob(Clob x) throws SQLException {
497 if (x == null) {
498 attribs.add(x);
499 return;
500 }
501 attribs.add(new SerialClob(x));
502 }
503
504 /**
505 * Writes a <code>Struct</code> object in the Java
506 * programming language to this <code>SQLOutputImpl</code>
507 * object. The driver converts this value to an SQL structured type
508 * before returning it to the database.
509 * <P>
510 * This method should be used when an SQL structured type has been
511 * mapped to a <code>Struct</code> object in the Java programming
512 * language (the standard mapping). The method
513 * <code>writeObject</code> should be used if an SQL structured type
514 * has been custom mapped to a class in the Java programming language.
515 *
516 * @param x an object representing the attributes of an SQL structured type
517 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
518 * use by a <code>SQLData</code> object attempting to write the attribute
519 * values of a UDT to the database.
520 */
521 public void writeStruct(Struct x) throws SQLException {
522 SerialStruct s = new SerialStruct(x, map);
523 ;
524 attribs.add(s);
525 }
526
527 /**
528 * Writes an <code>Array</code> object in the Java
529 * programming language to this <code>SQLOutputImpl</code>
530 * object. The driver converts this value to a serializable
531 * <code>SerialArray</code> SQL <code>ARRAY</code>
532 * value before returning it to the database.
533 *
534 * @param x an object representing an SQL <code>ARRAY</code> value
535 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
536 * use by a <code>SQLData</code> object attempting to write the attribute
537 * values of a UDT to the database.
538 */
539 public void writeArray(Array x) throws SQLException {
540 if (x == null) {
541 attribs.add(x);
542 return;
543 }
544 attribs.add(new SerialArray(x, map));
545 }
546
547 /**
548 * Writes an <code>java.sql.Type.DATALINK</code> object in the Java
549 * programming language to this <code>SQLOutputImpl</code> object. The
550 * driver converts this value to a serializable <code>SerialDatalink</code>
551 * SQL <code>DATALINK</code> value before return it to the database.
552 *
553 * @param url an object representing a SQL <code>DATALINK</code> value
554 * @throws SQLException if the <code>SQLOutputImpl</code> object is in
555 * use by a <code>SQLData</code> object attempting to write the attribute
556 * values of a UDT to the database.
557 */
558 public void writeURL(java.net.URL url) throws SQLException {
559 if (url == null) {
560 attribs.add(url);
561 return;
562 }
563 attribs.add(new SerialDatalink(url));
564
565 }
566
567 /**
568 * Writes the next attribute to the stream as a <code>String</code>
569 * in the Java programming language. The driver converts this to a
570 * SQL <code>NCHAR</code> or
571 * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value
572 * (depending on the argument's
573 * size relative to the driver's limits on <code>NVARCHAR</code> values)
574 * when it sends it to the stream.
575 *
576 * @param x the value to pass to the database
577 * @exception SQLException if a database access error occurs
578 * @since 1.6
579 */
580 public void writeNString(String x) throws SQLException {
581 throw new UnsupportedOperationException(
582 "Operation not supported");
583 }
584
585 /**
586 * Writes an SQL <code>NCLOB</code> value to the stream.
587 *
588 * @param x a <code>NClob</code> object representing data of an SQL
589 * <code>NCLOB</code> value
590 *
591 * @exception SQLException if a database access error occurs
592 * @since 1.6
593 */
594 public void writeNClob(NClob x) throws SQLException {
595 throw new UnsupportedOperationException(
596 "Operation not supported");
597 }
598
599 /**
600 * Writes an SQL <code>ROWID</code> value to the stream.
601 *
602 * @param x a <code>RowId</code> object representing data of an SQL
603 * <code>ROWID</code> value
604 *
605 * @exception SQLException if a database access error occurs
606 * @since 1.6
607 */
608 public void writeRowId(RowId x) throws SQLException {
609 throw new UnsupportedOperationException(
610 "Operation not supported");
611 }
612
613 /**
614 * Writes an SQL <code>XML</code> value to the stream.
615 *
616 * @param x a <code>SQLXML</code> object representing data of an SQL
617 * <code>XML</code> value
618 *
619 * @exception SQLException if a database access error occurs
620 * @since 1.6
621 */
622 public void writeSQLXML(SQLXML x) throws SQLException {
623 throw new UnsupportedOperationException(
624 "Operation not supported");
625 }
626
627 }
|