001    package railo.runtime.type.sql;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.IOException;
005    import java.io.OutputStream;
006    import java.io.Reader;
007    import java.io.Serializable;
008    import java.io.StringReader;
009    import java.io.StringWriter;
010    import java.io.Writer;
011    import java.sql.CallableStatement;
012    import java.sql.Clob;
013    import java.sql.PreparedStatement;
014    import java.sql.SQLException;
015    
016    import railo.commons.io.IOUtil;
017    import railo.runtime.exp.ExpressionException;
018    import railo.runtime.exp.PageException;
019    import railo.runtime.op.Caster;
020    
021    
022    
023    /**
024     * The representation (mapping) in the Java <sup><small>TM </small> </sup>
025     * programming language of an SQL <code>CLOB</code> value. An SQL
026     * <code>CLOB</code> is a built-in type that stores a Character Large Object
027     * as a column value in a row of a database table. By default drivers implement
028     * <code>Clob</code> using an SQL <code>locator(CLOB)</code>, which means
029     * that a <code>Clob</code> object contains a logical pointer to the SQL
030     * <code>CLOB</code> data rather than the data itself. A <code>Clob</code>
031     * object is valid for the duration of the transaction in which is was created.
032     * <p>
033     * Methods in the interfaces {@link DriverResultSet},{@link CallableStatement},
034     * and {@link PreparedStatement}, such as <code>getClob</code> and
035     * <code>setClob</code> allow a programmer to access an SQL <code>CLOB</code>
036     * value. The <code>Clob</code> interface provides methods for getting the
037     * length of an SQL <code>CLOB</code> (Character Large Object) value, for
038     * materializing a <code>CLOB</code> value on the client, and for determining
039     * the position of a pattern of bytes within a <code>CLOB</code> value. In
040     * addition, this interface has methods for updating a <code>CLOB</code>
041     * value.
042     */
043    public final class ClobImpl implements java.sql.Clob, Serializable {
044        
045        
046        
047      /**
048       * cast given value to a clob
049     * @param value
050     * @return clob
051     * @throws PageException 
052     */
053        public static Clob toClob(Object value) throws PageException {
054            if(value instanceof Clob) return (Clob)value;  
055            else if(value instanceof char[]) 
056                    return toClob(new String((char[])value));  
057            else if(value instanceof Reader) {
058                    StringWriter sw=new StringWriter();
059                    try {
060                            IOUtil.copy((Reader)value,sw,false,true);
061                    } 
062                    catch (IOException e) {
063                            throw ExpressionException.newInstance(e);
064                    }
065                    return toClob(sw.toString());  
066            }
067            return toClob(Caster.toString(value));
068        }
069        
070        public static Clob toClob(String value) {
071            return new ClobImpl(value);
072        }
073        
074        
075        
076        
077      /** The data represented as a string of this <code>CLOB</code> */
078      private String stringData = null;
079    
080      /**
081       * Creates a new <code>Clob</code> instance.
082       * 
083       * @param data a <code>String</code> of character data
084       */
085      private ClobImpl(String data) {
086        stringData = data;
087      }
088    
089      /**
090       * Returns the size of the <code>CLOB</code> value designated by this
091       * <code>Clob</code> object
092       * 
093       * @return length of the <code>CLOB</code> value that this <code>clob</code>
094       *         represents
095       * @exception SQLException if there is an error accessing the length of the
096       *              <code>CLOB</code>
097       */
098      public long length() throws SQLException {
099              return stringData.length();
100      }
101    
102      /**
103       * Retrieves the <code>CLOB</code> value designated by this
104       * <code>Clob</code> instance as a stream.
105       * 
106       * @return a stream containing the <code>CLOB</code> data
107       * @exception SQLException if there is an error accessing the
108       *              <code>CLOB</code> value
109       */
110      public java.io.InputStream getAsciiStream() throws SQLException       {
111              return new ByteArrayInputStream(stringData.getBytes());
112      }
113    
114      /**
115       * Materializes the <code>CLOB</code> value designated by this <Code>object
116       * as a stream of Unicode character.
117       * 
118       * @return A reader object with all the data in the <code>CLOB</code> value
119       *         designated by this clob object as unicode characters.
120       * @exception SQLException if there is an error accessing the
121       *              <code>CLOB</code> value
122       */
123      public java.io.Reader getCharacterStream() throws SQLException {
124              return new StringReader(stringData);
125      }
126      
127      public Reader getCharacterStream(long pos, long len) {
128              return new StringReader(stringData.substring((int)pos, (int)len));
129      }
130    
131      /**
132       * Returns a copy of the portion of the <code>CLOB</code> value represented
133       * by this <code>CLOB</code> object that starts at position <i>position </i>
134       * and has ip to <i>length </i> consecutive characters.
135       * 
136       * @param pos the position where to get the substring from
137       * @param length the length of the substring
138       * @return the substring
139       * @exception SQLException if there is an error accessing the
140       *              <code>CLOB</code>
141       */
142      public String getSubString(long pos, int length) throws SQLException {
143        if (length > stringData.length())
144          throw new SQLException("Clob contains only " + stringData.length()
145              + " characters (asking for " + length + ").");
146        return stringData.substring((int) pos-1, length);
147      }
148    
149      /**
150       * Retrieves the character position at which the specified string
151       * <code>searchstr</code> begins within the <code>CLOB</code> value that
152       * this <code>Clob</code> object represents. The search for
153       * <code>searchstr</code> begins at position <code>start</code>.
154       * 
155       * @param searchstr the byte array for which to search
156       * @param start the position at which to begin searching; the first position
157       *          is 1
158       * @return the position at which the pattern appears, else -1
159       * @exception SQLException if there is an error accessing the
160       *              <code>CLOB</code>
161       */
162      public long position(String searchstr, long start) throws SQLException {
163              return stringData.indexOf(searchstr, (int) start);
164      }
165    
166      /**
167       * Retrieves the character position at which the specified <code>Clob</code>
168       * object <code>searchstr</code> begins within the <code>CLOB</code> value
169       * that this <code>Clob</code> object represents. The search for
170       * <code>searchstr</code> begins at position <code>start</code>.
171       * 
172       * @param searchstr the byte array for which to search
173       * @param start the position at which to begin searching; the first position
174       *          is 1
175       * @return the position at which the pattern appears, else -1
176       * @exception SQLException if there is an error accessing the
177       *              <code>CLOB</code>
178       */
179      public long position(java.sql.Clob searchstr, long start) throws SQLException {
180              return position(searchstr.getSubString(0, (int) searchstr.length()),
181            (int) start);
182      }
183    
184      // -------------------------- JDBC 3.0 -----------------------------------
185    
186      /**
187       * Retrieves a stream to be used to write Ascii characters to the CLOB value
188       * that this Clob object represents, starting at position pos.
189       * 
190       * @param pos the position where to start the stream
191       * @return the ascii outputstream to this <code>clob</code> object
192       * @throws SQLException if there is an error accessing the <code>clob</code>
193       */
194      public OutputStream setAsciiStream(long pos) throws SQLException {
195          // TODO impl.
196          throw new SQLException("JDBC 3.0 Method setAsciiStream not implemented");
197      }
198    
199      /**
200       * Retrieves a stream to be used to write a stream of Unicode characters to
201       * the CLOB value that this Clob object represents, at position pos.
202       * 
203       * @param pos the position where to start the writer
204       * @return the writer to this <code>clob</code> object
205       * @throws SQLException if there is an error accessing the <code>clob</code>
206       */
207      public Writer setCharacterStream(long pos) throws SQLException {
208          // TODO impl.
209          throw new SQLException("JDBC 3.0 Method setCharacterStream not implemented");
210      }
211    
212      /**
213       * Writes the given Java String to the CLOB value that this Clob object
214       * designates at the position pos.
215       * 
216       * @param pos the position where to set the string
217       * @param str string to insert in the <code>clob</code>
218       * @return return value
219       * @throws SQLException if there is an error accessing the <code>clob</code>
220       */
221      public int setString(long pos, String str) throws SQLException {
222          // TODO impl.
223          throw new SQLException("JDBC 3.0 Method setString not implemented");
224      }
225    
226      /**
227       * Writes len characters of str, starting at character offset, to the CLOB
228       * value that this Clob represents.
229       * 
230       * @param pos the position
231       * @param str the string
232       * @param offset the offset
233       * @param len the length
234       * @return return value
235       * @throws SQLException if there is an error accessing the <code>clob</code>
236       */
237      public int setString(long pos, String str, int offset, int len) throws SQLException{
238          // TODO impl.
239          throw new SQLException("JDBC 3.0 Method setString not implemented");
240      }
241    
242      /**
243       * Truncates the CLOB value that this Clob designates to have a length of len
244       * characters.
245       * 
246       * @param len the length
247       * @throws SQLException if there is an error accessing the <code>clob</code>
248       */
249      public void truncate(long len) throws SQLException
250      {
251          // TODO impl.
252          throw new SQLException("JDBC 3.0 Method truncate not implemented");
253      }
254      
255    
256      /**
257       * @see java.lang.Object#toString()
258       */
259      public String toString() {
260          return stringData;
261      }
262    
263            public void free() {
264                    stringData="";
265            }
266    
267    
268    
269    }