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.concurrency;
020
021import java.io.ByteArrayInputStream;
022import java.io.ByteArrayOutputStream;
023import java.nio.charset.Charset;
024import java.util.concurrent.Callable;
025
026import lucee.commons.io.IOUtil;
027import lucee.commons.lang.ExceptionUtil;
028import lucee.runtime.PageContext;
029import lucee.runtime.PageContextImpl;
030import lucee.runtime.config.ConfigImpl;
031import lucee.runtime.engine.ThreadLocalPageContext;
032import lucee.runtime.exp.PageException;
033import lucee.runtime.net.http.HttpServletResponseDummy;
034import lucee.runtime.net.http.ReqRspUtil;
035import lucee.runtime.thread.ThreadUtil;
036import lucee.runtime.type.Struct;
037import lucee.runtime.type.UDF;
038
039public class UDFCaller2<P> implements Callable<Data<P>> { 
040
041        private PageContext parent;
042        private PageContextImpl pc;
043        private ByteArrayOutputStream baos;
044        
045        private UDF udf;
046        private boolean doIncludePath;
047        private Object[] arguments;
048        private Struct namedArguments;
049        private P passed;
050
051
052        private UDFCaller2(PageContext parent) {
053                this.parent = parent;
054                this.baos = new ByteArrayOutputStream();
055                this.pc=ThreadUtil.clonePageContext(parent, baos, false, false, true);
056        }
057        
058        public UDFCaller2(PageContext parent, UDF udf, Object[] arguments,P passed, boolean doIncludePath) {
059                this(parent);
060                this.udf=udf;
061                this.arguments=arguments;
062                this.doIncludePath=doIncludePath;
063                this.passed=passed;
064        }
065        public UDFCaller2(PageContext parent, UDF udf,Struct namedArguments, P passed,boolean doIncludePath) {
066                this(parent);
067                this.udf=udf;
068                this.namedArguments=namedArguments;
069                this.doIncludePath=doIncludePath;
070                this.passed=passed;
071        }
072        
073        
074        
075        public final Data<P> call() throws PageException {
076                ThreadLocalPageContext.register(pc);
077                pc.getRootOut().setAllowCompression(false); // make sure content is not compressed
078                String str=null;
079                Object result=null;
080                try{
081                        if(namedArguments!=null) result=udf.callWithNamedValues(pc, namedArguments, doIncludePath);
082                        else result=udf.call(pc, arguments, doIncludePath);
083                        
084                } 
085                finally{
086                        try {
087                        HttpServletResponseDummy rsp=(HttpServletResponseDummy) pc.getHttpServletResponse();
088                        
089                        Charset cs = ReqRspUtil.getCharacterEncoding(pc,rsp);
090                        //if(enc==null) enc="ISO-8859-1";
091                        
092                        pc.getOut().flush(); //make sure content is flushed
093                        
094                        ((ConfigImpl)pc.getConfig()).getFactory().releasePageContext(pc);
095                                str=IOUtil.toString((new ByteArrayInputStream(baos.toByteArray())), cs); // TODO add support for none string content
096                        } 
097                        catch (Throwable e) {
098                ExceptionUtil.rethrowIfNecessary(e);
099                                // TODO Auto-generated catch block
100                                e.printStackTrace();
101                        }
102                }
103                return new Data<P>(str,result,passed);
104        }
105}