001/**
002 *
003 * Copyright (c) 2014, the Railo Company Ltd. All rights reserved.
004 *
005 * This library is free software; you can redistribute it and/or
006 * modify it under the terms of the GNU Lesser General Public
007 * License as published by the Free Software Foundation; either 
008 * version 2.1 of the License, or (at your option) any later version.
009 * 
010 * This library is distributed in the hope that it will be useful,
011 * but WITHOUT ANY WARRANTY; without even the implied warranty of
012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
013 * Lesser General Public License for more details.
014 * 
015 * You should have received a copy of the GNU Lesser General Public 
016 * License along with this library.  If not, see <http://www.gnu.org/licenses/>.
017 * 
018 **/
019package lucee.runtime.op;
020
021import java.io.File;
022import java.io.InputStream;
023import java.io.OutputStream;
024import java.io.Serializable;
025import java.util.Iterator;
026import java.util.Map;
027import java.util.Map.Entry;
028
029import javax.servlet.http.Cookie;
030import javax.servlet.http.HttpServletRequest;
031import javax.servlet.http.HttpServletResponse;
032import javax.servlet.http.HttpSession;
033
034import lucee.commons.date.DateTimeUtil;
035import lucee.commons.io.IOUtil;
036import lucee.commons.io.res.Resource;
037import lucee.commons.io.res.util.ResourceUtil;
038import lucee.commons.lang.Pair;
039import lucee.loader.engine.CFMLEngine;
040import lucee.runtime.CFMLFactoryImpl;
041import lucee.runtime.Component;
042import lucee.runtime.PageContext;
043import lucee.runtime.config.Config;
044import lucee.runtime.config.RemoteClient;
045import lucee.runtime.db.DatasourceConnection;
046import lucee.runtime.db.SQL;
047import lucee.runtime.engine.ThreadLocalPageContext;
048import lucee.runtime.exp.DatabaseException;
049import lucee.runtime.exp.ExpressionException;
050import lucee.runtime.exp.PageException;
051import lucee.runtime.functions.system.ContractPath;
052import lucee.runtime.net.http.HttpServletRequestDummy;
053import lucee.runtime.net.http.HttpServletResponseDummy;
054import lucee.runtime.spooler.ExecutionPlan;
055import lucee.runtime.spooler.SpoolerTask;
056import lucee.runtime.spooler.remote.RemoteClientTask;
057import lucee.runtime.text.xml.XMLUtil;
058import lucee.runtime.type.Array;
059import lucee.runtime.type.ArrayImpl;
060import lucee.runtime.type.Collection;
061import lucee.runtime.type.Collection.Key;
062import lucee.runtime.type.KeyImpl;
063import lucee.runtime.type.Query;
064import lucee.runtime.type.QueryImpl;
065import lucee.runtime.type.Struct;
066import lucee.runtime.type.StructImpl;
067import lucee.runtime.type.dt.Date;
068import lucee.runtime.type.dt.DateImpl;
069import lucee.runtime.type.dt.DateTime;
070import lucee.runtime.type.dt.DateTimeImpl;
071import lucee.runtime.type.dt.Time;
072import lucee.runtime.type.dt.TimeImpl;
073import lucee.runtime.type.dt.TimeSpan;
074import lucee.runtime.type.dt.TimeSpanImpl;
075import lucee.runtime.type.scope.ClusterEntry;
076import lucee.runtime.type.scope.ClusterEntryImpl;
077import lucee.runtime.type.util.ListUtil;
078import lucee.runtime.util.Creation;
079
080import org.w3c.dom.Document;
081import org.xml.sax.InputSource;
082
083/**
084 * implemention of the ctration object
085 */
086public final class CreationImpl implements Creation,Serializable {
087
088    private static CreationImpl singelton;
089
090    private CreationImpl(CFMLEngine engine) {
091        // !!! do not store engine Object, the engine is not serializable
092        }
093
094        /**
095     * @return singleton instance
096     */
097    public static Creation getInstance(CFMLEngine engine) { 
098        if(singelton==null)singelton=new CreationImpl(engine);
099        return singelton;
100    }
101
102    @Override
103    public Array createArray() {
104        return new ArrayImpl();
105    }
106
107        @Override
108        public Array createArray(String list, String delimiter,boolean removeEmptyItem, boolean trim) {
109                if(removeEmptyItem)return ListUtil.listToArrayRemoveEmpty(list, delimiter);
110                if(trim)return ListUtil.listToArrayTrim(list, delimiter);
111                return ListUtil.listToArray(list, delimiter);
112        }
113        
114    @Override
115    public Array createArray(int dimension) throws PageException {
116        return new ArrayImpl(dimension);
117    }
118
119    @Override
120    public Struct createStruct() {
121        return new StructImpl();
122    }
123
124    @Override
125    public Struct createStruct(int type) {
126        return new StructImpl(type);
127    }
128
129    @Override
130    public Query createQuery(String[] columns, int rows, String name) {
131        return new QueryImpl(columns,rows,name);
132    }
133
134    @Override
135    public Query createQuery(Collection.Key[] columns, int rows, String name) throws DatabaseException {
136        return new QueryImpl(columns,rows,name);
137    }
138    
139    @Override
140    public Query createQuery(DatasourceConnection dc, SQL sql, int maxrow, String name) throws PageException {
141                return new QueryImpl(ThreadLocalPageContext.get(),dc,sql,maxrow,-1,null,name);
142        }
143    
144    public Query createQuery(DatasourceConnection dc, SQL sql, int maxrow, int fetchsize, int timeout, String name) throws PageException {
145                return new QueryImpl(ThreadLocalPageContext.get(),dc,sql,maxrow,fetchsize,TimeSpanImpl.fromMillis(timeout*1000),name);
146        }
147    
148    @Override
149    public DateTime createDateTime(long time) {
150        return new DateTimeImpl(time,false);
151    }
152
153    @Override
154    public TimeSpan createTimeSpan(int day,int hour,int minute,int second) {
155        return new TimeSpanImpl(day,hour,minute,second);
156    }
157
158    @Override
159    public Date createDate(long time) {
160        return new DateImpl(time);
161    }
162
163    @Override
164    public Time createTime(long time) {
165        return new TimeImpl(time,false);
166    }
167
168    @Override
169    public DateTime createDateTime(int year, int month, int day, int hour, int minute, int second, int millis) throws ExpressionException {
170        return DateTimeUtil.getInstance().toDateTime(ThreadLocalPageContext.getTimeZone(),year,month,day,hour,minute,second,millis);
171    }
172
173    @Override
174    public Date createDate(int year, int month, int day) throws ExpressionException {
175        return new DateImpl(DateTimeUtil.getInstance().toDateTime(null,year,month,day, 0, 0, 0,0));
176    }
177
178    @Override
179    public Time createTime(int hour, int minute, int second, int millis) {
180        return new TimeImpl(
181                        DateTimeUtil.getInstance().toTime(null,1899,12,30,hour,minute,second,millis,0),false);
182    }
183
184    @Override
185    public Document createDocument() throws PageException {
186        try {
187            return XMLUtil.newDocument();
188        } catch (Exception e) {
189            throw Caster.toPageException(e);
190        }
191    }
192
193    @Override
194    public Document createDocument(Resource res, boolean isHTML) throws PageException {
195        InputStream is=null;
196        try {
197            return XMLUtil.parse(new InputSource(is=res.getInputStream()),null,isHTML);
198        } catch (Exception e) {
199            throw Caster.toPageException(e);
200        }
201        finally {
202                IOUtil.closeEL(is);
203        }
204    }
205
206    @Override
207    public Document createDocument(String xml, boolean isHTML) throws PageException {
208        try {
209            return XMLUtil.parse(XMLUtil.toInputSource(null, xml),null,isHTML);
210        } catch (Exception e) {
211            throw Caster.toPageException(e);
212        }
213    }
214
215    @Override
216    public Document createDocument(InputStream is, boolean isHTML) throws PageException {
217        try {
218            return XMLUtil.parse(new InputSource(is),null,isHTML);
219        } catch (Exception e) {
220            throw Caster.toPageException(e);
221        }
222    }
223
224        @Override
225        public Key createKey(String key) {
226                return KeyImpl.init(key);
227        }
228
229        public SpoolerTask createRemoteClientTask(ExecutionPlan[] plans,RemoteClient remoteClient,Struct attrColl,String callerId, String type) {
230                return new RemoteClientTask(plans,remoteClient,attrColl,callerId, type);
231        }
232
233        public ClusterEntry createClusterEntry(Key key,Serializable value, int offset) {
234                return new ClusterEntryImpl(key,value,offset);
235        }
236
237        public Resource createResource(String path, boolean existing) throws PageException {
238                if(existing)return ResourceUtil.toResourceExisting(ThreadLocalPageContext.get(), path);
239                return ResourceUtil.toResourceNotExisting(ThreadLocalPageContext.get(), path);
240        }
241
242        public HttpServletRequest createHttpServletRequest(File contextRoot,String serverName, String scriptName,String queryString, 
243                        Cookie[] cookies, Map<String,Object> headers, Map<String, String> parameters, Map<String,Object> attributes, HttpSession session) {
244
245                // header
246                Pair<String,Object>[] _headers=new Pair[headers.size()];
247                {
248                        int index=0;
249                        Iterator<Entry<String, Object>> it = headers.entrySet().iterator();
250                        Entry<String, Object> entry;
251                        while(it.hasNext()){
252                                entry = it.next();
253                                _headers[index++]=new Pair<String,Object>(entry.getKey(), entry.getValue());
254                        }
255                }
256                // parameters
257                Pair<String,Object>[] _parameters=new Pair[headers.size()];
258                {
259                        int index=0;
260                        Iterator<Entry<String, String>> it = parameters.entrySet().iterator();
261                        Entry<String, String> entry;
262                        while(it.hasNext()){
263                                entry = it.next();
264                                _parameters[index++]=new Pair<String,Object>(entry.getKey(), entry.getValue());
265                        }
266                }
267                
268                return new HttpServletRequestDummy(ResourceUtil.toResource(contextRoot), serverName, scriptName, queryString, cookies,
269                                _headers, _parameters, Caster.toStruct(attributes,null), session);
270        }
271
272        public HttpServletResponse createHttpServletResponse(OutputStream io) {
273                return new HttpServletResponseDummy(io);
274        }
275
276        @Override
277        public PageContext createPageContext(HttpServletRequest req, HttpServletResponse rsp, OutputStream out) {
278                Config config = ThreadLocalPageContext.getConfig();
279                return (PageContext) ((CFMLFactoryImpl)config.getFactory()).getPageContext(config.getFactory().getServlet(), req, rsp, null, false, -1, false);
280        }
281
282        @Override
283        public Component createComponentFromName(PageContext pc, String fullName) throws PageException {
284                return pc.loadComponent(fullName);
285        }
286
287        @Override
288        public Component createComponentFromPath(PageContext pc, String path) throws PageException {    
289                path=path.trim();
290                String pathContracted=ContractPath.call(pc, path);
291        
292                if(pathContracted.toLowerCase().endsWith(".cfc"))
293                        pathContracted=pathContracted.substring(0,pathContracted.length()-4);
294                
295        pathContracted=pathContracted
296                        .replace(File.pathSeparatorChar, '.')
297                        .replace('/', '.')
298                        .replace('\\', '.');
299        
300        while(pathContracted.toLowerCase().startsWith("."))
301                        pathContracted=pathContracted.substring(1);
302        
303                return createComponentFromName(pc, pathContracted);
304        }
305
306
307}