001/*
002 * #%L
003 * Netarchivesuite - heritrix 3 monitor
004 * %%
005 * Copyright (C) 2005 - 2018 The Royal Danish Library, 
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023
024package dk.netarkivet.heritrix3.monitor;
025
026import java.io.IOException;
027import java.io.OutputStream;
028import java.util.ArrayList;
029import java.util.List;
030
031import javax.servlet.ServletConfig;
032import javax.servlet.ServletException;
033import javax.servlet.http.HttpServlet;
034import javax.servlet.http.HttpServletRequest;
035import javax.servlet.http.HttpServletResponse;
036import javax.servlet.http.HttpSession;
037
038import org.slf4j.Logger;
039import org.slf4j.LoggerFactory;
040
041import com.antiaction.common.servlet.AutoIncrement;
042import com.antiaction.common.servlet.PathMap;
043
044import dk.netarkivet.heritrix3.monitor.HttpLocaleHandler.HttpLocale;
045import dk.netarkivet.heritrix3.monitor.resources.ConfigResource;
046import dk.netarkivet.heritrix3.monitor.resources.H3BudgetResource;
047import dk.netarkivet.heritrix3.monitor.resources.H3CrawlLogCachedResource;
048import dk.netarkivet.heritrix3.monitor.resources.H3FilterResource;
049import dk.netarkivet.heritrix3.monitor.resources.H3FrontierDeleteResource;
050import dk.netarkivet.heritrix3.monitor.resources.H3FrontierResource;
051import dk.netarkivet.heritrix3.monitor.resources.H3JobResource;
052import dk.netarkivet.heritrix3.monitor.resources.H3ReportResource;
053import dk.netarkivet.heritrix3.monitor.resources.H3ScriptResource;
054import dk.netarkivet.heritrix3.monitor.resources.IndexResource;
055
056public class HistoryServlet extends HttpServlet implements ResourceManagerAbstract {
057
058    /**
059     * UID
060     */
061    private static final long serialVersionUID = -7452707006494237017L;
062
063    /** The logger for this class. */
064    private static final Logger LOG = LoggerFactory.getLogger(HistoryServlet.class);
065
066    public static NASEnvironment environment;
067
068    public static PathMap<Resource> pathMap;
069
070    protected AutoIncrement resourceAutoInc = new AutoIncrement();
071
072    @Override
073    public void init(ServletConfig servletConfig) throws ServletException {
074        super.init(servletConfig);
075
076        environment = new NASEnvironment(getServletContext(), servletConfig);
077        environment.start();
078
079        pathMap = new PathMap<Resource>();
080
081        System.out.println(this.getClass().getClassLoader());
082
083        IndexResource indexResource = new IndexResource();
084        indexResource.resources_init(environment);
085        indexResource.resources_add(this);
086
087        ConfigResource configResource = new ConfigResource();
088        configResource.resources_init(environment);
089        configResource.resources_add(this);
090
091        H3JobResource h3JobResource = new H3JobResource();
092        h3JobResource.resources_init(environment);
093        h3JobResource.resources_add(this);
094
095        H3CrawlLogCachedResource h3CrawlLogCachedResource = new H3CrawlLogCachedResource();
096        h3CrawlLogCachedResource.resources_init(environment);
097        h3CrawlLogCachedResource.resources_add(this);
098
099        H3FrontierResource h3FrontierResource = new H3FrontierResource();
100        h3FrontierResource.resources_init(environment);
101        h3FrontierResource.resources_add(this);
102
103        H3FrontierDeleteResource h3FrontierDeleteResource = new H3FrontierDeleteResource();
104        h3FrontierDeleteResource.resources_init(environment);
105        h3FrontierDeleteResource.resources_add(this);
106
107        H3ReportResource h3ReportResource = new H3ReportResource();
108        h3ReportResource.resources_init(environment);
109        h3ReportResource.resources_add(this);
110
111        H3ScriptResource h3ScriptResource = new H3ScriptResource();
112        h3ScriptResource.resources_init(environment);
113        h3ScriptResource.resources_add(this);
114
115        H3FilterResource h3FilterResource = new H3FilterResource();
116        h3FilterResource.resources_init(environment);
117        h3FilterResource.resources_add(this);
118
119        H3BudgetResource h3BudgetResource = new H3BudgetResource();
120        h3BudgetResource.resources_init(environment);
121        h3BudgetResource.resources_add(this);
122    }
123
124    public int resource_add(ResourceAbstract resources, String path,
125            boolean bSecured) {
126        int resource_id = resourceAutoInc.getId();
127        Resource resource = new Resource();
128        resource.resource_id = resource_id;
129        resource.resources = resources;
130        resource.bSecured = bSecured;
131        pathMap.add(path, resource);
132        return resource_id;
133    }
134
135    /*
136     * (non-Javadoc)
137     * 
138     * @see javax.servlet.GenericServlet#destroy()
139     */
140    @Override
141    public void destroy() {
142        if (environment != null) {
143            environment.cleanup();
144            environment = null;
145        }
146        LOG.info("{} destroyed.", this.getClass().getName());
147        super.destroy();
148    }
149
150    /*
151     * (non-Javadoc)
152     * 
153     * @see javax.servlet.http.HttpServlet#service(javax.servlet.http.HttpServletRequest
154     * , javax.servlet.http.HttpServletResponse)
155     */
156    @Override
157    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
158        HttpSession session = req.getSession();
159        try {
160            NASUser current_user = null;
161
162            // If we have a valid session look for an already logged in current
163            // user.
164            if (session != null) {
165                current_user = (NASUser) session.getAttribute("user");
166            }
167
168            // Look for cookies in case of no current user in session.
169            if (current_user == null && session != null && session.isNew()) {
170                // TODO
171                //current_user = environment.loginHandler.loginFromCookie(req, resp, session, this);
172            }
173
174            HttpLocale httpLocale = environment.httpLocaleUtils.localeGetSet(req, resp);
175
176            String action = req.getParameter("action");
177
178            // Logout, login or administration.
179            if (action != null && "logout".compareToIgnoreCase(action) == 0) {
180                // TODO
181                //environment.loginHandler.logoff(req, resp, session);
182            } else {
183                String pathInfo = req.getPathInfo();
184                if (pathInfo == null || pathInfo.length() == 0) {
185                    pathInfo = "/";
186                }
187
188                LOG.trace(req.getMethod() + " " + req.getPathInfo());
189
190                List<Integer> numerics = new ArrayList<Integer>();
191                Resource resource = pathMap.get(pathInfo, numerics);
192
193                if (resource != null) {
194                    if (resource.bSecured && current_user == null) {
195                        // TODO
196                        //environment.loginHandler.loginFromForm(req, resp, session, this);
197                        resp.sendError(HttpServletResponse.SC_UNAUTHORIZED, pathInfo);
198                    } else {
199                        resource.resources.resource_service(this.getServletContext(), current_user, req, resp, httpLocale, resource.resource_id, numerics, pathInfo);
200                    }
201                } else {
202                    resp.sendError(HttpServletResponse.SC_NOT_FOUND, pathInfo);
203                }
204            }
205        } catch (Throwable t) {
206            LOG.error(t.toString(), t);
207            StringBuilder sb = new StringBuilder();
208            sb.append( "<!DOCTYPE html><html lang=\"en\"><head>" );
209            sb.append( "<meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\">" );
210            sb.append( "<title>" );
211            sb.append( Integer.toString( HttpServletResponse.SC_INTERNAL_SERVER_ERROR ) );
212            sb.append( " Internal server error...</title>" );
213            sb.append( "</head><body><h1>" );
214            sb.append( Integer.toString( HttpServletResponse.SC_INTERNAL_SERVER_ERROR ) );
215            sb.append( " Internal server error..." );
216            sb.append( "</h1><pre>" );
217            throwable_stacktrace_dump( t, sb );
218            sb.append( "</pre></body></html>" );
219            resp.setContentType("text/html; charset=utf-8");
220            resp.setStatus( HttpServletResponse.SC_INTERNAL_SERVER_ERROR );
221            OutputStream out = resp.getOutputStream();
222            out.write( sb.toString().getBytes( "UTF-8" ) );
223            out.flush();
224            out.close();
225        }
226    }
227
228    public static void stacktrace_dump(StackTraceElement[] stackTraceElementArr, StringBuilder sb) {
229        StackTraceElement stackTraceElement;
230        String fileName;
231        if (stackTraceElementArr != null && stackTraceElementArr.length > 0) {
232            for (int i=0; i<stackTraceElementArr.length; ++i) {
233                stackTraceElement = stackTraceElementArr[i];
234                sb.append("\tat ");
235                sb.append(stackTraceElement.getClassName());
236                sb.append(".");
237                sb.append(stackTraceElement.getMethodName());
238                sb.append("(");
239                fileName = stackTraceElement.getFileName();
240                if (fileName != null) {
241                    sb.append(fileName);
242                    sb.append(":");
243                    sb.append(stackTraceElement.getLineNumber());
244                } else {
245                    sb.append("Unknown source");
246                }
247                sb.append(")");
248                sb.append("\n");
249            }
250        }
251    }
252
253    public static void throwable_stacktrace_dump(Throwable t, StringBuilder sb) {
254        String message;
255        if (t != null) {
256            sb.append(t.getClass().getName());
257            message = t.getMessage();
258            if (message != null) {
259                sb.append(": ");
260                sb.append(t.getMessage());
261            }
262            sb.append("\n");
263            stacktrace_dump(t.getStackTrace(), sb);
264            while ((t = t.getCause()) != null) {
265                sb.append("caused by ");
266                sb.append(t.getClass().getName());
267                message = t.getMessage();
268                if (message != null) {
269                    sb.append(": ");
270                    sb.append(t.getMessage());
271                }
272                sb.append("\n");
273                stacktrace_dump(t.getStackTrace(), sb);
274            }
275        }
276    }
277
278    public static class Resource {
279
280        public int resource_id;
281
282        public ResourceAbstract resources;
283
284        public boolean bSecured;
285
286    }
287
288}