You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@shiro.apache.org by ad...@apache.org on 2009/06/18 05:13:47 UTC

svn commit: r785881 [10/11] - in /incubator/shiro/trunk: ./ all/ core/src/main/java/org/apache/ki/ core/src/main/java/org/apache/shiro/ core/src/main/java/org/apache/shiro/aop/ core/src/main/java/org/apache/shiro/authc/ core/src/main/java/org/apache/sh...

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java?rev=785881&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroFilter.java Thu Jun 18 03:13:34 2009
@@ -0,0 +1,623 @@
+/*
+ * 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.shiro.web.servlet;
+
+import org.apache.commons.beanutils.PropertyUtils;
+import org.apache.shiro.config.Configuration;
+import org.apache.shiro.config.ConfigurationException;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.util.ClassUtils;
+import org.apache.shiro.util.LifecycleUtils;
+import static org.apache.shiro.util.StringUtils.clean;
+import org.apache.shiro.util.ThreadContext;
+import org.apache.shiro.web.DefaultWebSecurityManager;
+import org.apache.shiro.web.WebUtils;
+import org.apache.shiro.web.config.IniWebConfiguration;
+import org.apache.shiro.web.config.WebConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.*;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.beans.PropertyDescriptor;
+import java.io.IOException;
+import java.net.InetAddress;
+
+
+/**
+ * Main ServletFilter that configures and enables all Shiro functions within a web application.
+ * <p/>
+ * The following is a fully commented example that documents how to configure it:
+ * <p/>
+ * <pre>&lt;filter&gt;
+ * &lt;filter-name&gt;KiFilter&lt;/filter-name&gt;
+ * &lt;filter-class&gt;org.apache.shiro.web.servlet.KiFilter&lt;/filter-class&gt;
+ * &lt;init-param&gt;&lt;param-name&gt;config&lt;/param-name&gt;&lt;param-value&gt;
+ * #
+ * #NOTE:  This config looks pretty long - but its not - its only a few lines of actual config.
+ * #       Everything else is just heavily commented to explain things in-depth. Feel free to delete any
+ * #       comments that you don't want to read from your own configuration ;)
+ * #
+ * # Any commented values below that _don't_ start with 'example.pkg' are Shiro's defaults.  If you want to change any
+ * # values on those lines, you only need to uncomment the lines you want to change.
+ * #
+ * [main]
+ * # The 'main' section defines Shiro-wide configuration.
+ * #
+ * # The configuration is essentially an object graph definition in a .properties style format.  The beans defined
+ * # would be those that are used to construct the application's SecurityManager.  It is essentially 'poor man's'
+ * # dependency injection via a .properties format.
+ * #
+ * # --- Defining Realms ---
+ * #
+ * # Any Realm defined here will automatically be injected into Shiro's default SecurityManager created at startup.  For
+ * # example:
+ * #
+ * # myRealm = example.pkg.security.MyRealm
+ * #
+ * # This would instantiate the some.pkg.security.MyRealm class with a default no-arg constructor and inject it into
+ * # the SecurityManager.  More than one realm can be defined if needed.  You can create graphs and reference
+ * # other beans ('$' bean reference notation) while defining Realms and other objects:
+ * #
+ * # <b>connectionFactory</b> = example.pkg.ConnectionFactory
+ * # connectionFactory.driverClassName = a.jdbc.Driver
+ * # connectionFactory.username = aUsername
+ * # connectionFactory.password = aPassword
+ * # connectionFactory.minConnections = 3
+ * # connectionFactory.maxConnections = 10
+ * # ... etc...
+ * #
+ * # myJdbcRealm = example.pkg.jdbc.MyJdbcRealm
+ * # myJdbcRealm.connectionFactory = <b>$connectionFactory</b>
+ * # ... etc ...
+ * #
+ * # --- Realm Factories ---
+ * #
+ * # If the .properties style isn't robust enough for your needs, you also have the option of implementing the
+ * # {@link org.apache.shiro.realm.RealmFactory org.apache.shiro.realm.RealmFactory} interface with more complex construction
+ * # logic.  Then you can declare the implementation here instead.  The realms it returns will be injected in to the
+ * # SecurityManager just as the individual Realms are.  For example:
+ * #
+ * # aRealmFactory = some.pkg.ClassThatImplementsRealmFactory
+ * #
+ * # --- SessionManager properties ---
+ * #
+ * # Except for Realms and RealmFactories, all other objects should be defined and set on the SecurityManager directly.
+ * # The default 'securityManager' bean is an instance of {@link org.apache.shiro.web.DefaultWebSecurityManager}, so you
+ * # can set any of its corresponding properties as necessary:
+ * #
+ * # someObject = some.fully.qualified.ClassName
+ * # someObject.propertyN = foo
+ * # ...
+ * # securityManager.someObject = $someObject
+ * #
+ * # For example, if you wanted to change Shiro's default session mechanism, you can change the 'sessionMode' property.
+ * # By default, Shiro's Session infrastructure in a web environment will use the
+ * # Servlet container's HttpSession.  However, if you need to share session state across client types
+ * # (e.g. Web MVC plus Java Web Start or Flash), or are doing distributed/shared Sessions for
+ * # Single Sign On, HttpSessions aren't good enough.  You'll need to use Shiro's more powerful
+ * # (and client-agnostic) session management.  You can enable this by uncommenting the following line
+ * # and changing 'http' to 'shiro'
+ * #
+ * #securityManager.{@link org.apache.shiro.web.DefaultWebSecurityManager#setSessionMode(String) sessionMode} = http
+ * #
+ * [filters]
+ * # This section defines the 'pool' of all Filters available to the url path definitions in the [urls] section below.
+ * #
+ * # The following commented values are already provided by Shiro by default and are immediately usable
+ * # in the [urls] definitions below.  If you like, you may override any values by uncommenting only the lines
+ * # you need to change.
+ * #
+ * # Each Filter is configured based on its functionality and/or protocol.  You should read each
+ * # Filter's JavaDoc to fully understand what each does and how it works as well as how it would
+ * # affect the user experience.
+ * #
+ * # Form-based Authentication filter:
+ * #<a name="authc"></a>authc = {@link org.apache.shiro.web.filter.authc.FormAuthenticationFilter}
+ * #authc.{@link org.apache.shiro.web.filter.authc.FormAuthenticationFilter#setLoginUrl(String) loginUrl} = /login.jsp
+ * #authc.{@link org.apache.shiro.web.filter.authc.FormAuthenticationFilter#setUsernameParam(String) usernameParam} = username
+ * #authc.{@link org.apache.shiro.web.filter.authc.FormAuthenticationFilter#setPasswordParam(String) passwordParam} = password
+ * #authc.{@link org.apache.shiro.web.filter.authc.FormAuthenticationFilter#setRememberMeParam(String) rememberMeParam} = rememberMe
+ * #authc.{@link org.apache.shiro.web.filter.authc.FormAuthenticationFilter#setSuccessUrl(String) successUrl}  = /login.jsp
+ * #authc.{@link org.apache.shiro.web.filter.authc.FormAuthenticationFilter#setFailureKeyAttribute(String) failureKeyAttribute} = {@link org.apache.shiro.web.filter.authc.FormAuthenticationFilter#DEFAULT_ERROR_KEY_ATTRIBUTE_NAME}
+ * #
+ * # Http BASIC Authentication filter:
+ * #<a name="authcBasic"></a>authcBasic = {@link org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter}
+ * #authcBasic.{@link org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter#setApplicationName(String) applicationName} = application
+ * #
+ * # Roles filter: requires the requesting user to have one or more roles for the request to continue.
+ * # If they do not have the specified roles, they are redirected to the specified URL.
+ * #<a name="roles"></a>roles = {@link org.apache.shiro.web.filter.authz.RolesAuthorizationFilter}
+ * #roles.{@link org.apache.shiro.web.filter.authz.RolesAuthorizationFilter#setUnauthorizedUrl(String) unauthorizedUrl} =
+ * # (note the above url is null by default, which will cause an HTTP 403 (Access Denied) response instead
+ * # of redirecting to a page.  If you want to show a 'nice page' instead, you should specify that url.
+ * #
+ * # Permissions filter: requires the requesting user to have one or more permissions for the request to
+ * # continue, and if they do not, redirects them to the specified URL.
+ * #<a name="perms"></a>perms = {@link org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter}
+ * #perms.{@link org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter#setUnauthorizedUrl(String) unauthorizedUrl} =
+ * # (note the above url is null by default, which will cause an HTTP 403 (Access Denied) response instead
+ * # of redirecting to a page.  If you want to show a 'nice page' instead, you should specify that url.  Many
+ * # applications like to use the same url specified in roles.unauthorizedUrl above.
+ * #
+ * #
+ * # Define your own filters here as you would any other object as described in the '[main]' section above (properties,
+ * # $references, etc).  To properly handle url path matching (see the [urls] section below), your
+ * # filter should extend the {@link org.apache.shiro.web.filter.PathMatchingFilter PathMatchingFilter} abstract class.
+ * #
+ * [urls]
+ * # This section defines url path mappings.  Each mapping entry must be on a single line and conform to the
+ * # following representation:
+ * #
+ * # ant_path_expression = path_specific_filter_chain_definition
+ * #
+ * # For any request that matches a specified path, the corresponding value defines a comma-delimited chain of
+ * # filters to execute for that request.
+ * #
+ * # This is incredibly powerful in that you can define arbitrary filter chains for any given request pattern
+ * # to greatly customize the security experience.
+ * #
+ * # The path_specific_filter_chain_definition must match the following format:
+ * #
+ * # filter1[optional_config1], filter2[optional_config2], ..., filterN[optional_configN]
+ * #
+ * # where 'filterN' is the name of an filter defined above in the [filters] section and
+ * # '[optional_configN]' is an optional bracketed string that has meaning for that particular filter for
+ * # _that particular path_.  If the filter does not need specific config for that url path, you may
+ * # discard the brackets - that is, filterN[] just becomes filterN.
+ * #
+ * # And because filter tokens define chains, order matters!  Define the tokens for each path pattern
+ * # in the order you want them to filter (comma-delimited).
+ * #
+ * # Finally, each filter is free to handle the response however it wants if its necessary
+ * # conditions are not met (redirect, HTTP error code, direct rendering, etc).  Otherwise, it is expected to allow
+ * # the request to continue through the chain on to the final destination view.
+ * #
+ * # Examples:
+ * #
+ * # To illustrate chain configuration, look at the /account/** mapping below.  This says
+ * # &quot;apply the above 'authcBasic' filter to any request matching the '/account/**' pattern&quot;.  Since the
+ * # 'authcBasic' filter does not need any path-specific config, it doesn't have any config brackets [].
+ * #
+ * # The /remoting/** definition on the other hand uses the 'roles' and 'perms' filters which do use
+ * # bracket notation.  That definition says:
+ * #
+ * # &quot;To access /remoting/** urls, ensure that the user is first authenticated ('authcBasic'), then ensure that user
+ * # has the 'b2bClient' role, and then finally ensure that they have the 'remote:invoke:lan,wan' permission.&quot;
+ * #
+ * # (Note that because elements within brackets [ ] are comma-delimited themselves, we needed to escape the permission
+ * # actions of 'lan,wan' with quotes.  If we didn't do that, the permission filter would interpret
+ * # the text between the brackets as two permissions: 'remote:invoke:lan' and 'wan' instead of the
+ * # single desired 'remote:invoke:lan,wan' token.  So, you can use quotes wherever you need to escape internal
+ * # commas.)
+ * #
+ * /account/** = <a href="#authcBasic">authcBasic</a>
+ * /remoting/** = <a href="#authcBasic">authcBasic</a>, <a href="#roles">roles</a>[b2bClient], <a href="#perms">perms</a>[remote:invoke:"lan,wan"]
+ * #
+ * &lt;/param-value&gt;&lt;/init-param&gt;
+ * &lt;/filter&gt;
+ * #
+ * #
+ * &lt;filter-mapping&gt;
+ * &lt;filter-name&gt;KiFilter&lt;/filter-name&gt;
+ * &lt;url-pattern&gt;/*&lt;/url-pattern&gt;
+ * &lt;/filter-mapping&gt;</pre>
+ *
+ * @author Les Hazlewood
+ * @author Jeremy Haile
+ * @since 0.1
+ */
+public class ShiroFilter extends OncePerRequestFilter {
+
+    //TODO - complete JavaDoc
+
+    public static final String SECURITY_MANAGER_CONTEXT_KEY = SecurityManager.class.getName() + "_SERVLET_CONTEXT_KEY";
+
+    public static final String CONFIG_CLASS_NAME_INIT_PARAM_NAME = "configClassName";
+    public static final String CONFIG_INIT_PARAM_NAME = "config";
+    public static final String CONFIG_URL_INIT_PARAM_NAME = "configUrl";
+
+    private static final Logger log = LoggerFactory.getLogger(ShiroFilter.class);
+
+    protected String config;
+    protected String configUrl;
+    protected String configClassName;
+    protected WebConfiguration configuration;
+
+    // Reference to the security manager used by this filter
+    protected SecurityManager securityManager;
+
+    public ShiroFilter() {
+        this.configClassName = IniWebConfiguration.class.getName();
+    }
+
+    public WebConfiguration getConfiguration() {
+        return configuration;
+    }
+
+    public void setConfiguration(WebConfiguration configuration) {
+        this.configuration = configuration;
+    }
+
+    public SecurityManager getSecurityManager() {
+        return securityManager;
+    }
+
+    protected void setSecurityManager(org.apache.shiro.mgt.SecurityManager sm) {
+        this.securityManager = sm;
+    }
+
+    protected void onFilterConfigSet() throws Exception {
+        applyInitParams();
+        WebConfiguration config = configure();
+        setConfiguration(config);
+
+        // Retrieve and store a reference to the security manager
+        SecurityManager sm = ensureSecurityManager(config);
+        setSecurityManager(sm);
+    }
+
+    /**
+     * Retrieves the security manager for the given configuration.
+     *
+     * @param config the configuration for this filter.
+     * @return the security manager that this filter should use.
+     */
+    protected SecurityManager ensureSecurityManager(Configuration config) {
+        SecurityManager sm = config.getSecurityManager();
+
+        // If the config doesn't return a security manager, build one by default.
+        if (sm == null) {
+            if (log.isInfoEnabled()) {
+                log.info("Configuration instance [" + config + "] did not provide a SecurityManager.  No config " +
+                        "specified?  Defaulting to a " + DefaultWebSecurityManager.class.getName() + " instance...");
+            }
+            sm = new DefaultWebSecurityManager();
+        }
+
+        return sm;
+    }
+
+    protected void applyInitParams() {
+        FilterConfig config = getFilterConfig();
+
+        String configCN = clean(config.getInitParameter(CONFIG_CLASS_NAME_INIT_PARAM_NAME));
+        if (configCN != null) {
+            if (ClassUtils.isAvailable(configCN)) {
+                this.configClassName = configCN;
+            } else {
+                String msg = "configClassName fully qualified class name value [" + configCN + "] is not " +
+                        "available in the classpath.  Please ensure you have typed it correctly and the " +
+                        "corresponding class or jar is in the classpath.";
+                throw new ConfigurationException(msg);
+            }
+        }
+
+        this.config = clean(config.getInitParameter(CONFIG_INIT_PARAM_NAME));
+        this.configUrl = clean(config.getInitParameter(CONFIG_URL_INIT_PARAM_NAME));
+    }
+
+    protected WebConfiguration configure() {
+        WebConfiguration conf = (WebConfiguration) ClassUtils.newInstance(this.configClassName);
+        applyFilterConfig(conf);
+        applyUrlConfig(conf);
+        applyEmbeddedConfig(conf);
+        LifecycleUtils.init(conf);
+        return conf;
+    }
+
+    protected void applyFilterConfig(WebConfiguration conf) {
+        if (log.isDebugEnabled()) {
+            String msg = "Attempting to inject the FilterConfig (using 'setFilterConfig' method) into the " +
+                    "instantiated WebConfiguration for any wrapped Filter initialization...";
+            log.debug(msg);
+        }
+        try {
+            PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(conf, "filterConfig");
+            if (pd != null) {
+                PropertyUtils.setProperty(conf, "filterConfig", getFilterConfig());
+            }
+        } catch (Exception e) {
+            if (log.isDebugEnabled()) {
+                log.debug("Error setting FilterConfig on WebConfiguration instance.", e);
+            }
+        }
+    }
+
+    protected void applyEmbeddedConfig(WebConfiguration conf) {
+        if (this.config != null) {
+            try {
+                PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(conf, "config");
+
+                if (pd != null) {
+                    PropertyUtils.setProperty(conf, "config", this.config);
+                } else {
+                    String msg = "The 'config' filter param was specified, but there is no " +
+                            "'setConfig(String)' method on the Configuration instance [" + conf + "].  If you do " +
+                            "not require the 'config' filter param, please comment it out, or if you do need it, " +
+                            "please ensure your Configuration instance has a 'setConfig(String)' method to receive it.";
+                    throw new ConfigurationException(msg);
+                }
+            } catch (Exception e) {
+                String msg = "There was an error setting the 'config' property of the Configuration object.";
+                throw new ConfigurationException(msg, e);
+            }
+        }
+    }
+
+    protected void applyUrlConfig(WebConfiguration conf) {
+        if (this.configUrl != null) {
+            try {
+                PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor(conf, "configUrl");
+
+                if (pd != null) {
+                    PropertyUtils.setProperty(conf, "configUrl", this.configUrl);
+                } else {
+                    String msg = "The 'configUrl' filter param was specified, but there is no " +
+                            "'setConfigUrl(String)' method on the Configuration instance [" + conf + "].  If you do " +
+                            "not require the 'configUrl' filter param, please comment it out, or if you do need it, " +
+                            "please ensure your Configuration instance has a 'setConfigUrl(String)' method to receive it.";
+                    throw new ConfigurationException(msg);
+                }
+            } catch (Exception e) {
+                String msg = "There was an error setting the 'configUrl' property of the Configuration object.";
+                throw new ConfigurationException(msg, e);
+            }
+        }
+    }
+
+    protected boolean isHttpSessions() {
+        SecurityManager secMgr = getSecurityManager();
+        return !(secMgr instanceof DefaultWebSecurityManager) || ((DefaultWebSecurityManager) secMgr).isHttpSessionMode();
+    }
+
+    protected InetAddress getInetAddress(ServletRequest request) {
+        return WebUtils.getInetAddress(request);
+    }
+
+    /**
+     * Wraps the original HttpServletRequest in a {@link ShiroHttpServletRequest}, which is required for supporting
+     * Servlet Specification behavior backed by a {@link org.apache.shiro.subject.Subject Subject} instance.
+     *
+     * @param orig the original Servlet Container-provided incoming {@code HttpServletRequest} instance.
+     * @return {@link ShiroHttpServletRequest KiHttpServletRequest} instance wrapping the original.
+     * @since 1.0
+     */
+    protected ServletRequest wrapServletRequest(HttpServletRequest orig) {
+        return new ShiroHttpServletRequest(orig, getServletContext(), isHttpSessions());
+    }
+
+    /**
+     * 'Prepare's the {@code ServletRequest} instance that will be passed to the {@code FilterChain} for request
+     * processing.
+     * <p/>
+     * If the {@code ServletRequest} is an instance of {@link HttpServletRequest}, the value returned from this method
+     * is obtained by calling {@link #wrapServletRequest(javax.servlet.http.HttpServletRequest)} to allow Shiro-specific
+     * HTTP behavior, otherwise the original {@code ServletRequest} argument is returned.
+     *
+     * @param request  the incoming ServletRequest
+     * @param response the outgoing ServletResponse
+     * @param chain    the Servlet Container provided {@code FilterChain} that will receive the returned request.
+     * @return the {@code ServletRequest} instance that will be passed to the {@code FilterChain} for request processing.
+     * @since 1.0
+     */
+    @SuppressWarnings({"UnusedDeclaration"})
+    protected ServletRequest prepareServletRequest(ServletRequest request, ServletResponse response, FilterChain chain) {
+        ServletRequest toUse = request;
+        if (request instanceof HttpServletRequest) {
+            HttpServletRequest http = (HttpServletRequest) request;
+            toUse = wrapServletRequest(http);
+        }
+        return toUse;
+    }
+
+    /**
+     * Returns a new {@link ShiroHttpServletResponse} instance, wrapping the {@code orig} argument, in order to provide
+     * correct URL rewriting behavior required by the Servlet Specification when using Shiro-based sessions (and not
+     * Servlet Container HTTP-based sessions).
+     *
+     * @param orig    the original {@code HttpServletResponse} instance provided by the Servlet Container.
+     * @param request the {@code KiHttpServletRequest} instance wrapping the original request.
+     * @return the wrapped ServletResponse instance to use during {@link FilterChain} execution.
+     * @since 1.0
+     */
+    protected ServletResponse wrapServletResponse(HttpServletResponse orig, ShiroHttpServletRequest request) {
+        return new ShiroHttpServletResponse(orig, getServletContext(), request);
+    }
+
+    /**
+     * 'Prepare's the {@code ServletResponse} instance that will be passed to the {@code FilterChain} for request
+     * processing.
+     * <p/>
+     * This implementation delegates to {@link #wrapServletRequest(javax.servlet.http.HttpServletRequest)}
+     * only if Shiro-based sessions are enabled (that is, !{@link #isHttpSessions()}) and the request instance is a
+     * {@link ShiroHttpServletRequest}.  This ensures that any URL rewriting that occurs is handled correctly using the
+     * Shiro-managed Session's sessionId and not a servlet container session ID.
+     * <p/>
+     * If HTTP-based sessions are enabled (the default), then this method does nothing and just returns the
+     * {@code ServletResponse} argument as-is, relying on the default Servlet Container URL rewriting logic.
+     *
+     * @param request  the incoming ServletRequest
+     * @param response the outgoing ServletResponse
+     * @param chain    the Servlet Container provided {@code FilterChain} that will receive the returned request.
+     * @return the {@code ServletResponse} instance that will be passed to the {@code FilterChain} during request processing.
+     * @since 1.0
+     */
+    @SuppressWarnings({"UnusedDeclaration"})
+    protected ServletResponse prepareServletResponse(ServletRequest request, ServletResponse response, FilterChain chain) {
+        ServletResponse toUse = response;
+        if (!isHttpSessions() && (request instanceof ShiroHttpServletRequest) &&
+                (response instanceof HttpServletResponse)) {
+            //the ShiroHttpServletResponse exists to support URL rewriting for session ids.  This is only needed if
+            //using Shiro sessions (i.e. not simple HttpSession based sessions):
+            toUse = wrapServletResponse((HttpServletResponse) response, (ShiroHttpServletRequest) request);
+        }
+        return toUse;
+    }
+
+    /**
+     * Binds the current request/response pair and additional information to a thread-local to be made available to Shiro
+     * during the course of the request/response process.  This implementation binds the request/response pair to the
+     * currently executing thread via the {@link ThreadContext}, as well as the Request's
+     * {@link javax.servlet.ServletRequest#getRemoteAddr() remoteAddr} (client InetAddress), the application's
+     * configured {@link SecurityManager}, and sets up and binds the currently executing
+     * {@link org.apache.shiro.subject.Subject Subject} instance to ensure the Subject is available before any request
+     * processing occurs.
+     * <p/>
+     * To guarantee properly cleaned threads in a thread-pooled Servlet Container environment, the corresponding
+     * {@link #unbind} method must be called in a {@code finally} block to ensure that the thread remains clean even
+     * in the event of an exception thrown while processing the request.  This class's
+     * {@link #doFilterInternal(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)}
+     * method implement does indeed perform this.
+     *
+     * @param request  the incoming ServletRequest
+     * @param response the outgoing ServletResponse
+     * @since 1.0
+     */
+    protected void bind(ServletRequest request, ServletResponse response) {
+        WebUtils.bindInetAddressToThread(request);
+        WebUtils.bind(request);
+        WebUtils.bind(response);
+        ThreadContext.bind(getSecurityManager());
+        ThreadContext.bind(getSecurityManager().getSubject());
+    }
+
+    /**
+     * Unbinds (removes out of scope) the current {@code ServletRequest} and {@link ServletResponse}.
+     * <p/>
+     * This method implementation merely calls {@code ThreadContext}.{@link ThreadContext#clear() clear()} to ensure
+     * that <em>everything</em> that might have been bound to the thread by Shiro has been removed to ensure the underlying
+     * Thread may be safely re-used in a thread-pooled Servlet Container environment.
+     *
+     * @param request  the just-processed incoming servlet response - ignored
+     * @param response the just-processed outgoing servlet response - ignored
+     * @since 1.0
+     */
+    @SuppressWarnings({"UnusedDeclaration"})
+    protected void unbind(ServletRequest request, ServletResponse response) {
+        //arguments ignored, just clear the thread:
+        ThreadContext.clear();
+    }
+
+    /**
+     * {@code doFilterInternal} implementation that sets-up, executes, and cleans-up a Shiro-filtered request.  It
+     * performs the following ordered operations:
+     * <ol>
+     * <li>{@link #prepareServletRequest(ServletRequest, ServletResponse, FilterChain) Prepares}
+     * the incoming {@code ServletRequest} for use during Shiro's processing</li>
+     * <li>{@link #prepareServletResponse(ServletRequest, ServletResponse, FilterChain) Prepares}
+     * the outgoing {@code ServletResponse} for use during Shiro's processing</li>
+     * <li>{@link #bind(ServletRequest,ServletResponse) Binds} the request/response pair
+     * and associated data to the currently executing thread for use during processing</li>
+     * <li>{@link #executeChain(ServletRequest,ServletResponse,FilterChain) Executes}
+     * the appropriate {@code FilterChain}</li>
+     * <li>{@link #unbind(javax.servlet.ServletRequest, javax.servlet.ServletResponse) Unbinds} the request/response
+     * pair and any other associated data from the thread.
+     * </ul>
+     * <p/>
+     * The {@link #unbind(javax.servlet.ServletRequest, javax.servlet.ServletResponse) unbind} method is called in a
+     * {@code finally} block to guarantee the thread may be cleanly re-used in a thread-pooled Servlet Container
+     * environment.
+     *
+     * @param servletRequest  the incoming {@code ServletRequest}
+     * @param servletResponse the outgoing {@code ServletResponse}
+     * @param chain           the container-provided {@code FilterChain} to execute
+     * @throws ServletException if an error occurs
+     * @throws IOException      if an IO error occurs
+     */
+    protected void doFilterInternal(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain)
+            throws ServletException, IOException {
+
+        ServletRequest request = prepareServletRequest(servletRequest, servletResponse, chain);
+        ServletResponse response = prepareServletResponse(request, servletResponse, chain);
+
+        bind(request, response);
+
+        try {
+            executeChain(request, response, chain);
+        } finally {
+            unbind(request, response);
+        }
+    }
+
+    /**
+     * Returns the {@code FilterChain} to execute for the given request.
+     * <p/>
+     * The {@code origChain} argument is the
+     * original {@code FilterChain} supplied by the Servlet Container, but it may be modified to provide
+     * more behavior by appending further chains according to the Shiro configuration.
+     * <p/>
+     * This implementation returns the chain that will actually be executed by acquiring the chain from a
+     * <code>{@link #getConfiguration() getConfiguration()}.{@link org.apache.shiro.web.config.WebConfiguration#getChain getChain}(request,response,origChain)</code>
+     * method call.  The configuration itself determines which chain to execute, typically based on URL configuration.
+     * If no chain is returned from this method call (returns {@code null}), then the {@code origChain}
+     * will be returned by default.
+     *
+     * @param request   the incoming ServletRequest
+     * @param response  the outgoing ServletResponse
+     * @param origChain the original {@code FilterChain} provided by the Servlet Container
+     * @return the {@link FilterChain} to execute for the given request
+     * @since 1.0
+     */
+    protected FilterChain getExecutionChain(ServletRequest request, ServletResponse response, FilterChain origChain) {
+        FilterChain chain = getConfiguration().getChain(request, response, origChain);
+        if (chain == null) {
+            chain = origChain;
+            log.trace("No security filter chain configured for the current request.  Using default.");
+        } else {
+            log.trace(" Using configured filter chain for the current request.");
+        }
+        return chain;
+    }
+
+    /**
+     * Executes a {@link FilterChain} for the given request.
+     * <p/>
+     * This implementation first delegates to
+     * <code>{@link #getExecutionChain(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain) getExecutionChain}</code>
+     * to allow the application's Shiro configuration to determine exactly how the chain should execute.  The resulting
+     * value from that call is then executed directly by calling the returned {@code FilterChain}'s
+     * {@link FilterChain#doFilter doFilter} method.  That is:
+     * <p/>
+     * <pre>
+     * FilterChain chain = {@link #getExecutionChain}(request, response, origChain);
+     * chain.{@link FilterChain#doFilter doFilter}(request,response);</pre>
+     *
+     * @param request   the incoming ServletRequest
+     * @param response  the outgoing ServletResponse
+     * @param origChain the Servlet Container-provided chain that may be wrapped further by an application-configured
+     *                  chain of Filters.
+     * @throws IOException      if the underlying {@code chain.doFilter} call results in an IOException
+     * @throws ServletException if the underlying {@code chain.doFilter} call results in a ServletException
+     * @since 1.0
+     */
+    protected void executeChain(ServletRequest request, ServletResponse response, FilterChain origChain)
+            throws IOException, ServletException {
+        FilterChain chain = getExecutionChain(request, response, origChain);
+        chain.doFilter(request, response);
+    }
+
+    /**
+     * Destroys this Filter by destroying the {@link #getConfiguration() configuration} object.
+     */
+    public void destroy() {
+        LifecycleUtils.destroy(getConfiguration());
+    }
+}

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletRequest.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletRequest.java?rev=785881&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletRequest.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletRequest.java Thu Jun 18 03:13:34 2009
@@ -0,0 +1,240 @@
+/*
+ * 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.shiro.web.servlet;
+
+import java.security.Principal;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import javax.servlet.http.HttpSession;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+
+
+/**
+ * TODO class JavaDoc
+ *
+ * @author Les Hazlewood
+ * @since 0.2
+ */
+@SuppressWarnings({"deprecated", "deprecation"})
+public class ShiroHttpServletRequest extends HttpServletRequestWrapper {
+
+    //TODO - complete JavaDoc
+
+    //The following 7 constants support the Shiro's implementation of the Servlet Specification
+    public static final String COOKIE_SESSION_ID_SOURCE = "cookie";
+    public static final String URL_SESSION_ID_SOURCE = "url";
+    public static final String REFERENCED_SESSION_ID = ShiroHttpServletRequest.class.getName() + "_REQUESTED_SESSION_ID";
+    public static final String REFERENCED_SESSION_ID_IS_VALID = ShiroHttpServletRequest.class.getName() + "_REQUESTED_SESSION_ID_VALID";
+    public static final String REFERENCED_SESSION_IS_NEW = ShiroHttpServletRequest.class.getName() + "_REFERENCED_SESSION_IS_NEW";
+    public static final String REFERENCED_SESSION_ID_SOURCE = ShiroHttpServletRequest.class.getName() + "REFERENCED_SESSION_ID_SOURCE";
+    public static final String SESSION_ID_NAME = ShiroHttpSession.DEFAULT_SESSION_ID_NAME;
+    /**
+     * Key that may be used to alert that the request's  referenced Shiro Session has expired prior to
+     * request processing.
+     */
+    public static final String EXPIRED_SESSION_KEY = ShiroHttpServletRequest.class.getName() + "_EXPIRED_SESSION_KEY";
+
+    public static final String IDENTITY_REMOVED_KEY = ShiroHttpServletRequest.class.getName() + "_IDENTITY_REMOVED_KEY";
+
+    protected ServletContext servletContext = null;
+
+    protected HttpSession session = null;
+    protected boolean httpSessions = true;
+
+    public ShiroHttpServletRequest(HttpServletRequest wrapped, ServletContext servletContext,
+                                       boolean httpSessions) {
+        super(wrapped);
+        this.servletContext = servletContext;
+        this.httpSessions = httpSessions;
+    }
+
+    public boolean isHttpSessions() {
+        return httpSessions;
+    }
+
+    protected boolean isLoggedOut() {
+        Boolean loggedOut = (Boolean)getAttribute(IDENTITY_REMOVED_KEY);
+        return loggedOut != null && loggedOut;
+    }
+
+    public String getRemoteUser() {
+        String remoteUser;
+        Object scPrincipal = getSubjectPrincipal();
+        if (scPrincipal != null) {
+            if (scPrincipal instanceof String) {
+                return (String) scPrincipal;
+            } else if (scPrincipal instanceof Principal) {
+                remoteUser = ((Principal) scPrincipal).getName();
+            } else {
+                remoteUser = scPrincipal.toString();
+            }
+        } else {
+            remoteUser = super.getRemoteUser();
+        }
+        return remoteUser;
+    }
+
+    protected Subject getSubject() {
+        return SecurityUtils.getSubject();
+    }
+
+    protected Object getSubjectPrincipal() {
+        Object userPrincipal = null;
+        Subject subject = getSubject();
+        if (subject != null) {
+            userPrincipal = subject.getPrincipal();
+        }
+        return userPrincipal;
+    }
+
+    public boolean isUserInRole(String s) {
+        Subject subject = getSubject();
+        boolean inRole = (subject != null && subject.hasRole(s));
+        if (!inRole) {
+            inRole = super.isUserInRole(s);
+        }
+        return inRole;
+    }
+
+    public Principal getUserPrincipal() {
+        Principal userPrincipal;
+        Object scPrincipal = getSubjectPrincipal();
+        if (scPrincipal != null) {
+            if (scPrincipal instanceof Principal) {
+                userPrincipal = (Principal) scPrincipal;
+            } else {
+                userPrincipal = new ObjectPrincipal(scPrincipal);
+            }
+        } else {
+            userPrincipal = super.getUserPrincipal();
+        }
+        return userPrincipal;
+    }
+
+    public String getRequestedSessionId() {
+        String requestedSessionId = null;
+        if (isHttpSessions()) {
+            requestedSessionId = super.getRequestedSessionId();
+        } else {
+            Object sessionId = getAttribute(REFERENCED_SESSION_ID);
+            if (sessionId != null) {
+                requestedSessionId = sessionId.toString();
+            }
+        }
+
+        return requestedSessionId;
+    }
+
+    public HttpSession getSession(boolean create) {
+
+        HttpSession httpSession;
+
+        if (isHttpSessions()) {
+            httpSession = super.getSession(create);
+        } else {
+            if (this.session == null) {
+
+                boolean existing = getSubject().getSession(false) != null;
+
+                Session jsecSession = getSubject().getSession(create);
+                if (jsecSession != null) {
+                    this.session = new ShiroHttpSession(jsecSession, this, this.servletContext);
+                    if (!existing) {
+                        setAttribute(REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
+                    }
+                }
+            }
+            httpSession = this.session;
+        }
+
+        return httpSession;
+    }
+
+
+    public HttpSession getSession() {
+        return getSession(true);
+    }
+
+    public boolean isRequestedSessionIdValid() {
+        if (isHttpSessions()) {
+            return super.isRequestedSessionIdValid();
+        } else {
+            Boolean value = (Boolean) getAttribute(REFERENCED_SESSION_ID_IS_VALID);
+            return (value != null && value.equals(Boolean.TRUE));
+        }
+    }
+
+    public boolean isRequestedSessionIdFromCookie() {
+        if (isHttpSessions()) {
+            return super.isRequestedSessionIdFromCookie();
+        } else {
+            String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
+            return value != null && value.equals(COOKIE_SESSION_ID_SOURCE);
+        }
+    }
+
+    public boolean isRequestedSessionIdFromURL() {
+        if (isHttpSessions()) {
+            return super.isRequestedSessionIdFromURL();
+        } else {
+            String value = (String) getAttribute(REFERENCED_SESSION_ID_SOURCE);
+            return value != null && value.equals(URL_SESSION_ID_SOURCE);
+        }
+    }
+
+    public boolean isRequestedSessionIdFromUrl() {
+        return isRequestedSessionIdFromURL();
+    }
+
+    private class ObjectPrincipal implements java.security.Principal {
+        private Object object = null;
+
+        public ObjectPrincipal(Object object) {
+            this.object = object;
+        }
+
+        public Object getObject() {
+            return object;
+        }
+
+        public String getName() {
+            return getObject().toString();
+        }
+
+        public int hashCode() {
+            return object.hashCode();
+        }
+
+        public boolean equals(Object o) {
+            if (o instanceof ObjectPrincipal) {
+                ObjectPrincipal op = (ObjectPrincipal) o;
+                return getObject().equals(op.getObject());
+            }
+            return false;
+        }
+
+        public String toString() {
+            return object.toString();
+        }
+    }
+}

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletResponse.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletResponse.java?rev=785881&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletResponse.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpServletResponse.java Thu Jun 18 03:13:34 2009
@@ -0,0 +1,317 @@
+/*
+ * 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.shiro.web.servlet;
+
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpServletResponseWrapper;
+import javax.servlet.http.HttpSession;
+
+/**
+ * HttpServletResponse implementation to support URL Encoding of Shiro Session IDs.
+ *
+ * It is only used when using Shiro's native Session Management configuration (and not when using the Servlet
+ * Container session configuration, which is Shiro's default in a web environment).  Because the servlet container
+ * already performs url encoding of its own session ids, instances of this class are only needed when using Shiro
+ * native sessions.
+ *
+ * <p>Note that this implementation relies in part on source code from the Tomcat 6.x distribution for
+ * encoding URLs for session ID URL Rewriting (we didn't want to re-invent the wheel).  Since Shiro is also
+ * Apache 2.0 license, all regular licenses and conditions have remained in tact.
+ *
+ * @author Les Hazlewood
+ * @since 0.2
+ */
+@SuppressWarnings({"deprecated", "deprecation"})
+public class ShiroHttpServletResponse extends HttpServletResponseWrapper {
+
+    //TODO - complete JavaDoc
+
+    private static final String DEFAULT_SESSION_ID_PARAMETER_NAME = ShiroHttpSession.DEFAULT_SESSION_ID_NAME;
+
+    private ServletContext context = null;
+    //the associated request
+    private ShiroHttpServletRequest request = null;
+
+    public ShiroHttpServletResponse(HttpServletResponse wrapped, ServletContext context, ShiroHttpServletRequest request) {
+        super(wrapped);
+        this.context = context;
+        this.request = request;
+    }
+
+    public ServletContext getContext() {
+        return context;
+    }
+
+    public void setContext(ServletContext context) {
+        this.context = context;
+    }
+
+    public ShiroHttpServletRequest getRequest() {
+        return request;
+    }
+
+    public void setRequest(ShiroHttpServletRequest request) {
+        this.request = request;
+    }
+
+    /**
+     * Encode the session identifier associated with this response
+     * into the specified redirect URL, if necessary.
+     *
+     * @param url URL to be encoded
+     */
+    public String encodeRedirectURL(String url) {
+        if (isEncodeable(toAbsolute(url))) {
+            return toEncoded(url, request.getSession().getId());
+        } else {
+            return url;
+        }
+    }
+
+
+    public String encodeRedirectUrl(String s) {
+        return encodeRedirectURL(s);
+    }
+
+
+    /**
+     * Encode the session identifier associated with this response
+     * into the specified URL, if necessary.
+     *
+     * @param url URL to be encoded
+     */
+    public String encodeURL(String url) {
+        String absolute = toAbsolute(url);
+        if (isEncodeable(absolute)) {
+            // W3c spec clearly said
+            if (url.equalsIgnoreCase("")) {
+                url = absolute;
+            }
+            return toEncoded(url, request.getSession().getId());
+        } else {
+            return url;
+        }
+    }
+
+    public String encodeUrl(String s) {
+        return encodeURL(s);
+    }
+
+    /**
+     * Return <code>true</code> if the specified URL should be encoded with
+     * a session identifier.  This will be true if all of the following
+     * conditions are met:
+     * <ul>
+     * <li>The request we are responding to asked for a valid session
+     * <li>The requested session ID was not received via a cookie
+     * <li>The specified URL points back to somewhere within the web
+     * application that is responding to this request
+     * </ul>
+     *
+     * @param location Absolute URL to be validated
+     */
+    protected boolean isEncodeable(final String location) {
+
+        if (location == null)
+            return (false);
+
+        // Is this an intra-document reference?
+        if (location.startsWith("#"))
+            return (false);
+
+        // Are we in a valid session that is not using cookies?
+        final HttpServletRequest hreq = request;
+        final HttpSession session = hreq.getSession(false);
+        if (session == null)
+            return (false);
+        if (hreq.isRequestedSessionIdFromCookie())
+            return (false);
+
+        return doIsEncodeable(hreq, session, location);
+    }
+
+    private boolean doIsEncodeable(HttpServletRequest hreq, HttpSession session, String location) {
+        // Is this a valid absolute URL?
+        URL url = null;
+        try {
+            url = new URL(location);
+        } catch (MalformedURLException e) {
+            return (false);
+        }
+
+        // Does this URL match down to (and including) the context path?
+        if (!hreq.getScheme().equalsIgnoreCase(url.getProtocol()))
+            return (false);
+        if (!hreq.getServerName().equalsIgnoreCase(url.getHost()))
+            return (false);
+        int serverPort = hreq.getServerPort();
+        if (serverPort == -1) {
+            if ("https".equals(hreq.getScheme()))
+                serverPort = 443;
+            else
+                serverPort = 80;
+        }
+        int urlPort = url.getPort();
+        if (urlPort == -1) {
+            if ("https".equals(url.getProtocol()))
+                urlPort = 443;
+            else
+                urlPort = 80;
+        }
+        if (serverPort != urlPort)
+            return (false);
+
+        String contextPath = getRequest().getContextPath();
+        if (contextPath != null) {
+            String file = url.getFile();
+            if ((file == null) || !file.startsWith(contextPath))
+                return (false);
+            String tok = ";" + DEFAULT_SESSION_ID_PARAMETER_NAME + "=" + session.getId();
+            if (file.indexOf(tok, contextPath.length()) >= 0)
+                return (false);
+        }
+
+        // This URL belongs to our web application, so it is encodeable
+        return (true);
+
+    }
+
+
+    /**
+     * Convert (if necessary) and return the absolute URL that represents the
+     * resource referenced by this possibly relative URL.  If this URL is
+     * already absolute, return it unchanged.
+     *
+     * @param location URL to be (possibly) converted and then returned
+     * @throws IllegalArgumentException if a MalformedURLException is
+     *                                  thrown when converting the relative URL to an absolute one
+     */
+    private String toAbsolute(String location) {
+
+        if (location == null)
+            return (location);
+
+        boolean leadingSlash = location.startsWith("/");
+
+        if (leadingSlash || !hasScheme(location)) {
+
+            StringBuffer buf = new StringBuffer();
+
+            String scheme = request.getScheme();
+            String name = request.getServerName();
+            int port = request.getServerPort();
+
+            try {
+                buf.append(scheme).append("://").append(name);
+                if ((scheme.equals("http") && port != 80)
+                        || (scheme.equals("https") && port != 443)) {
+                    buf.append(':').append(port);
+                }
+                if (!leadingSlash) {
+                    String relativePath = request.getRequestURI();
+                    int pos = relativePath.lastIndexOf('/');
+                    relativePath = relativePath.substring(0, pos);
+
+                    String encodedURI = URLEncoder.encode(relativePath, getCharacterEncoding());
+                    buf.append(encodedURI).append('/');
+                }
+                buf.append(location);
+            } catch (IOException e) {
+                IllegalArgumentException iae = new IllegalArgumentException(location);
+                iae.initCause(e);
+                throw iae;
+            }
+
+            return buf.toString();
+
+        } else {
+            return location;
+        }
+    }
+
+    /**
+     * Determine if the character is allowed in the scheme of a URI.
+     * See RFC 2396, Section 3.1
+     */
+    public static boolean isSchemeChar(char c) {
+        return Character.isLetterOrDigit(c) ||
+                c == '+' || c == '-' || c == '.';
+    }
+
+
+    /**
+     * Determine if a URI string has a <code>scheme</code> component.
+     */
+    private boolean hasScheme(String uri) {
+        int len = uri.length();
+        for (int i = 0; i < len; i++) {
+            char c = uri.charAt(i);
+            if (c == ':') {
+                return i > 0;
+            } else if (!isSchemeChar(c)) {
+                return false;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return the specified URL with the specified session identifier
+     * suitably encoded.
+     *
+     * @param url       URL to be encoded with the session id
+     * @param sessionId Session id to be included in the encoded URL
+     */
+    protected String toEncoded(String url, String sessionId) {
+
+        if ((url == null) || (sessionId == null))
+            return (url);
+
+        String path = url;
+        String query = "";
+        String anchor = "";
+        int question = url.indexOf('?');
+        if (question >= 0) {
+            path = url.substring(0, question);
+            query = url.substring(question);
+        }
+        int pound = path.indexOf('#');
+        if (pound >= 0) {
+            anchor = path.substring(pound);
+            path = path.substring(0, pound);
+        }
+        StringBuffer sb = new StringBuffer(path);
+        if (sb.length() > 0) { // jsessionid can't be first.
+            sb.append(";");
+            sb.append(DEFAULT_SESSION_ID_PARAMETER_NAME);
+            sb.append("=");
+            sb.append(sessionId);
+        }
+        sb.append(anchor);
+        sb.append(query);
+        return (sb.toString());
+
+    }
+}

Added: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpSession.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpSession.java?rev=785881&view=auto
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpSession.java (added)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/ShiroHttpSession.java Thu Jun 18 03:13:34 2009
@@ -0,0 +1,248 @@
+/*
+ * 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.shiro.web.servlet;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+import javax.servlet.http.HttpSessionBindingEvent;
+import javax.servlet.http.HttpSessionBindingListener;
+import javax.servlet.http.HttpSessionContext;
+
+import org.apache.shiro.session.InvalidSessionException;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.web.session.WebSession;
+
+
+/**
+ * Wrapper class that uses a Shiro session under the hood for all session operations instead of the
+ * Servlet Container's session mechanism.  This is preferred in heterogeneous client environments where the Session
+ * is used on both the business tier as well as in multiple client technologies (web, swing, flash, etc).
+ *
+ * @author Les Hazlewood
+ * @since 0.2
+ */
+@SuppressWarnings({"deprecation"})
+public class ShiroHttpSession implements HttpSession {
+
+    //TODO - complete JavaDoc
+
+    public static final String DEFAULT_SESSION_ID_NAME = "JSESSIONID";
+
+    private static final Enumeration EMPTY_ENUMERATION = new Enumeration() {
+        public boolean hasMoreElements() {
+            return false;
+        }
+
+        public Object nextElement() {
+            return null;
+        }
+    };
+
+    private static final HttpSessionContext HTTP_SESSION_CONTEXT = new HttpSessionContext() {
+        public HttpSession getSession(String s) {
+            return null;
+        }
+
+        public Enumeration getIds() {
+            return EMPTY_ENUMERATION;
+        }
+    };
+
+    protected ServletContext servletContext = null;
+    protected HttpServletRequest currentRequest = null;
+    protected Session session = null; //'real' Shiro Session
+
+    public ShiroHttpSession(Session session, HttpServletRequest currentRequest, ServletContext servletContext) {
+        if (session instanceof WebSession) {
+            String msg = "Session constructor argument cannot be an instance of WebSession.  This is enforced to " +
+                    "prevent circular dependencies and infinite loops.";
+            throw new IllegalArgumentException(msg);
+        }
+        this.session = session;
+        this.currentRequest = currentRequest;
+        this.servletContext = servletContext;
+    }
+
+    public Session getSession() {
+        return this.session;
+    }
+
+    public long getCreationTime() {
+        try {
+            return getSession().getStartTimestamp().getTime();
+        } catch (Exception e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public String getId() {
+        return getSession().getId().toString();
+    }
+
+    public long getLastAccessedTime() {
+        return getSession().getLastAccessTime().getTime();
+    }
+
+    public ServletContext getServletContext() {
+        return this.servletContext;
+    }
+
+    public void setMaxInactiveInterval(int i) {
+        try {
+            getSession().setTimeout(i * 1000);
+        } catch (InvalidSessionException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public int getMaxInactiveInterval() {
+        try {
+            return (new Long(getSession().getTimeout() / 1000)).intValue();
+        } catch (InvalidSessionException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public HttpSessionContext getSessionContext() {
+        return HTTP_SESSION_CONTEXT;
+    }
+
+    public Object getAttribute(String s) {
+        try {
+            return getSession().getAttribute(s);
+        } catch (InvalidSessionException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public Object getValue(String s) {
+        return getAttribute(s);
+    }
+
+    @SuppressWarnings({"unchecked"})
+    protected Set<String> getKeyNames() {
+        Collection<Object> keySet;
+        try {
+            keySet = getSession().getAttributeKeys();
+        } catch (InvalidSessionException e) {
+            throw new IllegalStateException(e);
+        }
+        Set<String> keyNames;
+        if (keySet != null && !keySet.isEmpty()) {
+            keyNames = new HashSet<String>(keySet.size());
+            for (Object o : keySet) {
+                keyNames.add(o.toString());
+            }
+        } else {
+            keyNames = Collections.EMPTY_SET;
+        }
+        return keyNames;
+    }
+
+    public Enumeration getAttributeNames() {
+        Set<String> keyNames = getKeyNames();
+        final Iterator iterator = keyNames.iterator();
+        return new Enumeration() {
+            public boolean hasMoreElements() {
+                return iterator.hasNext();
+            }
+
+            public Object nextElement() {
+                return iterator.next();
+            }
+        };
+    }
+
+    public String[] getValueNames() {
+        Set<String> keyNames = getKeyNames();
+        String[] array = new String[keyNames.size()];
+        if (keyNames.size() > 0) {
+            array = keyNames.toArray(array);
+        }
+        return array;
+    }
+
+    protected void afterBound(String s, Object o) {
+        if (o instanceof HttpSessionBindingListener) {
+            HttpSessionBindingListener listener = (HttpSessionBindingListener) o;
+            HttpSessionBindingEvent event = new HttpSessionBindingEvent(this, s, o);
+            listener.valueBound(event);
+        }
+    }
+
+    protected void afterUnbound(String s, Object o) {
+        if (o instanceof HttpSessionBindingListener) {
+            HttpSessionBindingListener listener = (HttpSessionBindingListener) o;
+            HttpSessionBindingEvent event = new HttpSessionBindingEvent(this, s, o);
+            listener.valueUnbound(event);
+        }
+    }
+
+    public void setAttribute(String s, Object o) {
+        try {
+            getSession().setAttribute(s, o);
+            afterBound(s, o);
+        } catch (InvalidSessionException e) {
+            //noinspection finally
+            try {
+                afterUnbound(s, o);
+            } finally {
+                //noinspection ThrowFromFinallyBlock
+                throw new IllegalStateException(e);
+            }
+        }
+    }
+
+    public void putValue(String s, Object o) {
+        setAttribute(s, o);
+    }
+
+    public void removeAttribute(String s) {
+        try {
+            Object attribute = getSession().removeAttribute(s);
+            afterUnbound(s, attribute);
+        } catch (InvalidSessionException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public void removeValue(String s) {
+        removeAttribute(s);
+    }
+
+    public void invalidate() {
+        try {
+            getSession().stop();
+        } catch (InvalidSessionException e) {
+            throw new IllegalStateException(e);
+        }
+    }
+
+    public boolean isNew() {
+        Boolean value = (Boolean) currentRequest.getAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW);
+        return value != null && value.equals(Boolean.TRUE);
+    }
+}

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/package-info.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/package-info.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/package-info.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/servlet/package-info.java Thu Jun 18 03:13:34 2009
@@ -1,23 +1,23 @@
-/*
- * 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.
- */
-/**
- * Support implementations that depend heavily on the <tt>javax.servlet.*</tt> API and are meant to be
- * directly used in web.xml (Servlet Filters, Servlet Context Listeners, Servlets, etc)
- */
-package org.apache.ki.web.servlet;
+/*
+ * 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.
+ */
+/**
+ * Support implementations that depend heavily on the <tt>javax.servlet.*</tt> API and are meant to be
+ * directly used in web.xml (Servlet Filters, Servlet Context Listeners, Servlets, etc)
+ */
+package org.apache.shiro.web.servlet;

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DefaultWebSessionManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DefaultWebSessionManager.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DefaultWebSessionManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/DefaultWebSessionManager.java Thu Jun 18 03:13:34 2009
@@ -16,19 +16,19 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.session;
+package org.apache.shiro.web.session;
 
-import org.apache.ki.authz.AuthorizationException;
-import org.apache.ki.authz.HostUnauthorizedException;
-import org.apache.ki.session.InvalidSessionException;
-import org.apache.ki.session.Session;
-import org.apache.ki.session.mgt.DefaultSessionManager;
-import org.apache.ki.web.WebUtils;
-import org.apache.ki.web.attr.CookieAttribute;
-import org.apache.ki.web.attr.RequestParamAttribute;
-import org.apache.ki.web.attr.WebAttribute;
-import org.apache.ki.web.servlet.KiHttpServletRequest;
-import org.apache.ki.web.servlet.KiHttpSession;
+import org.apache.shiro.authz.AuthorizationException;
+import org.apache.shiro.authz.HostUnauthorizedException;
+import org.apache.shiro.session.InvalidSessionException;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.DefaultSessionManager;
+import org.apache.shiro.web.WebUtils;
+import org.apache.shiro.web.attr.CookieAttribute;
+import org.apache.shiro.web.attr.RequestParamAttribute;
+import org.apache.shiro.web.attr.WebAttribute;
+import org.apache.shiro.web.servlet.ShiroHttpServletRequest;
+import org.apache.shiro.web.servlet.ShiroHttpSession;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -152,7 +152,7 @@
     protected void ensureCookieSessionIdStore() {
         CookieAttribute<Serializable> cookieStore = getSessionIdCookieAttribute();
         if (cookieStore == null) {
-            cookieStore = new CookieAttribute<Serializable>(KiHttpSession.DEFAULT_SESSION_ID_NAME);
+            cookieStore = new CookieAttribute<Serializable>(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
             cookieStore.setCheckRequestParams(false);
             setSessionIdCookieAttribute(cookieStore);
         }
@@ -161,7 +161,7 @@
     protected void ensureRequestParamSessionIdStore() {
         RequestParamAttribute<Serializable> reqParamStore = getSessionIdRequestParamAttribute();
         if (reqParamStore == null) {
-            reqParamStore = new RequestParamAttribute<Serializable>(KiHttpSession.DEFAULT_SESSION_ID_NAME);
+            reqParamStore = new RequestParamAttribute<Serializable>(ShiroHttpSession.DEFAULT_SESSION_ID_NAME);
             setSessionIdRequestParamAttribute(reqParamStore);
         }
     }
@@ -213,7 +213,7 @@
     }
 
     private void markSessionIdValid(Serializable sessionId, ServletRequest request) {
-        request.setAttribute(KiHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
+        request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);
     }
 
     private void removeSessionIdCookie(ServletRequest request, ServletResponse response) {
@@ -225,17 +225,17 @@
         WebAttribute<Serializable> cookieSessionIdAttribute = getSessionIdCookieAttribute();
         Serializable id = cookieSessionIdAttribute.retrieveValue(request, response);
         if (id != null) {
-            request.setAttribute(KiHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
-                    KiHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
+            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
+                    ShiroHttpServletRequest.COOKIE_SESSION_ID_SOURCE);
         } else {
             id = getSessionIdRequestParamAttribute().retrieveValue(request, response);
             if (id != null) {
-                request.setAttribute(KiHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
-                        KiHttpServletRequest.URL_SESSION_ID_SOURCE);
+                request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,
+                        ShiroHttpServletRequest.URL_SESSION_ID_SOURCE);
             }
         }
         if (id != null) {
-            request.setAttribute(KiHttpServletRequest.REFERENCED_SESSION_ID, id);
+            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, id);
         }
         return id;
     }
@@ -259,8 +259,8 @@
     }
 
     protected void onSessionStart(ServletRequest request) {
-        request.removeAttribute(KiHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
-        request.setAttribute(KiHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
+        request.removeAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE);
+        request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_IS_NEW, Boolean.TRUE);
     }
 
     @Override
@@ -280,7 +280,7 @@
      * @param request  incoming servlet request
      * @param response outgoing servlet response
      * @return the Session associated with the incoming request or <tt>null</tt> if one does not exist.
-     * @throws org.apache.ki.authz.AuthorizationException
+     * @throws org.apache.shiro.authz.AuthorizationException
      *          if the caller is not authorized to access the session associated with the request.
      */
     public Session getSession(ServletRequest request, ServletResponse response)
@@ -290,7 +290,7 @@
         Serializable sessionId = getReferencedSessionId(request, response);
 
         if (sessionId != null) {
-            request.setAttribute(KiHttpServletRequest.REFERENCED_SESSION_ID, sessionId);
+            request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sessionId);
             try {
                 session = retrieveSessionFromDataSource(sessionId);
                 markSessionIdValid(sessionId, request);
@@ -311,7 +311,7 @@
             }
         } else {
             if (log.isTraceEnabled()) {
-                log.trace("A valid Ki session id was not associated with the current request.");
+                log.trace("A valid Shiro session id was not associated with the current request.");
             }
         }
 

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/ServletContainerSessionManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/ServletContainerSessionManager.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/ServletContainerSessionManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/ServletContainerSessionManager.java Thu Jun 18 03:13:34 2009
@@ -16,14 +16,14 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.session;
+package org.apache.shiro.web.session;
 
-import org.apache.ki.authz.AuthorizationException;
-import org.apache.ki.session.InvalidSessionException;
-import org.apache.ki.session.Session;
-import org.apache.ki.session.mgt.AbstractSessionManager;
-import org.apache.ki.session.mgt.SessionFactory;
-import org.apache.ki.web.WebUtils;
+import org.apache.shiro.authz.AuthorizationException;
+import org.apache.shiro.session.InvalidSessionException;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.AbstractSessionManager;
+import org.apache.shiro.session.mgt.SessionFactory;
+import org.apache.shiro.web.WebUtils;
 
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
@@ -39,8 +39,8 @@
  * Servlet container's HttpSession.
  * <p/>
  * Despite its name, this implementation <em>does not</em> itself manage Sessions since the Servlet container
- * provides the actual management support.  This class mainly exists to 'impersonate' a regular Ki
- * <tt>SessionManager</tt> so it can be pluggable into a normal Ki configuration in a pure web application.
+ * provides the actual management support.  This class mainly exists to 'impersonate' a regular Shiro
+ * <tt>SessionManager</tt> so it can be pluggable into a normal Shiro configuration in a pure web application.
  * <p/>
  * Note that because this implementation relies on the {@link HttpSession HttpSession}, it is only functional in a
  * servlet container.  I.e. it is <em>NOT</em> capable of supporting Sessions any clients other than

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSession.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSession.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSession.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSession.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.session;
+package org.apache.shiro.web.session;
 
 import java.io.Serializable;
 import java.net.InetAddress;
@@ -26,9 +26,10 @@
 import java.util.Enumeration;
 import javax.servlet.http.HttpSession;
 
-import org.apache.ki.session.InvalidSessionException;
-import org.apache.ki.session.Session;
-import org.apache.ki.web.servlet.KiHttpSession;
+import org.apache.shiro.session.InvalidSessionException;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.web.servlet.ShiroHttpSession;
+
 
 /**
  * TODO class JavaDoc
@@ -50,8 +51,8 @@
             String msg = "HttpSession constructor argument cannot be null.";
             throw new IllegalArgumentException(msg);
         }
-        if (httpSession instanceof KiHttpSession) {
-            String msg = "HttpSession constructor argument cannot be an instance of KiHttpSession.  This " +
+        if (httpSession instanceof ShiroHttpSession) {
+            String msg = "HttpSession constructor argument cannot be an instance of ShiroHttpSession.  This " +
                     "is enforced to prevent circular dependencies and infinite loops.";
             throw new IllegalArgumentException(msg);
         }
@@ -134,7 +135,7 @@
 
     private static String assertString(Object key) {
         if (!(key instanceof String)) {
-            String msg = "HttpSession based implementations of the Ki Session interface requires attribute keys " +
+            String msg = "HttpSession based implementations of the Shiro Session interface requires attribute keys " +
                     "to be String objects.  The HttpSession class does not support anything other than String keys.";
             throw new IllegalArgumentException(msg);
         }

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSessionManager.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSessionManager.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSessionManager.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/WebSessionManager.java Thu Jun 18 03:13:34 2009
@@ -16,13 +16,13 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.session;
+package org.apache.shiro.web.session;
 
 import javax.servlet.ServletRequest;
 import javax.servlet.ServletResponse;
 
-import org.apache.ki.session.Session;
-import org.apache.ki.session.mgt.SessionManager;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.session.mgt.SessionManager;
 
 
 /**

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/package-info.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/package-info.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/package-info.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/session/package-info.java Thu Jun 18 03:13:34 2009
@@ -1,22 +1,22 @@
-/*
- * 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.
- */
-/**
- * Components supporting Session management in web-enabled applications.
- */
-package org.apache.ki.web.session;
+/*
+ * 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.
+ */
+/**
+ * Components supporting Session management in web-enabled applications.
+ */
+package org.apache.shiro.web.session;

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/AuthenticatedTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/AuthenticatedTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/AuthenticatedTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/AuthenticatedTag.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
 import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.tagext.TagSupport;

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/GuestTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/GuestTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/GuestTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/GuestTag.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
 import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.tagext.TagSupport;

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasAnyRolesTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasAnyRolesTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasAnyRolesTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasAnyRolesTag.java Thu Jun 18 03:13:34 2009
@@ -16,9 +16,9 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
-import org.apache.ki.subject.Subject;
+import org.apache.shiro.subject.Subject;
 
 
 /**

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasPermissionTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasPermissionTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasPermissionTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasPermissionTag.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
 /**
  * @author Les Hazlewood

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasRoleTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasRoleTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasRoleTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/HasRoleTag.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
 /**
  * @author Les Hazlewood

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/LacksPermissionTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/LacksPermissionTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/LacksPermissionTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/LacksPermissionTag.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
 /**
  * @author Les Hazlewood

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/LacksRoleTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/LacksRoleTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/LacksRoleTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/LacksRoleTag.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
 /**
  * @author Les Hazlewood

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/NotAuthenticatedTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/NotAuthenticatedTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/NotAuthenticatedTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/NotAuthenticatedTag.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
 import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.tagext.TagSupport;
@@ -29,7 +29,7 @@
  * JSP tag that renders the tag body only if the current user has <em>not</em> executed a successful authentication
  * attempt <em>during their current session</em>.
  *
- * <p>The logically opposite tag of this one is the {@link org.apache.ki.web.tags.AuthenticatedTag}.
+ * <p>The logically opposite tag of this one is the {@link org.apache.shiro.web.tags.AuthenticatedTag}.
  *
  * @author Jeremy Haile
  * @since 0.2

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/PermissionTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/PermissionTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/PermissionTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/PermissionTag.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
 import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.tagext.TagSupport;

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/PrincipalTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/PrincipalTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/PrincipalTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/PrincipalTag.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
 import java.beans.BeanInfo;
 import java.beans.Introspector;

Modified: incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/RoleTag.java
URL: http://svn.apache.org/viewvc/incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/RoleTag.java?rev=785881&r1=785781&r2=785881&view=diff
==============================================================================
--- incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/RoleTag.java (original)
+++ incubator/shiro/trunk/web/src/main/java/org/apache/shiro/web/tags/RoleTag.java Thu Jun 18 03:13:34 2009
@@ -16,7 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-package org.apache.ki.web.tags;
+package org.apache.shiro.web.tags;
 
 import javax.servlet.jsp.JspException;
 import javax.servlet.jsp.tagext.TagSupport;