View Javadoc

1   // ========================================================================
2   // Copyright (c) 2010 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.annotations;
15  
16  import java.util.ArrayList;
17  
18  import javax.servlet.annotation.WebInitParam;
19  import javax.servlet.annotation.WebServlet;
20  import javax.servlet.http.HttpServlet;
21  
22  import org.eclipse.jetty.servlet.Holder;
23  import org.eclipse.jetty.servlet.ServletHolder;
24  import org.eclipse.jetty.servlet.ServletMapping;
25  import org.eclipse.jetty.util.LazyList;
26  import org.eclipse.jetty.util.log.Log;
27  import org.eclipse.jetty.util.log.Logger;
28  import org.eclipse.jetty.webapp.DiscoveredAnnotation;
29  import org.eclipse.jetty.webapp.MetaData;
30  import org.eclipse.jetty.webapp.WebAppContext;
31  import org.eclipse.jetty.webapp.Origin;
32  
33  /**
34   * WebServletAnnotation
35   *
36   *
37   */
38  public class WebServletAnnotation extends DiscoveredAnnotation
39  {
40      private static final Logger LOG = Log.getLogger(WebServletAnnotation.class);
41      
42      public WebServletAnnotation (WebAppContext context, String className)
43      {
44          super(context, className);
45      }
46  
47      /** 
48       * @see org.eclipse.jetty.annotations.ClassAnnotation#apply()
49       */
50      public void apply()
51      {
52          //TODO check this algorithm with new rules for applying descriptors and annotations in order
53          Class clazz = getTargetClass();
54          
55          if (clazz == null)
56          {
57              LOG.warn(_className+" cannot be loaded");
58              return;
59          }
60          
61          //Servlet Spec 8.1.1
62          if (!HttpServlet.class.isAssignableFrom(clazz))
63          {
64              LOG.warn(clazz.getName()+" is not assignable from javax.servlet.http.HttpServlet");
65              return;
66          }
67          
68          WebServlet annotation = (WebServlet)clazz.getAnnotation(WebServlet.class);
69          
70          if (annotation.urlPatterns().length > 0 && annotation.value().length > 0)
71          {
72              LOG.warn(clazz.getName()+ " defines both @WebServlet.value and @WebServlet.urlPatterns");
73              return;
74          }
75          
76          String[] urlPatterns = annotation.value();
77          if (urlPatterns.length == 0)
78              urlPatterns = annotation.urlPatterns();
79          
80          if (urlPatterns.length == 0)
81          {
82              LOG.warn(clazz.getName()+ " defines neither @WebServlet.value nor @WebServlet.urlPatterns");
83              return;
84          }
85          
86          //canonicalize the patterns
87          ArrayList<String> urlPatternList = new ArrayList<String>();
88          for (String p : urlPatterns)
89              urlPatternList.add(Util.normalizePattern(p));
90          
91          String servletName = (annotation.name().equals("")?clazz.getName():annotation.name());
92          
93          MetaData metaData = _context.getMetaData();
94  
95          //Find out if a <servlet>  of this type already exists with this name
96          ServletHolder[] holders = _context.getServletHandler().getServlets();
97          boolean isNew = true;
98          ServletHolder holder = null;
99          if (holders != null)
100         {
101             for (ServletHolder h : holders)
102             {
103                 if (h.getClassName().equals(clazz.getName()) && h.getName().equals(servletName))
104                 {
105                     holder = h;
106                     isNew = false;
107                     break;
108                 }
109             }
110         }
111 
112         if (isNew)
113         {
114             //No servlet of this name has already been defined, either by a descriptor
115             //or another annotation (which would be impossible).
116             holder = _context.getServletHandler().newServletHolder(Holder.Source.ANNOTATION);
117             holder.setHeldClass(clazz);   
118             metaData.setOrigin(servletName+".servlet.servlet-class");
119             
120             holder.setName(servletName);
121             holder.setDisplayName(annotation.displayName());
122             metaData.setOrigin(servletName+".servlet.display-name");
123             
124             holder.setInitOrder(annotation.loadOnStartup());
125             metaData.setOrigin(servletName+".servlet.load-on-startup");
126             
127             holder.setAsyncSupported(annotation.asyncSupported());
128             metaData.setOrigin(servletName+".servlet.async-supported");
129             
130             for (WebInitParam ip:annotation.initParams())
131             {
132                 holder.setInitParameter(ip.name(), ip.value());
133                 metaData.setOrigin(servletName+".servlet.init-param."+ip.name());
134             }
135           
136             _context.getServletHandler().addServlet(holder);
137             ServletMapping mapping = new ServletMapping();  
138             mapping.setServletName(holder.getName());
139             mapping.setPathSpecs( LazyList.toStringArray(urlPatternList));
140             _context.getServletHandler().addServletMapping(mapping);
141             metaData.setOrigin(servletName+".servlet.mappings");
142         }
143         else
144         {
145             //check if the existing servlet has each init-param from the annotation
146             //if not, add it
147             for (WebInitParam ip:annotation.initParams())
148             {
149               //if (holder.getInitParameter(ip.name()) == null)
150                 if (metaData.getOrigin(servletName+".servlet.init-param"+ip.name())==Origin.NotSet)
151                 {
152                     holder.setInitParameter(ip.name(), ip.value());
153                     metaData.setOrigin(servletName+".servlet.init-param."+ip.name());
154                 }  
155             }
156             
157             //check the url-patterns, if there annotation has a new one, add it
158             ServletMapping[] mappings = _context.getServletHandler().getServletMappings();
159 
160             //ServletSpec 3.0 p81 If a servlet already has url mappings from a 
161             //descriptor the annotation is ignored
162             if (mappings == null && metaData.getOriginDescriptor(servletName+".servlet.mappings") != null)
163             {
164                 ServletMapping mapping = new ServletMapping();
165                 mapping.setServletName(servletName);
166                 mapping.setPathSpecs(LazyList.toStringArray(urlPatternList));
167                 _context.getServletHandler().addServletMapping(mapping); 
168             }
169         }
170     }   
171 }