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(environment.templateMaster, "master.tpl", "UTF-8", MasterTemplateBuilder.class); 101 MasterTemplateBuilder masterTplBuilder = masterTplBuilderFactory.getTemplateBuilder(); 102 103 StringBuilder sb = new StringBuilder(); 104 105 List<Heritrix3JobMonitor> h3JobsList = environment.h3JobMonitorThread.getRunningH3Jobs(); 106 Heritrix3JobMonitor h3Job; 107 108 // Restart H3 job monitor thread. 109 String action = req.getParameter("action"); 110 if (action != null && action.length() > 0) { 111 if ("restart".equalsIgnoreCase(action)) { 112 if (environment.h3JobMonitorThread.thread != null) { 113 synchronized (environment.h3JobMonitorThread.thread) { 114 if (!environment.h3JobMonitorThread.thread.isAlive()) { 115 // The h3JobMonitorThread is dead. Restart it. 116 Heritrix3JobMonitorThread newH3JobMonitor = new Heritrix3JobMonitorThread(environment); 117 try { 118 newH3JobMonitor.init(); 119 newH3JobMonitor.start(); 120 } 121 catch (Throwable t) { 122 t.printStackTrace(); 123 } 124 environment.h3JobMonitorThread = newH3JobMonitor; 125 } 126 } 127 } 128 } 129 } 130 131 sb.append("<a href=\""); 132 sb.append(NASEnvironment.servicePath); 133 sb.append("config/"); 134 sb.append("\" class=\"btn btn-default\">"); 135 sb.append(environment.I18N.getString(locale, "configure")); 136 sb.append("</a>"); 137 sb.append("<br />\n"); 138 sb.append("<br />\n"); 139 140 // Check if H3 job monitor thread is still running. 141 if (environment.h3JobMonitorThread.thread != null) { 142 synchronized (environment.h3JobMonitorThread.thread) { 143 if (!environment.h3JobMonitorThread.thread.isAlive()) { 144 sb.append("The H3 job monitor thread is not running anymore. "); 145 sb.append("<a href=\"?action=restart"); 146 sb.append("\""); 147 sb.append(" class=\"btn btn-default\">"); 148 sb.append("Restart"); 149 sb.append("</a>"); 150 sb.append("<br />\n"); 151 sb.append("<pre>"); 152 sb.append("Stacktrace[]:"); 153 HistoryServlet.throwable_stacktrace_dump(environment.h3JobMonitorThread.throwable, sb); 154 sb.append("</pre>"); 155 sb.append("<br />\n"); 156 sb.append("<br />\n"); 157 } 158 } 159 } 160 161 List<HarvestChannelStructure> hcList = new ArrayList<HarvestChannelStructure>(); 162 Map<String, HarvestChannelStructure> hcMap = new HashMap<String, HarvestChannelStructure>(); 163 164 Iterator<HarvestChannel> hcIter = Heritrix3JobMonitorThread.harvestChannelDAO.getAll(true); 165 HarvestChannel hc; 166 HarvestChannelStructure hcs; 167 while (hcIter.hasNext()) { 168 hc = hcIter.next(); 169 hcs = new HarvestChannelStructure(hc); 170 hcList.add(hcs); 171 hcMap.put(hc.getName(), hcs); 172 } 173 174 Iterator<Heritrix3JobMonitor> j3JobIter = h3JobsList.iterator(); 175 String channelStr; 176 while (j3JobIter.hasNext()) { 177 h3Job = j3JobIter.next(); 178 if (h3Job.job != null) { 179 channelStr = h3Job.job.getChannel(); 180 if (channelStr != null) { 181 hcs = hcMap.get(channelStr); 182 hcs.h3JobList.add(h3Job); 183 } 184 } 185 } 186 187 for (int i=0; i<hcList.size(); ++i) { 188 hcs = hcList.get(i); 189 sb.append("<h5>"); 190 sb.append(hcs.hc.getName()); 191 if (hcs.hc.isDefault()) { 192 sb.append("*"); 193 } 194 sb.append(" "); 195 sb.append("("); 196 sb.append(environment.I18N.getString(locale, "harvest.channel.type")); 197 sb.append(": "); 198 if (hcs.hc.isSnapshot()) { 199 sb.append(environment.I18N.getString(locale, "harvest.channel.type.broad")); 200 } else { 201 sb.append(environment.I18N.getString(locale, "harvest.channel.type.focused")); 202 } 203 sb.append(")"); 204 sb.append("</h5>\n"); 205 if (hcs.h3JobList.size() > 0) { 206 for (int j=0; j<hcs.h3JobList.size(); ++j) { 207 h3Job = hcs.h3JobList.get(j); 208 if (j > 0) { 209 sb.append(" "); 210 } 211 sb.append("<a href=\""); 212 sb.append(NASEnvironment.servicePath); 213 sb.append("job/"); 214 sb.append(h3Job.jobId); 215 sb.append("/"); 216 sb.append("\" class=\"btn btn-default\">"); 217 sb.append("Job "); 218 sb.append(h3Job.jobId); 219 long lines = (h3Job.idxFile.length() / 8) - 1; 220 if (lines > 0) { 221 sb.append(" ("); 222 sb.append(lines); 223 sb.append(")"); 224 } 225 sb.append("</a>\n"); 226 } 227 } else { 228 sb.append("<p>"); 229 sb.append(environment.I18N.getString(locale, "running.jobs.monitor.not.on.this.channel")); 230 sb.append("</p>\n"); 231 } 232 } 233 234 StringBuilder menuSb = masterTplBuilder.buildMenu(new StringBuilder(), req, locale, null); 235 //String url = req.getPathInfo(); 236 //HTMLUtils.generateNavigationTree(menuSb, url, locale); 237 238 masterTplBuilder.insertContent("H3 Remote Access", menuSb.toString(), httpLocale.generateLanguageLinks(), 239 environment.I18N.getString(locale, "pagetitle;h3.remote.access"), sb.toString(), 240 "<meta http-equiv=\"refresh\" content=\""+Settings.get(HarvesterSettings.HARVEST_MONITOR_REFRESH_INTERVAL)+"\"/>\n").write(out); 241 242 out.flush(); 243 out.close(); 244 } 245 246}