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 coldfusion.cfc; 020 021import java.io.File; 022import java.io.IOException; 023import java.io.OutputStream; 024import java.io.Serializable; 025import java.util.HashMap; 026import java.util.Iterator; 027import java.util.Map; 028import java.util.Map.Entry; 029 030import javax.servlet.http.HttpServletRequest; 031import javax.servlet.http.HttpServletResponse; 032 033import lucee.loader.engine.CFMLEngine; 034import lucee.loader.engine.CFMLEngineFactory; 035import lucee.runtime.Component; 036import lucee.runtime.PageContext; 037import lucee.runtime.exp.PageException; 038import lucee.runtime.type.Collection.Key; 039import lucee.runtime.type.Struct; 040import lucee.runtime.util.Cast; 041import lucee.runtime.util.Creation; 042 043 044public class CFCProxy { 045 046 private CFMLEngine engine; 047 private Cast caster; 048 private Creation creator; 049 050 private Component cfc=null; 051 private String path; 052 private Map thisData; 053 private boolean invokeDirectly=true; 054 private boolean autoFlush; 055 056 public CFCProxy(String path) throws Throwable { 057 this(path, null, true); 058 } 059 060 public CFCProxy(String path, boolean invokeDirectly) throws Throwable { 061 this(path, null, invokeDirectly); 062 } 063 064 public CFCProxy(String path, Map initialThis) throws Throwable { 065 this(path, initialThis, true); 066 } 067 068 public CFCProxy(String path, Map initialThis, boolean invokeDirectly) throws Throwable { 069 engine = CFMLEngineFactory.getInstance(); 070 caster = engine.getCastUtil(); 071 creator = engine.getCreationUtil(); 072 073 this.path=path; 074 this.invokeDirectly=invokeDirectly; 075 setThisScope(initialThis); 076 } 077 078 private void initCFC(PageContext pc) { 079 if(cfc==null && (invokeDirectly || pc!=null)) { 080 try { 081 if(pc==null)pc=engine.getThreadPageContext(); 082 cfc=engine.getCreationUtil().createComponentFromPath(pc, path); 083 } catch (PageException pe) {} 084 } 085 } 086 087 public void setThisScope(Map data) { 088 if(data!=null) { 089 if(thisData==null)this.thisData=new HashMap(); 090 091 Iterator<Entry> it = data.entrySet().iterator(); 092 Entry entry; 093 while(it.hasNext()){ 094 entry = it.next(); 095 thisData.put(entry.getKey(), entry.getValue()); 096 } 097 } 098 } 099 100 public Map getThisScope() { 101 initCFC(null); 102 if(cfc==null)return null; 103 104 Struct rtn=creator.createStruct(); 105 Iterator<Entry<Key, Object>> it = cfc.entryIterator(); 106 Entry<Key, Object> entry; 107 while(it.hasNext()){ 108 entry = it.next(); 109 rtn.setEL(entry.getKey(), entry.getValue()); 110 } 111 return rtn; 112 } 113 114 public final Object invoke(String methodName, Object args[]) throws Throwable { 115 if(invokeDirectly) return _invoke(methodName, args); 116 return _invoke(methodName, args, null, null, null); 117 } 118 119 public final Object invoke(String methodName, Object args[], HttpServletRequest request, HttpServletResponse response) throws Throwable { 120 if(invokeDirectly) return _invoke(methodName, args); 121 return _invoke(methodName, args, request, response, null); 122 } 123 124 public final Object invoke(String methodName, Object args[], HttpServletRequest request, HttpServletResponse response, OutputStream out) throws Throwable { 125 if(invokeDirectly) return _invoke(methodName, args); 126 return _invoke(methodName, args, request, response, out); 127 } 128 129 public static boolean inInvoke() { 130 return false; 131 } 132 133 private Object _invoke(String methodName, Object[] args) throws PageException { 134 CFMLEngine engine = CFMLEngineFactory.getInstance(); 135 PageContext pc = engine.getThreadPageContext(); 136 initCFC(pc); 137 return cfc.call(pc, methodName, args); 138 } 139 140 private Object _invoke(String methodName, Object[] args, HttpServletRequest req, HttpServletResponse rsp, OutputStream out) throws PageException { 141 CFMLEngine engine = CFMLEngineFactory.getInstance(); 142 Creation creator = engine.getCreationUtil(); 143 PageContext originalPC = engine.getThreadPageContext(); 144 145 // no OutputStream 146 if(out==null)out=DevNullOutputStream.DEV_NULL_OUTPUT_STREAM; 147 148 // no Request 149 if(req==null){ 150 // TODO new File 151 req=creator.createHttpServletRequest(new File("."), "Lucee", "/", "", null, null, null, null, null); 152 } 153 // noRespone 154 if(rsp==null){ 155 rsp=creator.createHttpServletResponse(out); 156 } 157 158 159 PageContext pc = creator.createPageContext(req,rsp,out); 160 try{ 161 engine.registerThreadPageContext(pc); 162 initCFC(pc); 163 return cfc.call(pc, methodName, args); 164 } 165 finally{ 166 if(autoFlush) { 167 try { 168 pc.getRootWriter().flush(); 169 } catch (Throwable t) { 170 if(t instanceof ThreadDeath) throw (ThreadDeath)t; 171 } 172 } 173 engine.registerThreadPageContext(originalPC); 174 } 175 } 176 177 public void flush() throws IOException { 178 CFMLEngine engine = CFMLEngineFactory.getInstance(); 179 PageContext pc = engine.getThreadPageContext(); 180 pc.getRootWriter().flush(); 181 } 182 183 public void setAutoFlush(boolean autoFlush) { 184 this.autoFlush = autoFlush; 185 } 186 187 public void setApplicationExecution(boolean doApp) 188 { 189 //executeApplication = doApp; 190 } 191 192} 193 194final class DevNullOutputStream extends OutputStream implements Serializable { 195 196 public static final DevNullOutputStream DEV_NULL_OUTPUT_STREAM=new DevNullOutputStream(); 197 198 /** 199 * Constructor of the class 200 */ 201 private DevNullOutputStream() {} 202 203 /** 204 * @see java.io.OutputStream#close() 205 */ 206 public void close(){} 207 208 /** 209 * @see java.io.OutputStream#flush() 210 */ 211 public void flush() {} 212 213 /** 214 * @see java.io.OutputStream#write(byte[], int, int) 215 */ 216 public void write(byte[] b, int off, int len) {} 217 218 /** 219 * @see java.io.OutputStream#write(byte[]) 220 */ 221 public void write(byte[] b) {} 222 223 /** 224 * @see java.io.OutputStream#write(int) 225 */ 226 public void write(int b) {} 227 228}