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 }