001 package railo.runtime.converter; 002 003 import java.io.IOException; 004 import java.io.Serializable; 005 import java.util.Date; 006 import java.util.HashSet; 007 import java.util.Iterator; 008 import java.util.List; 009 import java.util.ListIterator; 010 import java.util.Map; 011 import java.util.Set; 012 013 import org.w3c.dom.Node; 014 015 import railo.commons.lang.StringUtil; 016 import railo.runtime.Component; 017 import railo.runtime.ComponentScope; 018 import railo.runtime.ComponentWrap; 019 import railo.runtime.component.Property; 020 import railo.runtime.exp.ExpressionException; 021 import railo.runtime.exp.PageException; 022 import railo.runtime.functions.displayFormatting.DateFormat; 023 import railo.runtime.functions.displayFormatting.TimeFormat; 024 import railo.runtime.op.Caster; 025 import railo.runtime.orm.hibernate.HBMCreator; 026 import railo.runtime.text.xml.XMLCaster; 027 import railo.runtime.type.Array; 028 import railo.runtime.type.Collection; 029 import railo.runtime.type.KeyImpl; 030 import railo.runtime.type.ObjectWrap; 031 import railo.runtime.type.Query; 032 import railo.runtime.type.Struct; 033 import railo.runtime.type.UDF; 034 import railo.runtime.type.cfc.ComponentAccess; 035 import railo.runtime.type.dt.DateTime; 036 import railo.runtime.type.dt.DateTimeImpl; 037 import railo.runtime.type.dt.TimeSpan; 038 import railo.runtime.type.util.ComponentUtil; 039 040 /** 041 * class to serialize and desirilize WDDX Packes 042 */ 043 public final class ScriptConverter { 044 private static final Collection.Key REMOTING_FETCH = KeyImpl.intern("remotingFetch"); 045 046 private int deep=1; 047 private boolean ignoreRemotingFetch=true; 048 049 /** 050 * constructor of the class 051 */ 052 public ScriptConverter() { 053 } 054 public ScriptConverter(boolean ignoreRemotingFetch) { 055 this.ignoreRemotingFetch=ignoreRemotingFetch; 056 } 057 058 059 /** 060 * serialize Serializable class 061 * @param serializable 062 * @param sb 063 * @throws ConverterException 064 */ 065 private void _serializeSerializable(Serializable serializable, StringBuffer sb) throws ConverterException { 066 067 sb.append(goIn()); 068 sb.append("evaluateJava('"); 069 try { 070 sb.append(JavaConverter.serialize(serializable)); 071 } catch (IOException e) { 072 throw new ConverterException(e); 073 } 074 sb.append("')"); 075 076 } 077 078 /** 079 * serialize a Date 080 * @param date Date to serialize 081 * @param sb 082 * @throws ConverterException 083 */ 084 private void _serializeDate(Date date, StringBuffer sb) throws ConverterException { 085 _serializeDateTime(new DateTimeImpl(date),sb); 086 } 087 /** 088 * serialize a DateTime 089 * @param dateTime DateTime to serialize 090 * @param sb 091 * @throws ConverterException 092 */ 093 private void _serializeDateTime(DateTime dateTime, StringBuffer sb) throws ConverterException { 094 095 096 try { 097 sb.append(goIn()); 098 sb.append("createDateTime("); 099 sb.append(DateFormat.call(null,dateTime,"yyyy,m,d")); 100 sb.append(','); 101 sb.append(TimeFormat.call(null,dateTime,"H,m,s,l,\"z\"")); 102 sb.append(')'); 103 } 104 catch (PageException e) { 105 throw new ConverterException(e); 106 } 107 } 108 109 /** 110 * serialize a Array 111 * @param array Array to serialize 112 * @param sb 113 * @param done 114 * @throws ConverterException 115 */ 116 private void _serializeArray(Array array, StringBuffer sb, Set<Object> done) throws ConverterException { 117 _serializeList(array.toList(),sb,done); 118 } 119 120 /** 121 * serialize a List (as Array) 122 * @param list List to serialize 123 * @param sb 124 * @param done 125 * @throws ConverterException 126 */ 127 private void _serializeList(List list, StringBuffer sb, Set<Object> done) throws ConverterException { 128 129 sb.append(goIn()); 130 sb.append("["); 131 boolean doIt=false; 132 ListIterator it=list.listIterator(); 133 while(it.hasNext()) { 134 if(doIt)sb.append(','); 135 doIt=true; 136 _serialize(it.next(),sb,done); 137 } 138 139 sb.append(']'); 140 } 141 142 /** 143 * serialize a Struct 144 * @param struct Struct to serialize 145 * @param sb 146 * @param done 147 * @throws ConverterException 148 */ 149 public void _serializeStruct(Struct struct, StringBuffer sb, Set<Object> done) throws ConverterException { 150 sb.append(goIn()); 151 sb.append('{'); 152 Iterator it=struct.keyIterator(); 153 boolean doIt=false; 154 deep++; 155 while(it.hasNext()) { 156 String key=Caster.toString(it.next(),""); 157 if(doIt)sb.append(','); 158 doIt=true; 159 sb.append('\''); 160 sb.append(escape(key)); 161 sb.append('\''); 162 sb.append(':'); 163 _serialize(struct.get(key,null),sb,done); 164 } 165 deep--; 166 167 sb.append('}'); 168 } 169 170 public String serializeStruct(Struct struct, Set ignoreSet) throws ConverterException { 171 StringBuffer sb =new StringBuffer(); 172 sb.append(goIn()); 173 sb.append("struct("); 174 boolean hasIgnores=ignoreSet!=null; 175 Iterator it=struct.keyIterator(); 176 boolean doIt=false; 177 deep++; 178 while(it.hasNext()) { 179 String key=Caster.toString(it.next(),""); 180 if(hasIgnores && ignoreSet.contains(key.toLowerCase())) continue; 181 if(doIt)sb.append(','); 182 doIt=true; 183 sb.append('\''); 184 sb.append(escape(key)); 185 sb.append('\''); 186 sb.append(':'); 187 _serialize(struct.get(key,null),sb,new HashSet<Object>()); 188 } 189 deep--; 190 191 return sb.append(')').toString(); 192 } 193 194 /** 195 * serialize a Map (as Struct) 196 * @param map Map to serialize 197 * @param sb 198 * @param done 199 * @throws ConverterException 200 */ 201 private void _serializeMap(Map map, StringBuffer sb, Set<Object> done) throws ConverterException { 202 sb.append(goIn()); 203 sb.append("struct("); 204 205 Iterator it=map.keySet().iterator(); 206 boolean doIt=false; 207 deep++; 208 while(it.hasNext()) { 209 Object key=it.next(); 210 if(doIt)sb.append(','); 211 doIt=true; 212 sb.append('\''); 213 sb.append(escape(key.toString())); 214 sb.append('\''); 215 sb.append(':'); 216 _serialize(map.get(key),sb,done); 217 } 218 deep--; 219 220 sb.append(')'); 221 } 222 /** 223 * serialize a Component 224 * @param component Component to serialize 225 * @param sb 226 * @param done 227 * @throws ConverterException 228 */ 229 private void _serializeComponent(Component c, StringBuffer sb, Set<Object> done) throws ConverterException { 230 231 ComponentAccess ci; 232 try { 233 ci = ComponentUtil.toComponentAccess(c); 234 } catch (ExpressionException ee) { 235 throw new ConverterException(ee.getMessage()); 236 } 237 ComponentWrap cw = new ComponentWrap(Component.ACCESS_PRIVATE,ci); 238 239 240 sb.append(goIn()); 241 try { 242 sb.append("evaluateComponent('"+c.getAbsName()+"','"+ComponentUtil.md5(ci)+"',struct("); 243 } catch (Exception e) { 244 throw new ConverterException(e); 245 } 246 247 boolean doIt=false; 248 Iterator it=cw.keyIterator(); 249 Object member; 250 deep++; 251 while(it.hasNext()) { 252 String key=Caster.toString(it.next(),""); 253 member = cw.get(key,null); 254 if(member instanceof UDF)continue; 255 if(doIt)sb.append(','); 256 doIt=true; 257 sb.append('\''); 258 sb.append(escape(key)); 259 sb.append('\''); 260 sb.append(':'); 261 _serialize(member,sb,done); 262 } 263 sb.append(")"); 264 deep--; 265 266 if(true){ 267 boolean isPeristent=ci.isPersistent(); 268 269 ComponentScope scope = ci.getComponentScope(); 270 it=scope.keyIterator(); 271 sb.append(",struct("); 272 deep++; 273 doIt=false; 274 Property p; 275 Boolean remotingFetch; 276 Struct props = ignoreRemotingFetch?null:ComponentUtil.getPropertiesAsStruct(ci,false); 277 while(it.hasNext()) { 278 String key=Caster.toString(it.next(),""); 279 if("this".equalsIgnoreCase(key))continue; 280 281 if(!ignoreRemotingFetch) { 282 p=(Property) props.get(key,null); 283 if(p!=null) { 284 remotingFetch=Caster.toBoolean(p.getDynamicAttributes().get(REMOTING_FETCH,null),null); 285 if(remotingFetch==null){ 286 if(isPeristent && HBMCreator.isRelated(p)) continue; 287 } 288 else if(!remotingFetch.booleanValue()) continue; 289 } 290 } 291 292 293 294 member = scope.get(key,null); 295 if(member instanceof UDF)continue; 296 if(doIt)sb.append(','); 297 doIt=true; 298 sb.append('\''); 299 sb.append(escape(key)); 300 sb.append('\''); 301 sb.append(':'); 302 _serialize(member,sb,done); 303 } 304 sb.append(")"); 305 deep--; 306 } 307 308 sb.append(")"); 309 //sb.append(""); 310 //throw new ConverterException("can't serialize a component "+component.getDisplayName()); 311 } 312 313 /** 314 * serialize a Query 315 * @param query Query to serialize 316 * @param sb 317 * @param done 318 * @throws ConverterException 319 */ 320 private void _serializeQuery(Query query, StringBuffer sb, Set<Object> done) throws ConverterException { 321 322 String[] keys = query.keysAsString(); 323 sb.append(goIn()); 324 sb.append("query("); 325 326 327 deep++; 328 boolean oDoIt=false; 329 int len=query.getRecordcount(); 330 for(int i=0;i<keys.length;i++) { 331 if(oDoIt)sb.append(','); 332 oDoIt=true; 333 sb.append(goIn()); 334 sb.append('\''); 335 sb.append(escape(keys[i])); 336 sb.append('\''); 337 sb.append(":["); 338 boolean doIt=false; 339 for(int y=1;y<=len;y++) { 340 if(doIt)sb.append(','); 341 doIt=true; 342 try { 343 _serialize(query.getAt(keys[i],y),sb,done); 344 } catch (PageException e) { 345 _serialize(e.getMessage(),sb,done); 346 } 347 } 348 sb.append(']'); 349 } 350 deep--; 351 352 sb.append(')'); 353 354 } 355 356 /** 357 * serialize a Object to his xml Format represenation 358 * @param object Object to serialize 359 * @param sb StringBuffer to write data 360 * @param done 361 * @throws ConverterException 362 */ 363 private void _serialize(Object object, StringBuffer sb, Set<Object> done) throws ConverterException { 364 //try { 365 deep++; 366 // NULL 367 if(object==null) { 368 sb.append(goIn()); 369 sb.append("nullValue()"); 370 deep--; 371 return; 372 } 373 // String 374 if(object instanceof String) { 375 sb.append(goIn()); 376 sb.append("'"); 377 sb.append(escape(object.toString())); 378 sb.append("'"); 379 deep--; 380 return; 381 } 382 // Number 383 if(object instanceof Number) { 384 sb.append(goIn()); 385 sb.append(Caster.toString(((Number)object).doubleValue())); 386 deep--; 387 return; 388 } 389 // Boolean 390 if(object instanceof Boolean) { 391 sb.append(goIn()); 392 sb.append(Caster.toString(((Boolean)object).booleanValue())); 393 deep--; 394 return; 395 } 396 // DateTime 397 if(object instanceof DateTime) { 398 _serializeDateTime((DateTime)object,sb); 399 deep--; 400 return; 401 } 402 // Date 403 if(object instanceof Date) { 404 _serializeDate((Date)object,sb); 405 deep--; 406 return; 407 } 408 // XML 409 if(object instanceof Node) { 410 _serializeXML((Node)object,sb); 411 deep--; 412 return; 413 } 414 if(object instanceof ObjectWrap) { 415 try { 416 _serialize(((ObjectWrap)object).getEmbededObject(), sb,done); 417 } catch (PageException e) { 418 throw new ConverterException(e); 419 } 420 deep--; 421 return; 422 } 423 // Timespan 424 if(object instanceof TimeSpan) { 425 _serializeTimeSpan((TimeSpan) object,sb); 426 deep--; 427 return; 428 } 429 Object raw = LazyConverter.toRaw(object); 430 if(done.contains(raw)) { 431 sb.append(goIn()); 432 sb.append("nullValue()"); 433 deep--; 434 return; 435 } 436 437 done.add(raw); 438 try { 439 // Component 440 if(object instanceof Component) { 441 _serializeComponent((Component)object,sb,done); 442 deep--; 443 return; 444 } 445 446 // Struct 447 if(object instanceof Struct) { 448 _serializeStruct((Struct)object,sb,done); 449 deep--; 450 return; 451 } 452 // Map 453 if(object instanceof Map) { 454 _serializeMap((Map)object,sb,done); 455 deep--; 456 return; 457 } 458 // Array 459 if(object instanceof Array) { 460 _serializeArray((Array)object,sb,done); 461 deep--; 462 return; 463 } 464 // List 465 if(object instanceof List) { 466 _serializeList((List)object,sb,done); 467 deep--; 468 return; 469 } 470 // Query 471 if(object instanceof Query) { 472 _serializeQuery((Query)object,sb,done); 473 deep--; 474 return; 475 } 476 // String Converter 477 if(object instanceof ScriptConvertable) { 478 sb.append(((ScriptConvertable)object).serialize()); 479 deep--; 480 return; 481 } 482 if(object instanceof Serializable) { 483 _serializeSerializable((Serializable)object,sb); 484 deep--; 485 return; 486 } 487 } 488 finally { 489 done.remove(raw); 490 } 491 throw new ConverterException("can't serialize Object of type [ "+Caster.toClassName(object)+" ]"); 492 //deep--; 493 /*} 494 catch(StackOverflowError soe){ 495 throw soe; 496 }*/ 497 } 498 499 500 501 private void _serializeXML(Node node, StringBuffer sb) { 502 node=XMLCaster.toRawNode(node); 503 sb.append(goIn()); 504 sb.append("xmlParse('"); 505 sb.append(escape(XMLCaster.toString(node,""))); 506 sb.append("')"); 507 508 } 509 510 private void _serializeTimeSpan(TimeSpan span, StringBuffer sb) { 511 512 sb.append(goIn()); 513 sb.append("createTimeSpan("); 514 sb.append(span.getDay()); 515 sb.append(','); 516 sb.append(span.getHour()); 517 sb.append(','); 518 sb.append(span.getMinute()); 519 sb.append(','); 520 sb.append(span.getSecond()); 521 sb.append(')'); 522 523 } 524 525 526 private String escape(String str) { 527 return StringUtil.replace(StringUtil.replace(str,"'","''",false),"#","##",false); 528 } 529 530 /** 531 * serialize a Object to his literal Format 532 * @param object Object to serialize 533 * @return serialized wddx package 534 * @throws ConverterException 535 */ 536 public String serialize(Object object) throws ConverterException { 537 deep=0; 538 StringBuffer sb=new StringBuffer(); 539 _serialize(object,sb,new HashSet<Object>()); 540 return sb.toString(); 541 } 542 543 544 /** 545 * @return return current blockquote 546 */ 547 private String goIn() { 548 /*StringBuffer rtn=new StringBuffer('\n'); 549 for(int i=0;i<deep;i++) rtn.append('\t'); 550 return rtn.toString(); 551 /*/ 552 553 return ""; 554 } 555 556 557 }