/**
* Copyright (c) 2014, the Railo Company Ltd.
* Copyright (c) 2015, Lucee Assosication Switzerland
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
package lucee.runtime.op;
import java.io.File;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import javax.servlet.ServletConfig;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import lucee.cli.servlet.ServletConfigImpl;
import lucee.cli.servlet.ServletContextImpl;
import lucee.commons.date.DateTimeUtil;
import lucee.commons.io.res.Resource;
import lucee.commons.io.res.util.ResourceUtil;
import lucee.commons.lang.Pair;
import lucee.commons.lang.types.RefBoolean;
import lucee.commons.lang.types.RefBooleanImpl;
import lucee.commons.lang.types.RefDouble;
import lucee.commons.lang.types.RefDoubleImpl;
import lucee.commons.lang.types.RefInteger;
import lucee.commons.lang.types.RefIntegerImpl;
import lucee.commons.lang.types.RefIntegerSync;
import lucee.commons.lang.types.RefLong;
import lucee.commons.lang.types.RefLongImpl;
import lucee.commons.lang.types.RefString;
import lucee.commons.lang.types.RefStringImpl;
import lucee.commons.lock.KeyLock;
import lucee.commons.lock.KeyLockImpl;
import lucee.loader.engine.CFMLEngine;
import lucee.runtime.CFMLFactory;
import lucee.runtime.Component;
import lucee.runtime.Mapping;
import lucee.runtime.MappingImpl;
import lucee.runtime.PageContext;
import lucee.runtime.component.Property;
import lucee.runtime.component.PropertyImpl;
import lucee.runtime.config.Config;
import lucee.runtime.config.ConfigWeb;
import lucee.runtime.config.Constants;
import lucee.runtime.config.RemoteClient;
import lucee.runtime.db.DatasourceConnection;
import lucee.runtime.db.SQL;
import lucee.runtime.engine.ThreadLocalPageContext;
import lucee.runtime.exp.ApplicationException;
import lucee.runtime.exp.DatabaseException;
import lucee.runtime.exp.ExpressionException;
import lucee.runtime.exp.PageException;
import lucee.runtime.functions.other.CreateGUID;
import lucee.runtime.functions.other.CreateUUID;
import lucee.runtime.functions.struct.StructNew;
import lucee.runtime.functions.system.ContractPath;
import lucee.runtime.listener.ApplicationListener;
import lucee.runtime.net.http.HttpServletRequestDummy;
import lucee.runtime.net.http.HttpServletResponseDummy;
import lucee.runtime.spooler.ExecutionPlan;
import lucee.runtime.spooler.SpoolerTask;
import lucee.runtime.spooler.remote.RemoteClientTask;
import lucee.runtime.type.Array;
import lucee.runtime.type.ArrayImpl;
import lucee.runtime.type.CastableStruct;
import lucee.runtime.type.Collection;
import lucee.runtime.type.Collection.Key;
import lucee.runtime.type.KeyImpl;
import lucee.runtime.type.Query;
import lucee.runtime.type.QueryImpl;
import lucee.runtime.type.Struct;
import lucee.runtime.type.StructImpl;
import lucee.runtime.type.dt.Date;
import lucee.runtime.type.dt.DateImpl;
import lucee.runtime.type.dt.DateTime;
import lucee.runtime.type.dt.DateTimeImpl;
import lucee.runtime.type.dt.Time;
import lucee.runtime.type.dt.TimeImpl;
import lucee.runtime.type.dt.TimeSpan;
import lucee.runtime.type.dt.TimeSpanImpl;
import lucee.runtime.type.scope.ClusterEntry;
import lucee.runtime.type.scope.ClusterEntryImpl;
import lucee.runtime.type.util.ArrayUtil;
import lucee.runtime.type.util.ListUtil;
import lucee.runtime.util.Creation;
/**
* implemention of the ctration object
*/
public final class CreationImpl implements Creation,Serializable {
private static CreationImpl singelton;
private CreationImpl(CFMLEngine engine) {
// !!! do not store engine Object, the engine is not serializable
}
/**
* @return singleton instance
*/
public static Creation getInstance(CFMLEngine engine) {
if(singelton==null)singelton=new CreationImpl(engine);
return singelton;
}
@Override
public Array createArray() {
return new ArrayImpl();
}
@Override
public Array createArray(String list, String delimiter,boolean removeEmptyItem, boolean trim) {
if(removeEmptyItem)return ListUtil.listToArrayRemoveEmpty(list, delimiter);
if(trim)return ListUtil.listToArrayTrim(list, delimiter);
return ListUtil.listToArray(list, delimiter);
}
@Override
public Array createArray(int dimension) throws PageException {
return ArrayUtil.getInstance(dimension);
}
@Override
public Struct createStruct() {
return new StructImpl();
}
@Override
public Struct createStruct(int type) {
return new StructImpl(type);
}
@Override
public Struct createStruct(String type) throws ApplicationException {
return new StructImpl(StructNew.toType(type));
}
@Override
public Query createQuery(String[] columns, int rows, String name) {
return new QueryImpl(columns,rows,name);
}
@Override
public Query createQuery(Collection.Key[] columns, int rows, String name) throws DatabaseException {
return new QueryImpl(columns,rows,name);
}
@Override
public Query createQuery(String[] columns, String[] types, int rows, String name) throws DatabaseException {
return new QueryImpl(columns,types,rows,name);
}
@Override
public Query createQuery(Collection.Key[] columns, String[] types, int rows, String name) throws DatabaseException {
return new QueryImpl(columns,types,rows,name);
}
@Override
public Query createQuery(DatasourceConnection dc, SQL sql, int maxrow, int fetchsize, int timeout, String name) throws PageException {
return new QueryImpl(ThreadLocalPageContext.get(),dc,sql,maxrow,fetchsize,TimeSpanImpl.fromMillis(timeout*1000),name);
}
@Override
public DateTime createDateTime(long time) {
return new DateTimeImpl(time,false);
}
@Override
public TimeSpan createTimeSpan(int day,int hour,int minute,int second) {
return new TimeSpanImpl(day,hour,minute,second);
}
@Override
public Date createDate(long time) {
return new DateImpl(time);
}
@Override
public Time createTime(long time) {
return new TimeImpl(time,false);
}
@Override
public DateTime createDateTime(int year, int month, int day, int hour, int minute, int second, int millis) throws ExpressionException {
return DateTimeUtil.getInstance().toDateTime(ThreadLocalPageContext.getTimeZone(),year,month,day,hour,minute,second,millis);
}
@Override
public Date createDate(int year, int month, int day) throws ExpressionException {
return new DateImpl(DateTimeUtil.getInstance().toDateTime(null,year,month,day, 0, 0, 0,0));
}
@Override
public Time createTime(int hour, int minute, int second, int millis) {
return new TimeImpl(
DateTimeUtil.getInstance().toTime(null,1899,12,30,hour,minute,second,millis,0),false);
}
@Override
public Key createKey(String key) {
return KeyImpl.init(key);
}
@Override
public SpoolerTask createRemoteClientTask(ExecutionPlan[] plans,RemoteClient remoteClient,Struct attrColl,String callerId, String type) {
return new RemoteClientTask(plans,remoteClient,attrColl,callerId, type);
}
@Override
public ClusterEntry createClusterEntry(Key key,Serializable value, int offset) {
return new ClusterEntryImpl(key,value,offset);
}
@Override
public Resource createResource(String path, boolean existing) throws PageException {
if(existing)return ResourceUtil.toResourceExisting(ThreadLocalPageContext.get(), path);
return ResourceUtil.toResourceNotExisting(ThreadLocalPageContext.get(), path);
}
@Override
public HttpServletRequest createHttpServletRequest(File contextRoot,String serverName, String scriptName,String queryString,
Cookie[] cookies, Map<String,Object> headers, Map<String, String> parameters, Map<String,Object> attributes, HttpSession session) {
// header
Pair<String,Object>[] _headers=new Pair[headers.size()];
{
int index=0;
Iterator<Entry<String, Object>> it = headers.entrySet().iterator();
Entry<String, Object> entry;
while(it.hasNext()){
entry = it.next();
_headers[index++]=new Pair<String,Object>(entry.getKey(), entry.getValue());
}
}
// parameters
Pair<String,Object>[] _parameters=new Pair[headers.size()];
{
int index=0;
Iterator<Entry<String, String>> it = parameters.entrySet().iterator();
Entry<String, String> entry;
while(it.hasNext()){
entry = it.next();
_parameters[index++]=new Pair<String,Object>(entry.getKey(), entry.getValue());
}
}
return new HttpServletRequestDummy(ResourceUtil.toResource(contextRoot), serverName, scriptName, queryString, cookies,
_headers, _parameters, Caster.toStruct(attributes,null), session,null);
}
@Override
public HttpServletResponse createHttpServletResponse(OutputStream io) {
return new HttpServletResponseDummy(io); // do not change, flex extension is depending on this
}
// FUTURE add to interface
public ServletConfig createServletConfig(File root, Map<String, Object> attributes, Map<String, String> params) {
final String servletName = "";
if(attributes==null)attributes = new HashMap<String, Object>();
if(params==null)params = new HashMap<String, String>();
if(root==null)root = new File("."); // working directory that the java command was called from
final ServletContextImpl servletContext = new ServletContextImpl(root, attributes, params, 1, 0);
final ServletConfigImpl servletConfig = new ServletConfigImpl(servletContext, servletName);
return servletConfig;
}
@Override
public PageContext createPageContext(HttpServletRequest req, HttpServletResponse rsp, OutputStream out) {
Config config = ThreadLocalPageContext.getConfig();
if(!(config instanceof ConfigWeb)) throw new RuntimeException("need a web context to create a PageContext");
CFMLFactory factory = ((ConfigWeb)config).getFactory();
return (PageContext) factory.getPageContext(factory.getServlet(), req, rsp, null, false, -1, false);
}
@Override
public Component createComponentFromName(PageContext pc, String fullName) throws PageException {
return pc.loadComponent(fullName);
}
@Override
public Component createComponentFromPath(PageContext pc, String path) throws PageException {
path=path.trim();
String pathContracted=ContractPath.call(pc, path);
if(Constants.isComponentExtension(ResourceUtil.getExtension(pathContracted, "")))
pathContracted=ResourceUtil.removeExtension(pathContracted, pathContracted);
pathContracted=pathContracted
.replace(File.pathSeparatorChar, '.')
.replace('/', '.')
.replace('\\', '.');
while(pathContracted.toLowerCase().startsWith("."))
pathContracted=pathContracted.substring(1);
return createComponentFromName(pc, pathContracted);
}
@Override
public RefBoolean createRefBoolean(boolean b) {
return new RefBooleanImpl(b);
}
@Override
public RefInteger createRefInteger(int i) {
return new RefIntegerImpl(i);
}
// FUTURE add this and more to interface
public RefInteger createRefInteger(int i, boolean _syncronized) {
return _syncronized?new RefIntegerSync(i):new RefIntegerImpl(i);
}
@Override
public RefLong createRefLong(long l) {
return new RefLongImpl(l);
}
@Override
public RefDouble createRefDouble(long d) {
return new RefDoubleImpl(d);
}
@Override
public RefString createRefString(String value) {
return new RefStringImpl(value);
}
@Override
public String createUUID() {
return CreateUUID.invoke();
}
@Override
public String createGUID() {
return CreateGUID.invoke();
}
@Override
public Property createProperty(String name, String type) {
PropertyImpl pi = new PropertyImpl();
pi.setName(name);
pi.setType(type);
return pi;
}
@Override
public Mapping createMapping(Config config, String virtual, String strPhysical,String strArchive, short inspect,
boolean physicalFirst, boolean hidden, boolean readonly,boolean topLevel, boolean appMapping,
boolean ignoreVirtual,ApplicationListener appListener,int listenerMode,int listenerType) {
return new MappingImpl(config, virtual, strPhysical, strArchive, inspect, physicalFirst, hidden, readonly, topLevel, appMapping, ignoreVirtual, appListener,listenerMode,listenerType);
}
@Override
public Struct createCastableStruct(Object value) {
return new CastableStruct(value);
}
@Override
public Struct createCastableStruct(Object value, int type) {
return new CastableStruct(value,type);
}
@Override
public DateTime now() {
return new DateTimeImpl();
}
@Override
public <K> KeyLock<K> createKeyLock() {
// TODO Auto-generated method stub
return new KeyLockImpl<K>();
}
}