public void visitContainerInitializer( WebAppContext context, ContainerInitializer containerInitializer) { if (containerInitializer == null) return; // add the ContainerInitializer to the list of container initializers List<ContainerInitializer> containerInitializers = (List<ContainerInitializer>) context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS); if (containerInitializers == null) { containerInitializers = new ArrayList<ContainerInitializer>(); context.setAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS, containerInitializers); } containerInitializers.add(containerInitializer); // Ensure a bean is set up on the context that will invoke the ContainerInitializers as the // context starts ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter) context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER); if (starter == null) { starter = new ServletContainerInitializersStarter(context); context.setAttribute(AnnotationConfiguration.CONTAINER_INITIALIZER_STARTER, starter); context.addBean(starter, true); } }
/** * @see * org.eclipse.jetty.webapp.AbstractConfiguration#postConfigure(org.eclipse.jetty.webapp.WebAppContext) */ @Override public void postConfigure(WebAppContext context) throws Exception { ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap = (ClassInheritanceMap) context.getAttribute(CLASS_INHERITANCE_MAP); List<ContainerInitializer> initializers = (List<ContainerInitializer>) context.getAttribute(CONTAINER_INITIALIZERS); context.removeAttribute(CLASS_INHERITANCE_MAP); if (classMap != null) classMap.clear(); context.removeAttribute(CONTAINER_INITIALIZERS); if (initializers != null) initializers.clear(); if (_discoverableAnnotationHandlers != null) _discoverableAnnotationHandlers.clear(); _classInheritanceHandler = null; if (_containerInitializerAnnotationHandlers != null) _containerInitializerAnnotationHandlers.clear(); if (_parserTasks != null) { _parserTasks.clear(); _parserTasks = null; } super.postConfigure(context); }
/** * @param context * @param scis * @throws Exception */ public void createServletContainerInitializerAnnotationHandlers( WebAppContext context, List<ServletContainerInitializer> scis) throws Exception { if (scis == null || scis.isEmpty()) return; // nothing to do List<ContainerInitializer> initializers = new ArrayList<ContainerInitializer>(); context.setAttribute(CONTAINER_INITIALIZERS, initializers); for (ServletContainerInitializer service : scis) { HandlesTypes annotation = service.getClass().getAnnotation(HandlesTypes.class); ContainerInitializer initializer = null; if (annotation != null) { // There is a HandlesTypes annotation on the on the ServletContainerInitializer Class<?>[] classes = annotation.value(); if (classes != null) { initializer = new ContainerInitializer(service, classes); // If we haven't already done so, we need to register a handler that will // process the whole class hierarchy to satisfy the ServletContainerInitializer if (context.getAttribute(CLASS_INHERITANCE_MAP) == null) { // MultiMap<String> map = new MultiMap<>(); ConcurrentHashMap<String, ConcurrentHashSet<String>> map = new ClassInheritanceMap(); context.setAttribute(CLASS_INHERITANCE_MAP, map); _classInheritanceHandler = new ClassInheritanceHandler(map); } for (Class<?> c : classes) { // The value of one of the HandlesTypes classes is actually an Annotation itself so // register a handler for it if (c.isAnnotation()) { if (LOG.isDebugEnabled()) LOG.debug("Registering annotation handler for " + c.getName()); _containerInitializerAnnotationHandlers.add( new ContainerInitializerAnnotationHandler(initializer, c)); } } } else { initializer = new ContainerInitializer(service, null); if (LOG.isDebugEnabled()) LOG.debug("No classes in HandlesTypes on initializer " + service.getClass()); } } else { initializer = new ContainerInitializer(service, null); if (LOG.isDebugEnabled()) LOG.debug("No annotation on initializer " + service.getClass()); } initializers.add(initializer); } // add a bean to the context which will call the servletcontainerinitializers when appropriate ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter) context.getAttribute(CONTAINER_INITIALIZER_STARTER); if (starter != null) throw new IllegalStateException("ServletContainerInitializersStarter already exists"); starter = new ServletContainerInitializersStarter(context); context.setAttribute(CONTAINER_INITIALIZER_STARTER, starter); context.addBean(starter, true); }
@Override public void preConfigure(final WebAppContext context) throws Exception { _webAppClassNameResolver = new WebAppClassNameResolver(context); _containerClassNameResolver = new ContainerClassNameResolver(context); String tmp = (String) context.getAttribute(SERVLET_CONTAINER_INITIALIZER_EXCLUSION_PATTERN); _sciExcludePattern = (tmp == null ? null : Pattern.compile(tmp)); }
/** * Jetty-specific extension that allows an ordering to be applied across ALL * ServletContainerInitializers. * * @return */ public ServletContainerInitializerOrdering getInitializerOrdering(WebAppContext context) { if (context == null) return null; String tmp = (String) context.getAttribute(SERVLET_CONTAINER_INITIALIZER_ORDER); if (tmp == null || "".equals(tmp.trim())) return null; return new ServletContainerInitializerOrdering(tmp); }
/** * Here is the order in which jars and osgi artifacts are scanned for discoverable annotations. * * <ol> * <li>The container jars are scanned. * <li>The WEB-INF/classes are scanned * <li>The osgi fragment to the web bundle are parsed. * <li>The WEB-INF/lib are scanned * <li>The required bundles are parsed * </ol> */ @Override public void parseWebInfLib( WebAppContext context, org.eclipse.jetty.annotations.AnnotationParser parser) throws Exception { AnnotationParser oparser = (AnnotationParser) parser; Bundle webbundle = (Bundle) context.getAttribute(OSGiWebappConstants.JETTY_OSGI_BUNDLE); Set<Bundle> fragAndRequiredBundles = (Set<Bundle>) context.getAttribute(OSGiWebInfConfiguration.FRAGMENT_AND_REQUIRED_BUNDLES); if (fragAndRequiredBundles != null) { // index and scan fragments for (Bundle bundle : fragAndRequiredBundles) { // skip bundles that have been uninstalled since we discovered them if (bundle.getState() == Bundle.UNINSTALLED) continue; Resource bundleRes = oparser.indexBundle(bundle); if (!context.getMetaData().getWebInfJars().contains(bundleRes)) { context.getMetaData().addWebInfJar(bundleRes); } if (bundle.getHeaders().get(Constants.FRAGMENT_HOST) != null) { // a fragment indeed: parseFragmentBundle(context, oparser, webbundle, bundle); } } } // scan ourselves oparser.indexBundle(webbundle); parseWebBundle(context, oparser, webbundle); // scan the WEB-INF/lib super.parseWebInfLib(context, parser); if (fragAndRequiredBundles != null) { // scan the required bundles for (Bundle requiredBundle : fragAndRequiredBundles) { // skip bundles that have been uninstalled since we discovered them if (requiredBundle.getState() == Bundle.UNINSTALLED) continue; if (requiredBundle.getHeaders().get(Constants.FRAGMENT_HOST) == null) { // a bundle indeed: parseRequiredBundle(context, oparser, webbundle, requiredBundle); } } } }
@Override public void deconfigure(WebAppContext context) throws Exception { context.removeAttribute(CLASS_INHERITANCE_MAP); context.removeAttribute(CONTAINER_INITIALIZERS); ServletContainerInitializersStarter starter = (ServletContainerInitializersStarter) context.getAttribute(CONTAINER_INITIALIZER_STARTER); if (starter != null) { context.removeBean(starter); context.removeAttribute(CONTAINER_INITIALIZER_STARTER); } }
/** * Overriden method which, contrary to the original implementation in the parent class, add * directly the web-fragment.xml resource to the MetaData, instead of re-creating it with a forced * jar prefix. */ @Override @SuppressWarnings("unchecked") public void findWebFragments(final WebAppContext context, final MetaData metaData) throws Exception { List<Resource> frags = (List<Resource>) context.getAttribute(FRAGMENT_RESOURCES); if (frags != null) { for (Resource frag : frags) { Resource parentResource = Util.chop(frag.getURL(), "/META-INF/web-fragment.xml"); metaData.addFragment(parentResource, frag); } } }
/** * @see * org.eclipse.jetty.webapp.AbstractConfiguration#configure(org.eclipse.jetty.webapp.WebAppContext) */ @Override public void configure(WebAppContext context) throws Exception { context.addDecorator(new AnnotationDecorator(context)); // Even if metadata is complete, we still need to scan for ServletContainerInitializers - if // there are any if (!context.getMetaData().isMetaDataComplete()) { // If metadata isn't complete, if this is a servlet 3 webapp or isConfigDiscovered is true, we // need to search for annotations if (context.getServletContext().getEffectiveMajorVersion() >= 3 || context.isConfigurationDiscovered()) { _discoverableAnnotationHandlers.add(new WebServletAnnotationHandler(context)); _discoverableAnnotationHandlers.add(new WebFilterAnnotationHandler(context)); _discoverableAnnotationHandlers.add(new WebListenerAnnotationHandler(context)); } } // Regardless of metadata, if there are any ServletContainerInitializers with @HandlesTypes, // then we need to scan all the // classes so we can call their onStartup() methods correctly createServletContainerInitializerAnnotationHandlers( context, getNonExcludedInitializers(context)); if (!_discoverableAnnotationHandlers.isEmpty() || _classInheritanceHandler != null || !_containerInitializerAnnotationHandlers.isEmpty()) scanForAnnotations(context); // Resolve container initializers List<ContainerInitializer> initializers = (List<ContainerInitializer>) context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS); if (initializers != null && initializers.size() > 0) { Map<String, Set<String>> map = (Map<String, Set<String>>) context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP); if (map == null) LOG.warn("ServletContainerInitializers: detected. Class hierarchy: empty"); for (ContainerInitializer i : initializers) i.resolveClasses(context, map); } }
/** * Work out how long we should wait for the async scanning to occur. * * @param context * @return */ protected int getMaxScanWait(WebAppContext context) { // try context attribute to get max time in sec to wait for scan completion Object o = context.getAttribute(MAX_SCAN_WAIT); if (o != null && o instanceof Number) { return ((Number) o).intValue(); } // try server attribute to get max time in sec to wait for scan completion o = context.getServer().getAttribute(MAX_SCAN_WAIT); if (o != null && o instanceof Number) { return ((Number) o).intValue(); } // try system property to get max time in sec to wait for scan completion return Integer.getInteger(MAX_SCAN_WAIT, DEFAULT_MAX_SCAN_WAIT).intValue(); }
public void visitMetaInfResource(WebAppContext context, Resource dir) { Collection<Resource> metaInfResources = (Collection<Resource>) context.getAttribute(MetaInfConfiguration.METAINF_RESOURCES); if (metaInfResources == null) { metaInfResources = new HashSet<Resource>(); context.setAttribute(MetaInfConfiguration.METAINF_RESOURCES, metaInfResources); } metaInfResources.add(dir); // also add to base resource of webapp Resource[] collection = new Resource[metaInfResources.size() + 1]; int i = 0; collection[i++] = context.getBaseResource(); for (Resource resource : metaInfResources) collection[i++] = resource; context.setBaseResource(new ResourceCollection(collection)); }
/** * Check if we should use multiple threads to scan for annotations or not * * @param context * @return */ protected boolean isUseMultiThreading(WebAppContext context) { // try context attribute to see if we should use multithreading Object o = context.getAttribute(MULTI_THREADED); if (o instanceof Boolean) { return ((Boolean) o).booleanValue(); } // try server attribute to see if we should use multithreading o = context.getServer().getAttribute(MULTI_THREADED); if (o instanceof Boolean) { return ((Boolean) o).booleanValue(); } // try system property to see if we should use multithreading return Boolean.valueOf( System.getProperty(MULTI_THREADED, Boolean.toString(DEFAULT_MULTI_THREADED))); }
public void doHandle(Class clazz) { // Check that the PreDestroy is on a class that we're interested in if (Util.supportsPostConstructPreDestroy(clazz)) { Method[] methods = clazz.getDeclaredMethods(); for (int i = 0; i < methods.length; i++) { Method m = (Method) methods[i]; if (m.isAnnotationPresent(PreDestroy.class)) { if (m.getParameterTypes().length != 0) throw new IllegalStateException(m + " has parameters"); if (m.getReturnType() != Void.TYPE) throw new IllegalStateException(m + " is not void"); if (m.getExceptionTypes().length != 0) throw new IllegalStateException(m + " throws checked exceptions"); if (Modifier.isStatic(m.getModifiers())) throw new IllegalStateException(m + " is static"); // ServletSpec 3.0 p80 If web.xml declares even one predestroy then all predestroys // in fragments must be ignored. Otherwise, they are additive. MetaData metaData = _context.getMetaData(); Origin origin = metaData.getOrigin("pre-destroy"); if (origin != null && (origin == Origin.WebXml || origin == Origin.WebDefaults || origin == Origin.WebOverride)) return; PreDestroyCallback callback = new PreDestroyCallback(); callback.setTarget(clazz.getName(), m.getName()); LifeCycleCallbackCollection lifecycles = (LifeCycleCallbackCollection) _context.getAttribute(LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION); if (lifecycles == null) { lifecycles = new LifeCycleCallbackCollection(); _context.setAttribute( LifeCycleCallbackCollection.LIFECYCLE_CALLBACK_COLLECTION, lifecycles); } lifecycles.add(callback); } } } }
/** * @param context * @param descriptor * @param node */ public void visitContextParam(WebAppContext context, Descriptor descriptor, XmlParser.Node node) throws Exception { String name = node.getString("param-name", false, true); String value = node.getString("param-value", false, true); List<String> values = new ArrayList<>(); // extract values switch (name) { case ServletContext.ORDERED_LIBS: case AnnotationConfiguration.CONTAINER_INITIALIZERS: case MetaInfConfiguration.METAINF_TLDS: case MetaInfConfiguration.METAINF_RESOURCES: context.removeAttribute(name); QuotedStringTokenizer tok = new QuotedStringTokenizer(value, ","); while (tok.hasMoreElements()) values.add(tok.nextToken().trim()); break; default: values.add(value); } // handle values switch (name) { case ServletContext.ORDERED_LIBS: { List<Object> libs = new ArrayList<>(); Object o = context.getAttribute(ServletContext.ORDERED_LIBS); if (o instanceof Collection<?>) libs.addAll((Collection<?>) o); libs.addAll(values); if (libs.size() > 0) context.setAttribute(ServletContext.ORDERED_LIBS, libs); break; } case AnnotationConfiguration.CONTAINER_INITIALIZERS: { for (String i : values) visitContainerInitializer( context, new ContainerInitializer(Thread.currentThread().getContextClassLoader(), i)); break; } case MetaInfConfiguration.METAINF_TLDS: { List<Object> tlds = new ArrayList<>(); String war = context.getBaseResource().getURI().toString(); Object o = context.getAttribute(MetaInfConfiguration.METAINF_TLDS); if (o instanceof Collection<?>) tlds.addAll((Collection<?>) o); for (String i : values) { Resource r = Resource.newResource(i.replace("${WAR}/", war)); if (r.exists()) tlds.add(r.getURL()); else throw new IllegalArgumentException("TLD not found: " + r); } if (tlds.size() > 0) context.setAttribute(MetaInfConfiguration.METAINF_TLDS, tlds); break; } case MetaInfConfiguration.METAINF_RESOURCES: { String war = context.getBaseResource().getURI().toString(); for (String i : values) { Resource r = Resource.newResource(i.replace("${WAR}/", war)); if (r.exists()) visitMetaInfResource(context, r); else throw new IllegalArgumentException("Resource not found: " + r); } break; } default: } }