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.engine;
020
021import java.io.IOException;
022import java.nio.charset.Charset;
023import java.util.ArrayList;
024import java.util.Iterator;
025import java.util.Map;
026
027import javax.servlet.http.HttpServletRequest;
028
029import lucee.commons.io.IOUtil;
030import lucee.commons.io.res.Resource;
031import lucee.commons.io.res.util.ResourceUtil;
032import lucee.commons.lang.ExceptionUtil;
033import lucee.commons.lang.StringUtil;
034import lucee.commons.lang.SystemOut;
035import lucee.runtime.PageContext;
036import lucee.runtime.functions.other.CreateUUID;
037import lucee.runtime.op.Caster;
038
039public class ResourceExecutionLog extends ExecutionLogSupport {
040        
041        private static int count=1;
042        private Resource file;
043        private StringBuffer content;
044        private PageContext pc;
045        private StringBuffer header;
046        private ArrayList<String> pathes=new ArrayList<String>();
047        private long start;
048        private Resource dir;
049        
050        
051        protected void _init(PageContext pc, Map<String, String> arguments) {
052                this.pc=pc;
053                
054                //header
055                HttpServletRequest req = pc.getHttpServletRequest();
056                
057                header=new StringBuffer();
058                createHeader(header,"context-path",req.getContextPath());
059                createHeader(header,"remote-user",req.getRemoteUser());
060                createHeader(header,"remote-addr",req.getRemoteAddr());
061                createHeader(header,"remote-host",req.getRemoteHost());
062                createHeader(header,"script-name",StringUtil.emptyIfNull(req.getContextPath())+StringUtil.emptyIfNull(req.getServletPath()));
063                createHeader(header,"server-name",req.getServerName());
064                createHeader(header,"protocol",req.getProtocol());
065                createHeader(header,"server-port",Caster.toString(req.getServerPort()));
066                createHeader(header,"path-info",StringUtil.replace(
067                                StringUtil.emptyIfNull(req.getRequestURI()), 
068                                StringUtil.emptyIfNull(req.getServletPath()),"", true));
069                //createHeader(header,"path-translated",pc.getBasePageSource().getDisplayPath());
070                createHeader(header,"query-string",req.getQueryString());
071                createHeader(header,"unit",unitShortToString(unit));
072                createHeader(header,"min-time-nano",min+"");
073                
074                content=new StringBuffer();
075                
076                
077                // directory
078                String strDirectory=arguments.get("directory");
079                if(dir==null) {
080                        if(StringUtil.isEmpty(strDirectory)) {
081                                dir=getTemp(pc);
082                        }
083                        else {
084                                try {
085                                        dir = ResourceUtil.toResourceNotExisting(pc, strDirectory,false,false);
086                                        if(!dir.exists()){
087                                                dir.createDirectory(true);
088                                        }
089                                        else if(dir.isFile()){
090                                                err(pc,"can not create directory ["+dir+"], there is already a file with same name.");
091                                        }
092                                } 
093                                catch (Throwable t) {
094                                        ExceptionUtil.rethrowIfNecessary(t);
095                                        err(pc,t);
096                                        dir=getTemp(pc);
097                                }
098                        }
099                }
100                file=dir.getRealResource((pc.getId())+"-"+CreateUUID.call(pc)+".exl");
101                file.createNewFile();
102                start=System.currentTimeMillis();
103        }
104
105        private static Resource getTemp(PageContext pc) {
106                Resource tmp = pc.getConfig().getConfigDir();
107                Resource dir = tmp.getRealResource("execution-log");
108                if(!dir.exists())dir.mkdirs();
109                return dir;
110        }
111
112        protected void _release() {
113                
114                // execution time
115                createHeader(header, "execution-time", Caster.toString(System.currentTimeMillis()-start));
116                header.append("\n");
117                
118                
119                //path
120                StringBuilder sb=new StringBuilder();
121                Iterator<String> it = pathes.iterator();
122                int count=0;
123                while(it.hasNext()){
124                        sb.append(count++);
125                        sb.append(":");
126                        sb.append(it.next());
127                        sb.append("\n");
128                }
129                sb.append("\n");
130                try {
131                        IOUtil.write(file, header+sb.toString()+content.toString(), (Charset)null, false);
132                } catch (IOException ioe) {
133                        err(pc,ioe);
134                }
135        }
136
137        private void createHeader(StringBuffer sb,String name, String value) {
138                sb.append(name);
139                sb.append(":");
140                sb.append(StringUtil.emptyIfNull(value));
141                sb.append("\n");
142        }
143
144        
145        
146        @Override
147        protected void _log(int startPos, int endPos, long startTime, long endTime) {
148                long diff=endTime-startTime;
149                if(unit==UNIT_MICRO)diff/=1000;
150                else if(unit==UNIT_MILLI)diff/=1000000;
151                
152                content.append(path(pc.getCurrentPageSource().getDisplayPath()));
153                content.append("\t");
154                content.append(startPos);
155                content.append("\t");
156                content.append(endPos);
157                content.append("\t");
158                content.append(diff);
159                content.append("\n");
160        }
161        
162
163        private int path(String path) {
164                int index= pathes.indexOf(path);
165                if(index==-1){
166                        pathes.add(path);
167                        return pathes.size()-1;
168                }
169                return index;
170        }
171
172        private void err(PageContext pc, String msg) {
173                SystemOut.print(pc.getConfig().getErrWriter(), msg);
174        }
175
176        private void err(PageContext pc, Throwable t) {
177                String msg =ExceptionUtil.getStacktrace(t,true);
178                SystemOut.print(pc.getConfig().getErrWriter(), msg);
179        }
180}