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.resources; 025 026import java.io.IOException; 027import java.util.ArrayList; 028import java.util.HashMap; 029import java.util.Iterator; 030import java.util.List; 031import java.util.Locale; 032import java.util.Map; 033 034import javax.servlet.ServletContext; 035import javax.servlet.ServletOutputStream; 036import javax.servlet.http.HttpServletRequest; 037import javax.servlet.http.HttpServletResponse; 038 039import com.antiaction.common.filter.Caching; 040import com.antiaction.common.templateengine.TemplateBuilderFactory; 041 042import dk.netarkivet.common.utils.Settings; 043import dk.netarkivet.harvester.HarvesterSettings; 044import dk.netarkivet.harvester.datamodel.HarvestChannel; 045import dk.netarkivet.heritrix3.monitor.Heritrix3JobMonitor; 046import dk.netarkivet.heritrix3.monitor.Heritrix3JobMonitorThread; 047import dk.netarkivet.heritrix3.monitor.HistoryServlet; 048import dk.netarkivet.heritrix3.monitor.NASEnvironment; 049import dk.netarkivet.heritrix3.monitor.NASUser; 050import dk.netarkivet.heritrix3.monitor.ResourceAbstract; 051import dk.netarkivet.heritrix3.monitor.ResourceManagerAbstract; 052import dk.netarkivet.heritrix3.monitor.HttpLocaleHandler.HttpLocale; 053 054public class IndexResource implements ResourceAbstract { 055 056 private NASEnvironment environment; 057 058 protected int R_INDEX = -1; 059 060 @Override 061 public void resources_init(NASEnvironment environment) { 062 this.environment = environment; 063 } 064 065 @Override 066 public void resources_add(ResourceManagerAbstract resourceManager) { 067 R_INDEX = resourceManager.resource_add(this, "/", false); 068 } 069 070 @Override 071 public void resource_service(ServletContext servletContext, NASUser nas_user, HttpServletRequest req, HttpServletResponse resp, HttpLocale httpLocale, int resource_id, List<Integer> numerics, String pathInfo) throws IOException { 072 if (NASEnvironment.contextPath == null) { 073 NASEnvironment.contextPath = req.getContextPath(); 074 } 075 if (NASEnvironment.servicePath == null) { 076 NASEnvironment.servicePath = req.getContextPath() + req.getServletPath() + "/"; 077 } 078 String method = req.getMethod().toUpperCase(); 079 if (resource_id == R_INDEX) { 080 if ("GET".equals(method)) { 081 index(req, resp, httpLocale, numerics); 082 } 083 } 084 } 085 086 public static class HarvestChannelStructure { 087 public HarvestChannel hc; 088 public List<Heritrix3JobMonitor> h3JobList = new ArrayList<Heritrix3JobMonitor>(); 089 public HarvestChannelStructure(HarvestChannel hc) { 090 this.hc = hc; 091 } 092 } 093 094 public void index(HttpServletRequest req, HttpServletResponse resp, HttpLocale httpLocale, List<Integer> numerics) throws IOException { 095 Locale locale = httpLocale.locale; 096 resp.setContentType("text/html; charset=UTF-8"); 097 ServletOutputStream out = resp.getOutputStream(); 098 Caching.caching_disable_headers(resp); 099 100 TemplateBuilderFactory<MasterTemplateBuilder> masterTplBuilderFactory = TemplateBuilderFactory.getInstance( 101 environment.templateMaster, "master.tpl", "UTF-8", MasterTemplateBuilder.class); 102 MasterTemplateBuilder masterTplBuilder = masterTplBuilderFactory.getTemplateBuilder(); 103 104 StringBuilder sb = new StringBuilder(); 105 106 List<Heritrix3JobMonitor> h3JobsList = environment.h3JobMonitorThread.getRunningH3Jobs(); 107 Heritrix3JobMonitor h3Job; 108 109 // Restart H3 job monitor thread. 110 String action = req.getParameter("action"); 111 if (action != null && action.length() > 0) { 112 if ("restart".equalsIgnoreCase(action)) { 113 if (environment.h3JobMonitorThread.thread != null) { 114 synchronized (environment.h3JobMonitorThread.thread) { 115 if (!environment.h3JobMonitorThread.thread.isAlive()) { 116 // The h3JobMonitorThread is dead. Restart it. 117 Heritrix3JobMonitorThread newH3JobMonitor = new Heritrix3JobMonitorThread(environment); 118 try { 119 newH3JobMonitor.init(); 120 newH3JobMonitor.start(); 121 } 122 catch (Throwable t) { 123 t.printStackTrace(); 124 } 125 environment.h3JobMonitorThread = newH3JobMonitor; 126 } 127 } 128 } 129 } 130 } 131 132 sb.append("<a href=\""); 133 sb.append(NASEnvironment.servicePath); 134 sb.append("config/"); 135 sb.append("\" class=\"btn btn-default\">"); 136 sb.append(environment.I18N.getString(locale, "configure")); 137 sb.append("</a>"); 138 sb.append("<br />\n"); 139 sb.append("<br />\n"); 140 141 // Check if H3 job monitor thread is still running. 142 if (environment.h3JobMonitorThread.thread != null) { 143 synchronized (environment.h3JobMonitorThread.thread) { 144 if (!environment.h3JobMonitorThread.thread.isAlive()) { 145 sb.append("The H3 job monitor thread is not running anymore. "); 146 sb.append("<a href=\"?action=restart"); 147 sb.append("\""); 148 sb.append(" class=\"btn btn-default\">"); 149 sb.append("Restart"); 150 sb.append("</a>"); 151 sb.append("<br />\n"); 152 sb.append("<pre>"); 153 sb.append("Stacktrace[]:"); 154 HistoryServlet.throwable_stacktrace_dump(environment.h3JobMonitorThread.throwable, sb); 155 sb.append("</pre>"); 156 sb.append("<br />\n"); 157 sb.append("<br />\n"); 158 } 159 } 160 } 161 162 List<HarvestChannelStructure> hcList = new ArrayList<HarvestChannelStructure>(); 163 Map<String, HarvestChannelStructure> hcMap = new HashMap<String, HarvestChannelStructure>(); 164 165 Iterator<HarvestChannel> hcIter = Heritrix3JobMonitorThread.harvestChannelDAO.getAll(true); 166 HarvestChannel hc; 167 HarvestChannelStructure hcs; 168 while (hcIter.hasNext()) { 169 hc = hcIter.next(); 170 hcs = new HarvestChannelStructure(hc); 171 hcList.add(hcs); 172 hcMap.put(hc.getName(), hcs); 173 } 174 175 Iterator<Heritrix3JobMonitor> j3JobIter = h3JobsList.iterator(); 176 String channelStr; 177 while (j3JobIter.hasNext()) { 178 h3Job = j3JobIter.next(); 179 if (h3Job.job != null) { 180 channelStr = h3Job.job.getChannel(); 181 if (channelStr != null) { 182 hcs = hcMap.get(channelStr); 183 hcs.h3JobList.add(h3Job); 184 } 185 } 186 } 187 188 for (int i=0; i<hcList.size(); ++i) { 189 hcs = hcList.get(i); 190 sb.append("<h5>"); 191 sb.append(hcs.hc.getName()); 192 if (hcs.hc.isDefault()) { 193 sb.append("*"); 194 } 195 sb.append(" "); 196 sb.append("("); 197 sb.append(environment.I18N.getString(locale, "harvest.channel.type")); 198 sb.append(": "); 199 if (hcs.hc.isSnapshot()) { 200 sb.append(environment.I18N.getString(locale, "harvest.channel.type.broad")); 201 } else { 202 sb.append(environment.I18N.getString(locale, "harvest.channel.type.focused")); 203 } 204 sb.append(")"); 205 sb.append("</h5>\n"); 206 if (hcs.h3JobList.size() > 0) { 207 for (int j=0; j<hcs.h3JobList.size(); ++j) { 208 h3Job = hcs.h3JobList.get(j); 209 if (j > 0) { 210 sb.append(" "); 211 } 212 sb.append("<a href=\""); 213 sb.append(NASEnvironment.servicePath); 214 sb.append("job/"); 215 sb.append(h3Job.jobId); 216 sb.append("/"); 217 sb.append("\" class=\"btn btn-default\">"); 218 sb.append("Job "); 219 sb.append(h3Job.jobId); 220 long lines = (h3Job.idxFile.length() / 8) - 1; 221 if (lines > 0) { 222 sb.append(" ("); 223 sb.append(lines); 224 sb.append(")"); 225 } 226 sb.append("</a>\n"); 227 } 228 } else { 229 sb.append("<p>"); 230 sb.append(environment.I18N.getString(locale, "running.jobs.monitor.not.on.this.channel")); 231 sb.append("</p>\n"); 232 } 233 } 234 235 StringBuilder menuSb = masterTplBuilder.buildMenu(new StringBuilder(), req, locale, null); 236 //String url = req.getPathInfo(); 237 //HTMLUtils.generateNavigationTree(menuSb, url, locale); 238 239 masterTplBuilder.insertContent("H3 Remote Access", menuSb.toString(), httpLocale.generateLanguageLinks(), 240 environment.I18N.getString(locale, "pagetitle;h3.remote.access"), sb.toString(), 241 "<meta http-equiv=\"refresh\" content=\""+Settings.get(HarvesterSettings.HARVEST_MONITOR_REFRESH_INTERVAL)+"\"/>\n").write(out); 242 243 out.flush(); 244 out.close(); 245 } 246 247}