001 package railo.runtime.tag; 002 003 import java.io.IOException; 004 005 import javax.xml.parsers.FactoryConfigurationError; 006 007 import railo.runtime.converter.ConverterException; 008 import railo.runtime.converter.JSConverter; 009 import railo.runtime.converter.WDDXConverter; 010 import railo.runtime.exp.ApplicationException; 011 import railo.runtime.exp.ExpressionException; 012 import railo.runtime.exp.PageException; 013 import railo.runtime.ext.tag.TagImpl; 014 import railo.runtime.op.Caster; 015 016 /** 017 * Serializes and de-serializes CFML data structures to the XML-based WDDX format. 018 * Generates JavaScript statements to instantiate JavaScript objects equivalent to the contents of a 019 * WDDX packet or some CFML data structures. 020 * 021 * 022 * 023 **/ 024 public final class Wddx extends TagImpl { 025 026 /** The value to be processed. */ 027 private Object input; 028 029 /** Specifies the action taken by the cfwddx tag. */ 030 private String action; 031 032 /** The name of the variable to hold the output of the operation. This attribute is required for 033 ** action = 'WDDX2CFML'. For all other actions, if this attribute is not provided, the result of the 034 ** WDDX processing is outputted in the HTML stream. */ 035 private String output; 036 037 private boolean validate; 038 039 /** The name of the top-level JavaScript object created by the deserialization process. The object 040 ** created is an instance of the WddxRecordset object, explained in WddxRecordset Object. */ 041 private String toplevelvariable; 042 043 /** Indicates whether to output time-zone information when serializing CFML to WDDX. If time-zone 044 ** information is taken into account, the hour-minute offset, as represented in the ISO8601 format, is 045 ** calculated in the date-time output. If time-zone information is not taken into account, the local 046 ** time is output. The default is Yes. */ 047 private boolean usetimezoneinfo; 048 049 private boolean xmlConform; 050 051 @Override 052 public void release() { 053 super.release(); 054 input=null; 055 action=null; 056 output=null; 057 validate=false; 058 toplevelvariable=null; 059 usetimezoneinfo=false; 060 xmlConform=false; 061 } 062 063 064 /** set the value input 065 * The value to be processed. 066 * @param input value to set 067 **/ 068 public void setInput(Object input) { 069 this.input=input; 070 } 071 072 /** set the value action 073 * Specifies the action taken by the cfwddx tag. 074 * @param action value to set 075 **/ 076 public void setAction(String action) { 077 this.action=action.toLowerCase(); 078 } 079 080 /** set the value output 081 * The name of the variable to hold the output of the operation. This attribute is required for 082 * action = 'WDDX2CFML'. For all other actions, if this attribute is not provided, the result of the 083 * WDDX processing is outputted in the HTML stream. 084 * @param output value to set 085 **/ 086 public void setOutput(String output) { 087 this.output=output; 088 } 089 090 /** set the value validate 091 * 092 * @param validate value to set 093 **/ 094 public void setValidate(boolean validate) { 095 this.validate=validate; 096 } 097 098 /** set the value toplevelvariable 099 * The name of the top-level JavaScript object created by the deserialization process. The object 100 * created is an instance of the WddxRecordset object, explained in WddxRecordset Object. 101 * @param toplevelvariable value to set 102 **/ 103 public void setToplevelvariable(String toplevelvariable) { 104 this.toplevelvariable=toplevelvariable; 105 } 106 107 /** set the value usetimezoneinfo 108 * Indicates whether to output time-zone information when serializing CFML to WDDX. If time-zone 109 * information is taken into account, the hour-minute offset, as represented in the ISO8601 format, is 110 * calculated in the date-time output. If time-zone information is not taken into account, the local 111 * time is output. The default is Yes. 112 * @param usetimezoneinfo value to set 113 **/ 114 public void setUsetimezoneinfo(boolean usetimezoneinfo) { 115 this.usetimezoneinfo=usetimezoneinfo; 116 } 117 118 /** 119 * sets if generated code is xml or wddx conform 120 * @param xmlConform 121 */ 122 public void setXmlconform(boolean xmlConform) { 123 this.xmlConform=xmlConform; 124 } 125 126 127 @Override 128 public int doStartTag() throws PageException { 129 try { 130 doIt(); 131 132 } catch (Exception e) { 133 throw Caster.toPageException(e); 134 } 135 return SKIP_BODY; 136 } 137 private void doIt() throws ExpressionException, PageException, ConverterException, IOException, FactoryConfigurationError { 138 // cfml > wddx 139 if(action.equals("cfml2wddx")) { 140 if(output!=null) pageContext.setVariable(output,cfml2wddx(input)); 141 else pageContext.forceWrite(cfml2wddx(input)); 142 } 143 144 // wddx > cfml 145 else if(action.equals("wddx2cfml")) { 146 if(output==null) throw new ApplicationException("at tag cfwddx the attribute output is required if you set action==wddx2cfml"); 147 pageContext.setVariable(output,wddx2cfml(Caster.toString(input))); 148 } 149 150 // cfml > js 151 else if(action.equals("cfml2js")) { 152 if(output!=null) pageContext.setVariable(output,cfml2js(input)); 153 else pageContext.forceWrite(cfml2js(input)); 154 } 155 156 // wddx > js 157 else if(action.equals("wddx2js")) { 158 if(output!=null) pageContext.setVariable(output,wddx2js(Caster.toString(input))); 159 else pageContext.forceWrite(wddx2js(Caster.toString(input))); 160 } 161 162 163 else throw new ExpressionException("invalid attribute action for tag cfwddx, attributes are [cfml2wddx, wddx2cfml,cfml2js, wddx2js]."); 164 165 } 166 167 private String cfml2wddx(Object input) throws ConverterException { 168 WDDXConverter converter =new WDDXConverter(pageContext.getTimeZone(),xmlConform,true); 169 if(!usetimezoneinfo)converter.setTimeZone(null); 170 return converter.serialize(input); 171 } 172 private Object wddx2cfml(String input) throws ConverterException, IOException, FactoryConfigurationError { 173 WDDXConverter converter =new WDDXConverter(pageContext.getTimeZone(),xmlConform,true); 174 converter.setTimeZone(pageContext.getTimeZone()); 175 return converter.deserialize(input,validate); 176 } 177 private String cfml2js(Object input) throws ConverterException { 178 if(toplevelvariable==null)missingTopLevelVariable(); 179 JSConverter converter =new JSConverter(); 180 return converter.serialize(input,toplevelvariable); 181 } 182 private String wddx2js(String input) throws ConverterException, IOException, FactoryConfigurationError { 183 if(toplevelvariable==null)missingTopLevelVariable(); 184 JSConverter converter =new JSConverter(); 185 return converter.serialize(wddx2cfml(input),toplevelvariable); 186 } 187 188 189 private ApplicationException missingTopLevelVariable() { 190 return new ApplicationException("at tag cfwddx the attribute topLevelVariable is required if you set action equal wddx2js or cfml2js"); 191 } 192 193 194 @Override 195 public int doEndTag() { 196 return EVAL_PAGE; 197 } 198 }