1 /* 2 * Copyright (c) 2003, 2010, 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 package javax.sql.rowset.serial; 27 28 import java.sql.*; 29 import javax.sql.*; 30 import java.io.*; 31 import java.lang.String; 32 import java.math.*; 33 import java.util.Map; 34 import java.util.Vector; 35 36 /** 37 * The output stream for writing the attributes of a 38 * custom-mapped user-defined type (UDT) back to the database. 39 * The driver uses this interface internally, and its 40 * methods are never directly invoked by an application programmer. 41 * <p> 42 * When an application calls the 43 * method <code>PreparedStatement.setObject</code>, the driver 44 * checks to see whether the value to be written is a UDT with 45 * a custom mapping. If it is, there will be an entry in a 46 * type map containing the <code>Class</code> object for the 47 * class that implements <code>SQLData</code> for this UDT. 48 * If the value to be written is an instance of <code>SQLData</code>, 49 * the driver will create an instance of <code>SQLOutputImpl</code> 50 * and pass it to the method <code>SQLData.writeSQL</code>. 51 * The method <code>writeSQL</code> in turn calls the 52 * appropriate <code>SQLOutputImpl.writeXXX</code> methods 53 * to write data from the <code>SQLData</code> object to 54 * the <code>SQLOutputImpl</code> output stream as the 55 * representation of an SQL user-defined type. 56 */ 57 public class SQLOutputImpl implements SQLOutput { 58 59 /** 60 * A reference to an existing vector that 61 * contains the attributes of a <code>Struct</code> object. 62 */ 63 private Vector<Object> attribs; 64 65 /** 66 * The type map the driver supplies to a newly created 67 * <code>SQLOutputImpl</code> object. This type map 68 * indicates the <code>SQLData</code> class whose 69 * <code>writeSQL</code> method will be called. This 70 * method will in turn call the appropriate 71 * <code>SQLOutputImpl</code> writer methods. 72 */ 73 private Map<String,Class<?>> map; 74 75 /** 76 * Creates a new <code>SQLOutputImpl</code> object 77 * initialized with the given vector of attributes and 78 * type map. The driver will use the type map to determine 79 * which <code>SQLData.writeSQL</code> method to invoke. 80 * This method will then call the appropriate 81 * <code>SQLOutputImpl</code> writer methods in order and 82 * thereby write the attributes to the new output stream. 83 * 84 * @param attributes a <code>Vector</code> object containing the attributes of 85 * the UDT to be mapped to one or more objects in the Java 86 * programming language 87 * 88 * @param map a <code>java.util.Map</code> object containing zero or 89 * more entries, with each entry consisting of 1) a <code>String</code> 90 * giving the fully qualified name of a UDT and 2) the 91 * <code>Class</code> object for the <code>SQLData</code> implementation 92 * that defines how the UDT is to be mapped 93 * @throws SQLException if the <code>attributes</code> or the <code>map</code> 94 * is a <code>null</code> value 95 */ 96 public SQLOutputImpl(Vector<Object> attributes, Map<String,Class<?>> map) 97 throws SQLException 98 { 99 if ((attributes == null) || (map == null)) { 100 throw new SQLException("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(Boolean.valueOf(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(Byte.valueOf(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(Short.valueOf(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(Integer.valueOf(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(Long.valueOf(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) throws SQLException{ 238 attribs.add(x); 239 } 240 241 /** 242 * Writes an array of <code>bytes</code> in the Java programming language 243 * to this <code>SQLOutputImpl</code> object. The driver converts 244 * it to an SQL <code>VARBINARY</code> or <code>LONGVARBINARY</code> 245 * before returning it to the database. 246 * 247 * @param x the value to pass to the database 248 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 249 * use by a <code>SQLData</code> object attempting to write the attribute 250 * values of a UDT to the database. 251 */ 252 public void writeBytes(byte[] x) throws SQLException { 253 attribs.add(x); 254 } 255 256 /** 257 * Writes a <code>java.sql.Date</code> object in the Java programming 258 * language to this <code>SQLOutputImpl</code> object. The driver converts 259 * it to an SQL <code>DATE</code> before returning it to the database. 260 * 261 * @param x the value to pass to the database 262 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 263 * use by a <code>SQLData</code> object attempting to write the attribute 264 * values of a UDT to the database. 265 */ 266 public void writeDate(java.sql.Date x) throws SQLException { 267 attribs.add(x); 268 } 269 270 /** 271 * Writes a <code>java.sql.Time</code> object in the Java programming 272 * language to this <code>SQLOutputImpl</code> object. The driver converts 273 * it to an SQL <code>TIME</code> before returning it to the database. 274 * 275 * @param x the value to pass to the database 276 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 277 * use by a <code>SQLData</code> object attempting to write the attribute 278 * values of a UDT to the database. 279 */ 280 public void writeTime(java.sql.Time x) throws SQLException { 281 attribs.add(x); 282 } 283 284 /** 285 * Writes a <code>java.sql.Timestamp</code> object in the Java programming 286 * language to this <code>SQLOutputImpl</code> object. The driver converts 287 * it to an SQL <code>TIMESTAMP</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 public void writeTimestamp(java.sql.Timestamp x) throws SQLException { 295 attribs.add(x); 296 } 297 298 /** 299 * Writes a stream of Unicode characters to this 300 * <code>SQLOutputImpl</code> object. The driver will do any necessary 301 * conversion from Unicode to the database <code>CHAR</code> format. 302 * 303 * @param x the value to pass to the database 304 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 305 * use by a <code>SQLData</code> object attempting to write the attribute 306 * values of a UDT to the database. 307 */ 308 public void writeCharacterStream(java.io.Reader x) throws SQLException { 309 BufferedReader bufReader = new BufferedReader(x); 310 try { 311 int i; 312 while( (i = bufReader.read()) != -1 ) { 313 char ch = (char)i; 314 StringBuffer strBuf = new StringBuffer(); 315 strBuf.append(ch); 316 317 String str = new String(strBuf); 318 String strLine = bufReader.readLine(); 319 320 writeString(str.concat(strLine)); 321 } 322 } catch(IOException ioe) { 323 324 } 325 } 326 327 /** 328 * Writes a stream of ASCII characters to this 329 * <code>SQLOutputImpl</code> object. The driver will do any necessary 330 * conversion from ASCII to the database <code>CHAR</code> format. 331 * 332 * @param x the value to pass to the database 333 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 334 * use by a <code>SQLData</code> object attempting to write the attribute 335 * values of a UDT to the database. 336 */ 337 public void writeAsciiStream(java.io.InputStream x) throws SQLException { 338 BufferedReader bufReader = new BufferedReader(new InputStreamReader(x)); 339 try { 340 int i; 341 while( (i=bufReader.read()) != -1 ) { 342 char ch = (char)i; 343 344 StringBuffer strBuf = new StringBuffer(); 345 strBuf.append(ch); 346 347 String str = new String(strBuf); 348 String strLine = bufReader.readLine(); 349 350 writeString(str.concat(strLine)); 351 } 352 }catch(IOException ioe) { 353 throw new SQLException(ioe.getMessage()); 354 } 355 } 356 357 /** 358 * Writes a stream of uninterpreted bytes to this <code>SQLOutputImpl</code> 359 * object. 360 * 361 * @param x the value to pass to the database 362 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 363 * use by a <code>SQLData</code> object attempting to write the attribute 364 * values of a UDT to the database. 365 */ 366 public void writeBinaryStream(java.io.InputStream x) throws SQLException { 367 BufferedReader bufReader = new BufferedReader(new InputStreamReader(x)); 368 try { 369 int i; 370 while( (i=bufReader.read()) != -1 ) { 371 char ch = (char)i; 372 373 StringBuffer strBuf = new StringBuffer(); 374 strBuf.append(ch); 375 376 String str = new String(strBuf); 377 String strLine = bufReader.readLine(); 378 379 writeString(str.concat(strLine)); 380 } 381 } catch(IOException ioe) { 382 throw new SQLException(ioe.getMessage()); 383 } 384 } 385 386 //================================================================ 387 // Methods for writing items of SQL user-defined types to the stream. 388 // These methods pass objects to the database as values of SQL 389 // Structured Types, Distinct Types, Constructed Types, and Locator 390 // Types. They decompose the Java object(s) and write leaf data 391 // items using the methods above. 392 //================================================================ 393 394 /** 395 * Writes to the stream the data contained in the given 396 * <code>SQLData</code> object. 397 * When the <code>SQLData</code> object is <code>null</code>, this 398 * method writes an SQL <code>NULL</code> to the stream. 399 * Otherwise, it calls the <code>SQLData.writeSQL</code> 400 * method of the given object, which 401 * writes the object's attributes to the stream. 402 * <P> 403 * The implementation of the method <code>SQLData.writeSQ</code> 404 * calls the appropriate <code>SQLOutputImpl.writeXXX</code> method(s) 405 * for writing each of the object's attributes in order. 406 * The attributes must be read from an <code>SQLInput</code> 407 * input stream and written to an <code>SQLOutputImpl</code> 408 * output stream in the same order in which they were 409 * listed in the SQL definition of the user-defined type. 410 * 411 * @param x the object representing data of an SQL structured or 412 * distinct type 413 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 414 * use by a <code>SQLData</code> object attempting to write the attribute 415 * values of a UDT to the database. 416 */ 417 public void writeObject(SQLData x) throws SQLException { 418 419 /* 420 * Except for the types that are passed as objects 421 * this seems to be the only way for an object to 422 * get a null value for a field in a structure. 423 * 424 * Note: this means that the class defining SQLData 425 * will need to track if a field is SQL null for itself 426 */ 427 if (x == null) { 428 attribs.add(x); 429 return; 430 } 431 432 /* 433 * We have to write out a SerialStruct that contains 434 * the name of this class otherwise we don't know 435 * what to re-instantiate during readSQL() 436 */ 437 attribs.add(new SerialStruct((SQLData)x, map)); 438 } 439 440 /** 441 * Writes a <code>Ref</code> object in the Java programming language 442 * to this <code>SQLOutputImpl</code> object. The driver converts 443 * it to a serializable <code>SerialRef</code> SQL <code>REF</code> value 444 * before returning it to the database. 445 * 446 * @param x an object representing an SQL <code>REF</code> value 447 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 448 * use by a <code>SQLData</code> object attempting to write the attribute 449 * values of a UDT to the database. 450 */ 451 public void writeRef(Ref x) throws SQLException { 452 if (x == null) { 453 attribs.add(x); 454 return; 455 } 456 attribs.add(new SerialRef(x)); 457 } 458 459 /** 460 * Writes a <code>Blob</code> object in the Java programming language 461 * to this <code>SQLOutputImpl</code> object. The driver converts 462 * it to a serializable <code>SerialBlob</code> SQL <code>BLOB</code> value 463 * before returning it to the database. 464 * 465 * @param x an object representing an SQL <code>BLOB</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 public void writeBlob(Blob x) throws SQLException { 471 if (x == null) { 472 attribs.add(x); 473 return; 474 } 475 attribs.add(new SerialBlob(x)); 476 } 477 478 /** 479 * Writes a <code>Clob</code> object in the Java programming language 480 * to this <code>SQLOutputImpl</code> object. The driver converts 481 * it to a serializable <code>SerialClob</code> SQL <code>CLOB</code> value 482 * before returning it to the database. 483 * 484 * @param x an object representing an SQL <code>CLOB</code> value 485 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 486 * use by a <code>SQLData</code> object attempting to write the attribute 487 * values of a UDT to the database. 488 */ 489 public void writeClob(Clob x) throws SQLException { 490 if (x == null) { 491 attribs.add(x); 492 return; 493 } 494 attribs.add(new SerialClob(x)); 495 } 496 497 /** 498 * Writes a <code>Struct</code> object in the Java 499 * programming language to this <code>SQLOutputImpl</code> 500 * object. The driver converts this value to an SQL structured type 501 * before returning it to the database. 502 * <P> 503 * This method should be used when an SQL structured type has been 504 * mapped to a <code>Struct</code> object in the Java programming 505 * language (the standard mapping). The method 506 * <code>writeObject</code> should be used if an SQL structured type 507 * has been custom mapped to a class in the Java programming language. 508 * 509 * @param x an object representing the attributes of an SQL structured type 510 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 511 * use by a <code>SQLData</code> object attempting to write the attribute 512 * values of a UDT to the database. 513 */ 514 public void writeStruct(Struct x) throws SQLException { 515 SerialStruct s = new SerialStruct(x,map);; 516 attribs.add(s); 517 } 518 519 /** 520 * Writes an <code>Array</code> object in the Java 521 * programming language to this <code>SQLOutputImpl</code> 522 * object. The driver converts this value to a serializable 523 * <code>SerialArray</code> SQL <code>ARRAY</code> 524 * value before returning it to the database. 525 * 526 * @param x an object representing an SQL <code>ARRAY</code> value 527 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 528 * use by a <code>SQLData</code> object attempting to write the attribute 529 * values of a UDT to the database. 530 */ 531 public void writeArray(Array x) throws SQLException { 532 if (x == null) { 533 attribs.add(x); 534 return; 535 } 536 attribs.add(new SerialArray(x, map)); 537 } 538 539 /** 540 * Writes an <code>java.sql.Type.DATALINK</code> object in the Java 541 * programming language to this <code>SQLOutputImpl</code> object. The 542 * driver converts this value to a serializable <code>SerialDatalink</code> 543 * SQL <code>DATALINK</code> value before return it to the database. 544 * 545 * @param url an object representing a SQL <code>DATALINK</code> value 546 * @throws SQLException if the <code>SQLOutputImpl</code> object is in 547 * use by a <code>SQLData</code> object attempting to write the attribute 548 * values of a UDT to the database. 549 */ 550 public void writeURL(java.net.URL url) throws SQLException { 551 if (url == null) { 552 attribs.add(url); 553 return; 554 } 555 attribs.add(new SerialDatalink(url)); 556 557 } 558 559 560 /** 561 * Writes the next attribute to the stream as a <code>String</code> 562 * in the Java programming language. The driver converts this to a 563 * SQL <code>NCHAR</code> or 564 * <code>NVARCHAR</code> or <code>LONGNVARCHAR</code> value 565 * (depending on the argument's 566 * size relative to the driver's limits on <code>NVARCHAR</code> values) 567 * when it sends it to the stream. 568 * 569 * @param x the value to pass to the database 570 * @exception SQLException if a database access error occurs 571 * @since 1.6 572 */ 573 public void writeNString(String x) throws SQLException { 574 throw new UnsupportedOperationException("Operation not supported"); 575 } 576 577 /** 578 * Writes an SQL <code>NCLOB</code> value to the stream. 579 * 580 * @param x a <code>NClob</code> object representing data of an SQL 581 * <code>NCLOB</code> value 582 * 583 * @exception SQLException if a database access error occurs 584 * @since 1.6 585 */ 586 public void writeNClob(NClob x) throws SQLException { 587 throw new UnsupportedOperationException("Operation not supported"); 588 } 589 590 591 /** 592 * Writes an SQL <code>ROWID</code> value to the stream. 593 * 594 * @param x a <code>RowId</code> object representing data of an SQL 595 * <code>ROWID</code> value 596 * 597 * @exception SQLException if a database access error occurs 598 * @since 1.6 599 */ 600 public void writeRowId(RowId x) throws SQLException { 601 throw new UnsupportedOperationException("Operation not supported"); 602 } 603 604 605 /** 606 * Writes an SQL <code>XML</code> value to the stream. 607 * 608 * @param x a <code>SQLXML</code> object representing data of an SQL 609 * <code>XML</code> value 610 * 611 * @exception SQLException if a database access error occurs 612 * @since 1.6 613 */ 614 public void writeSQLXML(SQLXML x) throws SQLException { 615 throw new UnsupportedOperationException("Operation not supported"); 616 } 617 618 }