1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.quickstart;
20
21 import java.io.File;
22 import java.io.FileOutputStream;
23 import java.io.IOException;
24 import java.util.Arrays;
25 import java.util.Collection;
26 import java.util.Collections;
27 import java.util.EventListener;
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.Set;
31
32 import javax.servlet.DispatcherType;
33 import javax.servlet.MultipartConfigElement;
34 import javax.servlet.ServletContext;
35 import javax.servlet.SessionCookieConfig;
36 import javax.servlet.SessionTrackingMode;
37 import javax.servlet.descriptor.JspPropertyGroupDescriptor;
38 import javax.servlet.descriptor.TaglibDescriptor;
39
40 import org.eclipse.jetty.annotations.AnnotationConfiguration;
41 import org.eclipse.jetty.http.MimeTypes;
42 import org.eclipse.jetty.plus.annotation.LifeCycleCallback;
43 import org.eclipse.jetty.plus.annotation.LifeCycleCallbackCollection;
44 import org.eclipse.jetty.security.ConstraintAware;
45 import org.eclipse.jetty.security.ConstraintMapping;
46 import org.eclipse.jetty.security.SecurityHandler;
47 import org.eclipse.jetty.security.authentication.FormAuthenticator;
48 import org.eclipse.jetty.servlet.ErrorPageErrorHandler;
49 import org.eclipse.jetty.servlet.FilterHolder;
50 import org.eclipse.jetty.servlet.FilterMapping;
51 import org.eclipse.jetty.servlet.Holder;
52 import org.eclipse.jetty.servlet.ServletHandler;
53 import org.eclipse.jetty.servlet.ServletHolder;
54 import org.eclipse.jetty.servlet.ServletMapping;
55 import org.eclipse.jetty.util.QuotedStringTokenizer;
56 import org.eclipse.jetty.util.log.Log;
57 import org.eclipse.jetty.util.log.Logger;
58 import org.eclipse.jetty.util.resource.JarResource;
59 import org.eclipse.jetty.util.resource.Resource;
60 import org.eclipse.jetty.util.security.Constraint;
61 import org.eclipse.jetty.webapp.MetaData;
62 import org.eclipse.jetty.webapp.MetaData.OriginInfo;
63 import org.eclipse.jetty.webapp.MetaInfConfiguration;
64 import org.eclipse.jetty.webapp.WebAppContext;
65 import org.eclipse.jetty.xml.XmlAppendable;
66
67
68
69
70
71 public class QuickStartWebApp extends WebAppContext
72 {
73 private static final Logger LOG = Log.getLogger(QuickStartWebApp.class);
74
75 public static final String[] __configurationClasses = new String[]
76 {
77 org.eclipse.jetty.quickstart.QuickStartConfiguration.class.getCanonicalName(),
78 org.eclipse.jetty.plus.webapp.EnvConfiguration.class.getCanonicalName(),
79 org.eclipse.jetty.plus.webapp.PlusConfiguration.class.getCanonicalName(),
80 org.eclipse.jetty.webapp.JettyWebXmlConfiguration.class.getCanonicalName()
81 };
82
83
84 private boolean _preconfigure=false;
85 private boolean _autoPreconfigure=false;
86 private boolean _startWebapp=false;
87 private PreconfigureDescriptorProcessor _preconfigProcessor;
88
89
90 public static final String[] __preconfigurationClasses = new String[]
91 {
92 org.eclipse.jetty.webapp.WebInfConfiguration.class.getCanonicalName(),
93 org.eclipse.jetty.webapp.WebXmlConfiguration.class.getCanonicalName(),
94 org.eclipse.jetty.webapp.MetaInfConfiguration.class.getCanonicalName(),
95 org.eclipse.jetty.webapp.FragmentConfiguration.class.getCanonicalName(),
96 org.eclipse.jetty.plus.webapp.EnvConfiguration.class.getCanonicalName(),
97 org.eclipse.jetty.plus.webapp.PlusConfiguration.class.getCanonicalName(),
98 org.eclipse.jetty.annotations.AnnotationConfiguration.class.getCanonicalName(),
99 };
100
101 public QuickStartWebApp()
102 {
103 super();
104 setConfigurationClasses(__preconfigurationClasses);
105 setAttribute("org.eclipse.jetty.server.webapp.ContainerIncludeJarPattern",".*\\.jar");
106 }
107
108 public boolean isPreconfigure()
109 {
110 return _preconfigure;
111 }
112
113
114
115
116
117
118 public void setPreconfigure(boolean preconfigure)
119 {
120 _preconfigure = preconfigure;
121 }
122
123 public boolean isAutoPreconfigure()
124 {
125 return _autoPreconfigure;
126 }
127
128 public void setAutoPreconfigure(boolean autoPrecompile)
129 {
130 _autoPreconfigure = autoPrecompile;
131 }
132
133 @Override
134 protected void startWebapp() throws Exception
135 {
136 if (isPreconfigure())
137 generateQuickstartWebXml(_preconfigProcessor.getXML());
138
139 if (_startWebapp)
140 super.startWebapp();
141 }
142
143 @Override
144 protected void doStart() throws Exception
145 {
146
147 Resource war = null;
148 Resource dir = null;
149
150 Resource base = getBaseResource();
151 if (base==null)
152 base=Resource.newResource(getWar());
153
154 if (base.isDirectory())
155 dir=base;
156 else if (base.toString().toLowerCase().endsWith(".war"))
157 {
158 war=base;
159 String w=war.toString();
160 dir=Resource.newResource(w.substring(0,w.length()-4));
161
162 if (!dir.exists())
163 {
164 LOG.info("Quickstart Extract " + war + " to " + dir);
165 dir.getFile().mkdirs();
166 JarResource.newJarResource(war).copyTo(dir.getFile());
167 }
168
169 setWar(null);
170 setBaseResource(dir);
171 }
172 else
173 throw new IllegalArgumentException();
174
175
176 Resource qswebxml=dir.addPath("/WEB-INF/quickstart-web.xml");
177
178 if (isPreconfigure())
179 {
180 _preconfigProcessor = new PreconfigureDescriptorProcessor();
181 getMetaData().addDescriptorProcessor(_preconfigProcessor);
182 _startWebapp=false;
183 }
184 else if (qswebxml.exists())
185 {
186 setConfigurationClasses(__configurationClasses);
187 _startWebapp=true;
188 }
189 else if (_autoPreconfigure)
190 {
191 LOG.info("Quickstart preconfigure: {}(war={},dir={})",this,war,dir);
192
193 _preconfigProcessor = new PreconfigureDescriptorProcessor();
194
195 getMetaData().addDescriptorProcessor(_preconfigProcessor);
196 setPreconfigure(true);
197 _startWebapp=true;
198 }
199 else
200 _startWebapp=true;
201
202 super.doStart();
203 }
204
205
206 public void generateQuickstartWebXml(String extraXML) throws IOException
207 {
208 getMetaData().getOrigins();
209
210
211 if (getBaseResource()==null)
212 throw new IllegalArgumentException("No base resource for "+this);
213
214 File webxml = new File(getWebInf().getFile(),"quickstart-web.xml");
215
216 LOG.info("Quickstart generate {}",webxml);
217
218 XmlAppendable out = new XmlAppendable(new FileOutputStream(webxml),"UTF-8");
219 MetaData md = getMetaData();
220
221 Map<String, String> webappAttr = new HashMap<>();
222 webappAttr.put("xmlns","http://xmlns.jcp.org/xml/ns/javaee");
223 webappAttr.put("xmlns:xsi","http://www.w3.org/2001/XMLSchema-instance");
224 webappAttr.put("xsi:schemaLocation","http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd");
225 webappAttr.put("metadata-complete","true");
226 webappAttr.put("version","3.1");
227
228 out.open("web-app",webappAttr);
229
230 if (getDisplayName() != null)
231 out.tag("display-name",getDisplayName());
232
233
234
235
236 String resourceBase=getBaseResource().getFile().getCanonicalFile().getAbsoluteFile().toURI().toString();
237
238
239 addContextParamFromAttribute(out,ServletContext.ORDERED_LIBS);
240
241 addContextParamFromAttribute(out,AnnotationConfiguration.CONTAINER_INITIALIZERS);
242
243 addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_TLDS,resourceBase);
244
245 addContextParamFromAttribute(out,MetaInfConfiguration.METAINF_RESOURCES,resourceBase);
246
247
248
249 for (String p : getInitParams().keySet())
250 out.open("context-param",origin(md,"context-param." + p))
251 .tag("param-name",p)
252 .tag("param-value",getInitParameter(p))
253 .close();
254
255 if (getEventListeners() != null)
256 for (EventListener e : getEventListeners())
257 out.open("listener",origin(md,e.getClass().getCanonicalName() + ".listener"))
258 .tag("listener-class",e.getClass().getCanonicalName())
259 .close();
260
261 ServletHandler servlets = getServletHandler();
262
263 if (servlets.getFilters() != null)
264 {
265 for (FilterHolder holder : servlets.getFilters())
266 outholder(out,md,"filter",holder);
267 }
268
269 if (servlets.getFilterMappings() != null)
270 {
271 for (FilterMapping mapping : servlets.getFilterMappings())
272 {
273 out.open("filter-mapping");
274 out.tag("filter-name",mapping.getFilterName());
275 if (mapping.getPathSpecs() != null)
276 for (String s : mapping.getPathSpecs())
277 out.tag("url-pattern",s);
278 if (mapping.getServletNames() != null)
279 for (String n : mapping.getServletNames())
280 out.tag("servlet-name",n);
281
282 if (!mapping.isDefaultDispatches())
283 {
284 if (mapping.appliesTo(DispatcherType.REQUEST))
285 out.tag("dispatcher","REQUEST");
286 if (mapping.appliesTo(DispatcherType.ASYNC))
287 out.tag("dispatcher","ASYNC");
288 if (mapping.appliesTo(DispatcherType.ERROR))
289 out.tag("dispatcher","ERROR");
290 if (mapping.appliesTo(DispatcherType.FORWARD))
291 out.tag("dispatcher","FORWARD");
292 if (mapping.appliesTo(DispatcherType.INCLUDE))
293 out.tag("dispatcher","INCLUDE");
294 }
295 out.close();
296 }
297 }
298
299 if (servlets.getServlets() != null)
300 {
301 for (ServletHolder holder : servlets.getServlets())
302 outholder(out,md,"servlet",holder);
303 }
304
305 if (servlets.getServletMappings() != null)
306 {
307 for (ServletMapping mapping : servlets.getServletMappings())
308 {
309 out.open("servlet-mapping",origin(md,mapping.getServletName() + ".servlet.mappings"));
310 out.tag("servlet-name",mapping.getServletName());
311 if (mapping.getPathSpecs() != null)
312 for (String s : mapping.getPathSpecs())
313 out.tag("url-pattern",s);
314 out.close();
315 }
316 }
317
318
319 SecurityHandler security = getSecurityHandler();
320
321 if (security!=null && (security.getRealmName()!=null || security.getAuthMethod()!=null))
322 {
323 out.open("login-config");
324 if (security.getAuthMethod()!=null)
325 out.tag("auth-method",origin(md,"auth-method"),security.getAuthMethod());
326 if (security.getRealmName()!=null)
327 out.tag("realm-name",origin(md,"realm-name"),security.getRealmName());
328
329
330 if (Constraint.__FORM_AUTH.equalsIgnoreCase(security.getAuthMethod()))
331 {
332 out.open("form-login-config");
333 out.tag("form-login-page",origin(md,"form-login-page"),security.getInitParameter(FormAuthenticator.__FORM_LOGIN_PAGE));
334 out.tag("form-error-page",origin(md,"form-error-page"),security.getInitParameter(FormAuthenticator.__FORM_ERROR_PAGE));
335 out.close();
336 }
337
338 out.close();
339 }
340
341 if (security instanceof ConstraintAware)
342 {
343 ConstraintAware ca = (ConstraintAware)security;
344 for (String r:ca.getRoles())
345 out.open("security-role")
346 .tag("role-name",r)
347 .close();
348
349 for (ConstraintMapping m : ca.getConstraintMappings())
350 {
351 out.open("security-constraint");
352
353 if (m.getConstraint().getAuthenticate())
354 {
355 out.open("auth-constraint");
356 if (m.getConstraint().getRoles()!=null)
357 for (String r : m.getConstraint().getRoles())
358 out.tag("role-name",r);
359
360 out.close();
361 }
362
363 switch (m.getConstraint().getDataConstraint())
364 {
365 case Constraint.DC_NONE:
366 out.open("user-data-constraint").tag("transport-guarantee","NONE").close();
367 break;
368
369 case Constraint.DC_INTEGRAL:
370 out.open("user-data-constraint").tag("transport-guarantee","INTEGRAL").close();
371 break;
372
373 case Constraint.DC_CONFIDENTIAL:
374 out.open("user-data-constraint").tag("transport-guarantee","CONFIDENTIAL").close();
375 break;
376
377 default:
378 break;
379
380 }
381
382 out.open("web-resource-collection");
383 {
384 if (m.getConstraint().getName()!=null)
385 out.tag("web-resource-name",m.getConstraint().getName());
386 if (m.getPathSpec()!=null)
387 out.tag("url-pattern",origin(md,"constraint.url."+m.getPathSpec()),m.getPathSpec());
388 if (m.getMethod()!=null)
389 out.tag("http-method",m.getMethod());
390
391 if (m.getMethodOmissions()!=null)
392 for (String o:m.getMethodOmissions())
393 out.tag("http-method-omission",o);
394
395 out.close();
396 }
397
398 out.close();
399
400 }
401 }
402
403 if (getWelcomeFiles() != null)
404 {
405 out.open("welcome-file-list");
406 for (String welcomeFile:getWelcomeFiles())
407 {
408 out.tag("welcome-file", welcomeFile);
409 }
410 out.close();
411 }
412
413 Map<String,String> localeEncodings = getLocaleEncodings();
414 if (localeEncodings != null && !localeEncodings.isEmpty())
415 {
416 out.open("locale-encoding-mapping-list");
417 for (Map.Entry<String, String> entry:localeEncodings.entrySet())
418 {
419 out.open("locale-encoding-mapping", origin(md,"locale-encoding."+entry.getKey()));
420 out.tag("locale", entry.getKey());
421 out.tag("encoding", entry.getValue());
422 out.close();
423 }
424 out.close();
425 }
426
427
428 if (getSessionHandler().getSessionManager() != null)
429 {
430 out.open("session-config");
431 int maxInactiveSec = getSessionHandler().getSessionManager().getMaxInactiveInterval();
432 out.tag("session-timeout", (maxInactiveSec==0?"0":Integer.toString(maxInactiveSec/60)));
433
434 Set<SessionTrackingMode> modes = getSessionHandler().getSessionManager().getEffectiveSessionTrackingModes();
435 if (modes != null)
436 {
437 for (SessionTrackingMode mode:modes)
438 out.tag("tracking-mode", mode.toString());
439 }
440
441
442 SessionCookieConfig cookieConfig = getSessionHandler().getSessionManager().getSessionCookieConfig();
443 if (cookieConfig != null)
444 {
445 out.open("cookie-config");
446 if (cookieConfig.getName() != null)
447 out.tag("name", origin(md,"cookie-config.name"), cookieConfig.getName());
448
449 if (cookieConfig.getDomain() != null)
450 out.tag("domain", origin(md, "cookie-config.domain"), cookieConfig.getDomain());
451
452 if (cookieConfig.getPath() != null)
453 out.tag("path", origin(md, "cookie-config.path"), cookieConfig.getPath());
454
455 if (cookieConfig.getComment() != null)
456 out.tag("comment", origin(md, "cookie-config.comment"), cookieConfig.getComment());
457
458 out.tag("http-only", origin(md, "cookie-config.http-only"), Boolean.toString(cookieConfig.isHttpOnly()));
459 out.tag("secure", origin(md, "cookie-config.secure"), Boolean.toString(cookieConfig.isSecure()));
460 out.tag("max-age", origin(md, "cookie-config.max-age"), Integer.toString(cookieConfig.getMaxAge()));
461 out.close();
462 }
463 out.close();
464 }
465
466
467 Map<String,String> errorPages = ((ErrorPageErrorHandler)getErrorHandler()).getErrorPages();
468 if (errorPages != null)
469 {
470 for (Map.Entry<String, String> entry:errorPages.entrySet())
471 {
472 out.open("error-page", origin(md, "error."+entry.getKey()));
473
474 if (!ErrorPageErrorHandler.GLOBAL_ERROR_PAGE.equals(entry.getKey()))
475 {
476 if (entry.getKey().matches("\\d{3}"))
477 out.tag("error-code", entry.getKey());
478 else
479 out.tag("exception-type", entry.getKey());
480 }
481 out.tag("location", entry.getValue());
482 out.close();
483 }
484 }
485
486
487 MimeTypes mimeTypes = getMimeTypes();
488 if (mimeTypes != null)
489 {
490 for (Map.Entry<String, String> entry:mimeTypes.getMimeMap().entrySet())
491 {
492 out.open("mime-mapping");
493 out.tag("extension", origin(md, "extension."+entry.getKey()), entry.getKey());
494 out.tag("mime-type", entry.getValue());
495 out.close();
496 }
497 }
498
499
500 JspConfig jspConfig = (JspConfig)getServletContext().getJspConfigDescriptor();
501 if (jspConfig != null)
502 {
503 out.open("jsp-config");
504 Collection<TaglibDescriptor> tlds = jspConfig.getTaglibs();
505 if (tlds != null && !tlds.isEmpty())
506 {
507 for (TaglibDescriptor tld:tlds)
508 {
509 out.open("taglib");
510 out.tag("taglib-uri", tld.getTaglibURI());
511 out.tag("taglib-location", tld.getTaglibLocation());
512 out.close();
513 }
514 }
515
516 Collection<JspPropertyGroupDescriptor> jspPropertyGroups = jspConfig.getJspPropertyGroups();
517 if (jspPropertyGroups != null && !jspPropertyGroups.isEmpty())
518 {
519 for (JspPropertyGroupDescriptor jspPropertyGroup:jspPropertyGroups)
520 {
521 out.open("jsp-property-group");
522 Collection<String> strings = jspPropertyGroup.getUrlPatterns();
523 if (strings != null && !strings.isEmpty())
524 {
525 for (String urlPattern:strings)
526 out.tag("url-pattern", urlPattern);
527 }
528
529 if (jspPropertyGroup.getElIgnored() != null)
530 out.tag("el-ignored", jspPropertyGroup.getElIgnored());
531
532 if (jspPropertyGroup.getPageEncoding() != null)
533 out.tag("page-encoding", jspPropertyGroup.getPageEncoding());
534
535 if (jspPropertyGroup.getScriptingInvalid() != null)
536 out.tag("scripting-invalid", jspPropertyGroup.getScriptingInvalid());
537
538 if (jspPropertyGroup.getIsXml() != null)
539 out.tag("is-xml", jspPropertyGroup.getIsXml());
540
541 if (jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral() != null)
542 out.tag("deferred-syntax-allowed-as-literal", jspPropertyGroup.getDeferredSyntaxAllowedAsLiteral());
543
544 if (jspPropertyGroup.getTrimDirectiveWhitespaces() != null)
545 out.tag("trim-directive-whitespaces", jspPropertyGroup.getTrimDirectiveWhitespaces());
546
547 if (jspPropertyGroup.getDefaultContentType() != null)
548 out.tag("default-content-type", jspPropertyGroup.getDefaultContentType());
549
550 if (jspPropertyGroup.getBuffer() != null)
551 out.tag("buffer", jspPropertyGroup.getBuffer());
552
553 if (jspPropertyGroup.getErrorOnUndeclaredNamespace() != null)
554 out.tag("error-on-undeclared-namespace", jspPropertyGroup.getErrorOnUndeclaredNamespace());
555
556 strings = jspPropertyGroup.getIncludePreludes();
557 if (strings != null && !strings.isEmpty())
558 {
559 for (String prelude:strings)
560 out.tag("include-prelude", prelude);
561 }
562
563 strings = jspPropertyGroup.getIncludeCodas();
564 if (strings != null && !strings.isEmpty())
565 {
566 for (String coda:strings)
567 out.tag("include-coda", coda);
568 }
569
570 out.close();
571 }
572 }
573
574 out.close();
575 }
576
577
578 LifeCycleCallbackCollection lifecycles = ((LifeCycleCallbackCollection)getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION));
579 if (lifecycles != null)
580 {
581 Collection<LifeCycleCallback> tmp = lifecycles.getPostConstructCallbacks();
582
583 for (LifeCycleCallback c:tmp)
584 {
585 out.open("post-construct");
586 out.tag("lifecycle-callback-class", c.getTargetClassName());
587 out.tag("lifecycle-callback-method", c.getMethodName());
588 out.close();
589 }
590
591 tmp = lifecycles.getPreDestroyCallbacks();
592 for (LifeCycleCallback c:tmp)
593 {
594 out.open("pre-destroy");
595 out.tag("lifecycle-callback-class", c.getTargetClassName());
596 out.tag("lifecycle-callback-method", c.getMethodName());
597 out.close();
598 }
599 }
600
601 out.literal(extraXML);
602
603 out.close();
604 }
605
606 private void addContextParamFromAttribute(XmlAppendable out, String attribute) throws IOException
607 {
608 addContextParamFromAttribute(out,attribute,null);
609 }
610
611 private void addContextParamFromAttribute(XmlAppendable out, String attribute, String resourceBase) throws IOException
612 {
613 Object o=getAttribute(attribute);
614 if (o==null)
615 return;
616
617 Collection<?> c = (o instanceof Collection)? (Collection<?>)o:Collections.singletonList(o);
618 StringBuilder v=new StringBuilder();
619 for (Object i:c)
620 {
621 if (i!=null)
622 {
623 if (v.length()>0)
624 v.append(",\n ");
625 else
626 v.append("\n ");
627 if (resourceBase==null)
628 QuotedStringTokenizer.quote(v,i.toString());
629 else
630 QuotedStringTokenizer.quote(v,i.toString().replace(resourceBase,"${WAR}/"));
631 }
632 }
633 out.open("context-param")
634 .tag("param-name",attribute)
635 .tagCDATA("param-value",v.toString())
636 .close();
637 }
638
639 private static void outholder(XmlAppendable out, MetaData md, String tag, Holder<?> holder) throws IOException
640 {
641 out.open(tag,Collections.singletonMap("source",holder.getSource().toString()));
642 String n = holder.getName();
643 out.tag(tag + "-name",n);
644
645 String ot = n + "." + tag + ".";
646
647 out.tag(tag + "-class",origin(md,ot + tag + "-class"),holder.getClassName());
648
649 for (String p : holder.getInitParameters().keySet())
650 {
651 if ("scratchdir".equalsIgnoreCase(p))
652 continue;
653 out.open("init-param",origin(md,ot + "init-param." + p))
654 .tag("param-name",p)
655 .tag("param-value",holder.getInitParameter(p))
656 .close();
657 }
658
659 if (holder instanceof ServletHolder)
660 {
661 ServletHolder s = (ServletHolder)holder;
662 if (s.getForcedPath() != null)
663 out.tag("jsp-file",s.getForcedPath());
664
665 if (s.getInitOrder() != 0)
666 out.tag("load-on-startup",Integer.toString(s.getInitOrder()));
667
668 if (s.getRunAsRole() != null)
669 out.open("run-as",origin(md,ot + "run-as"))
670 .tag("role-name",s.getRunAsRole())
671 .close();
672
673 Map<String,String> roles = s.getRoleRefMap();
674 if (roles!=null)
675 {
676 for (Map.Entry<String, String> e : roles.entrySet())
677 {
678 out.open("security-role-ref",origin(md,ot+"role-name."+e.getKey()))
679 .tag("role-name",e.getKey())
680 .tag("role-link",e.getValue())
681 .close();
682 }
683 }
684
685 if (!s.isEnabled())
686 out.tag("enabled",origin(md,ot + "enabled"),"false");
687
688
689 MultipartConfigElement multipartConfig = ((ServletHolder.Registration)s.getRegistration()).getMultipartConfig();
690 if (multipartConfig != null)
691 {
692 out.open("multipart-config", origin(md, s.getName()+".servlet.multipart-config"));
693 if (multipartConfig.getLocation() != null)
694 out.tag("location", multipartConfig.getLocation());
695 out.tag("max-file-size", Long.toString(multipartConfig.getMaxFileSize()));
696 out.tag("max-request-size", Long.toString(multipartConfig.getMaxRequestSize()));
697 out.tag("file-size-threshold", Long.toString(multipartConfig.getFileSizeThreshold()));
698 out.close();
699 }
700 }
701
702 out.tag("async-supported",origin(md,ot + "async-supported"),holder.isAsyncSupported()?"true":"false");
703 out.close();
704 }
705
706 public static Map<String, String> origin(MetaData md, String name)
707 {
708 if (!LOG.isDebugEnabled())
709 return Collections.emptyMap();
710 if (name == null)
711 return Collections.emptyMap();
712 OriginInfo origin = md.getOriginInfo(name);
713
714 if (origin == null)
715 return Collections.emptyMap();
716 return Collections.singletonMap("origin",origin.toString());
717
718 }
719
720 }