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 }