1/* 2 * Copyright (c) 2003, 2013, 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 26package javax.sql.rowset.serial; 27 28import java.io.BufferedReader; 29import java.io.IOException; 30import java.io.InputStreamReader; 31import java.sql.*; 32import java.util.Map; 33import java.util.Vector; 34 35/** 36 * The output stream for writing the attributes of a 37 * custom-mapped user-defined type (UDT) back to the database. 38 * The driver uses this interface internally, and its 39 * methods are never directly invoked by an application programmer. 40 * <p> 41 * When an application calls the 42 * method <code>PreparedStatement.setObject</code>, the driver 43 * checks to see whether the value to be written is a UDT with 44 * a custom mapping. If it is, there will be an entry in a 45 * type map containing the <code>Class</code> object for the 46 * class that implements <code>SQLData</code> for this UDT. 47 * If the value to be written is an instance of <code>SQLData</code>, 48 * the driver will create an instance of <code>SQLOutputImpl</code> 49 * and pass it to the method <code>SQLData.writeSQL</code>. 50 * The method <code>writeSQL</code> in turn calls the 51 * appropriate <code>SQLOutputImpl.writeXXX</code> methods 52 * to write data from the <code>SQLData</code> object to 53 * the <code>SQLOutputImpl</code> output stream as the 54 * representation of an SQL user-defined type. 55 * 56 * @since 1.5 57 */ 58public class SQLOutputImpl implements SQLOutput { 59 60 /** 61 * A reference to an existing vector that 62 * contains the attributes of a <code>Struct</code> object. 63 */ 64 @SuppressWarnings("rawtypes") 65 private Vector attribs; 66 67 /** 68 * The type map the driver supplies to a newly created 69 * <code>SQLOutputImpl</code> object. This type map 70 * indicates the <code>SQLData</code> class whose 71 * <code>writeSQL</code> method will be called. This 72 * method will in turn call the appropriate 73 * <code>SQLOutputImpl</code> writer methods. 74 */ 75 @SuppressWarnings("rawtypes") 76 private Map map; 77 78 /** 79 * Creates a new <code>SQLOutputImpl</code> object 80 * initialized with the given vector of attributes and 81 * type map. The driver will use the type map to determine 82 * which <code>SQLData.writeSQL</code> method to invoke. 83 * This method will then call the appropriate 84 * <code>SQLOutputImpl</code> writer methods in order and 85 * thereby write the attributes to the new output stream. 86 * 87 * @param attributes a <code>Vector</code> object containing the attributes of 88 * the UDT to be mapped to one or more objects in the Java 89 * programming language 90 * 91 * @param map a <code>java.util.Map</code> object containing zero or 92 * more entries, with each entry consisting of 1) a <code>String</code> 93 * giving the fully qualified name of a UDT and 2) the 94 * <code>Class</code> object for the <code>SQLData</code> implementation 95 * that defines how the UDT is to be mapped 96 * @throws SQLException if the <code>attributes</code> or the <code>map</code> 97 * is a <code>null</code> value 98 */ 99 public SQLOutputImpl(Vector<?> attributes, Map<String,?> map) 100 throws SQLException 101 { 102 if ((attributes == null) || (map == null)) { 103 throw new SQLException("Cannot instantiate a SQLOutputImpl " + 104 "instance with null parameters"); 105 } 106 this.attribs = attributes; 107 this.map = map; 108 } 109 110 //================================================================ 111 // Methods for writing attributes to the stream of SQL data. 112 // These methods correspond to the column-accessor methods of 113 // java.sql.ResultSet. 114 //================================================================ 115 116 /** 117 * Writes a <code>String</code> in the Java programming language 118 * to this <code>SQLOutputImpl</code> object. The driver converts 119 * it to an SQL <code>CHAR</code>, <code>VARCHAR</code>, or 120 * <code>LONGVARCHAR</code> before returning it to the database. 121 * 122 * @param x the value to pass to the database 123 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 124 * use by a <code>SQLData</code> object attempting to write the attribute 125 * values of a UDT to the database. 126 */ 127 @SuppressWarnings("unchecked") 128 public void writeString(String x) throws SQLException { 129 //System.out.println("Adding :"+x); 130 attribs.add(x); 131 } 132 133 /** 134 * Writes a <code>boolean</code> in the Java programming language 135 * to this <code>SQLOutputImpl</code> object. The driver converts 136 * it to an SQL <code>BIT</code> before returning it to the database. 137 * 138 * @param x the value to pass to the database 139 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 140 * use by a <code>SQLData</code> object attempting to write the attribute 141 * values of a UDT to the database. 142 */ 143 @SuppressWarnings("unchecked") 144 public void writeBoolean(boolean x) throws SQLException { 145 attribs.add(Boolean.valueOf(x)); 146 } 147 148 /** 149 * Writes a <code>byte</code> in the Java programming language 150 * to this <code>SQLOutputImpl</code> object. The driver converts 151 * it to an SQL <code>BIT</code> before returning it to the database. 152 * 153 * @param x the value to pass to the database 154 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 155 * use by a <code>SQLData</code> object attempting to write the attribute 156 * values of a UDT to the database. 157 */ 158 @SuppressWarnings("unchecked") 159 public void writeByte(byte x) throws SQLException { 160 attribs.add(Byte.valueOf(x)); 161 } 162 163 /** 164 * Writes a <code>short</code> in the Java programming language 165 * to this <code>SQLOutputImpl</code> object. The driver converts 166 * it to an SQL <code>SMALLINT</code> before returning it to the database. 167 * 168 * @param x the value to pass to the database 169 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 170 * use by a <code>SQLData</code> object attempting to write the attribute 171 * values of a UDT to the database. 172 */ 173 @SuppressWarnings("unchecked") 174 public void writeShort(short x) throws SQLException { 175 attribs.add(Short.valueOf(x)); 176 } 177 178 /** 179 * Writes an <code>int</code> in the Java programming language 180 * to this <code>SQLOutputImpl</code> object. The driver converts 181 * it to an SQL <code>INTEGER</code> before returning it to the database. 182 * 183 * @param x the value to pass to the database 184 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 185 * use by a <code>SQLData</code> object attempting to write the attribute 186 * values of a UDT to the database. 187 */ 188 @SuppressWarnings("unchecked") 189 public void writeInt(int x) throws SQLException { 190 attribs.add(Integer.valueOf(x)); 191 } 192 193 /** 194 * Writes a <code>long</code> in the Java programming language 195 * to this <code>SQLOutputImpl</code> object. The driver converts 196 * it to an SQL <code>BIGINT</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 @SuppressWarnings("unchecked") 204 public void writeLong(long x) throws SQLException { 205 attribs.add(Long.valueOf(x)); 206 } 207 208 /** 209 * Writes a <code>float</code> in the Java programming language 210 * to this <code>SQLOutputImpl</code> object. The driver converts 211 * it to an SQL <code>REAL</code> before returning it to the database. 212 * 213 * @param x the value to pass to the database 214 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 215 * use by a <code>SQLData</code> object attempting to write the attribute 216 * values of a UDT to the database. 217 */ 218 @SuppressWarnings("unchecked") 219 public void writeFloat(float x) throws SQLException { 220 attribs.add(Float.valueOf(x)); 221 } 222 223 /** 224 * Writes a <code>double</code> in the Java programming language 225 * to this <code>SQLOutputImpl</code> object. The driver converts 226 * it to an SQL <code>DOUBLE</code> before returning it to the database. 227 * 228 * @param x the value to pass to the database 229 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 230 * use by a <code>SQLData</code> object attempting to write the attribute 231 * values of a UDT to the database. 232 */ 233 @SuppressWarnings("unchecked") 234 public void writeDouble(double x) throws SQLException{ 235 attribs.add(Double.valueOf(x)); 236 } 237 238 /** 239 * Writes a <code>java.math.BigDecimal</code> object in the Java programming 240 * language to this <code>SQLOutputImpl</code> object. The driver converts 241 * it to an SQL <code>NUMERIC</code> before returning it to the database. 242 * 243 * @param x the value to pass to the database 244 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 245 * use by a <code>SQLData</code> object attempting to write the attribute 246 * values of a UDT to the database. 247 */ 248 @SuppressWarnings("unchecked") 249 public void writeBigDecimal(java.math.BigDecimal x) throws SQLException{ 250 attribs.add(x); 251 } 252 253 /** 254 * Writes an array of <code>bytes</code> in the Java programming language 255 * to this <code>SQLOutputImpl</code> object. The driver converts 256 * it to an SQL <code>VARBINARY</code> or <code>LONGVARBINARY</code> 257 * before returning it to the database. 258 * 259 * @param x the value to pass to the database 260 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 261 * use by a <code>SQLData</code> object attempting to write the attribute 262 * values of a UDT to the database. 263 */ 264 @SuppressWarnings("unchecked") 265 public void writeBytes(byte[] x) throws SQLException { 266 attribs.add(x); 267 } 268 269 /** 270 * Writes a <code>java.sql.Date</code> object in the Java programming 271 * language to this <code>SQLOutputImpl</code> object. The driver converts 272 * it to an SQL <code>DATE</code> before returning it to the database. 273 * 274 * @param x the value to pass to the database 275 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 276 * use by a <code>SQLData</code> object attempting to write the attribute 277 * values of a UDT to the database. 278 */ 279 @SuppressWarnings("unchecked") 280 public void writeDate(java.sql.Date x) throws SQLException { 281 attribs.add(x); 282 } 283 284 /** 285 * Writes a <code>java.sql.Time</code> object in the Java programming 286 * language to this <code>SQLOutputImpl</code> object. The driver converts 287 * it to an SQL <code>TIME</code> before returning it to the database. 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 @SuppressWarnings("unchecked") 295 public void writeTime(java.sql.Time x) throws SQLException { 296 attribs.add(x); 297 } 298 299 /** 300 * Writes a <code>java.sql.Timestamp</code> object in the Java programming 301 * language to this <code>SQLOutputImpl</code> object. The driver converts 302 * it to an SQL <code>TIMESTAMP</code> before returning it to the database. 303 * 304 * @param x the value to pass to the database 305 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 306 * use by a <code>SQLData</code> object attempting to write the attribute 307 * values of a UDT to the database. 308 */ 309 @SuppressWarnings("unchecked") 310 public void writeTimestamp(java.sql.Timestamp x) throws SQLException { 311 attribs.add(x); 312 } 313 314 /** 315 * Writes a stream of Unicode characters to this 316 * <code>SQLOutputImpl</code> object. The driver will do any necessary 317 * conversion from Unicode to the database <code>CHAR</code> format. 318 * 319 * @param x the value to pass to the database 320 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 321 * use by a <code>SQLData</code> object attempting to write the attribute 322 * values of a UDT to the database. 323 */ 324 @SuppressWarnings("unchecked") 325 public void writeCharacterStream(java.io.Reader x) throws SQLException { 326 BufferedReader bufReader = new BufferedReader(x); 327 try { 328 int i; 329 while( (i = bufReader.read()) != -1 ) { 330 char ch = (char)i; 331 StringBuffer strBuf = new StringBuffer(); 332 strBuf.append(ch); 333 334 String str = new String(strBuf); 335 String strLine = bufReader.readLine(); 336 337 writeString(str.concat(strLine)); 338 } 339 } catch(IOException ioe) { 340 341 } 342 } 343 344 /** 345 * Writes a stream of ASCII characters to this 346 * <code>SQLOutputImpl</code> object. The driver will do any necessary 347 * conversion from ASCII to the database <code>CHAR</code> format. 348 * 349 * @param x the value to pass to the database 350 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 351 * use by a <code>SQLData</code> object attempting to write the attribute 352 * values of a UDT to the database. 353 */ 354 @SuppressWarnings("unchecked") 355 public void writeAsciiStream(java.io.InputStream x) throws SQLException { 356 BufferedReader bufReader = new BufferedReader(new InputStreamReader(x)); 357 try { 358 int i; 359 while( (i=bufReader.read()) != -1 ) { 360 char ch = (char)i; 361 362 StringBuffer strBuf = new StringBuffer(); 363 strBuf.append(ch); 364 365 String str = new String(strBuf); 366 String strLine = bufReader.readLine(); 367 368 writeString(str.concat(strLine)); 369 } 370 }catch(IOException ioe) { 371 throw new SQLException(ioe.getMessage()); 372 } 373 } 374 375 /** 376 * Writes a stream of uninterpreted bytes to this <code>SQLOutputImpl</code> 377 * object. 378 * 379 * @param x the value to pass to the database 380 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 381 * use by a <code>SQLData</code> object attempting to write the attribute 382 * values of a UDT to the database. 383 */ 384 @SuppressWarnings("unchecked") 385 public void writeBinaryStream(java.io.InputStream x) throws SQLException { 386 BufferedReader bufReader = new BufferedReader(new InputStreamReader(x)); 387 try { 388 int i; 389 while( (i=bufReader.read()) != -1 ) { 390 char ch = (char)i; 391 392 StringBuffer strBuf = new StringBuffer(); 393 strBuf.append(ch); 394 395 String str = new String(strBuf); 396 String strLine = bufReader.readLine(); 397 398 writeString(str.concat(strLine)); 399 } 400 } catch(IOException ioe) { 401 throw new SQLException(ioe.getMessage()); 402 } 403 } 404 405 //================================================================ 406 // Methods for writing items of SQL user-defined types to the stream. 407 // These methods pass objects to the database as values of SQL 408 // Structured Types, Distinct Types, Constructed Types, and Locator 409 // Types. They decompose the Java object(s) and write leaf data 410 // items using the methods above. 411 //================================================================ 412 413 /** 414 * Writes to the stream the data contained in the given 415 * <code>SQLData</code> object. 416 * When the <code>SQLData</code> object is <code>null</code>, this 417 * method writes an SQL <code>NULL</code> to the stream. 418 * Otherwise, it calls the <code>SQLData.writeSQL</code> 419 * method of the given object, which 420 * writes the object's attributes to the stream. 421 * <P> 422 * The implementation of the method <code>SQLData.writeSQ</code> 423 * calls the appropriate <code>SQLOutputImpl.writeXXX</code> method(s) 424 * for writing each of the object's attributes in order. 425 * The attributes must be read from an <code>SQLInput</code> 426 * input stream and written to an <code>SQLOutputImpl</code> 427 * output stream in the same order in which they were 428 * listed in the SQL definition of the user-defined type. 429 * 430 * @param x the object representing data of an SQL structured or 431 * distinct type 432 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 433 * use by a <code>SQLData</code> object attempting to write the attribute 434 * values of a UDT to the database. 435 */ 436 @SuppressWarnings("unchecked") 437 public void writeObject(SQLData x) throws SQLException { 438 439 /* 440 * Except for the types that are passed as objects 441 * this seems to be the only way for an object to 442 * get a null value for a field in a structure. 443 * 444 * Note: this means that the class defining SQLData 445 * will need to track if a field is SQL null for itself 446 */ 447 if (x == null) { 448 attribs.add(null); 449 } else { 450 /* 451 * We have to write out a SerialStruct that contains 452 * the name of this class otherwise we don't know 453 * what to re-instantiate during readSQL() 454 */ 455 attribs.add(new SerialStruct(x, map)); 456 } 457 } 458 459 /** 460 * Writes a <code>Ref</code> object in the Java programming language 461 * to this <code>SQLOutputImpl</code> object. The driver converts 462 * it to a serializable <code>SerialRef</code> SQL <code>REF</code> value 463 * before returning it to the database. 464 * 465 * @param x an object representing an SQL <code>REF</code> value 466 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 467 * use by a <code>SQLData</code> object attempting to write the attribute 468 * values of a UDT to the database. 469 */ 470 @SuppressWarnings("unchecked") 471 public void writeRef(Ref x) throws SQLException { 472 if (x == null) { 473 attribs.add(null); 474 } else { 475 attribs.add(new SerialRef(x)); 476 } 477 } 478 479 /** 480 * Writes a <code>Blob</code> object in the Java programming language 481 * to this <code>SQLOutputImpl</code> object. The driver converts 482 * it to a serializable <code>SerialBlob</code> SQL <code>BLOB</code> value 483 * before returning it to the database. 484 * 485 * @param x an object representing an SQL <code>BLOB</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 @SuppressWarnings("unchecked") 491 public void writeBlob(Blob x) throws SQLException { 492 if (x == null) { 493 attribs.add(null); 494 } else { 495 attribs.add(new SerialBlob(x)); 496 } 497 } 498 499 /** 500 * Writes a <code>Clob</code> object in the Java programming language 501 * to this <code>SQLOutputImpl</code> object. The driver converts 502 * it to a serializable <code>SerialClob</code> SQL <code>CLOB</code> value 503 * before returning it to the database. 504 * 505 * @param x an object representing an SQL <code>CLOB</code> value 506 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 507 * use by a <code>SQLData</code> object attempting to write the attribute 508 * values of a UDT to the database. 509 */ 510 @SuppressWarnings("unchecked") 511 public void writeClob(Clob x) throws SQLException { 512 if (x == null) { 513 attribs.add(null); 514 } else { 515 attribs.add(new SerialClob(x)); 516 } 517 } 518 519 /** 520 * Writes a <code>Struct</code> object in the Java 521 * programming language to this <code>SQLOutputImpl</code> 522 * object. The driver converts this value to an SQL structured type 523 * before returning it to the database. 524 * <P> 525 * This method should be used when an SQL structured type has been 526 * mapped to a <code>Struct</code> object in the Java programming 527 * language (the standard mapping). The method 528 * <code>writeObject</code> should be used if an SQL structured type 529 * has been custom mapped to a class in the Java programming language. 530 * 531 * @param x an object representing the attributes of an SQL structured type 532 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 533 * use by a <code>SQLData</code> object attempting to write the attribute 534 * values of a UDT to the database. 535 */ 536 @SuppressWarnings("unchecked") 537 public void writeStruct(Struct x) throws SQLException { 538 SerialStruct s = new SerialStruct(x,map);; 539 attribs.add(s); 540 } 541 542 /** 543 * Writes an <code>Array</code> object in the Java 544 * programming language to this <code>SQLOutputImpl</code> 545 * object. The driver converts this value to a serializable 546 * <code>SerialArray</code> SQL <code>ARRAY</code> 547 * value before returning it to the database. 548 * 549 * @param x an object representing an SQL <code>ARRAY</code> value 550 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 551 * use by a <code>SQLData</code> object attempting to write the attribute 552 * values of a UDT to the database. 553 */ 554 @SuppressWarnings("unchecked") 555 public void writeArray(Array x) throws SQLException { 556 if (x == null) { 557 attribs.add(null); 558 } else { 559 attribs.add(new SerialArray(x, map)); 560 } 561 } 562 563 /** 564 * Writes an <code>java.sql.Type.DATALINK</code> object in the Java 565 * programming language to this <code>SQLOutputImpl</code> object. The 566 * driver converts this value to a serializable <code>SerialDatalink</code> 567 * SQL <code>DATALINK</code> value before return it to the database. 568 * 569 * @param url an object representing a SQL <code>DATALINK</code> value 570 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 571 * use by a <code>SQLData</code> object attempting to write the attribute 572 * values of a UDT to the database. 573 */ 574 @SuppressWarnings("unchecked") 575 public void writeURL(java.net.URL url) throws SQLException { 576 if (url == null) { 577 attribs.add(null); 578 } else { 579 attribs.add(new SerialDatalink(url)); 580 } 581 } 582 583 584 /** 585 * Writes the next attribute to the stream as a <code>String</code> 586 * in the Java programming language. The driver converts this to a 587 * SQL <code>NCHAR</code> or 588 * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value 589 * (depending on the argument's 590 * size relative to the driver's limits on <code>NVARCHAR</code> values) 591 * when it sends it to the stream. 592 * 593 * @param x the value to pass to the database 594 * @exception SQLException if a database access error occurs 595 * @since 1.6 596 */ 597 @SuppressWarnings("unchecked") 598 public void writeNString(String x) throws SQLException { 599 attribs.add(x); 600 } 601 602 /** 603 * Writes an SQL <code>NCLOB</code> value to the stream. 604 * 605 * @param x a <code>NClob</code> object representing data of an SQL 606 * <code>NCLOB</code> value 607 * 608 * @exception SQLException if a database access error occurs 609 * @since 1.6 610 */ 611 @SuppressWarnings("unchecked") 612 public void writeNClob(NClob x) throws SQLException { 613 attribs.add(x); 614 } 615 616 617 /** 618 * Writes an SQL <code>ROWID</code> value to the stream. 619 * 620 * @param x a <code>RowId</code> object representing data of an SQL 621 * <code>ROWID</code> value 622 * 623 * @exception SQLException if a database access error occurs 624 * @since 1.6 625 */ 626 @SuppressWarnings("unchecked") 627 public void writeRowId(RowId x) throws SQLException { 628 attribs.add(x); 629 } 630 631 632 /** 633 * Writes an SQL <code>XML</code> value to the stream. 634 * 635 * @param x a <code>SQLXML</code> object representing data of an SQL 636 * <code>XML</code> value 637 * 638 * @exception SQLException if a database access error occurs 639 * @since 1.6 640 */ 641 @SuppressWarnings("unchecked") 642 public void writeSQLXML(SQLXML x) throws SQLException { 643 attribs.add(x); 644 } 645 646} 647