Author: remm
Date: Mon Apr 16 16:30:55 2007
New Revision: 529444

URL: http://svn.apache.org/viewvc?view=rev&rev=529444
Log:
- Add session browser capabilities in the manager. Let me know if it creates 
problems (I checked XSS to some extent to,
  but please double check if you can).
- Submitted by Cédrik Lime.

Added:
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/JspHelper.java   
(with props)
    tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/
    
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/BaseSessionComparator.java
   (with props)
    
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/ReverseComparator.java
   (with props)
    
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/SessionUtils.java   
(with props)
Modified:
    
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java

Modified: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java?view=diff&rev=529444&r1=529443&r2=529444
==============================================================================
--- 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java 
(original)
+++ 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/HTMLManagerServlet.java 
Mon Apr 16 16:30:55 2007
@@ -23,6 +23,10 @@
 import java.io.PrintWriter;
 import java.io.StringWriter;
 import java.text.MessageFormat;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -30,9 +34,14 @@
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
 
 import org.apache.catalina.Container;
 import org.apache.catalina.Context;
+import org.apache.catalina.Session;
+import org.apache.catalina.manager.util.BaseSessionComparator;
+import org.apache.catalina.manager.util.ReverseComparator;
+import org.apache.catalina.manager.util.SessionUtils;
 import org.apache.catalina.util.RequestUtil;
 import org.apache.catalina.util.ServerInfo;
 import org.apache.tomcat.util.http.fileupload.DiskFileUpload;
@@ -50,7 +59,7 @@
 * makes it easier to administrate.
 * <p>
 * However if you use a software that parses the output of
-* <code>ManagerServlet</code you won't be able to upgrade
+* <code>ManagerServlet</code> you won't be able to upgrade
 * to this Servlet since the output are not in the
 * same format ar from <code>ManagerServlet</code>
 *
@@ -63,6 +72,11 @@
 
 public final class HTMLManagerServlet extends ManagerServlet {
 
+    protected static final String APPLICATION_MESSAGE = "message";
+    protected static final String APPLICATION_ERROR = "error";
+    protected String sessionsListJspPath  = "/sessionsList.jsp";
+    protected String sessionDetailJspPath = "/sessionDetail.jsp";
+
     // --------------------------------------------------------- Public Methods
 
     /**
@@ -100,7 +114,15 @@
         } else if (command.equals("/undeploy")) {
             message = undeploy(path);
         } else if (command.equals("/sessions")) {
-            message = sessions(path);
+            //message = sessions(path);
+            try {
+                doSessions(path, request, response);
+                return;
+            } catch (Exception e) {
+                log("HTMLManagerServlet.sessions[" + path + "]", e);
+                message = sm.getString("managerServlet.exception",
+                        e.toString());
+            }
         } else if (command.equals("/start")) {
             message = start(path);
         } else if (command.equals("/stop")) {
@@ -562,6 +584,309 @@
         return stringWriter.toString();
     }
 
+    /**
+     * @see javax.servlet.Servlet#getServletInfo()
+     */
+    public String getServletInfo() {
+        return "HTMLManagerServlet, Copyright (c) The Apache Software 
Foundation";
+    }   
+    
+    /**
+     * @see javax.servlet.GenericServlet#init()
+     */
+    public void init() throws ServletException {
+        super.init();
+    }   
+
+    // ------------------------------------------------ Sessions administration
+
+    /**
+     * 
+     * @param req
+     * @param resp
+     * @throws ServletException
+     * @throws IOException 
+     */
+    protected void doSessions(String path, HttpServletRequest req, 
HttpServletResponse resp) throws ServletException, IOException {
+        req.setAttribute("path", path);
+        String action = req.getParameter("action");
+        if (debug >= 1) {
+            log("sessions: Session action '" + action + "' for web application 
at '" + path + "'");
+        }
+        if ("sessionDetail".equals(action)) {
+               String sessionId = req.getParameter("sessionId");
+               displaySessionDetailPage(req, resp, path, sessionId);
+               return;
+        } else if ("invalidateSessions".equals(action)) {
+            String[] sessionIds = req.getParameterValues("sessionIds");
+            int i = invalidateSessions(path, sessionIds);
+            req.setAttribute(APPLICATION_MESSAGE, "" + i + " sessions 
invalidated.");
+        } else if ("removeSessionAttribute".equals(action)) {
+            String sessionId = req.getParameter("sessionId");
+            String name = req.getParameter("attributeName");
+            boolean removed = removeSessionAttribute(path, sessionId, name);
+            String outMessage = removed ? "Session attribute '" + name + "' 
removed." : "Session did not contain any attribute named '" + name + "'";
+            req.setAttribute(APPLICATION_MESSAGE, outMessage);
+            
resp.sendRedirect(resp.encodeRedirectURL(req.getRequestURL().append("?path=").append(path).append("&action=sessionDetail&sessionId=").append(sessionId).toString()));
+            return;
+        } // else
+        displaySessionsListPage(path, req, resp);
+    }
+
+    protected Session[] getSessionsForPath(String path) {
+        if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
+            throw new 
IllegalArgumentException(sm.getString("managerServlet.invalidPath",
+                                        RequestUtil.filter(path)));
+        }
+        String displayPath = path;
+        if( path.equals("/") )
+            path = "";
+        Context context = (Context) host.findChild(path);
+        if (null == context) {
+            throw new 
IllegalArgumentException(sm.getString("managerServlet.noContext",
+                                        RequestUtil.filter(displayPath)));
+        }
+        Session[] sessions = context.getManager().findSessions();
+        return sessions;
+    }
+    protected Session getSessionForPathAndId(String path, String id) throws 
IOException {
+        if ((path == null) || (!path.startsWith("/") && path.equals(""))) {
+            throw new 
IllegalArgumentException(sm.getString("managerServlet.invalidPath",
+                                        RequestUtil.filter(path)));
+        }
+        String displayPath = path;
+        if( path.equals("/") )
+            path = "";
+        Context context = (Context) host.findChild(path);
+        if (null == context) {
+            throw new 
IllegalArgumentException(sm.getString("managerServlet.noContext",
+                                        RequestUtil.filter(displayPath)));
+        }
+        Session session = context.getManager().findSession(id);
+        return session;
+    }
+
+    /**
+     * 
+     * @param req
+     * @param resp
+     * @throws ServletException
+     * @throws IOException
+     */
+    protected void displaySessionsListPage(String path, HttpServletRequest 
req, HttpServletResponse resp) throws ServletException, IOException {
+        List/*<Session>*/ activeSessions = 
Arrays.asList(getSessionsForPath(path));
+        String sortBy = req.getParameter("sort");
+        String orderBy = null;
+        if (null != sortBy && !"".equals(sortBy.trim())) {
+            Comparator comparator = getComparator(sortBy);
+            if (comparator != null) {
+                orderBy = req.getParameter("order");
+                if ("DESC".equalsIgnoreCase(orderBy)) {
+                    comparator = new ReverseComparator(comparator);
+                    // orderBy = "ASC";
+                } else {
+                    //orderBy = "DESC";
+                }
+                try {
+                                       Collections.sort(activeSessions, 
comparator);
+                               } catch (IllegalStateException ise) {
+                                       // at least 1 of the sessions is 
invalidated
+                                       req.setAttribute(APPLICATION_ERROR, 
"Can't sort session list: one session is invalidated");
+                               }
+            } else {
+                log("WARNING: unknown sort order: " + sortBy);
+            }
+        }
+        // keep sort order
+        req.setAttribute("sort", sortBy);
+        req.setAttribute("order", orderBy);
+        req.setAttribute("activeSessions", activeSessions);
+        //strong>NOTE</strong> - This header will be overridden
+        // automatically if a <code>RequestDispatcher.forward()</code> call is
+        // ultimately invoked.
+        resp.setHeader("Pragma", "No-cache"); // HTTP 1.0
+        resp.setHeader("Cache-Control", "no-cache,no-store,max-age=0"); // 
HTTP 1.1
+        resp.setDateHeader("Expires", 0); // 0 means now
+        
getServletContext().getRequestDispatcher(sessionsListJspPath).include(req, 
resp);
+    }
+
+    /**
+     * 
+     * @param req
+     * @param resp
+     * @throws ServletException
+     * @throws IOException
+     */
+    protected void displaySessionDetailPage(HttpServletRequest req, 
HttpServletResponse resp, String path, String sessionId) throws 
ServletException, IOException {
+        Session session = getSessionForPathAndId(path, sessionId);
+        //strong>NOTE</strong> - This header will be overridden
+        // automatically if a <code>RequestDispatcher.forward()</code> call is
+        // ultimately invoked.
+        resp.setHeader("Pragma", "No-cache"); // HTTP 1.0
+        resp.setHeader("Cache-Control", "no-cache,no-store,max-age=0"); // 
HTTP 1.1
+        resp.setDateHeader("Expires", 0); // 0 means now
+        req.setAttribute("currentSession", session);
+        
getServletContext().getRequestDispatcher(sessionDetailJspPath).include(req, 
resp);
+    }
+
+    /**
+     * Invalidate HttpSessions
+     * @param sessionIds
+     * @return number of invalidated sessions
+     * @throws IOException 
+     */
+    public int invalidateSessions(String path, String[] sessionIds) throws 
IOException {
+        if (null == sessionIds) {
+            return 0;
+        }
+        int nbAffectedSessions = 0;
+        for (int i = 0; i < sessionIds.length; ++i) {
+            String sessionId = sessionIds[i];
+            HttpSession session = getSessionForPathAndId(path, 
sessionId).getSession();
+            if (null == session) {
+                // Shouldn't happen, but let's play nice...
+               if (debug >= 1) {
+                       log("WARNING: can't invalidate null session " + 
sessionId);
+               }
+                continue;
+            }
+            try {
+                               session.invalidate();
+                               ++nbAffectedSessions;
+                   if (debug >= 1) {
+                       log("Invalidating session id " + sessionId);
+                   }
+                       } catch (IllegalStateException ise) {
+                               if (debug >= 1) {
+                                       log("Can't invalidate already 
invalidated session id " + sessionId);
+                               }
+                       }
+        }
+        return nbAffectedSessions;
+    }
+
+    /**
+     * Removes an attribute from an HttpSession
+     * @param sessionId
+     * @param attributeName
+     * @return true if there was an attribute removed, false otherwise
+     * @throws IOException 
+     */
+    public boolean removeSessionAttribute(String path, String sessionId, 
String attributeName) throws IOException {
+        HttpSession session = getSessionForPathAndId(path, 
sessionId).getSession();
+        if (null == session) {
+            // Shouldn't happen, but let's play nice...
+               if (debug >= 1) {
+                       log("WARNING: can't remove attribute '" + attributeName 
+ "' for null session " + sessionId);
+               }
+            return false;
+        }
+        boolean wasPresent = (null != session.getAttribute(attributeName));
+        try {
+            session.removeAttribute(attributeName);
+        } catch (IllegalStateException ise) {
+               if (debug >= 1) {
+                       log("Can't remote attribute '" + attributeName + "' for 
invalidated session id " + sessionId);
+               }
+        }
+        return wasPresent;
+    }
+
+    /**
+     * Sets the maximum inactive interval (session timeout) an HttpSession
+     * @param sessionId
+     * @param maxInactiveInterval in seconds
+     * @return old value for maxInactiveInterval
+     * @throws IOException 
+     */
+    public int setSessionMaxInactiveInterval(String path, String sessionId, 
int maxInactiveInterval) throws IOException {
+        HttpSession session = getSessionForPathAndId(path, 
sessionId).getSession();
+        if (null == session) {
+            // Shouldn't happen, but let's play nice...
+               if (debug >= 1) {
+                       log("WARNING: can't set timout for null session " + 
sessionId);
+               }
+            return 0;
+        }
+        try {
+                       int oldMaxInactiveInterval = 
session.getMaxInactiveInterval();
+                       session.setMaxInactiveInterval(maxInactiveInterval);
+                       return oldMaxInactiveInterval;
+        } catch (IllegalStateException ise) {
+               if (debug >= 1) {
+                       log("Can't set MaxInactiveInterval '" + 
maxInactiveInterval + "' for invalidated session id " + sessionId);
+               }
+               return 0;
+               }
+    }
+
+    protected Comparator getComparator(String sortBy) {
+        Comparator comparator = null;
+        if ("CreationTime".equalsIgnoreCase(sortBy)) {
+            comparator = new BaseSessionComparator() {
+                public Comparable getComparableObject(Session session) {
+                    return new Date(session.getCreationTime());
+                }
+            };
+        } else if ("id".equalsIgnoreCase(sortBy)) {
+            comparator = new BaseSessionComparator() {
+                public Comparable getComparableObject(Session session) {
+                    return session.getId();
+                }
+            };
+        } else if ("LastAccessedTime".equalsIgnoreCase(sortBy)) {
+            comparator = new BaseSessionComparator() {
+                public Comparable getComparableObject(Session session) {
+                    return new Date(session.getLastAccessedTime());
+                }
+            };
+        } else if ("MaxInactiveInterval".equalsIgnoreCase(sortBy)) {
+            comparator = new BaseSessionComparator() {
+                public Comparable getComparableObject(Session session) {
+                    return new Date(session.getMaxInactiveInterval());
+                }
+            };
+        } else if ("new".equalsIgnoreCase(sortBy)) {
+            comparator = new BaseSessionComparator() {
+                public Comparable getComparableObject(Session session) {
+                    return Boolean.valueOf(session.getSession().isNew());
+                }
+            };
+        } else if ("locale".equalsIgnoreCase(sortBy)) {
+            comparator = new BaseSessionComparator() {
+                public Comparable getComparableObject(Session session) {
+                    return JspHelper.guessDisplayLocaleFromSession(session);
+                }
+            };
+        } else if ("user".equalsIgnoreCase(sortBy)) {
+            comparator = new BaseSessionComparator() {
+                public Comparable getComparableObject(Session session) {
+                    return JspHelper.guessDisplayUserFromSession(session);
+                }
+            };
+        } else if ("UsedTime".equalsIgnoreCase(sortBy)) {
+            comparator = new BaseSessionComparator() {
+                public Comparable getComparableObject(Session session) {
+                    return new 
Date(SessionUtils.getUsedTimeForSession(session));
+                }
+            };
+        } else if ("InactiveTime".equalsIgnoreCase(sortBy)) {
+            comparator = new BaseSessionComparator() {
+                public Comparable getComparableObject(Session session) {
+                    return new 
Date(SessionUtils.getInactiveTimeForSession(session));
+                }
+            };
+        } else if ("TTL".equalsIgnoreCase(sortBy)) {
+            comparator = new BaseSessionComparator() {
+                public Comparable getComparableObject(Session session) {
+                    return new Date(SessionUtils.getTTLForSession(session));
+                }
+            };
+        }
+        //TODO: complete this to TTL, etc.
+        return comparator;
+    }
+
     // ------------------------------------------------------ Private Constants
 
     // These HTML sections are broken in relatively small sections, because of
@@ -586,7 +911,7 @@
         " <td class=\"row-left\" bgcolor=\"{5}\"><small><a 
href=\"{0}\">{0}</a></small></td>\n" +
         " <td class=\"row-left\" bgcolor=\"{5}\"><small>{1}</small></td>\n" +
         " <td class=\"row-center\" bgcolor=\"{5}\"><small>{2}</small></td>\n" +
-        " <td class=\"row-center\" bgcolor=\"{5}\"><small><a 
href=\"{3}\">{4}</a></small></td>\n";
+        " <td class=\"row-center\" bgcolor=\"{5}\"><small><a href=\"{3}\" 
target=\"_new\">{4}</a></small></td>\n";
 
     private static final String MANAGER_APP_ROW_BUTTON_SECTION =
         " <td class=\"row-left\" bgcolor=\"{8}\">\n" +

Added: tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/JspHelper.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/JspHelper.java?view=auto&rev=529444
==============================================================================
--- tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/JspHelper.java (added)
+++ tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/JspHelper.java Mon 
Apr 16 16:30:55 2007
@@ -0,0 +1,239 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.manager;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.text.DateFormat;
+import java.text.NumberFormat;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+
+import org.apache.catalina.Session;
+import org.apache.catalina.manager.util.SessionUtils;
+
+
+/**
+ * Helper JavaBean for JSPs, because JSTL 1.1/EL 2.0 is too dumb to
+ * to what I need (call methods with parameters), or I am too dumb to use it 
correctly. :)
+ * @author C&eacute;drik LIME
+ */
+public class JspHelper {
+
+    private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
+    private static final String DATE_FORMAT = "yyyy-MM-dd";
+    private static final String TIME_FORMAT = "HH:mm:ss";
+
+    /**
+     * Public constructor, so that this class can be considered a JavaBean
+     */
+    private JspHelper() {
+        super();
+    }
+
+    /**
+     * Try to get user locale from the session, if possible.
+     * IMPLEMENTATION NOTE: this method has explicit support for Tapestry 3 
and Struts 1.x
+     * @param in_session
+     * @return String
+     */
+    public static String guessDisplayLocaleFromSession(Session in_session) {
+        return localeToString(SessionUtils.guessLocaleFromSession(in_session));
+    }
+    private static String localeToString(Locale locale) {
+        if (locale != null) {
+            return locale.toString();//locale.getDisplayName();
+        } else {
+            return "";
+        }
+    }
+
+    /**
+     * Try to get user name from the session, if possible.
+     * @param in_session
+     * @return String
+     */
+    public static String guessDisplayUserFromSession(Session in_session) {
+        Object user = SessionUtils.guessUserFromSession(in_session);
+        return escapeXml(user);
+    }
+
+
+    public static String getDisplayCreationTimeForSession(Session in_session) {
+        try {
+                       DateFormat formatter = new 
SimpleDateFormat(DATE_TIME_FORMAT);
+                       return formatter.format(new 
Date(in_session.getCreationTime()));
+        } catch (IllegalStateException ise) {
+               //ignore: invalidated session
+               return "";
+               }
+    }
+
+    public static String getDisplayLastAccessedTimeForSession(Session 
in_session) {
+        try {
+                       DateFormat formatter = new 
SimpleDateFormat(DATE_TIME_FORMAT);
+                       return formatter.format(new 
Date(in_session.getLastAccessedTime()));
+        } catch (IllegalStateException ise) {
+               //ignore: invalidated session
+               return "";
+               }
+    }
+
+    public static String getDisplayUsedTimeForSession(Session in_session) {
+        return 
secondsToTimeString(SessionUtils.getUsedTimeForSession(in_session)/1000);
+    }
+
+    public static String getDisplayTTLForSession(Session in_session) {
+        return 
secondsToTimeString(SessionUtils.getTTLForSession(in_session)/1000);
+    }
+
+    public static String getDisplayInactiveTimeForSession(Session in_session) {
+        return 
secondsToTimeString(SessionUtils.getInactiveTimeForSession(in_session)/1000);
+    }
+
+    public static String secondsToTimeString(long in_seconds) {
+        StringBuffer buff = new StringBuffer(9);
+        long rest = in_seconds;
+        long hour = rest / 3600;
+        rest = rest % 3600;
+        long minute = rest / 60;
+        rest = rest % 60;
+        long second = rest;
+        if (hour < 10) {
+            buff.append('0');
+        }
+        buff.append(hour);
+        buff.append(':');
+        if (minute < 10) {
+            buff.append('0');
+        }
+        buff.append(minute);
+        buff.append(':');
+        if (second < 10) {
+            buff.append('0');
+        }
+        buff.append(second);
+        return buff.toString();
+    }
+
+
+    /**
+    * Following copied from 
org.apache.taglibs.standard.tag.common.core.OutSupport v1.1.2
+    * 
+    *  Optimized to create no extra objects and write directly
+    *  to the JspWriter using blocks of escaped and unescaped characters
+    *
+    */
+   private static void writeEscapedXml(char[] buffer, int length, Writer w) 
throws IOException {
+       int start = 0;
+
+       for (int i = 0; i < length; i++) {
+           char c = buffer[i];
+           if (c <= HIGHEST_SPECIAL) {
+               char[] escaped = specialCharactersRepresentation[c];
+               if (escaped != null) {
+                   // add unescaped portion
+                   if (start < i) {
+                       w.write(buffer,start,i-start);
+                   }
+                   // add escaped xml
+                   w.write(escaped);
+                   start = i + 1;
+               }
+           }
+       }
+       // add rest of unescaped portion
+       if (start < length) {
+           w.write(buffer,start,length-start);
+       }
+   }
+
+
+    /*
+     * Following copied from org.apache.taglibs.standard.tag.common.core.Util 
v1.1.2
+     */
+
+    private static final int HIGHEST_SPECIAL = '>';
+    private static char[][] specialCharactersRepresentation = new 
char[HIGHEST_SPECIAL + 1][];
+    static {
+        specialCharactersRepresentation['&'] = "&amp;".toCharArray();
+        specialCharactersRepresentation['<'] = "&lt;".toCharArray();
+        specialCharactersRepresentation['>'] = "&gt;".toCharArray();
+        specialCharactersRepresentation['"'] = "&#034;".toCharArray();
+        specialCharactersRepresentation['\''] = "&#039;".toCharArray();
+    }
+
+    public static String escapeXml(Object obj) {
+       return obj == null ? "" : escapeXml(String.valueOf(obj));
+    }
+    /**
+     * Performs the following substring replacements
+     * (to facilitate output to XML/HTML pages):
+     *
+     *    & -> &amp;
+     *    < -> &lt;
+     *    > -> &gt;
+     *    " -> &#034;
+     *    ' -> &#039;
+     *
+     * See also OutSupport.writeEscapedXml().
+     */
+    public static String escapeXml(String buffer) {
+       if (buffer == null) {
+                       return "";
+               }
+        int start = 0;
+        int length = buffer.length();
+        char[] arrayBuffer = buffer.toCharArray();
+        StringBuffer escapedBuffer = null;
+
+        for (int i = 0; i < length; i++) {
+            char c = arrayBuffer[i];
+            if (c <= HIGHEST_SPECIAL) {
+                char[] escaped = specialCharactersRepresentation[c];
+                if (escaped != null) {
+                    // create StringBuffer to hold escaped xml string
+                    if (start == 0) {
+                        escapedBuffer = new StringBuffer(length + 5);
+                    }
+                    // add unescaped portion
+                    if (start < i) {
+                        escapedBuffer.append(arrayBuffer,start,i-start);
+                    }
+                    start = i + 1;
+                    // add escaped xml
+                    escapedBuffer.append(escaped);
+                }
+            }
+        }
+        // no xml escaping was necessary
+        if (start == 0) {
+            return buffer;
+        }
+        // add rest of unescaped portion
+        if (start < length) {
+            escapedBuffer.append(arrayBuffer,start,length-start);
+        }
+        return escapedBuffer.toString();
+    }
+
+    public static String formatNumber(long number) {
+       return NumberFormat.getNumberInstance().format(number);
+    }
+}

Propchange: tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/JspHelper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/BaseSessionComparator.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/BaseSessionComparator.java?view=auto&rev=529444
==============================================================================
--- 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/BaseSessionComparator.java
 (added)
+++ 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/BaseSessionComparator.java
 Mon Apr 16 16:30:55 2007
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.manager.util;
+
+import java.util.Comparator;
+
+import org.apache.catalina.Session;
+
+/**
+ * Comparator which permits to compare on a session's content
+ * @author C&eacute;drik LIME
+ */
+public abstract class BaseSessionComparator implements Comparator {
+
+    /**
+     * 
+     */
+    public BaseSessionComparator() {
+        super();
+    }
+
+    public abstract Comparable getComparableObject(Session session);
+
+    /* (non-Javadoc)
+     * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+     */
+    public final int compare(Object o1, Object o2) {
+        Comparable c1 = getComparableObject((Session)o1);
+        Comparable c2 = getComparableObject((Session)o2);
+        return c1==null ? (c2==null ? 0 : -1) : (c2==null ? 1 : 
c1.compareTo(c2));
+    }
+}

Propchange: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/BaseSessionComparator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/ReverseComparator.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/ReverseComparator.java?view=auto&rev=529444
==============================================================================
--- 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/ReverseComparator.java
 (added)
+++ 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/ReverseComparator.java
 Mon Apr 16 16:30:55 2007
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.manager.util;
+
+import java.util.Comparator;
+
+/**
+ * Comparator which reverse the sort order
+ * @author C&eacute;drik LIME
+ */
+public class ReverseComparator implements Comparator {
+    protected Comparator comparator;
+
+    /**
+     * 
+     */
+    public ReverseComparator(Comparator comparator) {
+        super();
+        this.comparator = comparator;
+    }
+
+    /* (non-Javadoc)
+     * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
+     */
+    public int compare(Object o1, Object o2) {
+        int returnValue = comparator.compare(o1, o2);
+        return (- returnValue);
+    }
+}

Propchange: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/ReverseComparator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/SessionUtils.java
URL: 
http://svn.apache.org/viewvc/tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/SessionUtils.java?view=auto&rev=529444
==============================================================================
--- 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/SessionUtils.java 
(added)
+++ 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/SessionUtils.java 
Mon Apr 16 16:30:55 2007
@@ -0,0 +1,267 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.catalina.manager.util;
+
+import java.lang.reflect.Method;
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Locale;
+
+import javax.security.auth.Subject;
+import javax.servlet.http.HttpSession;
+
+import org.apache.catalina.Session;
+
+/**
+ * Utility methods on HttpSessions...
+ * @author C&eacute;drik LIME
+ */
+public class SessionUtils {
+
+    /**
+     * 
+     */
+    private SessionUtils() {
+        super();
+    }
+
+    /**
+     * The session attributes key under which the user's selected
+     * <code>java.util.Locale</code> is stored, if any.
+     */
+    // org.apache.struts.Globals.LOCALE_KEY
+    private static final String STRUTS_LOCALE_KEY = 
"org.apache.struts.action.LOCALE";//$NON-NLS-1$
+    // javax.servlet.jsp.jstl.core.Config.FMT_LOCALE
+    private static final String JSTL_LOCALE_KEY   = 
"javax.servlet.jsp.jstl.fmt.locale";//$NON-NLS-1$
+    // 
org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE_SESSION_ATTRIBUTE_NAME
+    private static final String SPRING_LOCALE_KEY = 
"org.springframework.web.servlet.i18n.SessionLocaleResolver.LOCALE";//$NON-NLS-1$
+    /**
+     * Lower and upper-case strings will be dynamically generated. Put 
mid-capitalised strings here!
+     */
+    private static final String[] LOCALE_TEST_ATTRIBUTES = new String[] {
+        STRUTS_LOCALE_KEY, SPRING_LOCALE_KEY, JSTL_LOCALE_KEY, "Locale", 
"java.util.Locale" };
+    /**
+     * Lower and upper-case strings will be dynamically generated. Put 
mid-capitalised strings here!
+     */
+    private static final String[] USER_TEST_ATTRIBUTES = new String[] {
+        "Login", "User", "userName", "UserName", "Utilisateur" };
+
+    /**
+     * Try to get user locale from the session, if possible.
+     * IMPLEMENTATION NOTE: this method has explicit support for Tapestry 3, 
Struts 1.x and Spring
+     * JSF check the browser meta tag "accept languages" to choose what 
langage to display.
+     * @param in_session
+     * @return String
+     */
+    public static Locale guessLocaleFromSession(final Session in_session) {
+       return guessLocaleFromSession(in_session.getSession());
+    }
+    public static Locale guessLocaleFromSession(final HttpSession in_session) {
+       if (null == in_session) {
+                       return null;
+               }
+        try {
+            Locale locale = null;
+            
+               // First search "known locations"
+               for (int i = 0; i < LOCALE_TEST_ATTRIBUTES.length; ++i) {
+                   Object obj = 
in_session.getAttribute(LOCALE_TEST_ATTRIBUTES[i]);
+                   if (null != obj && obj instanceof Locale) {
+                       locale = (Locale) obj;
+                       break;
+                   }
+                   obj = 
in_session.getAttribute(LOCALE_TEST_ATTRIBUTES[i].toLowerCase());
+                   if (null != obj && obj instanceof Locale) {
+                       locale = (Locale) obj;
+                       break;
+                   }
+                   obj = 
in_session.getAttribute(LOCALE_TEST_ATTRIBUTES[i].toUpperCase());
+                   if (null != obj && obj instanceof Locale) {
+                       locale = (Locale) obj;
+                       break;
+                   }
+               }
+       
+               if (null != locale) {
+                   return locale;
+               }
+       
+               // Tapestry 3.0: Engine stored in session under 
"org.apache.tapestry.engine:" + config.getServletName()
+               // TODO: Tapestry 4+
+               {
+                   final List tapestryArray = new ArrayList();
+                   for (Enumeration enumeration = 
in_session.getAttributeNames(); enumeration.hasMoreElements();) {
+                       String name = (String) enumeration.nextElement();
+                       if (name.indexOf("tapestry") > -1 && 
name.indexOf("engine") > -1 && null != in_session.getAttribute(name)) 
{//$NON-NLS-1$ //$NON-NLS-2$
+                           tapestryArray.add(in_session.getAttribute(name));
+                       }
+                   }
+                   if (tapestryArray.size() == 1) {
+                       // found a potential Engine! Let's call getLocale() on 
it.
+                       Object probableEngine = tapestryArray.get(0);
+                       if (null != probableEngine) {
+                           try {
+                               Method readMethod = 
probableEngine.getClass().getMethod("getLocale", null);//$NON-NLS-1$
+                               if (null != readMethod) {
+                                   // Call the property getter and return the 
value
+                                   Object possibleLocale = 
readMethod.invoke(probableEngine, null);
+                                   if (null != possibleLocale && 
possibleLocale instanceof Locale) {
+                                       locale = (Locale) possibleLocale;
+                                   }
+                               }
+                           } catch (Exception e) {
+                               // stay silent
+                           }
+                       }
+                   }
+               }
+               
+               if (null != locale) {
+                   return locale;
+               }
+       
+               // Last guess: iterate over all attributes, to find a Locale
+               // If there is only one, consider it to be /the/ locale
+               {
+                   final List localeArray = new ArrayList();
+                   for (Enumeration enumeration = 
in_session.getAttributeNames(); enumeration.hasMoreElements();) {
+                       String name = (String) enumeration.nextElement();
+                       Object obj = in_session.getAttribute(name);
+                       if (null != obj && obj instanceof Locale) {
+                           localeArray.add(obj);
+                       }
+                   }
+                   if (localeArray.size() == 1) {
+                       locale = (Locale) localeArray.get(0);
+                   }
+               }
+
+               return locale;
+        } catch (IllegalStateException ise) {
+               //ignore: invalidated session
+               return null;
+        }
+    }
+
+    /**
+     * Try to get user from the session, if possible.
+     * @param in_session
+     * @return Object
+     */
+    public static Object guessUserFromSession(final Session in_session) {
+       if (null == in_session) {
+                       return null;
+               }
+       if (in_session.getPrincipal() != null) {
+                       return in_session.getPrincipal().getName();
+               }
+       HttpSession httpSession = in_session.getSession();
+       try {
+               Object user = null;
+               // First search "known locations"
+               for (int i = 0; i < USER_TEST_ATTRIBUTES.length; ++i) {
+                   Object obj = 
httpSession.getAttribute(USER_TEST_ATTRIBUTES[i]);
+                   if (null != obj) {
+                       user = obj;
+                       break;
+                   }
+                   obj = 
httpSession.getAttribute(USER_TEST_ATTRIBUTES[i].toLowerCase());
+                   if (null != obj) {
+                       user = obj;
+                       break;
+                   }
+                   obj = 
httpSession.getAttribute(USER_TEST_ATTRIBUTES[i].toUpperCase());
+                   if (null != obj) {
+                       user = obj;
+                       break;
+                   }
+               }
+       
+               if (null != user) {
+                   return user;
+               }
+       
+               // Last guess: iterate over all attributes, to find a 
java.security.Principal or javax.security.auth.Subject
+               // If there is only one, consider it to be /the/ user
+               {
+                   final List principalArray = new ArrayList();
+                   for (Enumeration enumeration = 
httpSession.getAttributeNames(); enumeration.hasMoreElements();) {
+                       String name = (String) enumeration.nextElement();
+                       Object obj = httpSession.getAttribute(name);
+                       if (null != obj && (obj instanceof Principal || obj 
instanceof Subject)) {
+                           principalArray.add(obj);
+                       }
+                       // This workaround for JDK 1.3 compatibility. For JDK 
1.4+, use previous (commented) instanceof.
+//                     try {
+//                         Class subjectClass = 
Class.forName("javax.security.auth.Subject", true, 
Thread.currentThread().getContextClassLoader());
+//                         if (subjectClass.isInstance(obj)) {
+//                             principalArray.add(obj);
+//                         }
+//                     } catch (ClassNotFoundException cnfe) {
+//                         // This is JDK 1.3: javax.security.auth.Subject 
does not exist; do nothing
+//                     }
+                   }
+                   if (principalArray.size() == 1) {
+                       user = principalArray.get(0);
+                   }
+               }
+       
+               if (null != user) {
+                   return user;
+               }
+
+               return user;
+        } catch (IllegalStateException ise) {
+               //ignore: invalidated session
+               return null;
+        }
+    }
+
+
+    public static long getUsedTimeForSession(Session in_session) {
+        try {
+                       long diffMilliSeconds = 
in_session.getLastAccessedTime() - in_session.getCreationTime();
+                       return diffMilliSeconds;
+        } catch (IllegalStateException ise) {
+               //ignore: invalidated session
+               return -1;
+               }
+    }
+
+    public static long getTTLForSession(Session in_session) {
+        try {
+                       long diffMilliSeconds = 
(1000*in_session.getMaxInactiveInterval()) - (System.currentTimeMillis() - 
in_session.getLastAccessedTime());
+                       return diffMilliSeconds;
+        } catch (IllegalStateException ise) {
+               //ignore: invalidated session
+               return -1;
+               }
+    }
+
+    public static long getInactiveTimeForSession(Session in_session) {
+        try {
+                       long diffMilliSeconds =  System.currentTimeMillis() - 
in_session.getLastAccessedTime();
+                       return diffMilliSeconds;
+        } catch (IllegalStateException ise) {
+               //ignore: invalidated session
+               return -1;
+               }
+    }
+}

Propchange: 
tomcat/tc6.0.x/trunk/java/org/apache/catalina/manager/util/SessionUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to