001: /*
002: * LobFileStatement.java
003: *
004: * This file is part of SQL Workbench/J, http://www.sql-workbench.net
005: *
006: * Copyright 2002-2008, Thomas Kellerer
007: * No part of this code maybe reused without the permission of the author
008: *
009: * To contact the author please send an email to: support@sql-workbench.net
010: *
011: */
012: package workbench.util;
013:
014: import java.io.BufferedInputStream;
015: import java.io.File;
016: import java.io.FileInputStream;
017: import java.io.FileNotFoundException;
018: import java.io.IOException;
019: import java.io.InputStream;
020: import java.io.Reader;
021: import java.sql.PreparedStatement;
022: import java.sql.SQLException;
023: import workbench.db.WbConnection;
024: import workbench.resource.ResourceMgr;
025:
026: /**
027: * A class to analyze the {$blobfile= } and {$clobfile= }
028: * parameters in a SQL statement. This class supports INSERT and UPDATE
029: * statements. To retrieve a blob from the database {@link workbench.sql.wbcommands.WbSelectBlob}
030: * has to be used.
031: * @author support@sql-workbench.net
032: */
033: public class LobFileStatement {
034: private final String MARKER = "\\{\\$[cb]lobfile=[^\\}]*\\}";
035: private String sqlToUse;
036: private LobFileParameter[] parameters;
037: private int parameterCount = 0;
038: private String baseDir;
039:
040: public LobFileStatement(String sql) throws FileNotFoundException {
041: this (sql, null);
042: }
043:
044: public LobFileStatement(String sql, String dir)
045: throws FileNotFoundException {
046: this .baseDir = dir;
047:
048: LobFileParameterParser p = new LobFileParameterParser(sql);
049:
050: this .parameters = p.getParameters();
051: if (this .parameters == null)
052: return;
053:
054: parameterCount = this .parameters.length;
055: for (int index = 0; index < parameterCount; index++) {
056: if (parameters[index] == null) {
057: String msg = ResourceMgr
058: .getString("ErrUpdateBlobSyntax");
059: throw new IllegalArgumentException(msg);
060: }
061:
062: if (parameters[index].getFilename() == null) {
063: String msg = ResourceMgr
064: .getString("ErrUpdateBlobNoFileParameter");
065: throw new FileNotFoundException(msg);
066: }
067: File f = new File(parameters[index].getFilename());
068:
069: if (!f.isAbsolute() && this .baseDir != null) {
070: f = new File(this .baseDir, parameters[index]
071: .getFilename());
072: parameters[index].setFilename(f.getAbsolutePath());
073: }
074:
075: if (f.isDirectory() || !f.exists()) {
076: String msg = ResourceMgr.getFormattedString(
077: "ErrFileNotFound", parameters[index]
078: .getFilename());
079: throw new FileNotFoundException(msg);
080: }
081: }
082: this .sqlToUse = sql.replaceAll(MARKER, " ? ");
083: //LogMgr.logDebug("LobFileStatement.<init>", "Using SQL: " + sqlToUse);
084: }
085:
086: public String getPreparedSql() {
087: return sqlToUse;
088: }
089:
090: public LobFileParameter[] getParameters() {
091: return parameters;
092: }
093:
094: public int getParameterCount() {
095: return parameterCount;
096: }
097:
098: public boolean containsParameter() {
099: return (parameterCount > 0);
100: }
101:
102: public PreparedStatement prepareStatement(WbConnection conn)
103: throws SQLException, IOException {
104: if (this .parameters == null)
105: return null;
106: if (this .parameters.length == 0)
107: return null;
108: PreparedStatement pstmt = conn.getSqlConnection()
109: .prepareStatement(sqlToUse);
110: final int buffSize = 64 * 1024;
111: for (int i = 0; i < parameters.length; i++) {
112: File f = new File(parameters[i].getFilename());
113: int length = (int) f.length();
114: if (parameters[i].isBinary()) {
115: InputStream in = new BufferedInputStream(
116: new FileInputStream(f), buffSize);
117: parameters[i].setDataStream(in);
118: pstmt.setBinaryStream(i + 1, in, length);
119: } else if (parameters[i].getEncoding() == null) {
120: InputStream in = new BufferedInputStream(
121: new FileInputStream(f), buffSize);
122: parameters[i].setDataStream(in);
123: pstmt.setAsciiStream(i + 1, in, length);
124: } else {
125: Reader in = EncodingUtil.createBufferedReader(f,
126: parameters[i].getEncoding());
127: parameters[i].setDataStream(in);
128: // The value of the length parameter is actually wrong if
129: // a multi-byte encoding is used. So far only Derby seems to choke
130: // on this, so we need to calculate the file length in characters
131: // which is probably very slow so this is not turned on by default.
132: if (conn.getDbSettings().needsExactClobLength()) {
133: length = (int) FileUtil.getCharacterLength(f,
134: parameters[i].getEncoding());
135: }
136: pstmt.setCharacterStream(i + 1, in, length);
137: }
138: }
139: return pstmt;
140: }
141:
142: public void done() {
143: if (this .parameters == null)
144: return;
145:
146: for (int i = 0; i < parameters.length; i++) {
147: if (parameters[i] != null) {
148: parameters[i].close();
149: }
150: }
151: }
152:
153: }
|