Source Code Cross Referenced for OracleLobHandler.java in  » J2EE » spring-framework-2.5 » org » springframework » jdbc » support » lob » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.jdbc.support.lob 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.jdbc.support.lob;
018:
019:        import java.io.InputStream;
020:        import java.io.OutputStream;
021:        import java.io.Reader;
022:        import java.io.Writer;
023:        import java.lang.reflect.InvocationTargetException;
024:        import java.lang.reflect.Method;
025:        import java.sql.Blob;
026:        import java.sql.Clob;
027:        import java.sql.Connection;
028:        import java.sql.PreparedStatement;
029:        import java.sql.ResultSet;
030:        import java.sql.SQLException;
031:        import java.util.HashMap;
032:        import java.util.Iterator;
033:        import java.util.LinkedList;
034:        import java.util.List;
035:        import java.util.Map;
036:
037:        import org.apache.commons.logging.Log;
038:        import org.apache.commons.logging.LogFactory;
039:
040:        import org.springframework.dao.DataAccessResourceFailureException;
041:        import org.springframework.dao.InvalidDataAccessApiUsageException;
042:        import org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor;
043:        import org.springframework.util.FileCopyUtils;
044:
045:        /**
046:         * {@link LobHandler} implementation for Oracle databases. Uses proprietary API
047:         * to create <code>oracle.sql.BLOB</code> and <code>oracle.sql.CLOB</code>
048:         * instances, as necessary when working with Oracle's JDBC driver.
049:         * Note that this LobHandler requires Oracle JDBC driver 9i or higher!
050:         *
051:         * <p>While most databases are able to work with {@link DefaultLobHandler},
052:         * Oracle just accepts Blob/Clob instances created via its own proprietary
053:         * BLOB/CLOB API, and additionally doesn't accept large streams for
054:         * PreparedStatement's corresponding setter methods. Therefore, you need
055:         * to use a strategy like this LobHandler implementation.
056:         *
057:         * <p>Needs to work on a native JDBC Connection, to be able to cast it to
058:         * <code>oracle.jdbc.OracleConnection</code>. If you pass in Connections from a
059:         * connection pool (the usual case in a J2EE environment), you need to set an
060:         * appropriate {@link org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor}
061:         * to allow for automatical retrieval of the underlying native JDBC Connection.
062:         * LobHandler and NativeJdbcExtractor are separate concerns, therefore they
063:         * are represented by separate strategy interfaces.
064:         *
065:         * <p>Coded via reflection to avoid dependencies on Oracle classes.
066:         * Even reads in Oracle constants via reflection because of different Oracle
067:         * drivers (classes12, ojdbc14) having different constant values! As this
068:         * LobHandler initializes Oracle classes on instantiation, do not define this
069:         * as eager-initializing singleton if you do not want to depend on the Oracle
070:         * JAR being in the class path: use "lazy-init=true" to avoid this issue.
071:         *
072:         * @author Juergen Hoeller
073:         * @since 04.12.2003
074:         * @see #setNativeJdbcExtractor
075:         * @see oracle.sql.BLOB
076:         * @see oracle.sql.CLOB
077:         */
078:        public class OracleLobHandler extends AbstractLobHandler {
079:
080:            private static final String BLOB_CLASS_NAME = "oracle.sql.BLOB";
081:
082:            private static final String CLOB_CLASS_NAME = "oracle.sql.CLOB";
083:
084:            private static final String DURATION_SESSION_FIELD_NAME = "DURATION_SESSION";
085:
086:            private static final String MODE_READWRITE_FIELD_NAME = "MODE_READWRITE";
087:
088:            protected final Log logger = LogFactory.getLog(getClass());
089:
090:            private NativeJdbcExtractor nativeJdbcExtractor;
091:
092:            private Boolean cache = Boolean.TRUE;
093:
094:            private Class blobClass;
095:
096:            private Class clobClass;
097:
098:            private final Map durationSessionConstants = new HashMap(2);
099:
100:            private final Map modeReadWriteConstants = new HashMap(2);
101:
102:            /**
103:             * Set an appropriate NativeJdbcExtractor to be able to retrieve the underlying
104:             * native <code>oracle.jdbc.OracleConnection</code>. This is necessary for
105:             * DataSource-based connection pools, as those need to return wrapped JDBC
106:             * Connection handles that cannot be cast to a native Connection implementation.
107:             * <p>Effectively, this LobHandler just invokes a single NativeJdbcExtractor
108:             * method, namely <code>getNativeConnectionFromStatement</code> with a
109:             * PreparedStatement argument (falling back to a
110:             * <code>PreparedStatement.getConnection()</code> call if no extractor is set).
111:             * <p>A common choice is SimpleNativeJdbcExtractor, whose Connection unwrapping
112:             * (which is what OracleLobHandler needs) will work with many connection pools.
113:             * See SimpleNativeJdbcExtractor's javadoc for details.
114:             * @see org.springframework.jdbc.support.nativejdbc.NativeJdbcExtractor#getNativeConnectionFromStatement
115:             * @see org.springframework.jdbc.support.nativejdbc.SimpleNativeJdbcExtractor
116:             * @see oracle.jdbc.OracleConnection
117:             */
118:            public void setNativeJdbcExtractor(
119:                    NativeJdbcExtractor nativeJdbcExtractor) {
120:                this .nativeJdbcExtractor = nativeJdbcExtractor;
121:            }
122:
123:            /**
124:             * Set whether to cache the temporary LOB in the buffer cache.
125:             * This value will be passed into BLOB/CLOB.createTemporary. Default is "true".
126:             * @see oracle.sql.BLOB#createTemporary
127:             * @see oracle.sql.CLOB#createTemporary
128:             */
129:            public void setCache(boolean cache) {
130:                this .cache = new Boolean(cache);
131:            }
132:
133:            /**
134:             * Retrieve the <code>oracle.sql.BLOB</code> and <code>oracle.sql.CLOB</code>
135:             * classes via reflection, and initialize the values for the
136:             * DURATION_SESSION and MODE_READWRITE constants defined there.
137:             * @param con the Oracle Connection, for using the exact same class loader
138:             * that the Oracle driver was loaded with
139:             * @see oracle.sql.BLOB#DURATION_SESSION
140:             * @see oracle.sql.BLOB#MODE_READWRITE
141:             * @see oracle.sql.CLOB#DURATION_SESSION
142:             * @see oracle.sql.CLOB#MODE_READWRITE
143:             */
144:            protected synchronized void initOracleDriverClasses(Connection con) {
145:                if (this .blobClass == null) {
146:                    try {
147:                        // Initialize oracle.sql.BLOB class
148:                        this .blobClass = con.getClass().getClassLoader()
149:                                .loadClass(BLOB_CLASS_NAME);
150:                        this .durationSessionConstants.put(this .blobClass,
151:                                new Integer(this .blobClass.getField(
152:                                        DURATION_SESSION_FIELD_NAME).getInt(
153:                                        null)));
154:                        this .modeReadWriteConstants
155:                                .put(this .blobClass, new Integer(this .blobClass
156:                                        .getField(MODE_READWRITE_FIELD_NAME)
157:                                        .getInt(null)));
158:
159:                        // Initialize oracle.sql.CLOB class
160:                        this .clobClass = con.getClass().getClassLoader()
161:                                .loadClass(CLOB_CLASS_NAME);
162:                        this .durationSessionConstants.put(this .clobClass,
163:                                new Integer(this .clobClass.getField(
164:                                        DURATION_SESSION_FIELD_NAME).getInt(
165:                                        null)));
166:                        this .modeReadWriteConstants
167:                                .put(this .clobClass, new Integer(this .clobClass
168:                                        .getField(MODE_READWRITE_FIELD_NAME)
169:                                        .getInt(null)));
170:                    } catch (Exception ex) {
171:                        throw new InvalidDataAccessApiUsageException(
172:                                "Couldn't initialize OracleLobHandler because Oracle driver classes are not available. "
173:                                        + "Note that OracleLobHandler requires Oracle JDBC driver 9i or higher!",
174:                                ex);
175:                    }
176:                }
177:            }
178:
179:            public byte[] getBlobAsBytes(ResultSet rs, int columnIndex)
180:                    throws SQLException {
181:                logger.debug("Returning Oracle BLOB as bytes");
182:                Blob blob = rs.getBlob(columnIndex);
183:                return (blob != null ? blob.getBytes(1, (int) blob.length())
184:                        : null);
185:            }
186:
187:            public InputStream getBlobAsBinaryStream(ResultSet rs,
188:                    int columnIndex) throws SQLException {
189:                logger.debug("Returning Oracle BLOB as binary stream");
190:                Blob blob = rs.getBlob(columnIndex);
191:                return (blob != null ? blob.getBinaryStream() : null);
192:            }
193:
194:            public String getClobAsString(ResultSet rs, int columnIndex)
195:                    throws SQLException {
196:                logger.debug("Returning Oracle CLOB as string");
197:                Clob clob = rs.getClob(columnIndex);
198:                return (clob != null ? clob
199:                        .getSubString(1, (int) clob.length()) : null);
200:            }
201:
202:            public InputStream getClobAsAsciiStream(ResultSet rs,
203:                    int columnIndex) throws SQLException {
204:                logger.debug("Returning Oracle CLOB as ASCII stream");
205:                Clob clob = rs.getClob(columnIndex);
206:                return (clob != null ? clob.getAsciiStream() : null);
207:            }
208:
209:            public Reader getClobAsCharacterStream(ResultSet rs, int columnIndex)
210:                    throws SQLException {
211:                logger.debug("Returning Oracle CLOB as character stream");
212:                Clob clob = rs.getClob(columnIndex);
213:                return (clob != null ? clob.getCharacterStream() : null);
214:            }
215:
216:            public LobCreator getLobCreator() {
217:                return new OracleLobCreator();
218:            }
219:
220:            /**
221:             * LobCreator implementation for Oracle databases.
222:             * Creates Oracle-style temporary BLOBs and CLOBs that it frees on close.
223:             * @see #close
224:             */
225:            protected class OracleLobCreator implements  LobCreator {
226:
227:                private final List createdLobs = new LinkedList();
228:
229:                public void setBlobAsBytes(PreparedStatement ps,
230:                        int paramIndex, final byte[] content)
231:                        throws SQLException {
232:
233:                    if (content != null) {
234:                        Blob blob = (Blob) createLob(ps, false,
235:                                new LobCallback() {
236:                                    public void populateLob(Object lob)
237:                                            throws Exception {
238:                                        Method methodToInvoke = lob
239:                                                .getClass()
240:                                                .getMethod(
241:                                                        "getBinaryOutputStream",
242:                                                        new Class[0]);
243:                                        OutputStream out = (OutputStream) methodToInvoke
244:                                                .invoke(lob, (Object[]) null);
245:                                        FileCopyUtils.copy(content, out);
246:                                    }
247:                                });
248:                        ps.setBlob(paramIndex, blob);
249:                        if (logger.isDebugEnabled()) {
250:                            logger
251:                                    .debug("Set bytes for Oracle BLOB with length "
252:                                            + blob.length());
253:                        }
254:                    } else {
255:                        ps.setBlob(paramIndex, (Blob) null);
256:                        logger.debug("Set Oracle BLOB to null");
257:                    }
258:                }
259:
260:                public void setBlobAsBinaryStream(PreparedStatement ps,
261:                        int paramIndex, final InputStream binaryStream,
262:                        int contentLength) throws SQLException {
263:
264:                    if (binaryStream != null) {
265:                        Blob blob = (Blob) createLob(ps, false,
266:                                new LobCallback() {
267:                                    public void populateLob(Object lob)
268:                                            throws Exception {
269:                                        Method methodToInvoke = lob
270:                                                .getClass()
271:                                                .getMethod(
272:                                                        "getBinaryOutputStream",
273:                                                        (Class[]) null);
274:                                        OutputStream out = (OutputStream) methodToInvoke
275:                                                .invoke(lob, (Object[]) null);
276:                                        FileCopyUtils.copy(binaryStream, out);
277:                                    }
278:                                });
279:                        ps.setBlob(paramIndex, blob);
280:                        if (logger.isDebugEnabled()) {
281:                            logger
282:                                    .debug("Set binary stream for Oracle BLOB with length "
283:                                            + blob.length());
284:                        }
285:                    } else {
286:                        ps.setBlob(paramIndex, (Blob) null);
287:                        logger.debug("Set Oracle BLOB to null");
288:                    }
289:                }
290:
291:                public void setClobAsString(PreparedStatement ps,
292:                        int paramIndex, final String content)
293:                        throws SQLException {
294:
295:                    if (content != null) {
296:                        Clob clob = (Clob) createLob(ps, true,
297:                                new LobCallback() {
298:                                    public void populateLob(Object lob)
299:                                            throws Exception {
300:                                        Method methodToInvoke = lob
301:                                                .getClass()
302:                                                .getMethod(
303:                                                        "getCharacterOutputStream",
304:                                                        (Class[]) null);
305:                                        Writer writer = (Writer) methodToInvoke
306:                                                .invoke(lob, (Object[]) null);
307:                                        FileCopyUtils.copy(content, writer);
308:                                    }
309:                                });
310:                        ps.setClob(paramIndex, clob);
311:                        if (logger.isDebugEnabled()) {
312:                            logger
313:                                    .debug("Set string for Oracle CLOB with length "
314:                                            + clob.length());
315:                        }
316:                    } else {
317:                        ps.setClob(paramIndex, (Clob) null);
318:                        logger.debug("Set Oracle CLOB to null");
319:                    }
320:                }
321:
322:                public void setClobAsAsciiStream(PreparedStatement ps,
323:                        int paramIndex, final InputStream asciiStream,
324:                        int contentLength) throws SQLException {
325:
326:                    if (asciiStream != null) {
327:                        Clob clob = (Clob) createLob(ps, true,
328:                                new LobCallback() {
329:                                    public void populateLob(Object lob)
330:                                            throws Exception {
331:                                        Method methodToInvoke = lob.getClass()
332:                                                .getMethod(
333:                                                        "getAsciiOutputStream",
334:                                                        (Class[]) null);
335:                                        OutputStream out = (OutputStream) methodToInvoke
336:                                                .invoke(lob, (Object[]) null);
337:                                        FileCopyUtils.copy(asciiStream, out);
338:                                    }
339:                                });
340:                        ps.setClob(paramIndex, clob);
341:                        if (logger.isDebugEnabled()) {
342:                            logger
343:                                    .debug("Set ASCII stream for Oracle CLOB with length "
344:                                            + clob.length());
345:                        }
346:                    } else {
347:                        ps.setClob(paramIndex, (Clob) null);
348:                        logger.debug("Set Oracle CLOB to null");
349:                    }
350:                }
351:
352:                public void setClobAsCharacterStream(PreparedStatement ps,
353:                        int paramIndex, final Reader characterStream,
354:                        int contentLength) throws SQLException {
355:
356:                    if (characterStream != null) {
357:                        Clob clob = (Clob) createLob(ps, true,
358:                                new LobCallback() {
359:                                    public void populateLob(Object lob)
360:                                            throws Exception {
361:                                        Method methodToInvoke = lob
362:                                                .getClass()
363:                                                .getMethod(
364:                                                        "getCharacterOutputStream",
365:                                                        (Class[]) null);
366:                                        Writer writer = (Writer) methodToInvoke
367:                                                .invoke(lob, (Object[]) null);
368:                                        FileCopyUtils.copy(characterStream,
369:                                                writer);
370:                                    }
371:                                });
372:                        ps.setClob(paramIndex, clob);
373:                        if (logger.isDebugEnabled()) {
374:                            logger
375:                                    .debug("Set character stream for Oracle CLOB with length "
376:                                            + clob.length());
377:                        }
378:                    } else {
379:                        ps.setClob(paramIndex, (Clob) null);
380:                        logger.debug("Set Oracle CLOB to null");
381:                    }
382:                }
383:
384:                /**
385:                 * Create a LOB instance for the given PreparedStatement,
386:                 * populating it via the given callback.
387:                 */
388:                protected Object createLob(PreparedStatement ps, boolean clob,
389:                        LobCallback callback) throws SQLException {
390:
391:                    Connection con = null;
392:                    try {
393:                        con = getOracleConnection(ps);
394:                        initOracleDriverClasses(con);
395:                        Object lob = prepareLob(con, clob ? clobClass
396:                                : blobClass);
397:                        callback.populateLob(lob);
398:                        lob.getClass().getMethod("close", (Class[]) null)
399:                                .invoke(lob, (Object[]) null);
400:                        this .createdLobs.add(lob);
401:                        if (logger.isDebugEnabled()) {
402:                            logger.debug("Created new Oracle "
403:                                    + (clob ? "CLOB" : "BLOB"));
404:                        }
405:                        return lob;
406:                    } catch (SQLException ex) {
407:                        throw ex;
408:                    } catch (InvocationTargetException ex) {
409:                        if (ex.getTargetException() instanceof  SQLException) {
410:                            throw (SQLException) ex.getTargetException();
411:                        } else if (con != null
412:                                && ex.getTargetException() instanceof  ClassCastException) {
413:                            throw new InvalidDataAccessApiUsageException(
414:                                    "OracleLobCreator needs to work on [oracle.jdbc.OracleConnection], not on ["
415:                                            + con.getClass().getName()
416:                                            + "]: specify a corresponding NativeJdbcExtractor",
417:                                    ex.getTargetException());
418:                        } else {
419:                            throw new DataAccessResourceFailureException(
420:                                    "Could not create Oracle LOB", ex
421:                                            .getTargetException());
422:                        }
423:                    } catch (Exception ex) {
424:                        throw new DataAccessResourceFailureException(
425:                                "Could not create Oracle LOB", ex);
426:                    }
427:                }
428:
429:                /**
430:                 * Retrieve the underlying OracleConnection, using a NativeJdbcExtractor if set.
431:                 */
432:                protected Connection getOracleConnection(PreparedStatement ps)
433:                        throws SQLException, ClassNotFoundException {
434:
435:                    return (nativeJdbcExtractor != null) ? nativeJdbcExtractor
436:                            .getNativeConnectionFromStatement(ps) : ps
437:                            .getConnection();
438:                }
439:
440:                /**
441:                 * Create and open an oracle.sql.BLOB/CLOB instance via reflection.
442:                 */
443:                protected Object prepareLob(Connection con, Class lobClass)
444:                        throws Exception {
445:                    /*
446:                    BLOB blob = BLOB.createTemporary(con, false, BLOB.DURATION_SESSION);
447:                    blob.open(BLOB.MODE_READWRITE);
448:                    return blob;
449:                     */
450:                    Method createTemporary = lobClass.getMethod(
451:                            "createTemporary", new Class[] { Connection.class,
452:                                    boolean.class, int.class });
453:                    Object lob = createTemporary.invoke(null,
454:                            new Object[] { con, cache,
455:                                    durationSessionConstants.get(lobClass) });
456:                    Method open = lobClass.getMethod("open",
457:                            new Class[] { int.class });
458:                    open.invoke(lob, new Object[] { modeReadWriteConstants
459:                            .get(lobClass) });
460:                    return lob;
461:                }
462:
463:                /**
464:                 * Free all temporary BLOBs and CLOBs created by this creator.
465:                 */
466:                public void close() {
467:                    try {
468:                        for (Iterator it = this .createdLobs.iterator(); it
469:                                .hasNext();) {
470:                            /*
471:                            BLOB blob = (BLOB) it.next();
472:                            blob.freeTemporary();
473:                             */
474:                            Object lob = it.next();
475:                            Method freeTemporary = lob.getClass().getMethod(
476:                                    "freeTemporary", new Class[0]);
477:                            freeTemporary.invoke(lob, new Object[0]);
478:                            it.remove();
479:                        }
480:                    } catch (InvocationTargetException ex) {
481:                        logger.error("Could not free Oracle LOB", ex
482:                                .getTargetException());
483:                    } catch (Exception ex) {
484:                        throw new DataAccessResourceFailureException(
485:                                "Could not free Oracle LOB", ex);
486:                    }
487:                }
488:            }
489:
490:            /**
491:             * Internal callback interface for use with createLob.
492:             */
493:            protected static interface LobCallback {
494:
495:                /**
496:                 * Populate the given BLOB or CLOB instance with content.
497:                 * @throws Exception any exception including InvocationTargetException
498:                 */
499:                void populateLob(Object lob) throws Exception;
500:            }
501:
502:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.