/*
* Copyright (c) 1998-2012 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package org.ireland.jnetty.dispatch.servlet;
import java.util.ArrayList;
import java.util.Collection;
import org.ireland.jnetty.config.ConfigException;
import org.ireland.jnetty.dispatch.FilterChainInvocation;
import org.springframework.util.Assert;
/**
* Configuration for a servlet.
*
* 代表web.xml中一个"<servlet-mapping>"元素
*
* <servlet-mapping>
* <servlet-name>MyServlet</servlet-name>
* <url-pattern>/myservlet.do</url-pattern>
* <url-pattern>/my/*</url-pattern>
* <url-pattern>/mys/*</url-pattern>
* </servlet-mapping>
*
*/
public class ServletMapping
{
// <servlet>
private final ServletConfigImpl servletConfig;
// <url-pattern> 列表
private ArrayList<String> _urlPatterns = new ArrayList<String>();
/**
* Creates a new servlet mapping object.
*/
public ServletMapping(ServletConfigImpl servletConfig)
{
Assert.notNull(servletConfig);
this.servletConfig = servletConfig;
}
public ServletConfigImpl getServletConfig()
{
return servletConfig;
}
/**
* Gets the url patterns
*/
public Collection<String> getURLPatterns()
{
return _urlPatterns;
}
/**
* Sets the url pattern
*/
public void addURLPattern(String pattern)
{
if (pattern.indexOf('\n') > -1)
{
throw new ConfigException("'url-pattern' cannot contain newline");
}
if(_urlPatterns.contains(pattern)) //not to add the exist parrern
return;
_urlPatterns.add(pattern);
// server/13f4
if (servletConfig.getServletNameDefault() == null)
servletConfig.setServletNameDefault(pattern);
}
// ------------------------------------------------------------------
/**
* Returns true if the servlet-mapping matches the invocation URL.
*
* @param invocation
* the request's invocation
*/
boolean isMatch(FilterChainInvocation invocation)
{
return isMatch(invocation.getServletPath(), invocation.getPathInfo());
}
/**
* Returns true if the servlet-mapping matches the servlet path and path info.
* */
public boolean isMatch(String servletPath, String pathInfo)
{
String uri;
if (pathInfo == null)
uri = servletPath;
else if (servletPath == null)
uri = pathInfo;
else
uri = servletPath + pathInfo;
return isMatch(uri);
}
/**
* Returns true if the servlet-mapping matches the URI
*
* @param uri
* the request's uri(= servletPath + pathInfo)
*/
public boolean isMatch(String uri)
{
for (String urlPattern : _urlPatterns)
{
if (matchServletURL(uri,urlPattern) )
return true;
}
return false;
}
/**
* Return <code>true</code> if the context-relative request path matches the requirements of the specified filter
* mapping; otherwise, return <code>false</code>.
*
*
* @param requestPath
* Context-relative request path of this request(without query String)
*
* @param urlPattern
* URL mapping being checked
*/
private static boolean matchServletURL(String requestPath , String urlPattern)
{
if (urlPattern == null)
return (false);
// Case 1 - Exact Match
if (urlPattern.equals(requestPath))
return (true);
// Case 2 - Path Match ("/.../*")
if (urlPattern.equals("/*"))
return (true);
if (urlPattern.endsWith("/*"))
{
if (urlPattern.regionMatches(0, requestPath, 0, urlPattern.length() - 2))
{
if (requestPath.length() == (urlPattern.length() - 2))
{
return (true);
}
else if ('/' == requestPath.charAt(urlPattern.length() - 2))
{
return (true);
}
}
return (false);
}
// Case 3 - Extension Match
if (urlPattern.startsWith("*."))
{
int slash = requestPath.lastIndexOf('/');
int period = requestPath.lastIndexOf('.');
if ((slash >= 0) && (period > slash) && (period != requestPath.length() - 1) && ((requestPath.length() - period) == (urlPattern.length() - 1)))
{
return (urlPattern.regionMatches(2, requestPath, period + 1, urlPattern.length() - 2));
}
}
// Case 4 - "Default" Match
return (false); // NOTE - Not relevant for selecting filters
}
// ------------------------------------------------------------
/**
* Returns a printable representation of the servlet config object.
*/
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("ServletMapping[");
for (int i = 0; i < _urlPatterns.size(); i++)
{
String urlPattern = _urlPatterns.get(i);
if (urlPattern != null)
{
builder.append("url-pattern=");
builder.append(urlPattern);
builder.append(", ");
}
}
builder.append("name=");
builder.append(servletConfig.getServletName());
if (servletConfig.getServletClassName() != null)
{
builder.append(", class=");
builder.append(servletConfig.getServletClassName());
}
builder.append("]");
return builder.toString();
}
}