package railo.runtime.thread;
import java.io.ByteArrayOutputStream;
import java.io.Serializable;
import java.util.ConcurrentModificationException;
import java.util.Iterator;
import java.util.Map.Entry;
import javax.servlet.http.HttpServletRequest;
import railo.commons.io.DevNullOutputStream;
import railo.commons.io.log.LogAndSource;
import railo.commons.lang.ExceptionUtil;
import railo.commons.lang.Pair;
import railo.runtime.Page;
import railo.runtime.PageContext;
import railo.runtime.PageContextImpl;
import railo.runtime.PageSourceImpl;
import railo.runtime.config.Config;
import railo.runtime.config.ConfigImpl;
import railo.runtime.config.ConfigWeb;
import railo.runtime.config.ConfigWebImpl;
import railo.runtime.engine.ThreadLocalPageContext;
import railo.runtime.exp.Abort;
import railo.runtime.exp.PageException;
import railo.runtime.net.http.HttpServletResponseDummy;
import railo.runtime.net.http.HttpUtil;
import railo.runtime.net.http.ReqRspUtil;
import railo.runtime.op.Caster;
import railo.runtime.op.Duplicator;
import railo.runtime.type.Collection;
import railo.runtime.type.Collection.Key;
import railo.runtime.type.KeyImpl;
import railo.runtime.type.Struct;
import railo.runtime.type.StructImpl;
import railo.runtime.type.scope.Argument;
import railo.runtime.type.scope.ArgumentThreadImpl;
import railo.runtime.type.scope.Local;
import railo.runtime.type.scope.LocalImpl;
import railo.runtime.type.scope.Threads;
import railo.runtime.type.scope.Undefined;
public class ChildThreadImpl extends ChildThread implements Serializable {
private static final long serialVersionUID = -8902836175312356628L;
private static final Collection.Key KEY_ATTRIBUTES = KeyImpl.intern("attributes");
//private static final Set EMPTY = new HashSet();
private int threadIndex;
private PageContextImpl parent;
PageContextImpl pc =null;
private String tagName;
private long start;
private Threads scope;
// accesible from scope
Struct content=new StructImpl();
Struct catchBlock;
boolean terminated;
boolean completed;
ByteArrayOutputStream output;
// only used for type deamon
private Page page;
// only used for type task, demon attrs are not Serializable
private Struct attrs;
private SerializableCookie[] cookies;
private String serverName;
private String queryString;
private Pair[] parameters;
private String requestURI;
private Pair[] headers;
private Struct attributes;
private String template;
private long requestTimeout;
private boolean serializable;
String contentType;
String contentEncoding;
public ChildThreadImpl(PageContextImpl parent,Page page, String tagName,int threadIndex, Struct attrs, boolean serializable) {
this.serializable=serializable;
this.tagName=tagName;
this.threadIndex=threadIndex;
start=System.currentTimeMillis();
if(attrs==null) this.attrs=new StructImpl();
else this.attrs=attrs;
if(!serializable){
this.page=page;
if(parent!=null){
output = new ByteArrayOutputStream();
try{
this.parent=ThreadUtil.clonePageContext(parent, output,false,false,true);
}
catch(ConcurrentModificationException e){// MUST search for:hhlhgiug
this.parent=ThreadUtil.clonePageContext(parent, output,false,false,true);
}
//this.parent=parent;
}
}
else {
this.template=page.getPageSource().getFullRealpath();
HttpServletRequest req = parent.getHttpServletRequest();
serverName=req.getServerName();
queryString=ReqRspUtil.getQueryString(req);
cookies=SerializableCookie.toSerializableCookie(ReqRspUtil.getCookies(ThreadLocalPageContext.getConfig(parent),req));
parameters=HttpUtil.cloneParameters(req);
requestURI=req.getRequestURI();
headers=HttpUtil.cloneHeaders(req);
attributes=HttpUtil.getAttributesAsStruct(req);
requestTimeout=parent.getRequestTimeout();
// MUST here ist sill a mutch state values missing
}
}
public PageContext getPageContext(){
return pc;
}
public void run() {
execute(null);
}
public PageException execute(Config config) {
PageContext oldPc = ThreadLocalPageContext.get();
Page p=page;
if(parent!=null){
pc=parent;
ThreadLocalPageContext.register(pc);
}
else {
ConfigWebImpl cwi;
try {
cwi = (ConfigWebImpl)config;
DevNullOutputStream os = DevNullOutputStream.DEV_NULL_OUTPUT_STREAM;
pc=ThreadUtil.createPageContext(cwi, os, serverName, requestURI, queryString, SerializableCookie.toCookies(cookies), headers, parameters, attributes);
pc.setRequestTimeout(requestTimeout);
p=PageSourceImpl.loadPage(pc, cwi.getPageSources(oldPc==null?pc:oldPc,null, template, false,false,true));
//p=cwi.getPageSources(oldPc,null, template, false,false,true).loadPage(cwi);
} catch (PageException e) {
return e;
}
pc.addPageSource(p.getPageSource(), true);
}
pc.setThreadScope("thread", new ThreadsImpl(this));
pc.setThread(Thread.currentThread());
//String encodings = pc.getHttpServletRequest().getHeader("Accept-Encoding");
Undefined undefined=pc.us();
Argument newArgs=new ArgumentThreadImpl((Struct) Duplicator.duplicate(attrs,false));
LocalImpl newLocal=pc.getScopeFactory().getLocalInstance();
//Key[] keys = attrs.keys();
Iterator<Entry<Key, Object>> it = attrs.entryIterator();
Entry<Key, Object> e;
while(it.hasNext()){
e = it.next();
newArgs.setEL(e.getKey(),e.getValue());
}
newLocal.setEL(KEY_ATTRIBUTES, newArgs);
Argument oldArgs=pc.argumentsScope();
Local oldLocal=pc.localScope();
int oldMode=undefined.setMode(Undefined.MODE_LOCAL_OR_ARGUMENTS_ALWAYS);
pc.setFunctionScopes(newLocal,newArgs);
try {
p.threadCall(pc, threadIndex);
}
catch (Throwable t) {
if(!Abort.isSilentAbort(t)) {
ConfigWeb c = pc.getConfig();
if(c instanceof ConfigImpl) {
ConfigImpl ci=(ConfigImpl) c;
LogAndSource log = ci.getThreadLogger();
if(log!=null)log.error(this.getName(), ExceptionUtil.getStacktrace(t,true));
}
PageException pe = Caster.toPageException(t);
if(!serializable)catchBlock=pe.getCatchBlock(pc);
return pe;
}
}
finally {
completed=true;
pc.setFunctionScopes(oldLocal,oldArgs);
undefined.setMode(oldMode);
//pc.getScopeFactory().recycle(newArgs);
pc.getScopeFactory().recycle(newLocal);
if(pc.getHttpServletResponse() instanceof HttpServletResponseDummy) {
HttpServletResponseDummy rsp=(HttpServletResponseDummy) pc.getHttpServletResponse();
pc.flush();
contentType=rsp.getContentType();
Pair<String,Object>[] _headers = rsp.getHeaders();
if(_headers!=null)for(int i=0;i<_headers.length;i++){
if(_headers[i].getName().equalsIgnoreCase("Content-Encoding"))
contentEncoding=Caster.toString(_headers[i].getValue(),null);
}
}
((ConfigImpl)pc.getConfig()).getFactory().releasePageContext(pc);
pc=null;
if(oldPc!=null)ThreadLocalPageContext.register(oldPc);
}
return null;
}
@Override
public String getTagName() {
return tagName;
}
@Override
public long getStartTime() {
return start;
}
public Threads getThreadScope() {
if(scope==null) scope=new ThreadsImpl(this);
return scope;
}
public void terminated() {
terminated=true;
}
/**
* @return the pageSource
*/
public String getTemplate() {
return template;
}
}