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