Path: blob/master/src/java.sql.rowset/share/classes/javax/sql/rowset/serial/SQLInputImpl.java
40948 views
/*1* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/24package javax.sql.rowset.serial;2526import java.sql.*;27import java.util.Arrays;28import java.util.Map;29import sun.reflect.misc.ReflectUtil;3031/**32* An input stream used for custom mapping user-defined types (UDTs).33* An <code>SQLInputImpl</code> object is an input stream that contains a34* stream of values that are the attributes of a UDT.35* <p>36* This class is used by the driver behind the scenes when the method37* <code>getObject</code> is called on an SQL structured or distinct type38* that has a custom mapping; a programmer never invokes39* <code>SQLInputImpl</code> methods directly. They are provided here as a40* convenience for those who write <code>RowSet</code> implementations.41* <P>42* The <code>SQLInputImpl</code> class provides a set of43* reader methods analogous to the <code>ResultSet</code> getter44* methods. These methods make it possible to read the values in an45* <code>SQLInputImpl</code> object.46* <P>47* The method <code>wasNull</code> is used to determine whether the48* the last value read was SQL <code>NULL</code>.49* <P>When the method <code>getObject</code> is called with an50* object of a class implementing the interface <code>SQLData</code>,51* the JDBC driver calls the method <code>SQLData.getSQLType</code>52* to determine the SQL type of the UDT being custom mapped. The driver53* creates an instance of <code>SQLInputImpl</code>, populating it with the54* attributes of the UDT. The driver then passes the input55* stream to the method <code>SQLData.readSQL</code>, which in turn56* calls the <code>SQLInputImpl</code> reader methods57* to read the attributes from the input stream.58* @since 1.559* @see java.sql.SQLData60*/61public class SQLInputImpl implements SQLInput {6263/**64* <code>true</code> if the last value returned was <code>SQL NULL</code>;65* <code>false</code> otherwise.66*/67private boolean lastValueWasNull;6869/**70* The current index into the array of SQL structured type attributes71* that will be read from this <code>SQLInputImpl</code> object and72* mapped to the fields of a class in the Java programming language.73*/74private int idx;7576/**77* The array of attributes to be read from this stream. The order78* of the attributes is the same as the order in which they were79* listed in the SQL definition of the UDT.80*/81private Object attrib[];8283/**84* The type map to use when the method <code>readObject</code>85* is invoked. This is a <code>java.util.Map</code> object in which86* there may be zero or more entries. Each entry consists of the87* fully qualified name of a UDT (the value to be mapped) and the88* <code>Class</code> object for a class that implements89* <code>SQLData</code> (the Java class that defines how the UDT90* will be mapped).91*/92private Map<String,Class<?>> map;939495/**96* Creates an <code>SQLInputImpl</code> object initialized with the97* given array of attributes and the given type map. If any of the98* attributes is a UDT whose name is in an entry in the type map,99* the attribute will be mapped according to the corresponding100* <code>SQLData</code> implementation.101*102* @param attributes an array of <code>Object</code> instances in which103* each element is an attribute of a UDT. The order of the104* attributes in the array is the same order in which105* the attributes were defined in the UDT definition.106* @param map a <code>java.util.Map</code> object containing zero or more107* entries, with each entry consisting of 1) a <code>String</code>108* giving the fully109* qualified name of the UDT and 2) the <code>Class</code> object110* for the <code>SQLData</code> implementation that defines how111* the UDT is to be mapped112* @throws SQLException if the <code>attributes</code> or the <code>map</code>113* is a <code>null</code> value114*/115116public SQLInputImpl(Object[] attributes, Map<String,Class<?>> map)117throws SQLException118{119if ((attributes == null) || (map == null)) {120throw new SQLException("Cannot instantiate a SQLInputImpl " +121"object with null parameters");122}123// assign our local reference to the attribute stream124attrib = Arrays.copyOf(attributes, attributes.length);125// init the index point before the head of the stream126idx = -1;127// set the map128this.map = map;129}130131132/**133* Retrieves the next attribute in this <code>SQLInputImpl</code> object134* as an <code>Object</code> in the Java programming language.135*136* @return the next value in the input stream137* as an <code>Object</code> in the Java programming language138* @throws SQLException if the read position is located at an invalid139* position or if there are no further values in the stream140*/141private Object getNextAttribute() throws SQLException {142if (++idx >= attrib.length) {143throw new SQLException("SQLInputImpl exception: Invalid read " +144"position");145} else {146lastValueWasNull = attrib[idx] == null;147return attrib[idx];148}149}150151152//================================================================153// Methods for reading attributes from the stream of SQL data.154// These methods correspond to the column-accessor methods of155// java.sql.ResultSet.156//================================================================157158/**159* Retrieves the next attribute in this <code>SQLInputImpl</code> object as160* a <code>String</code> in the Java programming language.161* <p>162* This method does not perform type-safe checking to determine if the163* returned type is the expected type; this responsibility is delegated164* to the UDT mapping as defined by a <code>SQLData</code>165* implementation.166*167* @return the next attribute in this <code>SQLInputImpl</code> object;168* if the value is <code>SQL NULL</code>, return <code>null</code>169* @throws SQLException if the read position is located at an invalid170* position or if there are no further values in the stream.171*/172public String readString() throws SQLException {173return (String)getNextAttribute();174}175176/**177* Retrieves the next attribute in this <code>SQLInputImpl</code> object as178* a <code>boolean</code> in the Java programming language.179* <p>180* This method does not perform type-safe checking to determine if the181* returned type is the expected type; this responsibility is delegated182* to the UDT mapping as defined by a <code>SQLData</code>183* implementation.184*185* @return the next attribute in this <code>SQLInputImpl</code> object;186* if the value is <code>SQL NULL</code>, return <code>null</code>187* @throws SQLException if the read position is located at an invalid188* position or if there are no further values in the stream.189*/190public boolean readBoolean() throws SQLException {191Boolean attrib = (Boolean)getNextAttribute();192return (attrib == null) ? false : attrib.booleanValue();193}194195/**196* Retrieves the next attribute in this <code>SQLInputImpl</code> object as197* a <code>byte</code> in the Java programming language.198* <p>199* This method does not perform type-safe checking to determine if the200* returned type is the expected type; this responsibility is delegated201* to the UDT mapping as defined by a <code>SQLData</code>202* implementation.203*204* @return the next attribute in this <code>SQLInputImpl</code> object;205* if the value is <code>SQL NULL</code>, return <code>null</code>206* @throws SQLException if the read position is located at an invalid207* position or if there are no further values in the stream208*/209public byte readByte() throws SQLException {210Byte attrib = (Byte)getNextAttribute();211return (attrib == null) ? 0 : attrib.byteValue();212}213214/**215* Retrieves the next attribute in this <code>SQLInputImpl</code> object216* as a <code>short</code> in the Java programming language.217* <P>218* This method does not perform type-safe checking to determine if the219* returned type is the expected type; this responsibility is delegated220* to the UDT mapping as defined by a <code>SQLData</code> implementation.221*222* @return the next attribute in this <code>SQLInputImpl</code> object;223* if the value is <code>SQL NULL</code>, return <code>null</code>224* @throws SQLException if the read position is located at an invalid225* position or if there are no more values in the stream226*/227public short readShort() throws SQLException {228Short attrib = (Short)getNextAttribute();229return (attrib == null) ? 0 : attrib.shortValue();230}231232/**233* Retrieves the next attribute in this <code>SQLInputImpl</code> object234* as an <code>int</code> in the Java programming language.235* <P>236* This method does not perform type-safe checking to determine if the237* returned type is the expected type; this responsibility is delegated238* to the UDT mapping as defined by a <code>SQLData</code> implementation.239*240* @return the next attribute in this <code>SQLInputImpl</code> object;241* if the value is <code>SQL NULL</code>, return <code>null</code>242* @throws SQLException if the read position is located at an invalid243* position or if there are no more values in the stream244*/245public int readInt() throws SQLException {246Integer attrib = (Integer)getNextAttribute();247return (attrib == null) ? 0 : attrib.intValue();248}249250/**251* Retrieves the next attribute in this <code>SQLInputImpl</code> object252* as a <code>long</code> in the Java programming language.253* <P>254* This method does not perform type-safe checking to determine if the255* returned type is the expected type; this responsibility is delegated256* to the UDT mapping as defined by a <code>SQLData</code> implementation.257*258* @return the next attribute in this <code>SQLInputImpl</code> object;259* if the value is <code>SQL NULL</code>, return <code>null</code>260* @throws SQLException if the read position is located at an invalid261* position or if there are no more values in the stream262*/263public long readLong() throws SQLException {264Long attrib = (Long)getNextAttribute();265return (attrib == null) ? 0 : attrib.longValue();266}267268/**269* Retrieves the next attribute in this <code>SQLInputImpl</code> object270* as a <code>float</code> in the Java programming language.271* <P>272* This method does not perform type-safe checking to determine if the273* returned type is the expected type; this responsibility is delegated274* to the UDT mapping as defined by a <code>SQLData</code> implementation.275*276* @return the next attribute in this <code>SQLInputImpl</code> object;277* if the value is <code>SQL NULL</code>, return <code>null</code>278* @throws SQLException if the read position is located at an invalid279* position or if there are no more values in the stream280*/281public float readFloat() throws SQLException {282Float attrib = (Float)getNextAttribute();283return (attrib == null) ? 0 : attrib.floatValue();284}285286/**287* Retrieves the next attribute in this <code>SQLInputImpl</code> object288* as a <code>double</code> in the Java programming language.289* <P>290* This method does not perform type-safe checking to determine if the291* returned type is the expected type; this responsibility is delegated292* to the UDT mapping as defined by a <code>SQLData</code> implementation.293*294* @return the next attribute in this <code>SQLInputImpl</code> object;295* if the value is <code>SQL NULL</code>, return <code>null</code>296* @throws SQLException if the read position is located at an invalid297* position or if there are no more values in the stream298*/299public double readDouble() throws SQLException {300Double attrib = (Double)getNextAttribute();301return (attrib == null) ? 0 : attrib.doubleValue();302}303304/**305* Retrieves the next attribute in this <code>SQLInputImpl</code> object306* as a <code>java.math.BigDecimal</code>.307* <P>308* This method does not perform type-safe checking to determine if the309* returned type is the expected type; this responsibility is delegated310* to the UDT mapping as defined by a <code>SQLData</code> implementation.311*312* @return the next attribute in this <code>SQLInputImpl</code> object;313* if the value is <code>SQL NULL</code>, return <code>null</code>314* @throws SQLException if the read position is located at an invalid315* position or if there are no more values in the stream316*/317public java.math.BigDecimal readBigDecimal() throws SQLException {318return (java.math.BigDecimal)getNextAttribute();319}320321/**322* Retrieves the next attribute in this <code>SQLInputImpl</code> object323* as an array of bytes.324* <p>325* This method does not perform type-safe checking to determine if the326* returned type is the expected type; this responsibility is delegated327* to the UDT mapping as defined by a <code>SQLData</code> implementation.328*329* @return the next attribute in this <code>SQLInputImpl</code> object;330* if the value is <code>SQL NULL</code>, return <code>null</code>331* @throws SQLException if the read position is located at an invalid332* position or if there are no more values in the stream333*/334public byte[] readBytes() throws SQLException {335return (byte[])getNextAttribute();336}337338/**339* Retrieves the next attribute in this <code>SQLInputImpl</code> as340* a <code>java.sql.Date</code> object.341* <P>342* This method does not perform type-safe checking to determine if the343* returned type is the expected type; this responsibility is delegated344* to the UDT mapping as defined by a <code>SQLData</code> implementation.345*346* @return the next attribute in this <code>SQLInputImpl</code> object;347* if the value is <code>SQL NULL</code>, return <code>null</code>348* @throws SQLException if the read position is located at an invalid349* position or if there are no more values in the stream350*/351public java.sql.Date readDate() throws SQLException {352return (java.sql.Date)getNextAttribute();353}354355/**356* Retrieves the next attribute in this <code>SQLInputImpl</code> object as357* a <code>java.sql.Time</code> object.358* <P>359* This method does not perform type-safe checking to determine if the360* returned type is the expected type as this responsibility is delegated361* to the UDT mapping as implemented by a <code>SQLData</code>362* implementation.363*364* @return the attribute; if the value is <code>SQL NULL</code>, return365* <code>null</code>366* @throws SQLException if the read position is located at an invalid367* position; or if there are no further values in the stream.368*/369public java.sql.Time readTime() throws SQLException {370return (java.sql.Time)getNextAttribute();371}372373/**374* Retrieves the next attribute in this <code>SQLInputImpl</code> object as375* a <code>java.sql.Timestamp</code> object.376*377* @return the attribute; if the value is <code>SQL NULL</code>, return378* <code>null</code>379* @throws SQLException if the read position is located at an invalid380* position; or if there are no further values in the stream.381*/382public java.sql.Timestamp readTimestamp() throws SQLException {383return (java.sql.Timestamp)getNextAttribute();384}385386/**387* Retrieves the next attribute in this <code>SQLInputImpl</code> object388* as a stream of Unicode characters.389* <P>390* This method does not perform type-safe checking to determine if the391* returned type is the expected type as this responsibility is delegated392* to the UDT mapping as implemented by a <code>SQLData</code>393* implementation.394*395* @return the attribute; if the value is <code>SQL NULL</code>, return <code>null</code>396* @throws SQLException if the read position is located at an invalid397* position; or if there are no further values in the stream.398*/399public java.io.Reader readCharacterStream() throws SQLException {400return (java.io.Reader)getNextAttribute();401}402403/**404* Returns the next attribute in this <code>SQLInputImpl</code> object405* as a stream of ASCII characters.406* <P>407* This method does not perform type-safe checking to determine if the408* returned type is the expected type as this responsibility is delegated409* to the UDT mapping as implemented by a <code>SQLData</code>410* implementation.411*412* @return the attribute; if the value is <code>SQL NULL</code>,413* return <code>null</code>414* @throws SQLException if the read position is located at an invalid415* position; or if there are no further values in the stream.416*/417public java.io.InputStream readAsciiStream() throws SQLException {418return (java.io.InputStream)getNextAttribute();419}420421/**422* Returns the next attribute in this <code>SQLInputImpl</code> object423* as a stream of uninterpreted bytes.424* <P>425* This method does not perform type-safe checking to determine if the426* returned type is the expected type as this responsibility is delegated427* to the UDT mapping as implemented by a <code>SQLData</code>428* implementation.429*430* @return the attribute; if the value is <code>SQL NULL</code>, return431* <code>null</code>432* @throws SQLException if the read position is located at an invalid433* position; or if there are no further values in the stream.434*/435public java.io.InputStream readBinaryStream() throws SQLException {436return (java.io.InputStream)getNextAttribute();437}438439//================================================================440// Methods for reading items of SQL user-defined types from the stream.441//================================================================442443/**444* Retrieves the value at the head of this <code>SQLInputImpl</code>445* object as an <code>Object</code> in the Java programming language. The446* actual type of the object returned is determined by the default447* mapping of SQL types to types in the Java programming language unless448* there is a custom mapping, in which case the type of the object449* returned is determined by this stream's type map.450* <P>451* The JDBC technology-enabled driver registers a type map with the stream452* before passing the stream to the application.453* <P>454* When the datum at the head of the stream is an SQL <code>NULL</code>,455* this method returns <code>null</code>. If the datum is an SQL456* structured or distinct type with a custom mapping, this method457* determines the SQL type of the datum at the head of the stream,458* constructs an object of the appropriate class, and calls the method459* <code>SQLData.readSQL</code> on that object. The <code>readSQL</code>460* method then calls the appropriate <code>SQLInputImpl.readXXX</code>461* methods to retrieve the attribute values from the stream.462*463* @return the value at the head of the stream as an <code>Object</code>464* in the Java programming language; <code>null</code> if465* the value is SQL <code>NULL</code>466* @throws SQLException if the read position is located at an invalid467* position; or if there are no further values in the stream.468*/469public Object readObject() throws SQLException {470Object attrib = getNextAttribute();471if (attrib instanceof Struct) {472Struct s = (Struct)attrib;473// look up the class in the map474Class<?> c = map.get(s.getSQLTypeName());475if (c != null) {476// create new instance of the class477SQLData obj = null;478try {479ReflectUtil.checkPackageAccess(c);480@SuppressWarnings("deprecation")481Object tmp = c.newInstance();482obj = (SQLData)tmp;483} catch (Exception ex) {484throw new SQLException("Unable to Instantiate: ", ex);485}486// get the attributes from the struct487Object attribs[] = s.getAttributes(map);488// create the SQLInput "stream"489SQLInputImpl sqlInput = new SQLInputImpl(attribs, map);490// read the values...491obj.readSQL(sqlInput, s.getSQLTypeName());492return obj;493}494}495return attrib;496}497498/**499* Retrieves the value at the head of this <code>SQLInputImpl</code> object500* as a <code>Ref</code> object in the Java programming language.501*502* @return a <code>Ref</code> object representing the SQL503* <code>REF</code> value at the head of the stream; if the value504* is <code>SQL NULL</code> return <code>null</code>505* @throws SQLException if the read position is located at an invalid506* position; or if there are no further values in the stream.507*/508public Ref readRef() throws SQLException {509return (Ref)getNextAttribute();510}511512/**513* Retrieves the <code>BLOB</code> value at the head of this514* <code>SQLInputImpl</code> object as a <code>Blob</code> object515* in the Java programming language.516* <P>517* This method does not perform type-safe checking to determine if the518* returned type is the expected type as this responsibility is delegated519* to the UDT mapping as implemented by a <code>SQLData</code>520* implementation.521*522* @return a <code>Blob</code> object representing the SQL523* <code>BLOB</code> value at the head of this stream;524* if the value is <code>SQL NULL</code>, return525* <code>null</code>526* @throws SQLException if the read position is located at an invalid527* position; or if there are no further values in the stream.528*/529public Blob readBlob() throws SQLException {530return (Blob)getNextAttribute();531}532533/**534* Retrieves the <code>CLOB</code> value at the head of this535* <code>SQLInputImpl</code> object as a <code>Clob</code> object536* in the Java programming language.537* <P>538* This method does not perform type-safe checking to determine if the539* returned type is the expected type as this responsibility is delegated540* to the UDT mapping as implemented by a <code>SQLData</code>541* implementation.542*543* @return a <code>Clob</code> object representing the SQL544* <code>CLOB</code> value at the head of the stream;545* if the value is <code>SQL NULL</code>, return546* <code>null</code>547* @throws SQLException if the read position is located at an invalid548* position; or if there are no further values in the stream.549*/550public Clob readClob() throws SQLException {551return (Clob)getNextAttribute();552}553554/**555* Reads an SQL <code>ARRAY</code> value from the stream and556* returns it as an <code>Array</code> object in the Java programming557* language.558* <P>559* This method does not perform type-safe checking to determine if the560* returned type is the expected type as this responsibility is delegated561* to the UDT mapping as implemented by a <code>SQLData</code>562* implementation.563*564* @return an <code>Array</code> object representing the SQL565* <code>ARRAY</code> value at the head of the stream; *566* if the value is <code>SQL NULL</code>, return567* <code>null</code>568* @throws SQLException if the read position is located at an invalid569* position; or if there are no further values in the stream.570571*/572public Array readArray() throws SQLException {573return (Array)getNextAttribute();574}575576/**577* Ascertains whether the last value read from this578* <code>SQLInputImpl</code> object was <code>null</code>.579*580* @return <code>true</code> if the SQL value read most recently was581* <code>null</code>; otherwise, <code>false</code>; by default it582* will return false583* @throws SQLException if an error occurs determining the last value584* read was a <code>null</code> value or not;585*/586public boolean wasNull() throws SQLException {587return lastValueWasNull;588}589590/**591* Reads an SQL <code>DATALINK</code> value from the stream and592* returns it as an <code>URL</code> object in the Java programming593* language.594* <P>595* This method does not perform type-safe checking to determine if the596* returned type is the expected type as this responsibility is delegated597* to the UDT mapping as implemented by a <code>SQLData</code>598* implementation.599*600* @return an <code>URL</code> object representing the SQL601* <code>DATALINK</code> value at the head of the stream; *602* if the value is <code>SQL NULL</code>, return603* <code>null</code>604* @throws SQLException if the read position is located at an invalid605* position; or if there are no further values in the stream.606*/607public java.net.URL readURL() throws SQLException {608return (java.net.URL)getNextAttribute();609}610611//---------------------------- JDBC 4.0 -------------------------612613/**614* Reads an SQL <code>NCLOB</code> value from the stream and returns it as a615* <code>Clob</code> object in the Java programming language.616*617* @return a <code>NClob</code> object representing data of the SQL <code>NCLOB</code> value618* at the head of the stream; <code>null</code> if the value read is619* SQL <code>NULL</code>620* @exception SQLException if a database access error occurs621* @since 1.6622*/623public NClob readNClob() throws SQLException {624return (NClob)getNextAttribute();625}626627/**628* Reads the next attribute in the stream and returns it as a <code>String</code>629* in the Java programming language. It is intended for use when630* accessing <code>NCHAR</code>,<code>NVARCHAR</code>631* and <code>LONGNVARCHAR</code> columns.632*633* @return the attribute; if the value is SQL <code>NULL</code>, returns <code>null</code>634* @exception SQLException if a database access error occurs635* @since 1.6636*/637public String readNString() throws SQLException {638return (String)getNextAttribute();639}640641/**642* Reads an SQL <code>XML</code> value from the stream and returns it as a643* <code>SQLXML</code> object in the Java programming language.644*645* @return a <code>SQLXML</code> object representing data of the SQL <code>XML</code> value646* at the head of the stream; <code>null</code> if the value read is647* SQL <code>NULL</code>648* @exception SQLException if a database access error occurs649* @since 1.6650*/651public SQLXML readSQLXML() throws SQLException {652return (SQLXML)getNextAttribute();653}654655/**656* Reads an SQL <code>ROWID</code> value from the stream and returns it as a657* <code>RowId</code> object in the Java programming language.658*659* @return a <code>RowId</code> object representing data of the SQL <code>ROWID</code> value660* at the head of the stream; <code>null</code> if the value read is661* SQL <code>NULL</code>662* @exception SQLException if a database access error occurs663* @since 1.6664*/665public RowId readRowId() throws SQLException {666return (RowId)getNextAttribute();667}668669670}671672673