001    package railo.runtime.thread;
002    
003    import java.io.ByteArrayOutputStream;
004    import java.io.Serializable;
005    import java.util.ConcurrentModificationException;
006    
007    import javax.servlet.http.HttpServletRequest;
008    
009    import railo.commons.io.DevNullOutputStream;
010    import railo.commons.io.log.LogAndSource;
011    import railo.commons.lang.ExceptionUtil;
012    import railo.commons.lang.Pair;
013    import railo.runtime.Page;
014    import railo.runtime.PageContext;
015    import railo.runtime.PageContextImpl;
016    import railo.runtime.PageSourceImpl;
017    import railo.runtime.config.Config;
018    import railo.runtime.config.ConfigImpl;
019    import railo.runtime.config.ConfigWeb;
020    import railo.runtime.config.ConfigWebImpl;
021    import railo.runtime.engine.ThreadLocalPageContext;
022    import railo.runtime.exp.Abort;
023    import railo.runtime.exp.PageException;
024    import railo.runtime.net.http.HttpServletResponseDummy;
025    import railo.runtime.net.http.HttpUtil;
026    import railo.runtime.net.http.ReqRspUtil;
027    import railo.runtime.op.Caster;
028    import railo.runtime.type.Collection;
029    import railo.runtime.type.Collection.Key;
030    import railo.runtime.type.KeyImpl;
031    import railo.runtime.type.Scope;
032    import railo.runtime.type.Struct;
033    import railo.runtime.type.StructImpl;
034    import railo.runtime.type.scope.Argument;
035    import railo.runtime.type.scope.ArgumentPro;
036    import railo.runtime.type.scope.ArgumentThreadImpl;
037    import railo.runtime.type.scope.LocalImpl;
038    import railo.runtime.type.scope.Threads;
039    import railo.runtime.type.scope.Undefined;
040    
041    public class ChildThreadImpl extends ChildThread implements Serializable {
042    
043            private static final long serialVersionUID = -8902836175312356628L;
044    
045            private static final Collection.Key KEY_ATTRIBUTES = KeyImpl.intern("attributes");
046    
047            //private static final Set EMPTY = new HashSet(); 
048            
049            private int threadIndex;
050            private PageContextImpl parent;
051            PageContextImpl pc =null;
052            private String tagName;
053            private long start;
054            private Threads scope;
055            
056            // accesible from scope
057            Struct content=new StructImpl();
058            Struct catchBlock;
059            boolean terminated;
060            boolean completed;
061            ByteArrayOutputStream output;
062            
063            
064            // only used for type deamon
065            private Page page;
066            
067            // only used for type task, demon attrs are not Serializable
068            private Struct attrs;
069            private SerializableCookie[] cookies;
070            private String serverName;
071            private String queryString;
072            private Pair[] parameters;
073            private String requestURI;
074            private Pair[] headers;
075            private Struct attributes;
076            private String template;
077            private long requestTimeout;
078    
079            private boolean serializable;
080    
081            String contentType;
082    
083            String contentEncoding;
084            
085            
086            public ChildThreadImpl(PageContextImpl parent,Page page, String tagName,int threadIndex, Struct attrs, boolean serializable) {
087                    this.serializable=serializable;
088                    this.tagName=tagName;
089                    this.threadIndex=threadIndex;
090                    start=System.currentTimeMillis();
091                    if(attrs==null) this.attrs=new StructImpl();
092                    else this.attrs=attrs;
093                    
094                    
095                    if(!serializable){
096                            this.page=page;
097                            if(parent!=null){
098                                    output = new ByteArrayOutputStream();
099                                    try{
100                                            this.parent=ThreadUtil.clonePageContext(parent, output,false,false,true);
101                                    }
102                                    catch(ConcurrentModificationException e){// MUST search for:hhlhgiug
103                                            this.parent=ThreadUtil.clonePageContext(parent, output,false,false,true);
104                                    }
105                                    //this.parent=parent;
106                            }
107                    }
108                    else {
109                            this.template=page.getPageSource().getFullRealpath();
110                            HttpServletRequest req = parent.getHttpServletRequest();
111                            serverName=req.getServerName();
112                            queryString=req.getQueryString();
113                            cookies=SerializableCookie.toSerializableCookie(ReqRspUtil.getCookies(ThreadLocalPageContext.getConfig(parent),req));
114                            parameters=HttpUtil.cloneParameters(req);
115                            requestURI=req.getRequestURI();
116                            headers=HttpUtil.cloneHeaders(req);
117                            attributes=HttpUtil.getAttributesAsStruct(req);
118                            requestTimeout=parent.getRequestTimeout();
119                            // MUST here ist sill a mutch state values missing
120                    }
121            }
122    
123            public PageContext getPageContext(){
124                    return pc;
125            }
126            
127            
128            public void run()  {
129                    execute(null);
130            }
131            public PageException execute(Config config)   {
132                    PageContext oldPc = ThreadLocalPageContext.get();
133                    
134                    Page p=page;
135                    
136                    if(parent!=null){
137                            pc=parent;
138                            ThreadLocalPageContext.register(pc);
139                    }
140                    else {
141                            ConfigWebImpl cwi;
142                            try {
143                                    cwi = (ConfigWebImpl)config;
144                                    p=PageSourceImpl.loadPage(pc, cwi.getPageSources(oldPc,null, template, false,false,true));
145                                    //p=cwi.getPageSources(oldPc,null, template, false,false,true).loadPage(cwi);
146                            } catch (PageException e) {
147                                    return e;
148                            }
149                            DevNullOutputStream os = DevNullOutputStream.DEV_NULL_OUTPUT_STREAM;
150                            pc=ThreadUtil.createPageContext(cwi, os, serverName, requestURI, queryString, SerializableCookie.toCookies(cookies), headers, parameters, attributes);
151                            pc.setRequestTimeout(requestTimeout);pc.addPageSource(p.getPageSource(), true);
152                    }
153                    pc.setThreadScope("thread", new ThreadsImpl(this));
154                    pc.setThread(Thread.currentThread());
155                    
156                    //String encodings = pc.getHttpServletRequest().getHeader("Accept-Encoding");
157                    
158                    Undefined undefined=pc.us();
159                    
160                    ArgumentPro newArgs=new ArgumentThreadImpl((Struct) attrs.duplicate(false));//(ArgumentPro) pc.getScopeFactory().getArgumentInstance();// FUTURE
161            LocalImpl newLocal=pc.getScopeFactory().getLocalInstance();
162            Key[] keys = attrs.keys();
163                    for(int i=0;i<keys.length;i++){
164                            newArgs.setEL(keys[i],attrs.get(keys[i],null));
165                            //newLocal.setEL(keys[i],attrs.get(keys[i],null));
166                    }
167                    
168                    //print.out(newArgs);
169                    
170                    newLocal.setEL(KEY_ATTRIBUTES, newArgs);
171                    Argument oldArgs=pc.argumentsScope();
172            Scope oldLocal=pc.localScope();
173            
174            int oldMode=undefined.setMode(Undefined.MODE_LOCAL_OR_ARGUMENTS_ALWAYS);
175                    pc.setFunctionScopes(newLocal,newArgs);
176                    
177                    try {
178                            p.threadCall(pc, threadIndex); 
179                    }
180                    catch (Throwable t) {
181                            if(!Abort.isSilentAbort(t)) {
182                                    ConfigWeb c = pc.getConfig();
183                                    if(c instanceof ConfigImpl) {
184                                            ConfigImpl ci=(ConfigImpl) c;
185                                            LogAndSource log = ci.getThreadLogger();
186                                            if(log!=null)log.error(this.getName(), ExceptionUtil.getStacktrace(t,true));
187                                    }
188                                    PageException pe = Caster.toPageException(t);
189                                    if(!serializable)catchBlock=pe.getCatchBlock(pc);
190                                    return pe;
191                            }
192                    }
193                    finally {
194                            completed=true;
195                            pc.setFunctionScopes(oldLocal,oldArgs);
196                        undefined.setMode(oldMode);
197                        //pc.getScopeFactory().recycle(newArgs);
198                pc.getScopeFactory().recycle(newLocal);
199                
200                if(pc.getHttpServletResponse() instanceof HttpServletResponseDummy) {
201                        HttpServletResponseDummy rsp=(HttpServletResponseDummy) pc.getHttpServletResponse();
202                        pc.flush();
203                        contentType=rsp.getContentType();
204                        Pair[] _headers = rsp.getHeaders();
205                        if(_headers!=null)for(int i=0;i<_headers.length;i++){
206                            if(_headers[i].getName().equalsIgnoreCase("Content-Encoding"))
207                                    contentEncoding=Caster.toString(_headers[i].getValue(),null);
208                        }
209                }
210                
211                            ((ConfigImpl)pc.getConfig()).getFactory().releasePageContext(pc);
212                            pc=null;
213                            if(oldPc!=null)ThreadLocalPageContext.register(oldPc);
214                    }
215                    return null;
216            }
217    
218            /**
219             * @see railo.runtime.thread.ChildThread#getTagName()
220             */
221            public String getTagName() {
222                    return tagName;
223            }
224    
225            /**
226             * @see railo.runtime.thread.ChildThread#getStartTime()
227             */
228            public long getStartTime() {
229                    return start;
230            }
231    
232            /**
233             * @see railo.runtime.thread.ChildThread#getThreadScope()
234             */
235            public Threads getThreadScope() {
236                    if(scope==null) scope=new ThreadsImpl(this);
237                    return scope;
238            }
239    
240            public void terminated() {
241                    terminated=true;
242            }
243    
244            /**
245             * @return the pageSource
246             */
247            public String getTemplate() {
248                    return template;
249            }
250            
251            
252    }