001 /** 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.console.logmanager; 019 020 import org.apache.commons.logging.Log; 021 import org.apache.commons.logging.LogFactory; 022 import org.apache.geronimo.console.BasePortlet; 023 import org.apache.geronimo.console.util.PortletManager; 024 import org.apache.geronimo.gbean.AbstractName; 025 import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory; 026 import org.apache.geronimo.management.geronimo.WebAccessLog; 027 import org.apache.geronimo.management.geronimo.WebContainer; 028 import org.apache.geronimo.management.geronimo.WebManager; 029 030 import javax.portlet.ActionRequest; 031 import javax.portlet.ActionResponse; 032 import javax.portlet.PortletConfig; 033 import javax.portlet.PortletContext; 034 import javax.portlet.PortletException; 035 import javax.portlet.PortletRequestDispatcher; 036 import javax.portlet.PortletSession; 037 import javax.portlet.RenderRequest; 038 import javax.portlet.RenderResponse; 039 import javax.portlet.WindowState; 040 import java.io.IOException; 041 import java.io.Serializable; 042 import java.text.DateFormat; 043 import java.text.ParseException; 044 import java.text.SimpleDateFormat; 045 import java.util.Calendar; 046 import java.util.Date; 047 import java.util.LinkedHashMap; 048 import java.util.Map; 049 050 /** 051 * @version $Rev: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $ 052 */ 053 public class WebAccessLogViewerPortlet extends BasePortlet { 054 private final static String CRITERIA_KEY = "org.apache.geronimo.console.web.log.CRITERIA"; 055 private final static Log log = LogFactory.getLog(WebAccessLogViewerPortlet.class); 056 private static final int DEFAULT_MAX_RESULTS = 10; 057 058 protected PortletRequestDispatcher searchView; 059 060 protected PortletRequestDispatcher helpView; 061 062 protected void doHelp(RenderRequest renderRequest, 063 RenderResponse renderRespose) throws PortletException, IOException { 064 helpView.include(renderRequest, renderRespose); 065 } 066 067 protected void doView(RenderRequest renderRequest, 068 RenderResponse renderRespose) throws PortletException, IOException { 069 if (WindowState.MINIMIZED.equals(renderRequest.getWindowState())) { 070 return; 071 } 072 073 WebManager[] managers = PortletManager.getCurrentServer(renderRequest).getWebManagers(); 074 075 Criteria criteria = (Criteria) renderRequest.getPortletSession(true).getAttribute(CRITERIA_KEY, PortletSession.PORTLET_SCOPE); 076 077 078 //todo: new 079 Map products = new LinkedHashMap(); 080 String chosen = renderRequest.getParameter("selectedContainer"); 081 if(chosen != null) { // Carry on to render the results with the right selection 082 renderRequest.setAttribute("selectedContainer", chosen); 083 } 084 WebAccessLog chosenLog = null; 085 if(managers != null) { 086 for (int i = 0; i < managers.length; i++) { 087 WebManager manager = managers[i]; 088 AbstractName managerName = PortletManager.getNameFor(renderRequest, manager); 089 WebContainer[] containers = (WebContainer[]) manager.getContainers(); 090 if (containers != null) { 091 for (int j = 0; j < containers.length; j++) { 092 WebContainer container = containers[j]; 093 AbstractName containerName = PortletManager.getNameFor(renderRequest, container); 094 String combined = managerName+"%"+containerName; 095 if(containers.length == 1) { 096 products.put(manager.getProductName(), combined); 097 } else { 098 products.put(manager.getProductName()+" ("+containerName.getName().get(NameFactory.J2EE_NAME)+")", combined); 099 } 100 if(chosenLog == null) { // will pick the correct match, or the first if no selection is specified 101 if(chosen == null || chosen.equals(combined)) { 102 chosenLog = PortletManager.getWebAccessLog(renderRequest, managerName, containerName); 103 } 104 } 105 } 106 } else { 107 log.error("No web containers found for manager "+manager.getProductName()); 108 } 109 } 110 } else { 111 log.error("No web managers found!"); 112 } 113 renderRequest.setAttribute("webContainers", products); 114 final String[] logNames = chosenLog.getLogNames(); 115 renderRequest.setAttribute("webLogs", logNames); 116 String logToSearch = renderRequest.getParameter("selectedLog"); 117 if(logToSearch == null) { 118 logToSearch = logNames[0]; 119 } else { //what if the log options for Jetty were showing, but the user picked Tomcat to search? todo: fix this with some AJAX to repopulate the form when container is changed 120 boolean found = false; 121 for (int i = 0; i < logNames.length; i++) { 122 String test = logNames[i]; 123 if(test.equals(logToSearch)) { 124 found = true; 125 break; 126 } 127 } 128 if(!found) { // Must has been for the other container -- make it work. 129 logToSearch = logNames[0]; 130 } 131 } 132 133 String action = renderRequest.getParameter("action"); 134 if (criteria == null || (action != null && !"refresh".equals(action))) { 135 if(criteria == null) 136 criteria = new Criteria(); 137 138 String fromDate = renderRequest.getParameter("fromDate"); 139 String toDate = renderRequest.getParameter("toDate"); 140 String requestHost = renderRequest.getParameter("requestHost"); 141 String authUser = renderRequest.getParameter("authUser"); 142 String method = renderRequest.getParameter("requestMethod"); 143 String uri = renderRequest.getParameter("requestedURI"); 144 String result = renderRequest.getParameter("startResult"); 145 Integer max = criteria.maxResult; 146 try{ 147 max = Integer.parseInt(renderRequest.getParameter("maxResult")); 148 }catch(NumberFormatException e){ 149 //ignore 150 } 151 String ignoreDates = renderRequest.getParameter("ignoreDates"); 152 153 criteria.fromDate = fromDate == null || fromDate.equals("") ? null : fromDate; 154 criteria.toDate = toDate == null || toDate.equals("") ? null : toDate; 155 criteria.requestHost = requestHost == null || requestHost.equals("") ? null : requestHost; 156 criteria.authUser = authUser == null || authUser.equals("") ? null : authUser; 157 criteria.requestMethod = method == null || method.equals("") ? null : method; 158 criteria.requestedURI = uri == null || uri.equals("") ? null : uri; 159 criteria.startResult = result == null || result.equals("") ? null : result; 160 criteria.maxResult = max; 161 criteria.ignoreDates = ignoreDates != null && !ignoreDates.equals(""); 162 } 163 String fromDateStr = criteria.fromDate; 164 String toDateStr = criteria.toDate; 165 166 Calendar cal1 = Calendar.getInstance(), cal2 = Calendar.getInstance(); 167 // If not all dates were passed and ignoreDates is not enabled, filter on the current date. 168 // Note: This happens only when the portlet is loaded for the first time. Subsequent invocation (other than 169 // using "Refresh") will have either ignoreDates enabled or both the dates non null. 170 if((fromDateStr == null || toDateStr == null) && !criteria.ignoreDates) { 171 // just keep the month date and year 172 cal1.set(Calendar.MILLISECOND, 0); 173 cal1.set(Calendar.MINUTE, 0); 174 cal1.set(Calendar.SECOND, 0); 175 cal1.set(Calendar.HOUR_OF_DAY, 0); 176 177 cal2.set(Calendar.HOUR_OF_DAY, cal2.getMaximum(Calendar.HOUR_OF_DAY)); 178 cal2.set(Calendar.MINUTE, cal2.getMaximum(Calendar.MINUTE)); 179 cal2.set(Calendar.SECOND, cal2.getMaximum(Calendar.SECOND)); 180 cal2.set(Calendar.MILLISECOND, cal2.getMaximum(Calendar.MILLISECOND)); 181 182 WebAccessLog.SearchResults matchingItems = chosenLog.getMatchingItems(logToSearch, 183 null, null, null, null, cal1.getTime(), cal2.getTime(), null, Integer.valueOf(criteria.maxResult.intValue()-1)); 184 renderRequest.setAttribute("logs", matchingItems.getResults()); 185 renderRequest.setAttribute("logLength", new Integer(matchingItems.getLineCount())); 186 renderRequest.setAttribute("maxResult", criteria.maxResult); 187 renderRequest.setAttribute("ignoreDates", Boolean.valueOf(criteria.ignoreDates)); 188 189 } else { 190 // Get other search criteria 191 String requestHost = criteria.requestHost; 192 String authUser = criteria.authUser; 193 String requestMethod = criteria.requestMethod; 194 String requestedURI = criteria.requestedURI; 195 String startResult = criteria.startResult; 196 Integer iStartResult = null; 197 Integer iMaxResult = criteria.maxResult; 198 try{ 199 iStartResult = Integer.valueOf(startResult); 200 }catch(NumberFormatException e){ 201 //ignore 202 } 203 204 boolean ignoreDates = criteria.ignoreDates; 205 if (ignoreDates) { 206 WebAccessLog.SearchResults matchingItems = chosenLog.getMatchingItems(logToSearch, 207 requestHost, authUser, requestMethod, requestedURI, null, null, iStartResult, Integer.valueOf(iMaxResult.intValue()-1)); 208 renderRequest.setAttribute("logs", matchingItems.getResults()); 209 renderRequest.setAttribute("logLength", new Integer(matchingItems.getLineCount())); 210 } else { 211 Date fromDate = null, toDate = null; 212 // Check if the from and to date format is MM/DD/YYYY 213 DateFormat df = new SimpleDateFormat("MM/dd/yyyy"); 214 try { 215 fromDate = df.parse(fromDateStr); 216 // get the requested start date (defaults to 00:00:00:000 for time) 217 cal1.setTime(fromDate); 218 String mmddyyyy = (cal1.get(Calendar.MONTH) < 9 ? "0":"") + (cal1.get(Calendar.MONTH)+1); 219 mmddyyyy += "/"+(cal1.get(Calendar.DAY_OF_MONTH) < 10 ? "0":"") + (cal1.get(Calendar.DAY_OF_MONTH)); 220 mmddyyyy += "/"+cal1.get(Calendar.YEAR); 221 if(!mmddyyyy.equals(fromDateStr)) { 222 // This should not arise since date input has been validated using javascript. 223 // If this does occur, ignore dates in search criteria and log a WARNING 224 log.warn("From date must be a date in MM/DD/YYYY format, not '"+fromDateStr+"'. Dates will be ignored."); 225 fromDate = null; 226 } 227 toDate = df.parse(toDateStr); 228 cal2.setTime(toDate); 229 mmddyyyy = (cal2.get(Calendar.MONTH) < 9 ? "0":"") + (cal2.get(Calendar.MONTH)+1); 230 mmddyyyy += "/"+(cal2.get(Calendar.DAY_OF_MONTH) < 10 ? "0":"") + (cal2.get(Calendar.DAY_OF_MONTH)); 231 mmddyyyy += "/"+cal2.get(Calendar.YEAR); 232 if(!mmddyyyy.equals(toDateStr)) { 233 // This should not arise since date input has been validated using javascript. 234 // If this does occur, ignore to date in search criteria and log a WARNING 235 log.warn("To date must be a date in MM/DD/YYYY format, not "+toDateStr+"'. Dates will be ignored."); 236 toDate = null; 237 } else { 238 // get the requested end date - Note: must set time to end of day 239 cal2.set(Calendar.HOUR_OF_DAY, cal2.getMaximum(Calendar.HOUR_OF_DAY)); 240 cal2.set(Calendar.MINUTE, cal2.getMaximum(Calendar.MINUTE)); 241 cal2.set(Calendar.SECOND, cal2.getMaximum(Calendar.SECOND)); 242 cal2.set(Calendar.MILLISECOND, cal2.getMaximum(Calendar.MILLISECOND)); 243 toDate = cal2.getTime(); 244 } 245 } catch (ParseException e) { 246 // Should not occur since date input has been validated using javascript. 247 // If this does occur, ignore from and to dates and log a WARNING 248 log.warn("Error parsing input dates. Dates will be ignored.", e); 249 } 250 if(fromDate == null || toDate == null) { 251 fromDate = toDate = null; 252 } 253 WebAccessLog.SearchResults matchingItems = chosenLog.getMatchingItems(logToSearch, 254 requestHost, authUser, requestMethod, requestedURI, fromDate, toDate, iStartResult, Integer.valueOf(iMaxResult.intValue()-1)); 255 renderRequest.setAttribute("logs", matchingItems.getResults()); 256 renderRequest.setAttribute("logLength", new Integer(matchingItems.getLineCount())); 257 } 258 renderRequest.setAttribute("ignoreDates", new Boolean(ignoreDates)); 259 renderRequest.setAttribute("requestHost", requestHost); 260 renderRequest.setAttribute("authUser", authUser); 261 renderRequest.setAttribute("requestMethod", requestMethod); 262 renderRequest.setAttribute("requestedURI", requestedURI); 263 if(iStartResult != null)renderRequest.setAttribute("startResult", iStartResult); 264 if(iMaxResult != null)renderRequest.setAttribute("maxResult", iMaxResult); 265 } 266 renderRequest.setAttribute("toDate", toDateStr); 267 renderRequest.setAttribute("fromDate", fromDateStr); 268 renderRequest.getPortletSession(true).setAttribute(CRITERIA_KEY, criteria, PortletSession.PORTLET_SCOPE); 269 searchView.include(renderRequest, renderRespose); 270 } 271 272 public void init(PortletConfig portletConfig) throws PortletException { 273 PortletContext pc = portletConfig.getPortletContext(); 274 searchView = pc.getRequestDispatcher("/WEB-INF/view/webaccesslogmanager/view.jsp"); 275 helpView = pc.getRequestDispatcher("/WEB-INF/view/webaccesslogmanager/help.jsp"); 276 super.init(portletConfig); 277 } 278 279 public void processAction(ActionRequest actionRequest, 280 ActionResponse actionResponse) throws PortletException, IOException { 281 String[] paramNames = {"action", 282 "fromDate", 283 "toDate", 284 "ignoreDates", 285 "requestHost", 286 "authUser", 287 "requestMethod", 288 "requestedURI", 289 "startResult", 290 "maxResult"}; 291 // copy all action parameters to render parameters 292 for(int i = 0; i < paramNames.length; i++) { 293 if(actionRequest.getParameter(paramNames[i]) != null) { 294 actionResponse.setRenderParameter( 295 paramNames[i], 296 actionRequest.getParameter(paramNames[i])); 297 } 298 } 299 } 300 private static class Criteria implements Serializable { 301 Integer maxResult = new Integer(DEFAULT_MAX_RESULTS); 302 String fromDate = null; 303 String toDate = null; 304 boolean ignoreDates = false; 305 String requestHost = null; 306 String authUser = null; 307 String requestMethod = "ANY"; 308 String requestedURI = null; 309 String startResult = null; 310 } 311 312 }