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