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    }