1 package org.apache.ojb.broker.platforms; 2 3 17 18 import org.apache.ojb.broker.util.logging.Logger; 19 import org.apache.ojb.broker.util.logging.LoggerFactory; 20 import org.apache.ojb.broker.util.ClassHelper; 21 import org.apache.ojb.broker.util.sequence.SequenceManagerHelper; 22 23 import java.io.ByteArrayInputStream ; 24 import java.io.InputStreamReader ; 25 import java.io.Reader ; 26 import java.io.StringReader ; 27 import java.lang.reflect.Field ; 28 import java.security.AccessController ; 29 import java.security.PrivilegedAction ; 30 import java.sql.CallableStatement ; 31 import java.sql.Connection ; 32 import java.sql.DatabaseMetaData ; 33 import java.sql.PreparedStatement ; 34 import java.sql.SQLException ; 35 import java.sql.Statement ; 36 import java.sql.Types ; 37 import java.util.Properties ; 38 39 134 135 public class PlatformOracleImpl extends PlatformDefaultImpl 136 { 137 protected static final String THIN_URL_PREFIX = "jdbc:oracle:thin"; 138 protected static final int THIN_BLOB_MAX_SIZE = 2000; 140 protected static final int THIN_CLOB_MAX_SIZE = 4000; 142 143 147 protected static int ORACLE_JDBC_TYPE_CURSOR = -10; 148 149 private Logger logger = LoggerFactory.getLogger(PlatformOracleImpl.class); 150 151 154 public PlatformOracleImpl() 155 { 156 initOracleReflectedVars(); 157 } 158 159 164 public CallableStatement prepareNextValProcedureStatement(Connection con, String procedureName, String sequenceName) 165 throws PlatformException 166 { 167 try 168 { 169 String sp = "{?= call " + procedureName + " (?)}"; 170 CallableStatement cs = con.prepareCall(sp); 171 cs.registerOutParameter(1, Types.INTEGER); 172 cs.setString(2, sequenceName); 173 return cs; 174 } 175 catch (SQLException e) 176 { 177 throw new PlatformException(e); 178 } 179 } 180 181 184 public void afterStatementCreate(Statement stmt) throws PlatformException 185 { 186 try 187 { 188 stmt.setEscapeProcessing(true); 189 } 190 catch (SQLException e) 191 { 192 throw new PlatformException("Could not set escape processing", e); 193 } 194 } 195 196 204 public void setObjectForStatement(PreparedStatement ps, int index, Object value, int sqlType) 205 throws SQLException 206 { 207 if (((sqlType == Types.VARBINARY) || (sqlType == Types.LONGVARBINARY) || (sqlType == Types.BLOB)) 208 && (value instanceof byte[])) 209 { 210 byte buf[] = (byte[]) value; 211 int length = buf.length; 212 if (isUsingOracleThinDriver(ps.getConnection()) && length > THIN_BLOB_MAX_SIZE) 213 { 214 throw new SQLException ( 215 "Oracle thin driver cannot update BLOB values with length>2000. (Consider using Oracle9i as OJB platform.)"); 216 } 217 ByteArrayInputStream inputStream = new ByteArrayInputStream (buf); 218 changePreparedStatementResultSetType(ps); 219 ps.setBinaryStream(index, inputStream, length); 220 } 221 else if (value instanceof Double ) 222 { 223 ps.setDouble(index, ((Double ) value).doubleValue()); 225 } 226 else if (sqlType == Types.BIGINT && value instanceof Integer ) 227 { 228 ps.setLong(index, ((Integer ) value).intValue()); 230 } 231 else if (sqlType == Types.INTEGER && value instanceof Long ) 232 { 233 ps.setLong(index, ((Long ) value).longValue()); 234 } 235 else if (sqlType == Types.DATE && value instanceof String ) 236 { 237 ps.setString(index, (String ) value); 239 } 240 else if (sqlType == Types.CLOB && (value instanceof String || value instanceof byte[])) 241 { 242 Reader reader; 243 int length; 244 if (value instanceof String ) 245 { 246 String stringValue = (String ) value; 247 length = stringValue.length(); 248 reader = new StringReader (stringValue); 249 } 250 else 251 { 252 byte buf[] = (byte[]) value; 253 ByteArrayInputStream inputStream = new ByteArrayInputStream (buf); 254 reader = new InputStreamReader (inputStream); 255 length = buf.length; 256 } 257 if (isUsingOracleThinDriver(ps.getConnection()) && length > THIN_CLOB_MAX_SIZE) 258 { 259 throw new SQLException ( 260 "Oracle thin driver cannot insert CLOB values with length>4000. (Consider using Oracle9i as OJB platform.)"); 261 } 262 ps.setCharacterStream(index, reader, length); 263 } 264 else if ((sqlType == Types.CHAR || sqlType == Types.VARCHAR) 265 && 266 (value instanceof String || value instanceof Character )) 267 { 268 if (value instanceof String ) 269 { 270 ps.setString(index, (String ) value); 271 } 272 else { 274 ps.setString(index, value.toString()); 275 } 276 } 277 else 278 { 279 super.setObjectForStatement(ps, index, value, sqlType); 280 } 281 } 282 283 287 protected void changePreparedStatementResultSetType(PreparedStatement ps) 288 { 289 try 290 { 291 final Field f = ps.getClass().getSuperclass().getDeclaredField("m_userRsetType"); 292 AccessController.doPrivileged(new PrivilegedAction () 293 { 294 public Object run() 295 { 296 f.setAccessible(true); 297 return null; 298 } 299 }); 300 f.setInt(ps, 1); 301 f.setAccessible(false); 302 } 303 catch (Exception e) 304 { 305 logger.info("Not using classes12.zip."); 306 } 307 } 308 309 312 public byte getJoinSyntaxType() 313 { 314 return ORACLE_JOIN_SYNTAX; 315 } 316 317 public String createSequenceQuery(String sequenceName) 318 { 319 return "CREATE SEQUENCE " + sequenceName; 320 } 321 322 public String createSequenceQuery(String sequenceName, Properties prop) 323 { 324 334 StringBuffer query = new StringBuffer (createSequenceQuery(sequenceName)); 335 if(prop != null) 336 { 337 Boolean b; 338 Long value; 339 340 value = SequenceManagerHelper.getSeqIncrementBy(prop); 341 if(value != null) 342 { 343 query.append(" INCREMENT BY ").append(value.longValue()); 344 } 345 346 value = SequenceManagerHelper.getSeqStart(prop); 347 if(value != null) 348 { 349 query.append(" START WITH ").append(value.longValue()); 350 } 351 352 value = SequenceManagerHelper.getSeqMaxValue(prop); 353 if(value != null) 354 { 355 query.append(" MAXVALUE ").append(value.longValue()); 356 } 357 358 value = SequenceManagerHelper.getSeqMinValue(prop); 359 if(value != null) 360 { 361 query.append(" MINVALUE ").append(value.longValue()); 362 } 363 364 b = SequenceManagerHelper.getSeqCycleValue(prop); 365 if(b != null) 366 { 367 if(b.booleanValue()) query.append(" CYCLE"); 368 else query.append(" NOCYCLE"); 369 } 370 371 value = SequenceManagerHelper.getSeqCacheValue(prop); 372 if(value != null) 373 { 374 query.append(" CACHE ").append(value.longValue()); 375 } 376 377 b = SequenceManagerHelper.getSeqOrderValue(prop); 378 if(b != null) 379 { 380 if(b.booleanValue()) query.append(" ORDER"); 381 else query.append(" NOORDER"); 382 } 383 } 384 return query.toString(); 385 } 386 387 public String nextSequenceQuery(String sequenceName) 388 { 389 return "select " + sequenceName + ".nextval from dual"; 390 } 391 392 public String dropSequenceQuery(String sequenceName) 393 { 394 return "drop sequence " + sequenceName; 395 } 396 397 400 public void registerOutResultSet(CallableStatement stmt, int position) 401 throws SQLException 402 { 403 stmt.registerOutParameter(position, ORACLE_JDBC_TYPE_CURSOR); 404 } 405 406 413 protected static boolean isUsingOracleThinDriver(Connection conn) 414 { 415 if (conn == null) 416 { 417 return false; 418 } 419 final DatabaseMetaData dbMetaData; 420 final String dbUrl; 421 try 422 { 423 dbMetaData = conn.getMetaData(); 424 dbUrl = dbMetaData.getURL(); 425 if (dbUrl != null && dbUrl.startsWith(THIN_URL_PREFIX)) 426 { 427 return true; 428 } 429 } 430 catch (Exception e) 431 { 432 } 434 return false; 435 } 436 437 440 protected void initOracleReflectedVars() 441 { 442 try 443 { 444 final Class oracleTypes = ClassHelper.getClass("oracle.jdbc.OracleTypes", false); 446 final Field cursorField = oracleTypes.getField("CURSOR"); 447 ORACLE_JDBC_TYPE_CURSOR = cursorField.getInt(null); 448 } 449 catch (ClassNotFoundException e) 450 { 451 log.warn("PlatformOracleImpl could not find Oracle JDBC classes"); 452 } 453 catch (NoSuchFieldException e) 454 { 455 log.warn("PlatformOracleImpl could not find Oracle JDBC type fields"); 456 } 457 catch (IllegalAccessException e) 458 { 459 log.warn("PlatformOracleImpl could not get Oracle JDBC type values"); 460 } 461 } 462 463 } 464 | Popular Tags |