001/** 002 * 003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. 004 * 005 * This library is free software; you can redistribute it and/or 006 * modify it under the terms of the GNU Lesser General Public 007 * License as published by the Free Software Foundation; either 008 * version 2.1 of the License, or (at your option) any later version. 009 * 010 * This library is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 013 * Lesser General Public License for more details. 014 * 015 * You should have received a copy of the GNU Lesser General Public 016 * License along with this library. If not, see <http://www.gnu.org/licenses/>. 017 * 018 **/ 019package lucee.runtime.orm.hibernate; 020 021import java.io.BufferedReader; 022import java.io.BufferedWriter; 023import java.io.IOException; 024import java.io.InputStream; 025import java.io.InputStreamReader; 026import java.io.OutputStream; 027import java.io.OutputStreamWriter; 028import java.io.Reader; 029import java.io.Serializable; 030import java.io.StringWriter; 031import java.io.Writer; 032import java.lang.reflect.Method; 033import java.nio.charset.Charset; 034import java.sql.ResultSet; 035import java.util.ArrayList; 036import java.util.Iterator; 037import java.util.List; 038 039import javax.xml.parsers.FactoryConfigurationError; 040import javax.xml.parsers.ParserConfigurationException; 041 042import lucee.commons.io.res.Resource; 043import lucee.commons.lang.types.RefBoolean; 044import lucee.loader.engine.CFMLEngineFactory; 045import lucee.loader.util.Util; 046import lucee.runtime.Component; 047import lucee.runtime.MappingImpl; 048import lucee.runtime.PageContext; 049import lucee.runtime.component.Property; 050import lucee.runtime.component.PropertyImpl; 051import lucee.runtime.config.Config; 052import lucee.runtime.config.ConfigWebImpl; 053import lucee.runtime.db.DataSource; 054import lucee.runtime.db.DatasourceConnection; 055import lucee.runtime.db.SQL; 056import lucee.runtime.db.SQLItem; 057import lucee.runtime.db.SQLItemImpl; 058import lucee.runtime.engine.ThreadLocalPageContext; 059import lucee.runtime.exp.PageException; 060import lucee.runtime.op.Caster; 061import lucee.runtime.op.Operator; 062import lucee.runtime.orm.hibernate.tuplizer.proxy.ComponentProProxy; 063import lucee.runtime.text.xml.XMLUtil; 064import lucee.runtime.type.Array; 065import lucee.runtime.type.Collection; 066import lucee.runtime.type.Collection.Key; 067import lucee.runtime.type.Query; 068import lucee.runtime.type.QueryImpl; 069import lucee.runtime.type.Struct; 070import lucee.runtime.type.dt.DateTime; 071import lucee.runtime.type.scope.Argument; 072import lucee.runtime.type.util.ListUtil; 073import lucee.runtime.util.Cast; 074import lucee.runtime.util.Creation; 075import lucee.runtime.util.Decision; 076 077import org.hibernate.JDBCException; 078import org.hibernate.exception.ConstraintViolationException; 079import org.w3c.dom.Document; 080import org.w3c.dom.Node; 081import org.xml.sax.SAXException; 082 083public class CommonUtil { 084 085 public static final Key ENTITY_NAME = CommonUtil.createKey("entityname"); 086 public static final Key FIELDTYPE = CommonUtil.createKey("fieldtype"); 087 public static final Key POST_INSERT=CommonUtil.createKey("postInsert"); 088 public static final Key POST_UPDATE=CommonUtil.createKey("postUpdate"); 089 public static final Key PRE_DELETE=CommonUtil.createKey("preDelete"); 090 public static final Key POST_DELETE=CommonUtil.createKey("postDelete"); 091 public static final Key PRE_LOAD=CommonUtil.createKey("preLoad"); 092 public static final Key POST_LOAD=CommonUtil.createKey("postLoad"); 093 public static final Key PRE_UPDATE=CommonUtil.createKey("preUpdate"); 094 public static final Key PRE_INSERT=CommonUtil.createKey("preInsert"); 095 public static final Key INIT=CommonUtil.createKey("init"); 096 private static final short INSPECT_UNDEFINED = (short)4; /*ConfigImpl.INSPECT_UNDEFINED*/ 097 098 private static Charset charset; 099 100 public static final Charset UTF8; 101 public static final Charset ISO88591; 102 public static final Charset UTF16BE; 103 public static final Charset UTF16LE; 104 105 static { 106 UTF8=Charset.forName("utf-8"); 107 ISO88591=Charset.forName("iso-8859-1"); 108 UTF16BE=Charset.forName("utf-16BE"); 109 UTF16LE=Charset.forName("UTF-16LE"); 110 111 String strCharset=System.getProperty("file.encoding"); 112 if(strCharset==null || strCharset.equalsIgnoreCase("MacRoman")) 113 strCharset="cp1252"; 114 115 if(strCharset.equalsIgnoreCase("utf-8")) charset=UTF8; 116 else charset=Charset.forName(strCharset); 117 } 118 119 120 121 private static Cast caster; 122 private static Decision decision; 123 private static Creation creator; 124 125 126 public static Object castTo(PageContext pc, Class trgClass, Object obj) throws PageException { 127 return Caster.castTo(pc, trgClass, obj); 128 } 129 130 public static Array toArray(Object obj) throws PageException { 131 return caster().toArray(obj); 132 } 133 public static Array toArray(Object obj, Array defaultValue) { 134 return caster().toArray(obj,defaultValue); 135 } 136 137 public static Boolean toBoolean(String str) throws PageException { 138 return caster().toBoolean(str); 139 } 140 public static Boolean toBoolean(String str, Boolean defaultValue) { 141 return caster().toBoolean(str,defaultValue); 142 } 143 public static Boolean toBoolean(Object obj) throws PageException { 144 return caster().toBoolean(obj); 145 } 146 public static Boolean toBoolean(Object obj, Boolean defaultValue) { 147 return caster().toBoolean(obj,defaultValue); 148 } 149 150 public static Boolean toBooleanValue(String str) throws PageException { 151 return caster().toBooleanValue(str); 152 } 153 public static Boolean toBooleanValue(String str, Boolean defaultValue) { 154 return caster().toBooleanValue(str,defaultValue); 155 } 156 public static boolean toBooleanValue(Object obj) throws PageException { 157 return caster().toBooleanValue(obj); 158 } 159 public static boolean toBooleanValue(Object obj, boolean defaultValue) { 160 return caster().toBooleanValue(obj,defaultValue); 161 } 162 163 public static Component toComponent(Object obj) throws PageException { 164 return Caster.toComponent(obj); 165 } 166 public static Component toComponent(Object obj, Component defaultValue) { 167 return Caster.toComponent(obj,defaultValue); 168 } 169 170 public static Object toList(String[] arr, String delimiter) { 171 return ListUtil.arrayToList(arr, delimiter); 172 } 173 174 public static String toString(Object obj, String defaultValue) { 175 return caster().toString(obj,defaultValue); 176 } 177 public static String toString(Object obj) throws PageException { 178 return caster().toString(obj); 179 } 180 public static String toString(boolean b) { 181 return caster().toString(b); 182 } 183 public static String toString(double d) { 184 return caster().toString(d); 185 } 186 public static String toString(int i) { 187 return caster().toString(i); 188 } 189 public static String toString(long l) { 190 return caster().toString(l); 191 } 192 193 /** 194 * reads String data from File 195 * @param file 196 * @param charset 197 * @return readed string 198 * @throws IOException 199 */ 200 public static String toString(Resource file, Charset charset) throws IOException { 201 Reader r = null; 202 try { 203 r = getReader(file,charset); 204 String str = toString(r); 205 return str; 206 } 207 finally { 208 closeEL(r); 209 } 210 } 211 212 public static String toString(Reader reader) throws IOException { 213 StringWriter sw=new StringWriter(512); 214 copy(toBufferedReader(reader),sw); 215 sw.close(); 216 return sw.toString(); 217 } 218 219 public static BufferedReader toBufferedReader(Reader r) { 220 if(r instanceof BufferedReader) return (BufferedReader) r; 221 return new BufferedReader(r); 222 } 223 224 private static final void copy(Reader r, Writer w) throws IOException { 225 copy(r,w,0xffff); 226 } 227 228 private static final void copy(Reader r, Writer w, int blockSize) throws IOException { 229 char[] buffer = new char[blockSize]; 230 int len; 231 232 while((len = r.read(buffer)) !=-1) 233 w.write(buffer, 0, len); 234 } 235 236 public static Reader getReader(Resource res, Charset charset) throws IOException { 237 InputStream is=null; 238 try { 239 is = res.getInputStream(); 240 boolean markSupported=is.markSupported(); 241 if(markSupported) is.mark(4); 242 int first = is.read(); 243 int second = is.read(); 244 // FE FF UTF-16, big-endian 245 if (first == 0xFE && second == 0xFF) { 246 return _getReader(is, UTF16BE); 247 } 248 // FF FE UTF-16, little-endian 249 if (first == 0xFF && second == 0xFE) { 250 return _getReader(is, UTF16LE); 251 } 252 253 int third=is.read(); 254 // EF BB BF UTF-8 255 if (first == 0xEF && second == 0xBB && third == 0xBF) { 256 //is.reset(); 257 return _getReader(is,UTF8); 258 } 259 260 if(markSupported) { 261 is.reset(); 262 return _getReader(is,charset); 263 } 264 } 265 catch(IOException ioe) { 266 closeEL(is); 267 throw ioe; 268 } 269 270 // when mark not supported return new reader 271 closeEL(is); 272 is=null; 273 try { 274 is=res.getInputStream(); 275 } 276 catch(IOException ioe) { 277 closeEL(is); 278 throw ioe; 279 } 280 return _getReader(is, charset); 281 } 282 283 private static Reader _getReader(InputStream is, Charset cs) { 284 if(cs==null) cs=charset; 285 return new BufferedReader(new InputStreamReader(is,cs)); 286 } 287 288 public static String[] toStringArray(String list, char delimiter) { 289 return ListUtil.listToStringArray(list, delimiter); 290 } 291 public static String[] toStringArray(String list, String delimiter) { 292 return ListUtil.toStringArray(ListUtil.listToArray(list,delimiter),""); //TODO better 293 } 294 295 public static Integer toInteger(Object obj) throws PageException { 296 return caster().toInteger(obj); 297 } 298 public static Integer toInteger(Object obj, Integer defaultValue) { 299 return caster().toInteger(obj, defaultValue); 300 } 301 public static int toIntValue(Object obj) throws PageException { 302 return caster().toIntValue(obj); 303 } 304 public static int toIntValue(Object obj, int defaultValue) { 305 return caster().toIntValue(obj,defaultValue); 306 } 307 308 public static Array toArray(Argument arg) { 309 Array trg=createArray(); 310 int[] keys = arg.intKeys(); 311 for(int i=0;i<keys.length;i++){ 312 trg.setEL(keys[i], 313 arg.get(keys[i],null)); 314 } 315 return trg; 316 } 317 318 public static PageException toPageException(Throwable t) { 319 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 320 PageException pe = caster().toPageException(t);; 321 if (t instanceof org.hibernate.HibernateException) { 322 org.hibernate.HibernateException he = (org.hibernate.HibernateException)t; 323 Throwable cause = he.getCause(); 324 if(cause != null) { 325 pe = caster().toPageException( cause ); 326 ExceptionUtil.setAdditional(pe, CommonUtil.createKey("hibernate exception"), t ); 327 } 328 } 329 if ( t instanceof JDBCException ) { 330 JDBCException je = (JDBCException)t; 331 ExceptionUtil.setAdditional(pe, CommonUtil.createKey("sql"), je.getSQL()); 332 } 333 if( t instanceof ConstraintViolationException) { 334 ConstraintViolationException cve = (ConstraintViolationException)t; 335 if(!Util.isEmpty(cve.getConstraintName())) { 336 ExceptionUtil.setAdditional(pe, CommonUtil.createKey("constraint name"), cve.getConstraintName()); 337 } 338 } 339 return pe; 340 341 } 342 public static Serializable toSerializable(Object obj) throws PageException { 343 return caster().toSerializable(obj); 344 } 345 public static Serializable toSerializable(Object obj,Serializable defaultValue) { 346 return caster().toSerializable(obj,defaultValue); 347 } 348 349 public static Struct toStruct(Object obj) throws PageException { 350 return caster().toStruct(obj); 351 } 352 public static Struct toStruct(Object obj, Struct defaultValue) { 353 return caster().toStruct(obj,defaultValue); 354 } 355 356 public static SQLItem toSQLItem(Object value, int type) { 357 return new SQLItemImpl(value,type); 358 } 359 360 public static Object[] toNativeArray(Object obj) throws PageException { 361 return Caster.toNativeArray(obj); 362 } 363 364 public static String toTypeName(Object obj) { 365 return caster().toTypeName(obj); 366 } 367 public static Node toXML(Object obj) throws PageException { 368 return caster().toXML(obj); 369 } 370 public static Node toXML(Object obj, Node defaultValue) { 371 return caster().toXML(obj,defaultValue); 372 } 373 374 375 public static Document toDocument(Resource res, Charset cs) throws IOException, SAXException { 376 return XMLUtil.parse(XMLUtil.toInputSource(res,cs), null, false); 377 } 378 379 380 381 382 public static boolean isArray(Object obj) { 383 return decision().isArray(obj); 384 } 385 386 public static boolean isStruct(Object obj) { 387 return decision().isStruct(obj); 388 } 389 390 public static Array createArray(){ 391 return creator().createArray(); 392 } 393 394 public static DateTime createDateTime(long time) { 395 return creator().createDateTime(time); 396 } 397 398 public static Property createProperty(String name, String type) { 399 PropertyImpl pi = new PropertyImpl(); 400 pi.setName(name); 401 pi.setType(type); 402 return pi; 403 } 404 405 public static Struct createStruct(){ 406 return creator().createStruct(); 407 } 408 public static Collection.Key createKey(String key){ 409 return creator().createKey(key); 410 } 411 public static Query createQuery(Collection.Key[] columns, int rows, String name) throws PageException{ 412 return creator().createQuery(columns, rows, name); 413 } 414 public static Query createQuery(Array names, Array types, int rows, String name) throws PageException{ 415 return new QueryImpl(names,types,rows,name); 416 } 417 418 public static RefBoolean createRefBoolean() { 419 return new RefBooleanImpl(); 420 } 421 422 public static Key[] keys(Collection coll) { 423 if(coll==null) return new Key[0]; 424 Iterator<Key> it = coll.keyIterator(); 425 List<Key> rtn=new ArrayList<Key>(); 426 if(it!=null)while(it.hasNext()){ 427 rtn.add(it.next()); 428 } 429 return rtn.toArray(new Key[rtn.size()]); 430 } 431 432 433 434 private static Creation creator() { 435 if(creator==null) 436 creator=CFMLEngineFactory.getInstance().getCreationUtil(); 437 return creator; 438 } 439 440 private static Decision decision() { 441 if(decision==null) 442 decision=CFMLEngineFactory.getInstance().getDecisionUtil(); 443 return decision; 444 } 445 private static Cast caster() { 446 if(caster==null) 447 caster=CFMLEngineFactory.getInstance().getCastUtil(); 448 return caster; 449 } 450 451 452 /** 453 * represents a SQL Statement with his defined arguments for a prepared statement 454 */ 455 static class SQLImpl implements SQL { 456 457 private String strSQL; 458 459 /** 460 * Constructor only with SQL String 461 * @param strSQL SQL String 462 */ 463 public SQLImpl(String strSQL) { 464 this.strSQL=strSQL; 465 } 466 467 468 public void addItems(SQLItem item) { 469 470 } 471 472 @Override 473 public SQLItem[] getItems() { 474 return new SQLItem[0]; 475 } 476 477 @Override 478 public int getPosition() { 479 return 0; 480 } 481 482 @Override 483 public void setPosition(int position) { 484 } 485 486 487 @Override 488 public String getSQLString() { 489 return strSQL; 490 } 491 492 @Override 493 public void setSQLString(String strSQL) { 494 this.strSQL= strSQL; 495 } 496 497 @Override 498 public String toString() { 499 return strSQL; 500 } 501 502 @Override 503 public String toHashString() { 504 return strSQL; 505 } 506 } 507 508 /** 509 * Integer Type that can be modified 510 */ 511 public static final class RefBooleanImpl implements RefBoolean {//MUST add interface Castable 512 513 private boolean value; 514 515 516 public RefBooleanImpl() {} 517 518 /** 519 * @param value 520 */ 521 public RefBooleanImpl(boolean value) { 522 this.value=value; 523 } 524 525 /** 526 * @param value 527 */ 528 public void setValue(boolean value) { 529 this.value = value; 530 } 531 532 /** 533 * @return returns value as Boolean Object 534 */ 535 public Boolean toBoolean() { 536 return value?Boolean.TRUE:Boolean.FALSE; 537 } 538 539 /** 540 * @return returns value as boolean value 541 */ 542 public boolean toBooleanValue() { 543 return value; 544 } 545 546 @Override 547 public String toString() { 548 return value?"true":"false"; 549 } 550 } 551 552 public static DataSource getDataSource(PageContext pc, String name) throws PageException { 553 try{ 554 Method m = pc.getClass().getMethod("getDataSource", new Class[]{String.class}); 555 return (DataSource) m.invoke(pc, new Object[]{name}); 556 } 557 catch (Throwable t) { 558 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 559 throw caster().toPageException(t); 560 } 561 } 562 563 public static DatasourceConnection getDatasourceConnection(PageContext pc, DataSource ds) throws PageException { 564 return ((ConfigWebImpl)pc.getConfig()).getDatasourceConnectionPool().getDatasourceConnection(ds,null,null); // TODO use reflection 565 } 566 567 public static void releaseDatasourceConnection(PageContext pc, DatasourceConnection dc) { 568 ((ConfigWebImpl)pc.getConfig()).getDatasourceConnectionPool().releaseDatasourceConnection(pc.getConfig(),dc,true); // TODO use reflection 569 } 570 571 public static MappingImpl createMapping(Config config, String virtual, String physical) { 572 return new MappingImpl(config, 573 virtual, 574 physical, 575 null,INSPECT_UNDEFINED,true,false,false,false,true,true,null 576 ); 577 } 578 579 public static String last(String list, char delimiter) { 580 return ListUtil.last(list, delimiter); 581 } 582 583 public static String last(String list, String delimiter) { 584 return ListUtil.last(list, delimiter,true); 585 } 586 587 public static int listFindNoCaseIgnoreEmpty(String list, String value, char delimiter) { 588 return ListUtil.listFindNoCaseIgnoreEmpty(list,value,delimiter); 589 } 590 591 public static String[] trimItems(String[] arr) { 592 for(int i=0;i<arr.length;i++) { 593 arr[i]=arr[i].trim(); 594 } 595 return arr; 596 } 597 598 public static Document getDocument(Node node) { 599 return XMLUtil.getDocument(node); 600 } 601 public static Document newDocument() throws ParserConfigurationException, FactoryConfigurationError { 602 return XMLUtil.newDocument(); 603 } 604 public static void setFirst(Node parent, Node node) { 605 XMLUtil.setFirst(parent, node); 606 } 607 608 public static Property[] getProperties(Component c,boolean onlyPeristent, boolean includeBaseProperties, boolean preferBaseProperties, boolean inheritedMappedSuperClassOnly) { 609 return ComponentProProxy.getProperties(c, onlyPeristent, includeBaseProperties, preferBaseProperties, inheritedMappedSuperClassOnly); 610 } 611 612 public static void write(Resource res, String string, Charset cs, boolean append) throws IOException { 613 if(cs==null) cs=charset; 614 615 Writer writer=null; 616 try { 617 writer=getWriter(res, cs,append); 618 writer.write(string); 619 } 620 finally { 621 closeEL(writer); 622 } 623 } 624 625 public static Writer getWriter(Resource res, Charset charset, boolean append) throws IOException { 626 OutputStream os=null; 627 try { 628 os=res.getOutputStream(append); 629 } 630 catch(IOException ioe) { 631 closeEL(os); 632 throw ioe; 633 } 634 return getWriter(os, charset); 635 } 636 637 public static Writer getWriter(OutputStream os, Charset cs) { 638 if(cs==null) cs=charset; 639 return new BufferedWriter(new OutputStreamWriter(os,charset)); 640 } 641 642 public static BufferedReader toBufferedReader(Resource res, Charset charset) throws IOException { 643 return toBufferedReader(getReader(res,(Charset)null)); 644 } 645 646 public static boolean equalsComplexEL(Object left, Object right) { 647 return Operator.equalsComplexEL(left, right, false,true); 648 } 649 650 public static void setEntity(Component c, boolean entity) { 651 ComponentProProxy.setEntity(c,entity); 652 } 653 654 public static PageContext pc() { 655 //return CFMLEngineFactory.getInstance().getThreadPageContext(); 656 return ThreadLocalPageContext.get(); 657 } 658 659 public static Config config() { 660 //return CFMLEngineFactory.getInstance().getThreadPageContext().getConfig(); 661 return ThreadLocalPageContext.getConfig(); 662 } 663 664 public static boolean isPersistent(Component c) { 665 return ComponentProProxy.isPersistent(c); 666 } 667 668 public static Object getMetaStructItem(Component c, Key name) { 669 return ComponentProProxy.getMetaStructItem(c,name); 670 } 671 672 public static void closeEL(OutputStream os) { 673 if(os!=null) { 674 try { 675 os.close(); 676 } 677 catch (Throwable t) { 678 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 679 } 680 } 681 } 682 683 public static void closeEL(Writer w) { 684 if(w!=null) { 685 try { 686 w.close(); 687 } 688 catch (Throwable t) { 689 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 690 } 691 } 692 } 693 694 public static void closeEL(ResultSet rs) { 695 if(rs!=null) { 696 try { 697 rs.close(); 698 } 699 catch (Throwable t) { 700 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 701 } 702 } 703 } 704 705 public static void closeEL(InputStream is) { 706 try { 707 if(is!=null)is.close(); 708 } 709 catch (Throwable t) { 710 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 711 } 712 } 713 714 public static void closeEL(Reader r) { 715 try { 716 if(r!=null)r.close(); 717 } 718 catch (Throwable t) { 719 lucee.commons.lang.ExceptionUtil.rethrowIfNecessary(t); 720 } 721 } 722}