blob: efcef9d0026257ce4739fff07ccd0da3bfd0dc48 [file] [log] [blame]
//
// ========================================================================
// Copyright (c) 1995-2017 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
//
package org.eclipse.jetty.annotations;
import java.util.ArrayList;
import java.util.EnumSet;
import javax.servlet.DispatcherType;
import javax.servlet.Filter;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import org.eclipse.jetty.servlet.FilterHolder;
import org.eclipse.jetty.servlet.FilterMapping;
import org.eclipse.jetty.servlet.Holder;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.webapp.DiscoveredAnnotation;
import org.eclipse.jetty.webapp.MetaData;
import org.eclipse.jetty.webapp.Origin;
import org.eclipse.jetty.webapp.WebAppContext;
/**
* WebFilterAnnotation
*
*
*/
public class WebFilterAnnotation extends DiscoveredAnnotation
{
private static final Logger LOG = Log.getLogger(WebFilterAnnotation.class);
/**
* @param context
* @param className
*/
public WebFilterAnnotation(WebAppContext context, String className)
{
super(context, className);
}
public WebFilterAnnotation(WebAppContext context, String className, Resource resource)
{
super(context, className, resource);
}
/**
* @see DiscoveredAnnotation#apply()
*/
public void apply()
{
// TODO verify against rules for annotation v descriptor
Class clazz = getTargetClass();
if (clazz == null)
{
LOG.warn(_className+" cannot be loaded");
return;
}
//Servlet Spec 8.1.2
if (!Filter.class.isAssignableFrom(clazz))
{
LOG.warn(clazz.getName()+" is not assignable from javax.servlet.Filter");
return;
}
MetaData metaData = _context.getMetaData();
WebFilter filterAnnotation = (WebFilter)clazz.getAnnotation(WebFilter.class);
if (filterAnnotation.value().length > 0 && filterAnnotation.urlPatterns().length > 0)
{
LOG.warn(clazz.getName()+" defines both @WebFilter.value and @WebFilter.urlPatterns");
return;
}
String name = (filterAnnotation.filterName().equals("")?clazz.getName():filterAnnotation.filterName());
String[] urlPatterns = filterAnnotation.value();
if (urlPatterns.length == 0)
urlPatterns = filterAnnotation.urlPatterns();
FilterHolder holder = _context.getServletHandler().getFilter(name);
if (holder == null)
{
//Filter with this name does not already exist, so add it
holder = _context.getServletHandler().newFilterHolder(Holder.Source.ANNOTATION);
holder.setName(name);
holder.setHeldClass(clazz);
metaData.setOrigin(name+".filter.filter-class",filterAnnotation,clazz);
holder.setDisplayName(filterAnnotation.displayName());
metaData.setOrigin(name+".filter.display-name",filterAnnotation,clazz);
for (WebInitParam ip: filterAnnotation.initParams())
{
holder.setInitParameter(ip.name(), ip.value());
metaData.setOrigin(name+".filter.init-param."+ip.name(),ip,clazz);
}
FilterMapping mapping = new FilterMapping();
mapping.setFilterName(holder.getName());
if (urlPatterns.length > 0)
{
ArrayList<String> paths = new ArrayList<String>();
for (String s:urlPatterns)
{
paths.add(Util.normalizePattern(s));
}
mapping.setPathSpecs(paths.toArray(new String[paths.size()]));
}
if (filterAnnotation.servletNames().length > 0)
{
ArrayList<String> names = new ArrayList<String>();
for (String s : filterAnnotation.servletNames())
{
names.add(s);
}
mapping.setServletNames(names.toArray(new String[names.size()]));
}
EnumSet<DispatcherType> dispatcherSet = EnumSet.noneOf(DispatcherType.class);
for (DispatcherType d : filterAnnotation.dispatcherTypes())
{
dispatcherSet.add(d);
}
mapping.setDispatcherTypes(dispatcherSet);
metaData.setOrigin(name+".filter.mappings",filterAnnotation,clazz);
holder.setAsyncSupported(filterAnnotation.asyncSupported());
metaData.setOrigin(name+".filter.async-supported",filterAnnotation,clazz);
_context.getServletHandler().addFilter(holder);
_context.getServletHandler().addFilterMapping(mapping);
}
else
{
//A Filter definition for the same name already exists from web.xml
//ServletSpec 3.0 p81 if the Filter is already defined and has mappings,
//they override the annotation. If it already has DispatcherType set, that
//also overrides the annotation. Init-params are additive, but web.xml overrides
//init-params of the same name.
for (WebInitParam ip: filterAnnotation.initParams())
{
//if (holder.getInitParameter(ip.name()) == null)
if (metaData.getOrigin(name+".filter.init-param."+ip.name())==Origin.NotSet)
{
holder.setInitParameter(ip.name(), ip.value());
metaData.setOrigin(name+".filter.init-param."+ip.name(),ip,clazz);
}
}
FilterMapping[] mappings = _context.getServletHandler().getFilterMappings();
boolean mappingExists = false;
if (mappings != null)
{
for (FilterMapping m:mappings)
{
if (m.getFilterName().equals(name))
{
mappingExists = true;
break;
}
}
}
//if a descriptor didn't specify at least one mapping, use the mappings from the annotation and the DispatcherTypes
//from the annotation
if (!mappingExists)
{
FilterMapping mapping = new FilterMapping();
mapping.setFilterName(holder.getName());
if (urlPatterns.length > 0)
{
ArrayList<String> paths = new ArrayList<String>();
for (String s:urlPatterns)
{
paths.add(Util.normalizePattern(s));
}
mapping.setPathSpecs(paths.toArray(new String[paths.size()]));
}
if (filterAnnotation.servletNames().length > 0)
{
ArrayList<String> names = new ArrayList<String>();
for (String s : filterAnnotation.servletNames())
{
names.add(s);
}
mapping.setServletNames(names.toArray(new String[names.size()]));
}
EnumSet<DispatcherType> dispatcherSet = EnumSet.noneOf(DispatcherType.class);
for (DispatcherType d : filterAnnotation.dispatcherTypes())
{
dispatcherSet.add(d);
}
mapping.setDispatcherTypes(dispatcherSet);
_context.getServletHandler().addFilterMapping(mapping);
metaData.setOrigin(name+".filter.mappings",filterAnnotation,clazz);
}
}
}
}