You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by co...@apache.org on 2009/04/04 18:24:36 UTC

svn commit: r761964 [9/10] - in /tomcat/trunk/modules/tomcat-lite/java: ./ org/ org/apache/ org/apache/tomcat/ org/apache/tomcat/addons/ org/apache/tomcat/integration/ org/apache/tomcat/integration/jmx/ org/apache/tomcat/integration/simple/ org/apache/...

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,214 @@
+/*
+ * 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.tomcat.servlets.jsp;
+
+import java.util.Vector;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+
+import org.apache.tomcat.addons.UserTemplateClassMapper;
+
+/** 
+ * Extracted from Jasper - maps a template file ( foo/my.jsp ) to a classname
+ * that is generated by the UserTemplateCompiler.
+ * 
+ * TODO: transform this to an interface, paired with UserTemplateCompiler.
+ * 
+ * @author Costin Manolache
+ */
+public class SimpleTemplateClassMapper implements UserTemplateClassMapper {
+
+    /** 
+     * Load the proxied jsp, if any.
+     * @param config 
+     * @throws ServletException 
+     */
+    public Servlet loadProxy(String jspFile, 
+                             ServletContext ctx, 
+                             ServletConfig config) throws ServletException {
+        String mangledClass = getClassName( jspFile );
+
+        HttpServlet jsp = null;
+        Class jspC = null;
+        
+        // Already created
+        if( jspC == null ) {
+            try {
+                jspC=Class.forName( mangledClass );
+            } catch( Throwable t ) {
+                // Not found - first try 
+            }
+        }
+        
+        if (jspC == null) {
+            // Class not found - needs to be compiled
+            return compileAndInitPage(ctx, jspFile, config);
+        }
+        
+        try {
+            jsp=(HttpServlet)jspC.newInstance();
+        } catch( Throwable t ) {
+            t.printStackTrace();
+        }
+        jsp.init(config);
+        return jsp;
+    }
+    
+    public boolean needsReload(String jspFile, Servlet s) {
+        return false;
+    }
+    
+    protected Servlet compileAndInitPage(ServletContext ctx, 
+                                      String jspUri, 
+                                      ServletConfig cfg) 
+        throws ServletException {
+        throw new ServletException("Pre-compiled page not found, please " +
+        		"add a compiler addon to compile at runtime");
+    }
+    
+    /** Convert an identifier to a class name, using jasper conventions
+     * 
+     * @param jspUri a relative JSP file
+     * @return class name that would be generated by jasper
+     */
+    public String getClassName( String jspUri ) {
+        int iSep = jspUri.lastIndexOf('/') + 1;
+        String className = makeJavaIdentifier(jspUri.substring(iSep));
+        String basePackageName = JSP_PACKAGE_NAME;
+
+        iSep--;
+        String derivedPackageName = (iSep > 0) ?
+                makeJavaPackage(jspUri.substring(1,iSep)) : "";
+        
+        if (derivedPackageName.length() == 0) {
+            return basePackageName + "." + className;
+        }
+        return basePackageName + '.' + derivedPackageName + "." + className;
+    }
+
+    // ------------- Copied from jasper ---------------------------
+
+    private static final String JSP_PACKAGE_NAME = "org.apache.jsp";
+
+    private static final String makeJavaIdentifier(String identifier) {
+        StringBuffer modifiedIdentifier = 
+            new StringBuffer(identifier.length());
+        if (!Character.isJavaIdentifierStart(identifier.charAt(0))) {
+            modifiedIdentifier.append('_');
+        }
+        for (int i = 0; i < identifier.length(); i++) {
+            char ch = identifier.charAt(i);
+            if (Character.isJavaIdentifierPart(ch) && ch != '_') {
+                modifiedIdentifier.append(ch);
+            } else if (ch == '.') {
+                modifiedIdentifier.append('_');
+            } else {
+                modifiedIdentifier.append(mangleChar(ch));
+            }
+        }
+        if (isJavaKeyword(modifiedIdentifier.toString())) {
+            modifiedIdentifier.append('_');
+        }
+        return modifiedIdentifier.toString();
+    }
+
+    private static final String javaKeywords[] = {
+        "abstract", "assert", "boolean", "break", "byte", "case",
+        "catch", "char", "class", "const", "continue",
+        "default", "do", "double", "else", "enum", "extends",
+        "final", "finally", "float", "for", "goto",
+        "if", "implements", "import", "instanceof", "int",
+        "interface", "long", "native", "new", "package",
+        "private", "protected", "public", "return", "short",
+        "static", "strictfp", "super", "switch", "synchronized",
+        "this", "throws", "transient", "try", "void",
+        "volatile", "while" };
+
+    private static final String makeJavaPackage(String path) {
+        String classNameComponents[] = split(path,"/");
+        StringBuffer legalClassNames = new StringBuffer();
+        for (int i = 0; i < classNameComponents.length; i++) {
+            legalClassNames.append(makeJavaIdentifier(classNameComponents[i]));
+            if (i < classNameComponents.length - 1) {
+                legalClassNames.append('.');
+            }
+        }
+        return legalClassNames.toString();
+    }
+
+    private static final String [] split(String path, String pat) {
+        Vector comps = new Vector();
+        int pos = path.indexOf(pat);
+        int start = 0;
+        while( pos >= 0 ) {
+            if(pos > start ) {
+                String comp = path.substring(start,pos);
+                comps.add(comp);
+            }
+            start = pos + pat.length();
+            pos = path.indexOf(pat,start);
+        }
+        if( start < path.length()) {
+            comps.add(path.substring(start));
+        }
+        String [] result = new String[comps.size()];
+        for(int i=0; i < comps.size(); i++) {
+            result[i] = (String)comps.elementAt(i);
+        }
+        return result;
+    }
+            
+
+    /**
+     * Test whether the argument is a Java keyword
+     */
+    private static boolean isJavaKeyword(String key) {
+        int i = 0;
+        int j = javaKeywords.length;
+        while (i < j) {
+            int k = (i+j)/2;
+            int result = javaKeywords[k].compareTo(key);
+            if (result == 0) {
+                return true;
+            }
+            if (result < 0) {
+                i = k+1;
+            } else {
+                j = k;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Mangle the specified character to create a legal Java class name.
+     */
+    private static final String mangleChar(char ch) {
+        char[] result = new char[5];
+        result[0] = '_';
+        result[1] = Character.forDigit((ch >> 12) & 0xf, 16);
+        result[2] = Character.forDigit((ch >> 8) & 0xf, 16);
+        result[3] = Character.forDigit((ch >> 4) & 0xf, 16);
+        result[4] = Character.forDigit(ch & 0xf, 16);
+        return new String(result);
+    }
+    
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SimpleTemplateClassMapper.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,61 @@
+/*
+ */
+package org.apache.tomcat.servlets.jsp;
+
+import java.util.Stack;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/** For SingleThreadedServlet support. 
+ * 
+ * This is container independent.
+ * 
+ * Will maintain a pool of servlets, etc 
+ * 
+ * @author Costin Manolache
+ */
+public class SingleThreadedProxyServlet extends HttpServlet {
+
+    private Class classClass = null;
+    private transient boolean singleThreadModel = false;
+    /**
+     * Stack containing the STM instances.
+     */
+    private transient Stack instancePool = null;
+
+    /**
+     * Extra params: 
+     *   - servlet-class - the class of the single-threaded servlet
+     *   - 
+     * 
+     */
+    public void init() {
+        
+    }
+    
+    public void service(HttpServletRequest req, HttpServletResponse res) throws ServletException {
+        synchronized (instancePool) {
+            if (instancePool.isEmpty()) {
+                try {
+                    Servlet newServlet = null; // loadServlet();
+
+                    // todo: should we init each of them ?
+                    
+                    newServlet.service(req, res);
+                    
+                    
+                } catch (Throwable e) {
+                    throw new ServletException("allocate ",
+                            e);
+                }
+            }
+            Servlet s = (Servlet) instancePool.pop();
+        }
+
+        
+    }
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/SingleThreadedProxyServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,108 @@
+/*
+ * 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.tomcat.servlets.jsp;
+
+import java.io.IOException;
+import java.util.HashMap;
+
+import javax.servlet.Servlet;
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tomcat.addons.UserTemplateClassMapper;
+import org.apache.tomcat.integration.ObjectManager;
+
+
+/** 
+ *
+ * @author Costin Manolache
+ */
+public class WildcardTemplateServlet extends HttpServlet {
+
+    // for the '*.jsp' case - need to keep track of the jsps
+    HashMap<String, Servlet> jsps=new HashMap<String, Servlet>();
+
+    UserTemplateClassMapper mapper;
+    
+    /** 
+     * If called from a <jsp-file> servlet, compile the servlet and init it.
+     */
+    public void init(ServletConfig config) throws ServletException {
+        super.init(config);
+        ObjectManager om = 
+            (ObjectManager) config.getServletContext().getAttribute(ObjectManager.ATTRIBUTE);
+        mapper = 
+            (UserTemplateClassMapper) om.get(
+                    UserTemplateClassMapper.class);
+        if (mapper == null) {
+            mapper = new SimpleTemplateClassMapper();
+        }
+    }
+
+    // TODO: use context extensions to register the servlet as if it would be 
+    // loaded from web.xml
+    
+    protected void service(HttpServletRequest req, HttpServletResponse res)
+        throws ServletException, IOException 
+    {
+        // This is a *.jsp mapping.
+        String jspPath = null;
+
+        /** 
+         * Magic to get the jsp file from the mappings or container
+         */
+        if (jspPath == null) {
+            jspPath = (String)req.getAttribute("org.apache.catalina.jsp_file");
+        }
+        if (jspPath == null) {
+            // RequestDispatcher.include()
+            jspPath = (String)req.getAttribute("javax.servlet.include.servlet_path");
+            if (jspPath != null) {
+                String pathInfo = (String)req.getAttribute("javax.servlet.include.path_info");
+                if (pathInfo != null) {
+                    jspPath += pathInfo;
+                }
+            } else {
+                jspPath = req.getServletPath();
+                String pathInfo = req.getPathInfo();
+                if (pathInfo != null) {
+                    jspPath += pathInfo;
+                }
+            }
+        }
+        
+        // now we should have jspUri == the path to the jsp.
+        Servlet realJspServlet = jsps.get(jspPath);
+        
+        // TODO: support reload
+        
+        if (realJspServlet == null) {
+            realJspServlet = mapper.loadProxy(jspPath, 
+                    getServletContext(), getServletConfig());
+            if (realJspServlet != null) {
+                jsps.put(jspPath, realJspServlet);
+            } else {
+                throw new ServletException(jspPath + " not found");
+            }
+        }
+        
+        realJspServlet.service(req,  res);
+    }    
+} 

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/jsp/WildcardTemplateServlet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/AccessFilter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/AccessFilter.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/AccessFilter.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/AccessFilter.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,146 @@
+/*
+ * Copyright 1999-2001,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.servlets.sec;
+
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.tomcat.addons.UserAuthentication;
+
+
+/**
+ * Access control. 
+ * 
+ * In Catalina, the AuthenticatorBase.invoke() will apply the security
+ * filters based on LoginConfig. All constraints are applied in the 
+ * valve. For sessions - the Principal will be cached. The TTL needs to be
+ * indicated by the authenticator.
+ * 
+ * This works differently - it's a regular filter, could be modified and 
+ * set in web.xml explicitely, or set by the container when reading web.xml
+ * 
+ * 
+ * Mappings:
+ * 
+ *  /[FORM]/j_security_check ( with j_password, j_username params )
+ *   -> authentication servlet
+ *   Assert: no other j_security_check mapping
+ *   
+ *  
+ * For each security rule we define one AccessFilter, configured with the 
+ * right init-params.  
+ * 
+ * 1. For each security_constraint, create a (base) filter named: _access_nnn, 
+ * and add init-params for roles 
+ * 
+ * 1.1 For each web-resource-collection, take the method set, sort it. Create
+ * one filter for each set of methods, named _access_nnn_methodlist
+ * 
+ * 2.For each pattern in each web-resource-collection, add a mapping to 
+ * the appropriate filter, at the end of web.xml ( after normal filters
+ * and servlets ).
+ *   
+ * 
+ * @author Costin Manolache
+ */
+public class AccessFilter implements Filter {
+  
+    // web-resource-collection: name -> url+method rules
+    // Since filters don't match method, for each method subset we need a new
+    // filter instance
+    private String[] methods; 
+    
+    // Wildcard on roles - anyone authenticated can access the resource
+    private boolean allRoles = false;
+
+    // if false - no access control needed. 
+    // if true - must check roles - either allRoles or specific list
+    private boolean authConstraint = false;
+
+    // roles to check
+    private String authRoles[] = new String[0];
+
+    /**
+     * The user data constraint for this security constraint.  Must be NONE,
+     * INTEGRAL, or CONFIDENTIAL.
+     */
+    private String userConstraint = "NONE";
+
+    
+    public void destroy() {
+    }
+
+    public static class AuthToken {
+        public String headerValue; // key
+        public long expiry; 
+        public Principal principal;
+    }
+
+    Map cachedTokens = new HashMap();
+
+    UserAuthentication auth;
+    String method;
+    
+    public void doFilter(ServletRequest request, 
+                         ServletResponse servletResponse, 
+                         FilterChain chain) 
+            throws IOException, ServletException {
+        
+        HttpServletResponse res = (HttpServletResponse)servletResponse;
+        HttpServletRequest req = (HttpServletRequest)request;
+
+        String method = req.getMethod();
+        // exclude the context path
+        String uri = req.getServletPath() + req.getPathInfo(); 
+        
+        // no authorization or principal not found. 
+        // Call the auth servlet.
+        // TODO: use URL or RD.include.
+        
+        Principal p = auth.authenticate(req, res, method);
+        // set the principal on req!
+        if (p == null) {
+            // couldn't authenticate - response is set.
+            return;
+        } else {
+            // we are ok - cache the response, forward
+            
+            chain.doFilter(req, res);
+        }
+        
+    }
+
+
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/AccessFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/BasicAuthentication.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/BasicAuthentication.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/BasicAuthentication.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/BasicAuthentication.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,94 @@
+/*
+ * 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.tomcat.servlets.sec;
+
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.addons.UserAuthentication;
+
+
+/**
+ * Implements Basic authentication.
+ */
+public class BasicAuthentication implements UserAuthentication {
+
+    private static Log log = LogFactory.getLog(BasicAuthentication.class);
+    String realm;
+    
+    @Override
+    public Principal authenticate(HttpServletRequest request,
+                                  HttpServletResponse response,
+                                  String requestedMethod) throws IOException {
+            
+        if (realm == null)
+            realm = request.getServerName() + ":" + request.getServerPort();
+
+        // Validate any credentials already included with this request
+        String authorization = request.getHeader("authorization");
+        if (authorization != null) {
+            Principal principal = null; // processDigestHeader(request, authorization);
+            if (principal != null) {
+                return principal;
+            }
+        }
+
+        String domain = request.getContextPath();
+        String authHeader = getAuthenticateHeader(domain, false);
+        
+        response.setHeader("WWW-Authenticate", authHeader);
+        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+        return null;
+    }
+    
+    
+    /** Generate the auth header
+     */
+    protected String getAuthenticateHeader(String domain,
+                                           boolean stale) {
+
+        long currentTime = System.currentTimeMillis();
+        return "";
+    }
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    public Principal authenticate(final String username, String clientDigest,
+                                  String nOnce, String nc, String cnonce,
+                                  String qop, String realm,
+                                  String md5a2) {
+
+        
+        String serverDigest = null;
+
+        return null;
+    }
+
+
+    @Override
+    public boolean isUserInRole(HttpServletRequest req, Principal p, String role) {
+        return false;
+    }
+    
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/BasicAuthentication.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/FormAuthentication.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/FormAuthentication.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/FormAuthentication.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/FormAuthentication.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,95 @@
+/*
+ * 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.tomcat.servlets.sec;
+
+
+import java.io.IOException;
+import java.security.Principal;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.addons.UserAuthentication;
+
+
+/**
+ * Implements Form authentication.
+ */
+public class FormAuthentication implements UserAuthentication {
+
+    private static Log log = LogFactory.getLog(FormAuthentication.class);
+    String realm;
+    String url;
+    
+    @Override
+    public Principal authenticate(HttpServletRequest request,
+                                  HttpServletResponse response,
+                                  String requestedMethod) throws IOException {
+            
+        if (realm == null)
+            realm = request.getServerName() + ":" + request.getServerPort();
+
+        // Validate any credentials already included with this request
+        String authorization = request.getHeader("authorization");
+        if (authorization != null) {
+            Principal principal = null; // processDigestHeader(request, authorization);
+            if (principal != null) {
+                return principal;
+            }
+        }
+
+        String domain = request.getContextPath();
+        String authHeader = getAuthenticateHeader(domain, false);
+        
+        response.setHeader("WWW-Authenticate", authHeader);
+        response.sendError(HttpServletResponse.SC_UNAUTHORIZED);
+        return null;
+    }
+    
+    
+    /** Generate the auth header
+     */
+    protected String getAuthenticateHeader(String domain,
+                                           boolean stale) {
+
+        long currentTime = System.currentTimeMillis();
+        return "";
+    }
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    public Principal authenticate(final String username, String clientDigest,
+                                  String nOnce, String nc, String cnonce,
+                                  String qop, String realm,
+                                  String md5a2) {
+
+        
+        String serverDigest = null;
+
+        return null;
+    }
+
+
+    @Override
+    public boolean isUserInRole(HttpServletRequest req, Principal p, String role) {
+        return false;
+    }
+    
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/FormAuthentication.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/IPFilter.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/IPFilter.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/IPFilter.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/IPFilter.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,118 @@
+/*
+ * Copyright 1999-2001,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.servlets.sec;
+
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.regex.Pattern;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+
+
+/**
+ * Reimplementation of catalina IP valve.
+ * 
+ */
+public class IPFilter implements Filter {
+    /**
+     * The set of <code>allow</code> regular expressions we will evaluate.
+     */
+    protected Pattern allows[] = new Pattern[0];
+
+
+    /**
+     * The set of <code>deny</code> regular expressions we will evaluate.
+     */
+    protected Pattern denies[] = new Pattern[0];
+
+    // --------------------------------------------------------- Public Methods
+
+    public void setAllows(String pattern) {
+        allows = getPatterns(pattern);
+    }
+    
+    public void setDenies(String pattern) {
+        denies = getPatterns(pattern);
+    }
+    
+    private Pattern[] getPatterns(String pattern) {
+        String[] patSplit = pattern.split(",");
+        ArrayList allowsAL = new ArrayList();
+        for( int i=0; i<patSplit.length; i++) {
+            patSplit[i] = patSplit[i].trim();
+            if (!patSplit[i].equals("")) {
+                allowsAL.add(Pattern.compile(patSplit[i]));
+            }
+        }
+        // TODO
+        Pattern[] result = new Pattern[allowsAL.size()];
+        allowsAL.toArray(result);
+        return result;
+    }
+    
+    public void destroy() {
+    }
+
+
+    public void doFilter(ServletRequest request, 
+                         ServletResponse servletResponse, 
+                         FilterChain chain) 
+            throws IOException, ServletException {
+        
+        HttpServletResponse response = (HttpServletResponse)servletResponse;
+        String property = request.getRemoteAddr();
+        
+        // Check the deny patterns, if any
+        for (int i = 0; i < denies.length; i++) {
+            if (denies[i].matcher(property).matches()) {
+                response.sendError(HttpServletResponse.SC_FORBIDDEN);
+                return;
+            }
+        }
+
+        // Check the allow patterns, if any
+        for (int i = 0; i < allows.length; i++) {
+            if (allows[i].matcher(property).matches()) {
+                chain.doFilter(request, response);
+                return;
+            }
+        }
+
+        // Allow if denies specified but not allows
+        if ((denies.length > 0) && (allows.length == 0)) {
+            chain.doFilter(request, response);
+            return;
+        }
+
+        // Deny this request
+        response.sendError(HttpServletResponse.SC_FORBIDDEN);
+    }
+
+
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/IPFilter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/SimpleUserAuthDB.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/SimpleUserAuthDB.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/SimpleUserAuthDB.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/SimpleUserAuthDB.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,83 @@
+/*
+ * Copyright 1999-2001,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.servlets.sec;
+
+
+import java.io.IOException;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Properties;
+
+import javax.servlet.ServletConfig;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/** 
+ * Load user/passwords from a file.
+ * 
+ * @author Costin Manolache
+ */
+public class SimpleUserAuthDB implements UserDB {
+    
+    private static final String USER_PREFIX = "u.";
+    private static final String ROLE_PREFIX = "r.";
+    
+    HashMap users = new HashMap();
+    HashMap roles = new HashMap();
+    
+    boolean hasMessageDigest = false;
+    String realm = null;
+    
+    public void addUser(String name, String pass) {
+        users.put(name, pass);
+    }
+    
+    public void addRole(String user, String value) {
+        String[] userRoles = value.split(",");
+        roles.put(user, userRoles);
+    }
+    
+    public void setFilename(String fileName) {
+        
+    }
+    
+    public void init(Properties p) throws ServletException {
+    }
+    
+    public void init(ServletConfig servletConfig) throws ServletException {
+        Enumeration names = servletConfig.getInitParameterNames();
+        while (names.hasMoreElements()) {
+            String name = (String)names.nextElement();
+            String value = servletConfig.getInitParameter(name);
+            if (name.startsWith(USER_PREFIX)) {
+                addUser(name.substring(USER_PREFIX.length()), value);
+            }
+            if (name.startsWith(ROLE_PREFIX)) {
+                addRole(name.substring(ROLE_PREFIX.length()), value);
+            }
+        }
+    }
+
+    public void checkAuth(String method, String cookie) {
+        
+    }
+
+
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/SimpleUserAuthDB.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/UserDB.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/UserDB.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/UserDB.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/UserDB.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,14 @@
+/*
+ */
+package org.apache.tomcat.servlets.sec;
+
+/**
+ * Interface to a password/role storage, used by the classes in
+ * this directory. 
+ * 
+ * @author Costin Manolache
+ */
+public interface UserDB {
+
+    //public void auth(String user, String md5);
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/sec/UserDB.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/session/HttpSessionImpl.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/session/HttpSessionImpl.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/session/HttpSessionImpl.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/session/HttpSessionImpl.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,784 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed 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.tomcat.servlets.session;
+
+
+import java.io.Serializable;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionAttributeListener;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+import javax.servlet.http.HttpSessionContext;
+import javax.servlet.http.HttpSessionEvent;
+import javax.servlet.http.HttpSessionListener;
+
+import org.apache.tomcat.servlets.util.Enumerator;
+
+/**
+ * Standard implementation of the <b>Session</b> interface.  
+ * 
+ * This is a minimal, non-serializable HttpSession. You can use a different 
+ * session manager, but you should keep in mind that persistent or distributed
+ * sessions are a bad thing. 
+ * 
+ * The session is best for caching data across requests, and tracking the 
+ * user flow. For any data you don't want to lose or is worth preserving - 
+ * use a transaction manager, or any form of storage that provides the 
+ * set of ACID characteristics you need. 
+ * 
+ * Even the most sophisticated sessions managers can't guarantee data integrity
+ * in 100% of cases, and can't notify you of the cases where a replication 
+ * failed. Using such a manager might fool users into making incorrect 
+ * assumptions. Computers and networks do crash at random points, and all
+ * the theory on transactions exists for a good reason.
+ * 
+ * Note: this is a user-space implementation, i.e. this can be used in any
+ * container by using the WebappSessionManager class.
+ *
+ * @author Costin Manolache - removed most of the code
+ * @author Craig R. McClanahan
+ * @author Sean Legassick
+ * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
+ */
+public class HttpSessionImpl  implements HttpSession, Serializable {
+
+    /**
+     * Type array, used as param to toArray()
+     */
+    protected static final String EMPTY_ARRAY[] = new String[0];
+
+    /**
+     * The HTTP session context associated with this session.
+     */
+    protected HttpSessionContext sessionContext = null;
+
+
+    /**
+     * The Manager with which this Session is associated.
+     */
+    protected transient SimpleSessionManager manager = null;
+
+    /**
+     * The session identifier of this Session.
+     */
+    protected String id = null;
+
+    /**
+     * The collection of user data attributes associated with this Session.
+     */
+    protected Map attributes = new HashMap();
+
+    /**
+     * The time this session was created, in milliseconds since midnight,
+     * January 1, 1970 GMT.
+     */
+    protected long creationTime = 0L;
+
+    /**
+     * The last accessed time for this Session.
+     */
+    protected long lastAccessedTime = creationTime;
+
+    /**
+     * The current accessed time for this session.
+     */
+    protected long thisAccessedTime = creationTime;
+
+    /**
+     * The maximum time interval, in seconds, between client requests before
+     * the servlet container may invalidate this session.  A negative time
+     * indicates that the session should never time out.
+     */
+    protected int maxInactiveInterval = -1;
+
+    /**
+     * The access count for this session - how many requests are using this
+     * session ( so we can prevent expiry )
+     */
+    protected transient int accessCount = 0;
+
+    /**
+     * We are currently processing a session expiration, so bypass
+     * certain IllegalStateException tests.  
+     */
+    protected transient boolean expiring = false;
+
+
+    /**
+     * Flag indicating whether this session is new or not.
+     */
+    protected boolean isNew = false;
+
+
+    /**
+     * Flag indicating whether this session is valid or not.
+     */
+    protected boolean isValid = false;
+
+
+    /** Only the manager can create sessions, so it knows about them.
+     */
+    HttpSessionImpl(SimpleSessionManager manager) {
+        this.manager = manager;
+    }
+
+    // ----------   API methods ---------
+
+    /**
+     * Return the session identifier for this session.
+     */
+    public String getId() {
+        return this.id;
+    }
+
+    /**
+     * Return the last time the client sent a request associated with this
+     * session, as the number of milliseconds since midnight, January 1, 1970
+     * GMT.  Actions that your application takes, such as getting or setting
+     * a value associated with the session, do not affect the access time.
+     */
+    public long getLastAccessedTime() {
+        checkValid();
+         return this.lastAccessedTime;
+
+    }
+
+    /**
+     * Return the maximum time interval, in seconds, between client requests
+     * before the servlet container will invalidate the session.  A negative
+     * time indicates that the session should never time out.
+     */
+    public int getMaxInactiveInterval() {
+        return this.maxInactiveInterval;
+    }
+
+
+    /**
+     * Set the maximum time interval, in seconds, between client requests
+     * before the servlet container will invalidate the session.  A negative
+     * time indicates that the session should never time out.
+     *
+     * @param interval The new maximum interval
+     */
+    public void setMaxInactiveInterval(int interval) {
+        this.maxInactiveInterval = interval;
+        if (isValid && interval == 0) {
+            expire();
+        }
+    }
+
+    /**
+     * Return the time when this session was created, in milliseconds since
+     * midnight, January 1, 1970 GMT.
+     *
+     * @exception IllegalStateException if this method is called on an
+     *  invalidated session
+     */
+    public long getCreationTime() {
+        checkValid();
+        return this.creationTime;
+
+    }
+
+    public ServletContext getServletContext() {
+        if (manager == null)
+            return null; // Should never happen
+        ServletContext context = (ServletContext)manager.getContext();
+        return context;
+    }
+
+
+    public HttpSessionContext getSessionContext() {
+        if (sessionContext == null)
+            sessionContext = new StandardSessionContext();
+        return (sessionContext);
+    }
+
+    /**
+     * Return the object bound with the specified name in this session, or
+     * <code>null</code> if no object is bound with that name.
+     *
+     * @param name Name of the attribute to be returned
+     *
+     * @exception IllegalStateException if this method is called on an
+     *  invalidated session
+     */
+    public Object getAttribute(String name) {
+        checkValid();
+        return attributes.get(name);
+    }
+
+
+    /**
+     * Return an <code>Enumeration</code> of <code>String</code> objects
+     * containing the names of the objects bound to this session.
+     *
+     * @exception IllegalStateException if this method is called on an
+     *  invalidated session
+     */
+    public Enumeration getAttributeNames() {
+        checkValid();
+        return new Enumerator(attributes.keySet(), true);
+    }
+
+
+    /**
+     * Return the object bound with the specified name in this session, or
+     * <code>null</code> if no object is bound with that name.
+     *
+     * @param name Name of the value to be returned
+     *
+     * @exception IllegalStateException if this method is called on an
+     *  invalidated session
+     *
+     * @deprecated As of Version 2.2, this method is replaced by
+     *  <code>getAttribute()</code>
+     */
+    public Object getValue(String name) {
+        return (getAttribute(name));
+    }
+
+
+    /**
+     * Return the set of names of objects bound to this session.  If there
+     * are no such objects, a zero-length array is returned.
+     *
+     * @exception IllegalStateException if this method is called on an
+     *  invalidated session
+     *
+     * @deprecated As of Version 2.2, this method is replaced by
+     *  <code>getAttributeNames()</code>
+     */
+    public String[] getValueNames() {
+        checkValid();
+        return keys(); // same, but no check for validity
+    }
+
+
+    /**
+     * Invalidates this session and unbinds any objects bound to it.
+     *
+     * @exception IllegalStateException if this method is called on
+     *  an invalidated session
+     */
+    public void invalidate() {
+        checkValid();
+        expire();
+    }
+
+
+    /**
+     * Return <code>true</code> if the client does not yet know about the
+     * session, or if the client chooses not to join the session.  For
+     * example, if the server used only cookie-based sessions, and the client
+     * has disabled the use of cookies, then a session would be new on each
+     * request.
+     *
+     * @exception IllegalStateException if this method is called on an
+     *  invalidated session
+     */
+    public boolean isNew() {
+        checkValid();
+        return (this.isNew);
+    }
+
+    public void putValue(String name, Object value) {
+        setAttribute(name, value);
+    }
+
+    public void removeAttribute(String name) {
+        checkValid();
+        removeAttributeInternal(name, true);
+    }
+
+    public void removeValue(String name) {
+        removeAttribute(name);
+    }
+
+
+    /**
+     * Bind an object to this session, using the specified name.  If an object
+     * of the same name is already bound to this session, the object is
+     * replaced.
+     * <p>
+     * After this method executes, and if the object implements
+     * <code>HttpSessionBindingListener</code>, the container calls
+     * <code>valueBound()</code> on the object.
+     *
+     * @param name Name to which the object is bound, cannot be null
+     * @param value Object to be bound, cannot be null
+     *
+     * @exception IllegalArgumentException if an attempt is made to add a
+     *  non-serializable object in an environment marked distributable.
+     * @exception IllegalStateException if this method is called on an
+     *  invalidated session
+     */
+    public void setAttribute(String name, Object value) {
+        // Name cannot be null
+        if (name == null) return;
+
+        // Null value is the same as removeAttribute()
+        if (value == null) {
+            removeAttribute(name);
+            return;
+        }
+
+        checkValid();
+        
+        if ((manager != null) && manager.getDistributable() &&
+          !(value instanceof Serializable))
+            throw new IllegalArgumentException("setAttribute() not serializable");
+
+        // Construct an event with the new value
+        HttpSessionBindingEvent event = null;
+
+        // Call the valueBound() method if necessary
+        if (value instanceof HttpSessionBindingListener) {
+            // Don't call any notification if replacing with the same value
+            Object oldValue = attributes.get(name);
+            if (value != oldValue) {
+                event = new HttpSessionBindingEvent(getSession(), name, value);
+                try {
+                    ((HttpSessionBindingListener) value).valueBound(event);
+                } catch (Throwable t){
+                    manager.log.error("Listener valueBound() error", t); 
+                }
+            }
+        }
+
+        // Replace or add this attribute
+        Object unbound = attributes.put(name, value);
+
+        // Call the valueUnbound() method if necessary
+        if ((unbound != null) && (unbound != value) &&
+            (unbound instanceof HttpSessionBindingListener)) {
+            try {
+                ((HttpSessionBindingListener) unbound).valueUnbound
+                    (new HttpSessionBindingEvent(getSession(), name));
+            } catch (Throwable t) {
+                manager.log.error("Listener valueUnbound()", t);
+            }
+        }
+
+        // Notify interested application event listeners
+        ServletContext context = manager.getContext();
+        List listeners = manager.getEventListeners();
+        if (listeners.size() == 0)
+            return;
+        for (int i = 0; i < listeners.size(); i++) {
+            if (!(listeners.get(i) instanceof HttpSessionAttributeListener))
+                continue;
+            HttpSessionAttributeListener listener =
+                (HttpSessionAttributeListener) listeners.get(i);
+            try {
+                if (unbound != null) {
+                    if (event == null) {
+                        event = new HttpSessionBindingEvent
+                            (getSession(), name, unbound);
+                    }
+                    listener.attributeReplaced(event);
+                } else {
+                    if (event == null) {
+                        event = new HttpSessionBindingEvent
+                            (getSession(), name, value);
+                    }
+                    listener.attributeAdded(event);
+                }
+            } catch (Throwable t) {
+                manager.log.error("Listener attibuteAdded/Replaced()", t);
+            }
+        }
+
+    }
+
+    // -------- Implementation - interactions with SessionManager -----
+    
+    /**
+     * Set the creation time for this session.  This method is called by the
+     * Manager when an existing Session instance is reused.
+     */
+    public void setCreationTime(long time) {
+        this.creationTime = time;
+        this.lastAccessedTime = time;
+        this.thisAccessedTime = time;
+    }
+
+    /**
+     * Set the session identifier for this session and notify listeners about
+     * new session
+     *
+     * @param id The new session identifier
+     */
+    public void setId(String id) {
+
+        if ((this.id != null) && (manager != null))
+            manager.remove(this);
+
+        this.id = id;
+
+        if (manager != null)
+            manager.add(this);
+        tellNew();
+    }
+
+
+    /**
+     * Inform the listeners about the new session.
+     */
+    public void tellNew() {
+        // Notify interested application event listeners
+        ServletContext context = manager.getContext();
+        List listeners = manager.getEventListeners();
+        if (listeners.size() > 0) {
+            HttpSessionEvent event =
+                new HttpSessionEvent(getSession());
+            for (int i = 0; i < listeners.size(); i++) {
+                Object listenerObj = listeners.get(i);
+                if (!(listenerObj instanceof HttpSessionListener))
+                    continue;
+                HttpSessionListener listener =
+                    (HttpSessionListener) listenerObj;
+                try {
+                    listener.sessionCreated(event);
+                } catch (Throwable t) {
+                    manager.log.error("listener.sessionCreated()", t);
+                }
+            }
+        }
+
+    }
+
+    /**
+     * Return the Manager within which this Session is valid.
+     */
+    public SimpleSessionManager getManager() {
+        return (this.manager);
+    }
+
+
+
+    /**
+     * Set the <code>isNew</code> flag for this session.
+     *
+     * @param isNew The new value for the <code>isNew</code> flag
+     */
+    public void setNew(boolean isNew) {
+        this.isNew = isNew;
+    }
+
+    public HttpSession getSession() {
+        return this;
+    }
+
+    private void checkValid() {
+        if ( !isValid() ) {
+            throw new IllegalStateException("checkValid");
+        }
+    }
+
+    /**
+     * Return the <code>isValid</code> flag for this session.
+     */
+    public boolean isValid() {
+        if (this.expiring) {
+            return true;
+        }
+        if (!this.isValid ) {
+            return false;
+        }
+        if (accessCount > 0) {
+            return true;
+        }
+        if (maxInactiveInterval >= 0) { 
+            long timeNow = System.currentTimeMillis();
+            int timeIdle = (int) ((timeNow - thisAccessedTime) / 1000L);
+            if (timeIdle >= maxInactiveInterval) {
+                expire(true);
+            }
+        }
+        return this.isValid;
+    }
+
+    public void setValid(boolean isValid) {
+        this.isValid = isValid;
+    }
+
+    /**
+     * Update the accessed time information for this session.  This method
+     * should be called by the context when a request comes in for a particular
+     * session, even if the application does not reference it.
+     */
+    public void access() {
+        this.lastAccessedTime = this.thisAccessedTime;
+        this.thisAccessedTime = System.currentTimeMillis();
+
+        evaluateIfValid();
+        accessCount++;
+    }
+
+
+    /**
+     * End the access.
+     */
+    public void endAccess() {
+        isNew = false;
+        accessCount--;
+    }
+
+    /**
+     * Perform the internal processing required to invalidate this session,
+     * without triggering an exception if the session has already expired.
+     */
+    public void expire() {
+        expire(true);
+    }
+
+
+    /**
+     * Perform the internal processing required to invalidate this session,
+     * without triggering an exception if the session has already expired.
+     *
+     * @param notify Should we notify listeners about the demise of
+     *  this session?
+     */
+    public void expire(boolean notify) {
+
+        // Mark this session as "being expired" if needed
+        if (expiring)
+            return;
+
+        synchronized (this) {
+
+            if (manager == null)
+                return;
+
+            expiring = true;
+        
+            // Notify interested application event listeners
+            // FIXME - Assumes we call listeners in reverse order
+            ServletContext context = manager.getContext();
+            List listeners = manager.getEventListeners();
+            if (notify && (listeners.size() > 0)) {
+                HttpSessionEvent event =
+                    new HttpSessionEvent(getSession());
+                for (int i = 0; i < listeners.size(); i++) {
+                    Object listenerObj = listeners.get(i);
+                    int j = (listeners.size() - 1) - i;
+                    if (!(listenerObj instanceof HttpSessionListener))
+                        continue;
+                    HttpSessionListener listener =
+                        (HttpSessionListener) listenerObj;
+                    try {
+                        listener.sessionDestroyed(event);
+                    } catch (Throwable t) {
+                        manager.log.error("listener.sessionDestroyed", t);
+                    }
+                }
+            }
+            accessCount = 0;
+            isValid = false;
+
+            /*
+             * Compute how long this session has been alive, and update
+             * session manager's related properties accordingly
+             */
+            long timeNow = System.currentTimeMillis();
+            int timeAlive = (int) ((timeNow - creationTime)/1000);
+            manager.addExpiredSession(timeAlive);
+
+            // Remove this session from our manager's active sessions
+            manager.remove(this);
+
+            expiring = false;
+
+            // Unbind any objects associated with this session
+            String keys[] = keys();
+            for (int i = 0; i < keys.length; i++)
+                removeAttributeInternal(keys[i], notify);
+        }
+    }
+
+
+    /**
+     * Release all object references, and initialize instance variables, in
+     * preparation for reuse of this object.
+     */
+    public void recycle() {
+
+        // Reset the instance variables associated with this Session
+        attributes.clear();
+        creationTime = 0L;
+        expiring = false;
+        id = null;
+        lastAccessedTime = 0L;
+        maxInactiveInterval = -1;
+        accessCount = 0;
+        isNew = false;
+        isValid = false;
+        manager = null;
+
+    }
+
+    /**
+     * Return a string representation of this object.
+     */
+    public String toString() {
+
+        StringBuffer sb = new StringBuffer();
+        sb.append("StandardSession[");
+        sb.append(id);
+        sb.append("]");
+        return (sb.toString());
+    }
+
+    protected void evaluateIfValid() {
+        /*
+         * If this session has expired or is in the process of expiring or
+         * will never expire, return
+         */
+        if (!this.isValid || expiring || maxInactiveInterval < 0)
+            return;
+
+        isValid();
+
+    }
+              
+    /**
+     * Return the names of all currently defined session attributes
+     * as an array of Strings.  If there are no defined attributes, a
+     * zero-length array is returned.
+     */
+    protected String[] keys() {
+        return ((String[]) attributes.keySet().toArray(EMPTY_ARRAY));
+    }
+
+
+    /**
+     * Remove the object bound with the specified name from this session.  If
+     * the session does not have an object bound with this name, this method
+     * does nothing.
+     * <p>
+     * After this method executes, and if the object implements
+     * <code>HttpSessionBindingListener</code>, the container calls
+     * <code>valueUnbound()</code> on the object.
+     *
+     * @param name Name of the object to remove from this session.
+     * @param notify Should we notify interested listeners that this
+     *  attribute is being removed?
+     */
+    protected void removeAttributeInternal(String name, boolean notify) {
+        // Remove this attribute from our collection
+        Object value = attributes.remove(name);
+
+        // Do we need to do valueUnbound() and attributeRemoved() notification?
+        if (!notify || (value == null)) {
+            return;
+        }
+
+        // Call the valueUnbound() method if necessary
+        HttpSessionBindingEvent event = null;
+        if (value instanceof HttpSessionBindingListener) {
+            event = new HttpSessionBindingEvent(getSession(), name, value);
+            ((HttpSessionBindingListener) value).valueUnbound(event);
+        }
+
+        // Notify interested application event listeners
+        ServletContext context = manager.getContext();
+        List listeners = manager.getEventListeners();
+        if (listeners.size() == 0)
+            return;
+        for (int i = 0; i < listeners.size(); i++) {
+            if (!(listeners.get(i) instanceof HttpSessionAttributeListener))
+                continue;
+            HttpSessionAttributeListener listener =
+                (HttpSessionAttributeListener) listeners.get(i);
+            try {
+                if (event == null) {
+                    event = new HttpSessionBindingEvent
+                        (getSession(), name, value);
+                }
+                listener.attributeRemoved(event);
+            } catch (Throwable t) {
+                manager.log.error("listener.attributeRemoved", t);
+            }
+        }
+
+    }
+    
+}
+
+
+// ------------------------------------------------------------ Protected Class
+
+
+/**
+ * This class is a dummy implementation of the <code>HttpSessionContext</code>
+ * interface, to conform to the requirement that such an object be returned
+ * when <code>HttpSession.getSessionContext()</code> is called.
+ *
+ * @author Craig R. McClanahan
+ *
+ * @deprecated As of Java Servlet API 2.1 with no replacement.  The
+ *  interface will be removed in a future version of this API.
+ */
+
+final class StandardSessionContext implements HttpSessionContext {
+
+
+    protected HashMap dummy = new HashMap();
+
+    /**
+     * Return the session identifiers of all sessions defined
+     * within this context.
+     *
+     * @deprecated As of Java Servlet API 2.1 with no replacement.
+     *  This method must return an empty <code>Enumeration</code>
+     *  and will be removed in a future version of the API.
+     */
+    public Enumeration getIds() {
+
+        return (new Enumerator(dummy));
+
+    }
+
+
+    /**
+     * Return the <code>HttpSession</code> associated with the
+     * specified session identifier.
+     *
+     * @param id Session identifier for which to look up a session
+     *
+     * @deprecated As of Java Servlet API 2.1 with no replacement.
+     *  This method must return null and will be removed in a
+     *  future version of the API.
+     */
+    public HttpSession getSession(String id) {
+
+        return (null);
+
+    }
+
+
+
+}

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/session/HttpSessionImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/session/RandomGenerator.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/session/RandomGenerator.java?rev=761964&view=auto
==============================================================================
--- tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/session/RandomGenerator.java (added)
+++ tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/session/RandomGenerator.java Sat Apr  4 16:24:34 2009
@@ -0,0 +1,352 @@
+package org.apache.tomcat.servlets.session;
+
+import java.io.DataInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.lang.reflect.Method;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Random;
+
+import org.apache.juli.logging.Log;
+import org.apache.juli.logging.LogFactory;
+
+/**
+ *  Generates random IDs, useable as cookies.
+ * 
+ *  Based on code from tomcat session manager - but general purpose.
+ *  Can use /dev/urandom or similar file.
+ *  
+ * 
+ */
+public class RandomGenerator {
+    protected DataInputStream randomIS=null;
+    protected String devRandomSource="/dev/urandom";
+
+    protected static Log log = LogFactory.getLog(RandomGenerator.class);
+
+    /**
+     * The message digest algorithm to be used when generating session
+     * identifiers.  This must be an algorithm supported by the
+     * <code>java.security.MessageDigest</code> class on your platform.
+     */
+    protected String algorithm = "MD5";
+
+    /**
+     * The session id length of Sessions created by this Manager.
+     */
+    protected int sessionIdLength = 16;
+
+    
+    /**
+     * Return the MessageDigest implementation to be used when
+     * creating session identifiers.
+     */
+    protected MessageDigest digest = null;
+
+    public String jvmRoute;
+
+    /**
+     * A String initialization parameter used to increase the entropy of
+     * the initialization of our random number generator.
+     */
+    protected String entropy = null;
+
+    /**
+     * A random number generator to use when generating session identifiers.
+     */
+    protected Random random = null;
+
+    /**
+     * Return the message digest algorithm for this Manager.
+     */
+    public String getAlgorithm() {
+        return (this.algorithm);
+    }
+    
+    public void init() {
+        // Initialize random number generation
+        getRandomBytes(new byte[16]);
+    }
+
+
+    /**
+     * Set the message digest algorithm for this Manager.
+     *
+     * @param algorithm The new message digest algorithm
+     */
+    public void setAlgorithm(String algorithm) {
+        this.algorithm = algorithm;
+    }
+    
+    /**
+     * Return the MessageDigest object to be used for calculating
+     * session identifiers.  If none has been created yet, initialize
+     * one the first time this method is called.
+     */
+    public synchronized MessageDigest getDigest() {
+
+        if (this.digest == null) {
+            long t1=System.currentTimeMillis();
+            try {
+                this.digest = MessageDigest.getInstance(algorithm);
+            } catch (NoSuchAlgorithmException e) {
+                log.error("Algorithm not found", e);
+                try {
+                    this.digest = MessageDigest.getInstance("MD5");
+                } catch (NoSuchAlgorithmException f) {
+                    log.error("No message digest available", f);
+                    this.digest = null;
+                }
+            }
+            long t2=System.currentTimeMillis();
+            if( log.isDebugEnabled() )
+                log.debug("getDigest() " + (t2-t1));
+        }
+
+        return (this.digest);
+
+    }
+    
+    /**
+     * Generate and return a new session identifier.
+     */
+    public synchronized String generateSessionId() {
+
+        byte random[] = new byte[16];
+        String result = null;
+
+        // Render the result as a String of hexadecimal digits
+        StringBuffer buffer = new StringBuffer();
+        int resultLenBytes = 0;
+
+        while (resultLenBytes < this.sessionIdLength) {
+            getRandomBytes(random);
+            random = getDigest().digest(random);
+            for (int j = 0;
+            j < random.length && resultLenBytes < this.sessionIdLength;
+            j++) {
+                byte b1 = (byte) ((random[j] & 0xf0) >> 4);
+                byte b2 = (byte) (random[j] & 0x0f);
+                if (b1 < 10)
+                    buffer.append((char) ('0' + b1));
+                else
+                    buffer.append((char) ('A' + (b1 - 10)));
+                if (b2 < 10)
+                    buffer.append((char) ('0' + b2));
+                else
+                    buffer.append((char) ('A' + (b2 - 10)));
+                resultLenBytes++;
+            }
+        }
+        if (jvmRoute != null) {
+            buffer.append('.').append(jvmRoute);
+        }
+        result = buffer.toString();
+        return (result);
+
+    }
+    
+    protected void getRandomBytes(byte bytes[]) {
+        // Generate a byte array containing a session identifier
+        if (devRandomSource != null && randomIS == null) {
+            setRandomFile(devRandomSource);
+        }
+        if (randomIS != null) {
+            try {
+                int len = randomIS.read(bytes);
+                if (len == bytes.length) {
+                    return;
+                }
+                if(log.isDebugEnabled())
+                    log.debug("Got " + len + " " + bytes.length );
+            } catch (Exception ex) {
+                // Ignore
+            }
+            devRandomSource = null;
+            
+            try {
+                randomIS.close();
+            } catch (Exception e) {
+                log.warn("Failed to close randomIS.");
+            }
+            
+            randomIS = null;
+        }
+        getRandom().nextBytes(bytes);
+    }
+
+    /**
+     * Return the random number generator instance we should use for
+     * generating session identifiers.  If there is no such generator
+     * currently defined, construct and seed a new one.
+     */
+    public Random getRandom() {
+        if (this.random == null) {
+            // Calculate the new random number generator seed
+            long seed = System.currentTimeMillis();
+            long t1 = seed;
+            char entropy[] = getEntropy().toCharArray();
+            for (int i = 0; i < entropy.length; i++) {
+                long update = ((byte) entropy[i]) << ((i % 8) * 8);
+                seed ^= update;
+            }
+            try {
+                // Construct and seed a new random number generator
+                Class clazz = Class.forName(randomClass);
+                this.random = (Random) clazz.newInstance();
+                this.random.setSeed(seed);
+            } catch (Exception e) {
+                // Fall back to the simple case
+                log.error("Failed to create random " + randomClass, e);
+                this.random = new java.util.Random();
+                this.random.setSeed(seed);
+            }
+            if(log.isDebugEnabled()) {
+                long t2=System.currentTimeMillis();
+                if( (t2-t1) > 100 )
+                    log.debug("Init random: " + " " + (t2-t1));
+            }
+        }
+        
+        return (this.random);
+
+    }
+    
+    /**
+     * Return the entropy increaser value, or compute a semi-useful value
+     * if this String has not yet been set.
+     */
+    public String getEntropy() {
+
+        // Calculate a semi-useful value if this has not been set
+        if (this.entropy == null) {
+            // Use APR to get a crypto secure entropy value
+            byte[] result = new byte[32];
+            boolean apr = false;
+            try {
+                String methodName = "random";
+                Class paramTypes[] = new Class[2];
+                paramTypes[0] = result.getClass();
+                paramTypes[1] = int.class;
+                Object paramValues[] = new Object[2];
+                paramValues[0] = result;
+                paramValues[1] = new Integer(32);
+                Method method = Class.forName("org.apache.tomcat.jni.OS")
+                    .getMethod(methodName, paramTypes);
+                method.invoke(null, paramValues);
+                apr = true;
+            } catch (Throwable t) {
+                // Ignore
+            }
+            if (apr) {
+                setEntropy(new String(result));
+            } else {
+                setEntropy(this.toString());
+            }
+        }
+
+        return (this.entropy);
+
+    }
+
+
+    /**
+     * Set the entropy increaser value.
+     *
+     * @param entropy The new entropy increaser value
+     */
+    public void setEntropy(String entropy) {
+        this.entropy = entropy;
+    }
+
+
+    /**
+     * Return the random number generator class name.
+     */
+    public String getRandomClass() {
+
+        return (this.randomClass);
+
+    }
+
+
+    /**
+     * Set the random number generator class name.
+     *
+     * @param randomClass The new random number generator class name
+     */
+    public void setRandomClass(String randomClass) {
+        this.randomClass = randomClass;
+    }
+    
+    /**
+     * The Java class name of the random number generator class to be used
+     * when generating session identifiers.
+     */
+    protected String randomClass = "java.security.SecureRandom";
+    /** 
+     * Use /dev/random-type special device. This is new code, but may reduce
+     * the big delay in generating the random.
+     *
+     *  You must specify a path to a random generator file. Use /dev/urandom
+     *  for linux ( or similar ) systems. Use /dev/random for maximum security
+     *  ( it may block if not enough "random" exist ). You can also use
+     *  a pipe that generates random.
+     *
+     *  The code will check if the file exists, and default to java Random
+     *  if not found. There is a significant performance difference, very
+     *  visible on the first call to getSession ( like in the first JSP )
+     *  - so use it if available.
+     */
+    public void setRandomFile( String s ) {
+        // as a hack, you can use a static file - and genarate the same
+        // session ids ( good for strange debugging )
+        try{
+            devRandomSource=s;
+            File f=new File( devRandomSource );
+            if( ! f.exists() ) return;
+            randomIS= new DataInputStream( new FileInputStream(f));
+            randomIS.readLong();
+            if( log.isDebugEnabled() )
+                log.debug( "Opening " + devRandomSource );
+        } catch( IOException ex ) {
+            try {
+                randomIS.close();
+            } catch (Exception e) {
+                log.warn("Failed to close randomIS.");
+            }
+            
+            randomIS=null;
+        }
+    }
+
+    public String getRandomFile() {
+        return devRandomSource;
+    }
+
+
+    /**
+     * Gets the session id length (in bytes) of Sessions created by
+     * this Manager.
+     *
+     * @return The session id length
+     */
+    public int getSessionIdLength() {
+
+        return (this.sessionIdLength);
+
+    }
+
+
+    /**
+     * Sets the session id length (in bytes) for Sessions created by this
+     * Manager.
+     *
+     * @param idLength The session id length
+     */
+    public void setSessionIdLength(int idLength) {
+        this.sessionIdLength = idLength;
+    }
+}
\ No newline at end of file

Propchange: tomcat/trunk/modules/tomcat-lite/java/org/apache/tomcat/servlets/session/RandomGenerator.java
------------------------------------------------------------------------------
    svn:eol-style = native



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org