1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.annotations;
20
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.List;
24
25 import javax.servlet.Servlet;
26 import javax.servlet.annotation.WebInitParam;
27 import javax.servlet.annotation.WebServlet;
28 import javax.servlet.http.HttpServlet;
29
30 import org.eclipse.jetty.servlet.Holder;
31 import org.eclipse.jetty.servlet.ServletHolder;
32 import org.eclipse.jetty.servlet.ServletMapping;
33 import org.eclipse.jetty.util.ArrayUtil;
34 import org.eclipse.jetty.util.LazyList;
35 import org.eclipse.jetty.util.log.Log;
36 import org.eclipse.jetty.util.log.Logger;
37 import org.eclipse.jetty.util.resource.Resource;
38 import org.eclipse.jetty.webapp.DiscoveredAnnotation;
39 import org.eclipse.jetty.webapp.MetaData;
40 import org.eclipse.jetty.webapp.Origin;
41 import org.eclipse.jetty.webapp.WebAppContext;
42
43
44
45
46
47
48 public class WebServletAnnotation extends DiscoveredAnnotation
49 {
50 private static final Logger LOG = Log.getLogger(WebServletAnnotation.class);
51
52 public WebServletAnnotation (WebAppContext context, String className)
53 {
54 super(context, className);
55 }
56
57
58 public WebServletAnnotation (WebAppContext context, String className, Resource resource)
59 {
60 super(context, className, resource);
61 }
62
63
64
65
66 public void apply()
67 {
68
69 Class<? extends Servlet> clazz = (Class<? extends Servlet>)getTargetClass();
70
71 if (clazz == null)
72 {
73 LOG.warn(_className+" cannot be loaded");
74 return;
75 }
76
77
78 if (!HttpServlet.class.isAssignableFrom(clazz))
79 {
80 LOG.warn(clazz.getName()+" is not assignable from javax.servlet.http.HttpServlet");
81 return;
82 }
83
84 WebServlet annotation = (WebServlet)clazz.getAnnotation(WebServlet.class);
85
86 if (annotation.urlPatterns().length > 0 && annotation.value().length > 0)
87 {
88 LOG.warn(clazz.getName()+ " defines both @WebServlet.value and @WebServlet.urlPatterns");
89 return;
90 }
91
92 String[] urlPatterns = annotation.value();
93 if (urlPatterns.length == 0)
94 urlPatterns = annotation.urlPatterns();
95
96 if (urlPatterns.length == 0)
97 {
98 LOG.warn(clazz.getName()+ " defines neither @WebServlet.value nor @WebServlet.urlPatterns");
99 return;
100 }
101
102
103 ArrayList<String> urlPatternList = new ArrayList<String>();
104 for (String p : urlPatterns)
105 urlPatternList.add(Util.normalizePattern(p));
106
107 String servletName = (annotation.name().equals("")?clazz.getName():annotation.name());
108
109 MetaData metaData = _context.getMetaData();
110 ServletMapping mapping = null;
111
112
113 ServletHolder[] holders = _context.getServletHandler().getServlets();
114
115 ServletHolder holder = null;
116 if (holders != null)
117 {
118 for (ServletHolder h : holders)
119 {
120 if (h.getName() != null && servletName.equals(h.getName()))
121 {
122 holder = h;
123 break;
124 }
125 }
126 }
127
128
129 if (holder == null)
130 {
131
132
133 holder = _context.getServletHandler().newServletHolder(Holder.Source.ANNOTATION);
134 holder.setHeldClass(clazz);
135 metaData.setOrigin(servletName+".servlet.servlet-class",annotation,clazz);
136
137 holder.setName(servletName);
138 holder.setDisplayName(annotation.displayName());
139 metaData.setOrigin(servletName+".servlet.display-name",annotation,clazz);
140
141 holder.setInitOrder(annotation.loadOnStartup());
142 metaData.setOrigin(servletName+".servlet.load-on-startup",annotation,clazz);
143
144 holder.setAsyncSupported(annotation.asyncSupported());
145 metaData.setOrigin(servletName+".servlet.async-supported",annotation,clazz);
146
147 for (WebInitParam ip:annotation.initParams())
148 {
149 holder.setInitParameter(ip.name(), ip.value());
150 metaData.setOrigin(servletName+".servlet.init-param."+ip.name(),ip,clazz);
151 }
152
153 _context.getServletHandler().addServlet(holder);
154
155
156 mapping = new ServletMapping();
157 mapping.setServletName(holder.getName());
158 mapping.setPathSpecs( LazyList.toStringArray(urlPatternList));
159 }
160 else
161 {
162
163
164
165
166 if (holder.getClassName() == null)
167 holder.setClassName(clazz.getName());
168 if (holder.getHeldClass() == null)
169 holder.setHeldClass(clazz);
170
171
172
173 for (WebInitParam ip:annotation.initParams())
174 {
175 if (metaData.getOrigin(servletName+".servlet.init-param."+ip.name())==Origin.NotSet)
176 {
177 holder.setInitParameter(ip.name(), ip.value());
178 metaData.setOrigin(servletName+".servlet.init-param."+ip.name(),ip,clazz);
179 }
180 }
181
182
183
184
185
186
187 List<ServletMapping> existingMappings = getServletMappingsForServlet(servletName);
188
189
190
191 if (existingMappings.isEmpty() || !containsNonDefaultMappings(existingMappings))
192 {
193 mapping = new ServletMapping();
194 mapping.setServletName(servletName);
195 mapping.setPathSpecs(LazyList.toStringArray(urlPatternList));
196 }
197 }
198
199
200
201
202
203
204 if (mapping != null)
205 {
206
207
208
209
210 List<ServletMapping> allMappings = ArrayUtil.asMutableList(_context.getServletHandler().getServletMappings());
211
212
213
214
215 for (String p:urlPatternList)
216 {
217 ServletMapping existingMapping = _context.getServletHandler().getServletMapping(p);
218 if (existingMapping != null && existingMapping.isDefault())
219 {
220 String[] updatedPaths = ArrayUtil.removeFromArray(existingMapping.getPathSpecs(), p);
221
222 if (updatedPaths == null || updatedPaths.length == 0)
223 {
224 boolean success = allMappings.remove(existingMapping);
225 if (LOG.isDebugEnabled()) LOG.debug("Removed empty mapping {} from defaults descriptor success:{}",existingMapping, success);
226 }
227 else
228 {
229 existingMapping.setPathSpecs(updatedPaths);
230 if (LOG.isDebugEnabled()) LOG.debug("Removed path {} from mapping {} from defaults descriptor ", p,existingMapping);
231 }
232 }
233 _context.getMetaData().setOrigin(servletName+".servlet.mapping."+p, annotation, clazz);
234 }
235 allMappings.add(mapping);
236 _context.getServletHandler().setServletMappings(allMappings.toArray(new ServletMapping[allMappings.size()]));
237 }
238 }
239
240
241
242
243
244
245
246
247 private List<ServletMapping> getServletMappingsForServlet (String name)
248 {
249 ServletMapping[] allMappings = _context.getServletHandler().getServletMappings();
250 if (allMappings == null)
251 return Collections.emptyList();
252
253 List<ServletMapping> mappings = new ArrayList<ServletMapping>();
254 for (ServletMapping m:allMappings)
255 {
256 if (m.getServletName() != null && name.equals(m.getServletName()))
257 {
258 mappings.add(m);
259 }
260 }
261 return mappings;
262 }
263
264
265
266
267
268
269 private boolean containsNonDefaultMappings (List<ServletMapping> mappings)
270 {
271 if (mappings == null)
272 return false;
273 for (ServletMapping m:mappings)
274 {
275 if (!m.isDefault())
276 return true;
277 }
278 return false;
279 }
280 }