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