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: 563404 $ $Date: 2007-08-07 02:38:34 -0400 (Tue, 07 Aug 2007) $
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 we assume than no fields were passed and just
168            // filter on the current date.
169            if(fromDateStr == null || toDateStr == null) {
170                // just keep the month date and year
171                cal1.set(Calendar.MILLISECOND, 0);
172                cal1.set(Calendar.MINUTE, 0);
173                cal1.set(Calendar.SECOND, 0);
174                cal1.set(Calendar.HOUR_OF_DAY, 0);
175    
176                cal2.set(Calendar.HOUR_OF_DAY, cal2.getMaximum(Calendar.HOUR_OF_DAY));
177                cal2.set(Calendar.MINUTE, cal2.getMaximum(Calendar.MINUTE));
178                cal2.set(Calendar.SECOND, cal2.getMaximum(Calendar.SECOND));
179                cal2.set(Calendar.MILLISECOND, cal2.getMaximum(Calendar.MILLISECOND));
180    
181                WebAccessLog.SearchResults matchingItems = chosenLog.getMatchingItems(logToSearch,
182                                            null, null, null, null, cal1.getTime(), cal2.getTime(), null, Integer.valueOf(criteria.maxResult.intValue()-1));
183                renderRequest.setAttribute("logs", matchingItems.getResults());
184                renderRequest.setAttribute("logLength", new Integer(matchingItems.getLineCount()));
185                renderRequest.setAttribute("maxResult", criteria.maxResult);
186                renderRequest.setAttribute("ignoreDates", Boolean.valueOf(criteria.ignoreDates));
187                
188            } else {
189                // Get other search criteria
190                String requestHost = criteria.requestHost;
191                String authUser = criteria.authUser;
192                String requestMethod = criteria.requestMethod;
193                String requestedURI = criteria.requestedURI;
194                String startResult = criteria.startResult;
195                Integer iStartResult = null;
196                Integer iMaxResult = criteria.maxResult;
197                try{
198                    iStartResult = Integer.valueOf(startResult);
199                }catch(NumberFormatException e){
200                    //ignore
201                }
202                
203                boolean ignoreDates = criteria.ignoreDates;
204                if (ignoreDates) {
205                    WebAccessLog.SearchResults matchingItems = chosenLog.getMatchingItems(logToSearch,
206                                                    requestHost, authUser, requestMethod, requestedURI, null, null, iStartResult, Integer.valueOf(iMaxResult.intValue()-1));
207                    renderRequest.setAttribute("logs", matchingItems.getResults());
208                    renderRequest.setAttribute("logLength", new Integer(matchingItems.getLineCount()));
209                } else {
210                    Date fromDate = null, toDate = null;
211                    // Check if the from and to date format is MM/DD/YYYY
212                    DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
213                    try {
214                        fromDate = df.parse(fromDateStr);
215                        // get the requested start date (defaults to 00:00:00:000 for time)
216                        cal1.setTime(fromDate);
217                        String mmddyyyy = (cal1.get(Calendar.MONTH) < 9 ? "0":"") + (cal1.get(Calendar.MONTH)+1);
218                        mmddyyyy += "/"+(cal1.get(Calendar.DAY_OF_MONTH) < 10 ? "0":"") + (cal1.get(Calendar.DAY_OF_MONTH));
219                        mmddyyyy += "/"+cal1.get(Calendar.YEAR);
220                        if(!mmddyyyy.equals(fromDateStr)) {
221                            // This should not arise since date input has been validated using javascript.
222                            // If this does occur, ignore dates in search criteria and log a WARNING
223                            log.warn("From date must be a date in MM/DD/YYYY format, not '"+fromDateStr+"'. Dates will be ignored.");
224                            fromDate = null;
225                        }
226                        toDate = df.parse(toDateStr);
227                        cal2.setTime(toDate);
228                        mmddyyyy = (cal2.get(Calendar.MONTH) < 9 ? "0":"") + (cal2.get(Calendar.MONTH)+1);
229                        mmddyyyy += "/"+(cal2.get(Calendar.DAY_OF_MONTH) < 10 ? "0":"") + (cal2.get(Calendar.DAY_OF_MONTH));
230                        mmddyyyy += "/"+cal2.get(Calendar.YEAR);
231                        if(!mmddyyyy.equals(toDateStr)) {
232                            // This should not arise since date input has been validated using javascript.
233                            // If this does occur, ignore to date in search criteria and log a WARNING
234                            log.warn("To date must be a date in MM/DD/YYYY format, not "+toDateStr+"'. Dates will be ignored.");
235                            toDate = null;
236                        } else {
237                            // get the requested end date - Note: must set time to end of day
238                            cal2.set(Calendar.HOUR_OF_DAY, cal2.getMaximum(Calendar.HOUR_OF_DAY));
239                            cal2.set(Calendar.MINUTE, cal2.getMaximum(Calendar.MINUTE));
240                            cal2.set(Calendar.SECOND, cal2.getMaximum(Calendar.SECOND));
241                            cal2.set(Calendar.MILLISECOND, cal2.getMaximum(Calendar.MILLISECOND));
242                            toDate = cal2.getTime();
243                        }
244                    } catch (ParseException e) {
245                        // Should not occur since date input has been validated using javascript.
246                        // If this does occur, ignore from and to dates and log a WARNING
247                        log.warn("Error parsing input dates.  Dates will be ignored.", e);
248                    }
249                    if(fromDate == null || toDate == null) {
250                        fromDate = toDate = null;
251                    }
252                    WebAccessLog.SearchResults matchingItems = chosenLog.getMatchingItems(logToSearch,
253                                                    requestHost, authUser, requestMethod, requestedURI, fromDate, toDate, iStartResult, Integer.valueOf(iMaxResult.intValue()-1));
254                    renderRequest.setAttribute("logs", matchingItems.getResults());
255                    renderRequest.setAttribute("logLength", new Integer(matchingItems.getLineCount()));
256                }
257                renderRequest.setAttribute("ignoreDates", new Boolean(ignoreDates));
258                renderRequest.setAttribute("requestHost", requestHost);
259                renderRequest.setAttribute("authUser", authUser);
260                renderRequest.setAttribute("requestMethod", requestMethod);
261                renderRequest.setAttribute("requestedURI", requestedURI);
262                if(iStartResult != null)renderRequest.setAttribute("startResult", iStartResult);
263                if(iMaxResult != null)renderRequest.setAttribute("maxResult", iMaxResult);
264            }
265            renderRequest.setAttribute("toDate", toDateStr);
266            renderRequest.setAttribute("fromDate", fromDateStr);
267            renderRequest.getPortletSession(true).setAttribute(CRITERIA_KEY, criteria, PortletSession.PORTLET_SCOPE);
268            searchView.include(renderRequest, renderRespose);
269        }
270    
271        public void init(PortletConfig portletConfig) throws PortletException {
272            PortletContext pc = portletConfig.getPortletContext();
273            searchView = pc.getRequestDispatcher("/WEB-INF/view/webaccesslogmanager/view.jsp");
274            helpView = pc.getRequestDispatcher("/WEB-INF/view/webaccesslogmanager/help.jsp");
275            super.init(portletConfig);
276        }
277    
278        public void processAction(ActionRequest actionRequest,
279                ActionResponse actionResponse) throws PortletException, IOException {
280            //todo: according to portlet spec, all forms should submit to Action not Render
281        }
282        private static class Criteria implements Serializable {
283            Integer maxResult = new Integer(DEFAULT_MAX_RESULTS);
284            String fromDate = null;
285            String toDate = null;
286            boolean ignoreDates = false;
287            String requestHost = null;
288            String authUser = null;
289            String requestMethod = "ANY";
290            String requestedURI = null;
291            String startResult = null;
292        }
293    
294    }