/** * * Copyright (c) 2014, the Railo Company Ltd. All rights reserved. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see <http://www.gnu.org/licenses/>. * **/ package coldfusion.cfc; import java.io.File; import java.io.IOException; import java.io.OutputStream; import java.io.Serializable; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Map.Entry; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import lucee.loader.engine.CFMLEngine; import lucee.loader.engine.CFMLEngineFactory; import lucee.runtime.Component; import lucee.runtime.PageContext; import lucee.runtime.exp.PageException; import lucee.runtime.type.Collection.Key; import lucee.runtime.type.Struct; import lucee.runtime.util.Cast; import lucee.runtime.util.Creation; public class CFCProxy { private final CFMLEngine engine; private final Cast caster; private final Creation creator; private Component cfc = null; private final String path; private Map thisData; private boolean invokeDirectly = true; private boolean autoFlush; public CFCProxy(final String path) throws Throwable { this(path, null, true); } public CFCProxy(final String path, final boolean invokeDirectly) throws Throwable { this(path, null, invokeDirectly); } public CFCProxy(final String path, final Map initialThis) throws Throwable { this(path, initialThis, true); } public CFCProxy(final String path, final Map initialThis, final boolean invokeDirectly) throws Throwable { engine = CFMLEngineFactory.getInstance(); caster = engine.getCastUtil(); creator = engine.getCreationUtil(); this.path = path; this.invokeDirectly = invokeDirectly; setThisScope(initialThis); } private void initCFC(PageContext pc) { if (cfc == null && (invokeDirectly || pc != null)) try { if (pc == null) pc = engine.getThreadPageContext(); cfc = engine.getCreationUtil() .createComponentFromPath(pc, path); } catch (final PageException pe) { } } @SuppressWarnings("rawtypes") public void setThisScope(final Map data) { if (data != null) { if (thisData == null) this.thisData = new HashMap(); final Iterator<Entry> it = data.entrySet().iterator(); Entry entry; while (it.hasNext()) { entry = it.next(); thisData.put(entry.getKey(), entry.getValue()); } } } @SuppressWarnings("rawtypes") public Map getThisScope() { initCFC(null); if (cfc == null) return null; final Struct rtn = creator.createStruct(); final Iterator<Entry<Key, Object>> it = cfc.entryIterator(); Entry<Key, Object> entry; while (it.hasNext()) { entry = it.next(); rtn.setEL(entry.getKey(), entry.getValue()); } return rtn; } public final Object invoke(final String methodName, final Object args[]) throws Throwable { if (invokeDirectly) return _invoke(methodName, args); return _invoke(methodName, args, null, null, null); } public final Object invoke(final String methodName, final Object args[], final HttpServletRequest request, final HttpServletResponse response) throws Throwable { if (invokeDirectly) return _invoke(methodName, args); return _invoke(methodName, args, request, response, null); } public final Object invoke(final String methodName, final Object args[], final HttpServletRequest request, final HttpServletResponse response, final OutputStream out) throws Throwable { if (invokeDirectly) return _invoke(methodName, args); return _invoke(methodName, args, request, response, out); } public static boolean inInvoke() { return false; } private Object _invoke(final String methodName, final Object[] args) throws PageException { final CFMLEngine engine = CFMLEngineFactory.getInstance(); final PageContext pc = engine.getThreadPageContext(); initCFC(pc); return cfc.call(pc, methodName, args); } private Object _invoke(final String methodName, final Object[] args, HttpServletRequest req, HttpServletResponse rsp, OutputStream out) throws PageException { final CFMLEngine engine = CFMLEngineFactory.getInstance(); final Creation creator = engine.getCreationUtil(); final PageContext originalPC = engine.getThreadPageContext(); // no OutputStream if (out == null) out = DevNullOutputStream.DEV_NULL_OUTPUT_STREAM; // no Request if (req == null) // TODO new File req = creator.createHttpServletRequest(new File("."), "Lucee", "/", "", null, null, null, null, null); // noRespone if (rsp == null) rsp = creator.createHttpServletResponse(out); final PageContext pc = creator.createPageContext(req, rsp, out); try { engine.registerThreadPageContext(pc); initCFC(pc); return cfc.call(pc, methodName, args); } finally { if (autoFlush) try { pc.getRootWriter().flush(); } catch (final Throwable t) { } engine.registerThreadPageContext(originalPC); } } public void flush() throws IOException { final CFMLEngine engine = CFMLEngineFactory.getInstance(); final PageContext pc = engine.getThreadPageContext(); pc.getRootWriter().flush(); } public void setAutoFlush(final boolean autoFlush) { this.autoFlush = autoFlush; } public void setApplicationExecution(final boolean doApp) { //executeApplication = doApp; } } final class DevNullOutputStream extends OutputStream implements Serializable { private static final long serialVersionUID = -4707810151743493285L; public static final DevNullOutputStream DEV_NULL_OUTPUT_STREAM = new DevNullOutputStream(); /** * Constructor of the class */ private DevNullOutputStream() { } /** * @see java.io.OutputStream#close() */ @Override public void close() { } /** * @see java.io.OutputStream#flush() */ @Override public void flush() { } /** * @see java.io.OutputStream#write(byte[], int, int) */ @Override public void write(final byte[] b, final int off, final int len) { } /** * @see java.io.OutputStream#write(byte[]) */ @Override public void write(final byte[] b) { } /** * @see java.io.OutputStream#write(int) */ @Override public void write(final int b) { } }