1 16 package org.apache.cocoon.acting; 17 18 import java.io.BufferedInputStream ; 19 import java.io.ByteArrayInputStream ; 20 import java.io.File ; 21 import java.io.FileInputStream ; 22 import java.io.InputStream ; 23 import java.math.BigDecimal ; 24 import java.sql.Array ; 25 import java.sql.Clob ; 26 import java.sql.Date ; 27 import java.sql.PreparedStatement ; 28 import java.sql.ResultSet ; 29 import java.sql.SQLException ; 30 import java.sql.Time ; 31 import java.sql.Timestamp ; 32 import java.sql.Types ; 33 import java.text.DateFormat ; 34 import java.text.SimpleDateFormat ; 35 import java.util.Collections ; 36 import java.util.HashMap ; 37 import java.util.Map ; 38 39 import org.apache.avalon.excalibur.datasource.DataSourceComponent; 40 import org.apache.avalon.framework.activity.Disposable; 41 import org.apache.avalon.framework.configuration.Configurable; 42 import org.apache.avalon.framework.configuration.Configuration; 43 import org.apache.avalon.framework.configuration.ConfigurationException; 44 import org.apache.avalon.framework.parameters.Parameters; 45 import org.apache.avalon.framework.service.ServiceException; 46 import org.apache.avalon.framework.service.ServiceManager; 47 import org.apache.avalon.framework.service.ServiceSelector; 48 import org.apache.cocoon.environment.Request; 49 import org.apache.cocoon.util.ImageProperties; 50 import org.apache.cocoon.util.ImageUtils; 51 52 174 public abstract class AbstractDatabaseAction extends AbstractComplementaryConfigurableAction implements Configurable, Disposable { 175 protected Map files = new HashMap (); 176 protected static final Map typeConstants; 177 protected ServiceSelector dbselector; 178 179 static { 180 183 Map constants = new HashMap (); 184 constants.put("ascii", new Integer (Types.CLOB)); 185 constants.put("big-decimal", new Integer (Types.BIGINT)); 186 constants.put("binary", new Integer (Types.BLOB)); 187 constants.put("byte", new Integer (Types.TINYINT)); 188 constants.put("string", new Integer (Types.VARCHAR)); 189 constants.put("date", new Integer (Types.DATE)); 190 constants.put("double", new Integer (Types.DOUBLE)); 191 constants.put("float", new Integer (Types.FLOAT)); 192 constants.put("int", new Integer (Types.INTEGER)); 193 constants.put("long", new Integer (Types.NUMERIC)); 194 constants.put("short", new Integer (Types.SMALLINT)); 195 constants.put("time", new Integer (Types.TIME)); 196 constants.put("time-stamp", new Integer (Types.TIMESTAMP)); 197 constants.put("now", new Integer (Types.LONGVARBINARY)); 198 constants.put("image",new Integer (Types.BLOB)); 203 constants.put("image-width",new Integer (Types.INTEGER)); 204 constants.put("image-height",new Integer (Types.INTEGER)); 205 constants.put("image-size",new Integer (Types.INTEGER)); 206 constants.put("row-index",new Integer (Types.INTEGER)); 207 constants.put("image-mime-type",new Integer (Types.VARCHAR)); 208 constants.put("array", new Integer (Types.ARRAY)); 209 constants.put("row", new Integer (Types.STRUCT)); 210 constants.put("object", new Integer (Types.OTHER)); 211 typeConstants = Collections.unmodifiableMap(constants); 212 } 213 214 217 public void service(ServiceManager manager) throws ServiceException { 218 super.service(manager); 219 this.dbselector = (ServiceSelector) manager.lookup(DataSourceComponent.ROLE + "Selector"); 220 } 221 224 protected final DataSourceComponent getDataSource(Configuration conf) throws ServiceException { 225 Configuration dsn = conf.getChild("connection"); 226 return (DataSourceComponent) this.dbselector.select(dsn.getValue("")); 227 } 228 229 232 protected final boolean isLargeObject (String type) { 233 if ("ascii".equals(type)) return true; 234 if ("binary".equals(type)) return true; 235 if ("image".equals(type)) return true; 236 237 return false; 238 } 239 240 243 protected Object getColumn(ResultSet set, Request request, Configuration entry) 244 throws Exception { 245 Integer type = (Integer ) AbstractDatabaseAction.typeConstants.get(entry.getAttribute("type")); 246 String attribute = entry.getAttribute("param", ""); 247 String dbcol = entry.getAttribute("dbcol", ""); 248 Object value = null; 249 250 switch (type.intValue()) { 251 case Types.CLOB: 252 Clob dbClob = set.getClob(dbcol); 253 int length = (int) dbClob.length(); 254 InputStream asciiStream = new BufferedInputStream (dbClob.getAsciiStream()); 255 byte[] buffer = new byte[length]; 256 asciiStream.read(buffer); 257 String str = new String (buffer); 258 asciiStream.close(); 259 value = str; 260 break; 261 case Types.BIGINT: 262 value = set.getBigDecimal(dbcol); 263 break; 264 case Types.TINYINT: 265 value = new Byte (set.getByte(dbcol)); 266 break; 267 case Types.VARCHAR: 268 value = set.getString(dbcol); 269 break; 270 case Types.DATE: 271 value = set.getDate(dbcol); 272 break; 273 case Types.DOUBLE: 274 value = new Double (set.getDouble(dbcol)); 275 break; 276 case Types.FLOAT: 277 value = new Float (set.getFloat(dbcol)); 278 break; 279 case Types.INTEGER: 280 value = new Integer (set.getInt(dbcol)); 281 break; 282 case Types.NUMERIC: 283 value = new Long (set.getLong(dbcol)); 284 break; 285 case Types.SMALLINT: 286 value = new Short (set.getShort(dbcol)); 287 break; 288 case Types.TIME: 289 value = set.getTime(dbcol); 290 break; 291 case Types.TIMESTAMP: 292 value = set.getTimestamp(dbcol); 293 break; 294 case Types.ARRAY: 295 value = set.getArray(dbcol); 296 break; 297 case Types.BIT: 298 value = new Integer (set.getInt(dbcol)); 299 break; 300 case Types.CHAR: 301 value = new Integer (set.getInt(dbcol)); 302 break; 303 case Types.STRUCT: 304 value = set.getObject(dbcol); 305 break; 306 case Types.OTHER: 307 value = set.getObject(dbcol); 308 break; 309 310 default: 311 value = ""; 313 break; 314 } 315 316 setRequestAttribute(request,attribute,value); 317 318 return value; 319 } 320 321 330 protected void setColumn(PreparedStatement statement, int position, Request request, Configuration entry) 331 throws Exception { 332 setColumn(statement,position,request,entry,entry.getAttribute("param","")); 333 } 334 335 351 protected void setColumn(PreparedStatement statement, int position, Request request, Configuration entry, String param) 352 throws Exception { 353 Object value = request.getParameter(param); 354 if (value == null) value = request.getAttribute(param); 355 if (value == null) value = request.get(param); 356 setColumn(statement,position,request,entry,param,value); 357 } 358 359 369 protected void setColumn(PreparedStatement statement, int position, Request request, Configuration entry, String param, Object value) throws Exception { 370 setColumn(statement,position,request,entry,param,value,0); 371 } 372 373 384 protected void setColumn(PreparedStatement statement, int position, Request request, Configuration entry, String param, Object value, int rowIndex) throws Exception { 385 getLogger().debug("Setting column "+position+" named "+param+" with value "+value); 386 if (value instanceof String ) { 387 value = ((String ) value).trim(); 388 } 389 String typeName = entry.getAttribute("type"); 390 Integer typeObject = (Integer ) AbstractDatabaseAction.typeConstants.get(typeName); 391 if (typeObject == null) { 392 throw new SQLException ("Can't set column because the type "+typeName+" is unrecognized"); 393 } 394 if (value == null) { 395 396 if (typeName.equals("image-width") || typeName.equals("image-height") || typeName.equals("image-size") || typeName.equals("row-index") || typeName.equals("image-mime-type")) { 397 398 } else { 399 statement.setNull(position, typeObject.intValue()); 400 return; 401 } 402 } 403 if ("".equals(value)) { 404 switch (typeObject.intValue()) { 405 case Types.CHAR: 406 case Types.CLOB: 407 case Types.VARCHAR: 408 410 break; 411 case Types.INTEGER: 412 if (typeName.equals("image-width") || typeName.equals("image-height") || typeName.equals("image-size") || typeName.equals("row-index")) { 413 414 break; 415 } 416 default: 417 419 statement.setNull(position, typeObject.intValue()); 420 return; 421 } 422 } 423 424 427 setRequestAttribute(request,param,value); 428 File file; 429 430 switch (typeObject.intValue()) { 431 case Types.CLOB: 432 int length = -1; 433 InputStream asciiStream = null; 434 435 if (value instanceof File ) { 436 File asciiFile = (File ) value; 437 asciiStream = new BufferedInputStream (new FileInputStream (asciiFile)); 438 length = (int) asciiFile.length(); 439 } else { 440 String asciiText = (String ) value; 441 asciiStream = new BufferedInputStream (new ByteArrayInputStream (asciiText.getBytes())); 442 length = asciiText.length(); 443 } 444 445 statement.setAsciiStream(position, asciiStream, length); 446 break; 447 case Types.BIGINT: 448 BigDecimal bd = null; 449 450 if (value instanceof BigDecimal ) { 451 bd = (BigDecimal ) value; 452 } else { 453 bd = new BigDecimal ((String ) value); 454 } 455 456 statement.setBigDecimal(position, bd); 457 break; 458 case Types.TINYINT: 459 Byte b = null; 460 461 if (value instanceof Byte ) { 462 b = (Byte ) value; 463 } else { 464 b = new Byte ((String ) value); 465 } 466 467 statement.setByte(position, b.byteValue()); 468 break; 469 case Types.DATE: 470 Date d = null; 471 472 if (value instanceof Date ) { 473 d = (Date ) value; 474 } else if (value instanceof java.util.Date ) { 475 d = new Date (((java.util.Date ) value).getTime()); 476 } else { 477 d = new Date (this.dateValue((String ) value, entry.getAttribute("format", "M/d/yyyy"))); 478 } 479 480 statement.setDate(position, d); 481 break; 482 case Types.DOUBLE: 483 Double db = null; 484 485 if (value instanceof Double ) { 486 db = (Double ) value; 487 } else { 488 db = new Double ((String ) value); 489 } 490 491 statement.setDouble(position, db.doubleValue()); 492 break; 493 case Types.FLOAT: 494 Float f = null; 495 496 if (value instanceof Float ) { 497 f = (Float ) value; 498 } else { 499 f = new Float ((String ) value); 500 } 501 502 statement.setFloat(position, f.floatValue()); 503 break; 504 case Types.NUMERIC: 505 Long l = null; 506 507 if (value instanceof Long ) { 508 l = (Long ) value; 509 } else { 510 l = new Long ((String ) value); 511 } 512 513 statement.setLong(position, l.longValue()); 514 break; 515 case Types.SMALLINT: 516 Short s = null; 517 518 if (value instanceof Short ) { 519 s = (Short ) value; 520 } else { 521 s = new Short ((String ) value); 522 } 523 524 statement.setShort(position, s.shortValue()); 525 break; 526 case Types.TIME: 527 Time t = null; 528 529 if (value instanceof Time ) { 530 t = (Time ) value; 531 } else { 532 t = new Time (this.dateValue((String ) value, entry.getAttribute("format", "h:m:s a"))); 533 } 534 535 statement.setTime(position, t); 536 break; 537 case Types.TIMESTAMP: 538 Timestamp ts = null; 539 540 if (value instanceof Time ) { 541 ts = (Timestamp ) value; 542 } else { 543 ts = new Timestamp (this.dateValue((String ) value, entry.getAttribute("format", "M/d/yyyy h:m:s a"))); 544 } 545 546 statement.setTimestamp(position, ts); 547 break; 548 case Types.ARRAY: 549 statement.setArray(position, (Array ) value); break; 551 case Types.STRUCT: 552 case Types.OTHER: 553 statement.setObject(position, value); 554 break; 555 case Types.LONGVARBINARY: 556 statement.setTimestamp(position, new Timestamp ((new java.util.Date ()).getTime())); 557 break; 558 case Types.VARCHAR: 559 if ("string".equals(typeName)) { 560 statement.setString(position, (String ) value); 561 break; 562 } else if ("image-mime-type".equals(typeName)) { 563 String imageAttr = param.substring(0, (param.length() - "-mime-type".length())); 564 file = (File ) request.get(imageAttr); 565 synchronized (this.files) { 566 Parameters parameters = (Parameters) this.files.get(file); 567 String imageMimeType = parameters.getParameter("image-mime-type", 568 (String ) settings.get("image-mime-type","")); 569 statement.setString(position, imageMimeType); 570 572 setRequestAttribute(request, param, imageMimeType); 573 } 574 break; 575 } 576 case Types.BLOB: 577 if (value instanceof File ) { 578 file = (File )value; 579 } else if (value instanceof String ) { 580 file = new File ((String )value); 581 } else { 582 throw new SQLException ("Invalid type for blob: "+value.getClass().getName()); 583 } 584 FileInputStream input = new FileInputStream (file); 586 statement.setBinaryStream(position, input, (int)file.length()); 587 if ("image".equals(typeName)) { 588 590 Parameters parameters = new Parameters(); 591 parameters.setParameter("image-size", Long.toString(file.length())); 592 ImageProperties prop = ImageUtils.getImageProperties(file); 593 parameters.setParameter("image-width", Integer.toString(prop.width)); 594 parameters.setParameter("image-height", Integer.toString(prop.height)); 595 parameters.setParameter("image-mime-type",prop.type); 597 synchronized (this.files) { 598 this.files.put(file, parameters); 599 } 600 } 601 break; 602 case Types.INTEGER: 603 if ("int".equals(typeName)) { 604 Integer i = null; 605 if (value instanceof Integer ) { 606 i = (Integer ) value; 607 } else { 608 i = new Integer ((String ) value); 609 } 610 statement.setInt(position, i.intValue()); 611 break; 612 } else if ("image-width".equals(typeName)) { 613 614 616 String imageAttr = param.substring(0, (param.length() - "-width".length())); 617 file = (File ) request.get(imageAttr); 618 synchronized (this.files) { 619 Parameters parameters = (Parameters) this.files.get(file); 620 statement.setInt(position, parameters.getParameterAsInteger("image-width", 621 Integer.parseInt((String )settings.get("image-width","-1")))); 622 624 setRequestAttribute(request, 625 param, 626 parameters.getParameter("image-width", 627 (String ) settings.get("image-width",""))); 628 } 629 break; 630 } else if ("image-height".equals(typeName)) { 631 632 String imageAttr = param.substring(0, (param.length() - "-height".length())); 633 file = (File ) request.get(imageAttr); 634 synchronized (this.files) { 635 Parameters parameters = (Parameters) this.files.get(file); 636 statement.setInt(position, parameters.getParameterAsInteger("image-height", 637 Integer.parseInt((String )settings.get("image-height","-1")))); 638 setRequestAttribute(request, 639 param, 640 parameters.getParameter("image-height", 641 (String ) settings.get("image-height",""))); 642 } 643 break; 644 } else if ("image-size".equals(typeName)) { 645 646 String imageAttr = param.substring(0, (param.length() - "-size".length())); 647 file = (File ) request.get(imageAttr); 648 synchronized (this.files) { 649 Parameters parameters = (Parameters) this.files.get(file); 650 statement.setInt(position, parameters.getParameterAsInteger("image-size", 651 Integer.parseInt((String )settings.get("image-height","-1")))); 652 setRequestAttribute(request, 653 param, 654 parameters.getParameter("image-size", 655 (String ) settings.get("image-size",""))); 656 } 657 break; 658 } else if ("row-index".equals(typeName)) { 659 statement.setInt(position,rowIndex); 660 break; 661 } 662 default: 663 throw new SQLException ("Impossible exception - invalid type "+typeName); 664 } 665 } 666 667 670 private final long dateValue(String value, String format) throws Exception { 671 DateFormat formatter = new SimpleDateFormat (format); 672 return formatter.parse(value).getTime(); 673 } 674 675 678 public void dispose() { 679 this.manager.release(dbselector); 680 } 681 682 686 protected void setRequestAttribute(Request request, String key, Object value) { 687 request.setAttribute("org.apache.cocoon.acting.AbstractDatabaseAction:"+key,value); 688 } 689 690 693 protected Object getRequestAttribute(Request request, String key) { 694 return request.getAttribute("org.apache.cocoon.acting.AbstractDatabaseAction:"+key); 695 } 696 697 704 protected StringBuffer buildList(Configuration[] values, String separator) throws ConfigurationException { 705 StringBuffer buffer = new StringBuffer (); 706 for (int i = 0; i < values.length; i++) { 707 if (i > 0) { 708 buffer.append(separator); 709 } 710 buffer.append(values[i].getAttribute("dbcol")); 711 buffer.append(" = ?"); 712 } 713 return buffer; 714 } 715 716 723 protected StringBuffer buildList(Configuration[] values, int begin) throws ConfigurationException { 724 StringBuffer buffer = new StringBuffer (); 725 int length = values.length; 726 boolean prependComma = begin > 0; 727 for (int i = 0; i < length; i++) { 728 if (prependComma) { 729 buffer.append(", "); 730 } else { 731 prependComma = true; 732 } 733 buffer.append(values[i].getAttribute("dbcol")); 734 } 735 return buffer; 736 } 737 } 738 | Popular Tags |