View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2013 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.annotations;
20  
21  import java.util.List;
22  import java.util.Set;
23  import java.util.concurrent.ConcurrentHashMap;
24  
25  import org.eclipse.jetty.plus.annotation.ContainerInitializer;
26  import org.eclipse.jetty.util.ConcurrentHashSet;
27  import org.eclipse.jetty.util.component.AbstractLifeCycle;
28  import org.eclipse.jetty.util.log.Log;
29  import org.eclipse.jetty.util.log.Logger;
30  import org.eclipse.jetty.webapp.WebAppContext;
31  
32  
33  /**
34   * ServletContainerInitializersStarter
35   *
36   * Call the onStartup() method on all ServletContainerInitializers, after having 
37   * found all applicable classes (if any) to pass in as args.
38   */
39  public class ServletContainerInitializersStarter extends AbstractLifeCycle
40  {
41      private static final Logger LOG = Log.getLogger(ServletContainerInitializersStarter.class);
42      WebAppContext _context;
43  
44      
45      /**
46       * @param context
47       */
48      public ServletContainerInitializersStarter(WebAppContext context)
49      {
50          _context = context;
51      }
52   
53     /** 
54      * Call the doStart method of the ServletContainerInitializers
55      * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart()
56      */
57      public void doStart()
58      {
59          List<ContainerInitializer> initializers = (List<ContainerInitializer>)_context.getAttribute(AnnotationConfiguration.CONTAINER_INITIALIZERS);
60          if (initializers == null)
61              return;
62  
63         ConcurrentHashMap<String, ConcurrentHashSet<String>> map = ( ConcurrentHashMap<String, ConcurrentHashSet<String>>)_context.getAttribute(AnnotationConfiguration.CLASS_INHERITANCE_MAP);
64          
65          for (ContainerInitializer i : initializers)
66          {
67              configureHandlesTypes(_context, i, map);
68  
69              //instantiate ServletContainerInitializers, call doStart
70              try
71              {
72                  if (LOG.isDebugEnabled())
73                      LOG.debug("Calling ServletContainerInitializer "+i.getTarget().getClass().getName());
74                  i.callStartup(_context);
75              }
76              catch (Exception e)
77              {
78                  LOG.warn(e);
79                  throw new RuntimeException(e);
80              }
81          }
82      }
83    
84  
85      private void configureHandlesTypes (WebAppContext context, ContainerInitializer initializer, ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap)
86      {
87          doHandlesTypesAnnotations(context, initializer, classMap);
88          doHandlesTypesClasses(context, initializer, classMap);
89      }
90      
91      private void doHandlesTypesAnnotations(WebAppContext context, ContainerInitializer initializer, ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap)
92      {
93          if (initializer == null)
94              return;
95          if (context == null)
96              throw new IllegalArgumentException("WebAppContext null");
97          
98          //We have already found the classes that directly have an annotation that was in the HandlesTypes
99          //annotation of the ServletContainerInitializer. For each of those classes, walk the inheritance
100         //hierarchy to find classes that extend or implement them.
101         Set<String> annotatedClassNames = initializer.getAnnotatedTypeNames();
102         if (annotatedClassNames != null && !annotatedClassNames.isEmpty())
103         {
104             if (classMap == null)
105                 throw new IllegalStateException ("No class hierarchy");
106 
107             for (String name : annotatedClassNames)
108             {
109                 //add the class that has the annotation
110                 initializer.addApplicableTypeName(name);
111 
112                 //find and add the classes that inherit the annotation               
113                 addInheritedTypes(classMap, initializer, (ConcurrentHashSet<String>)classMap.get(name));
114             }
115         }
116     }
117 
118     
119 
120     private void doHandlesTypesClasses (WebAppContext context, ContainerInitializer initializer, ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap)
121     {
122         if (initializer == null)
123             return;
124         if (context == null)
125             throw new IllegalArgumentException("WebAppContext null");
126 
127         //Now we need to look at the HandlesTypes classes that were not annotations. We need to
128         //find all classes that extend or implement them.
129         if (initializer.getInterestedTypes() != null)
130         {
131             if (classMap == null)
132                 throw new IllegalStateException ("No class hierarchy");
133 
134             for (Class c : initializer.getInterestedTypes())
135             {
136                 if (!c.isAnnotation())
137                 {
138                     //find and add the classes that implement or extend the class.
139                     //but not including the class itself
140                     addInheritedTypes(classMap, initializer, (ConcurrentHashSet<String>)classMap.get(c.getName()));
141                 }
142             }
143         }
144     }
145     
146     
147     private void addInheritedTypes (ConcurrentHashMap<String, ConcurrentHashSet<String>> classMap, ContainerInitializer initializer, ConcurrentHashSet<String> names)
148     {
149         if (names == null || names.isEmpty())
150             return;
151      
152         for (String s : names)
153         {
154             //add the name of the class
155             initializer.addApplicableTypeName(s);
156 
157             //walk the hierarchy and find all types that extend or implement the class
158             addInheritedTypes(classMap, initializer, (ConcurrentHashSet<String>)classMap.get(s));
159         }
160     }
161 }