View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  
20  package org.apache.myfaces.application;
21  
22  import java.lang.reflect.Constructor;
23  import java.util.ArrayList;
24  import java.util.List;
25  import javax.faces.FacesException;
26  import javax.faces.context.FacesContext;
27  import javax.faces.event.SystemEvent;
28  import javax.faces.event.SystemEventListener;
29  
30  /**
31   *
32   * lu4242
33   */
34  class _ApplicationUtils
35  {
36      
37      static SystemEvent _createEvent(FacesContext facesContext, Class<? extends SystemEvent> systemEventClass,
38              Object source, SystemEvent event)
39      {
40          if (event == null)
41          {
42              try
43              {
44                  Constructor<?>[] constructors = systemEventClass.getConstructors();
45                  Constructor<? extends SystemEvent> constructor = null;
46               
47                  // try to lookup the new 2 parameter constructor
48                  for (Constructor<?> c : constructors)
49                  {
50                      if (c.getParameterTypes().length == 2)
51                      {
52                          // Safe cast, since the constructor belongs
53                          // to a class of type SystemEvent
54                          constructor = (Constructor<? extends SystemEvent>) c;
55                          break;
56                      }
57                  }
58                  if (constructor != null)
59                  {
60                      event = constructor.newInstance(facesContext, source);
61                  }
62                  
63                  // try to lookup the old 1 parameter constructor
64                  if (constructor == null)
65                  {
66                      for (Constructor<?> c : constructors)
67                      {
68                          if (c.getParameterTypes().length == 1)
69                          {
70                              // Safe cast, since the constructor belongs
71                              // to a class of type SystemEvent
72                              constructor = (Constructor<? extends SystemEvent>) c;
73                              break;
74                          }
75                      }
76                      if (constructor != null)
77                      {
78                          event = constructor.newInstance(source);
79                      }
80                  }
81              }
82              catch (Exception e)
83              {
84                  throw new FacesException("Couldn't instanciate system event of type " + 
85                          systemEventClass.getName(), e);
86              }
87          }
88  
89          return event;
90      }
91  
92      static SystemEvent _traverseListenerList(FacesContext facesContext, List<? extends SystemEventListener> listeners,
93                                                       Class<? extends SystemEvent> systemEventClass, Object source,
94                                                       SystemEvent event)
95      {
96          if (listeners != null && !listeners.isEmpty())
97          {
98              // perf: org.apache.myfaces.application.ApplicationImpl.
99              //    SystemListenerEntry.getSpecificSourceListenersNotNull(Class<?>)
100             // or javax.faces.component.UIComponent.subscribeToEvent(
101             //      Class<? extends SystemEvent>, ComponentSystemEventListener)
102             // creates a ArrayList:
103             for (int i  = 0, size = listeners.size(); i < size; i++)
104             {
105                 SystemEventListener listener = listeners.get(i);
106                 // Call SystemEventListener.isListenerForSource(java.lang.Object), passing the source argument.
107                 // If this returns false, take no action on the listener.
108                 if (listener.isListenerForSource(source))
109                 {
110                     // Otherwise, if the event to be passed to the listener instances has not yet been constructed,
111                     // construct the event, passing source as the argument to the one-argument constructor that takes
112                     // an Object. This same event instance must be passed to all listener instances.
113                     event = _createEvent(facesContext, systemEventClass, source, event);
114 
115                     // Call SystemEvent.isAppropriateListener(javax.faces.event.FacesListener), passing the listener
116                     // instance as the argument. If this returns false, take no action on the listener.
117                     if (event.isAppropriateListener(listener))
118                     {
119                         // Call SystemEvent.processListener(javax.faces.event.FacesListener), passing the listener
120                         // instance.
121                         event.processListener(listener);
122                     }
123                 }
124             }
125         }
126 
127         return event;
128     }
129     
130     // Do it with a copy because the list could be changed during a event
131     // see MYFACES-2935
132     static SystemEvent _traverseListenerListWithCopy(FacesContext facesContext,
133             List<? extends SystemEventListener> listeners,
134             Class<? extends SystemEvent> systemEventClass, Object source,
135             SystemEvent event)
136     {
137         if (listeners != null && !listeners.isEmpty())
138         {
139             List<SystemEventListener> listenersCopy = new ArrayList<SystemEventListener>();
140             int processedListenerIndex = 0;
141             
142             for (int i = 0; i < listeners.size(); i++)
143             {
144                 listenersCopy.add(listeners.get(i));
145             }
146             
147             // If the inner for is succesful, processedListenerIndex == listenersCopy.size()
148             // and the loop will be complete.
149             while (processedListenerIndex < listenersCopy.size())
150             {                
151                 for (; processedListenerIndex < listenersCopy.size(); processedListenerIndex++ )
152                 {
153                     SystemEventListener listener = listenersCopy.get(processedListenerIndex);
154                     // Call SystemEventListener.isListenerForSource(java.lang.Object), passing the source argument.
155                     // If this returns false, take no action on the listener.
156                     if (listener.isListenerForSource(source))
157                     {
158                         // Otherwise, if the event to be passed to the listener instances has not yet been constructed,
159                         // construct the event, passing source as the argument
160                         // to the one-argument constructor that takes
161                         // an Object. This same event instance must be passed to all listener instances.
162                         event = _createEvent(facesContext, systemEventClass, source, event);
163     
164                         // Call SystemEvent.isAppropriateListener(javax.faces.event.FacesListener), passing the listener
165                         // instance as the argument. If this returns false, take no action on the listener.
166                         if (event.isAppropriateListener(listener))
167                         {
168                             // Call SystemEvent.processListener(javax.faces.event.FacesListener), passing the listener
169                             // instance.
170                             event.processListener(listener);
171                         }
172                     }
173                 }
174                 
175                 boolean listChanged = false;
176                 if (listeners.size() == listenersCopy.size())
177                 {
178                     for (int i = 0; i < listenersCopy.size(); i++)
179                     {
180                         if (listenersCopy.get(i) != listeners.get(i))
181                         {
182                             listChanged = true;
183                             break;
184                         }
185                     }
186                 }
187                 else
188                 {
189                     listChanged = true;
190                 }
191                 
192                 if (listChanged)
193                 {
194                     for (int i = 0; i < listeners.size(); i++)
195                     {
196                         SystemEventListener listener = listeners.get(i);
197                         
198                         // check if listenersCopy.get(i) is valid
199                         if (i < listenersCopy.size())
200                         {
201                             // The normal case is a listener was added, 
202                             // so as heuristic, check first
203                             // if we can find it at the same location
204                             if (!listener.equals(listenersCopy.get(i)) &&
205                                 !listenersCopy.contains(listener))
206                             {
207                                 listenersCopy.add(listener);
208                             }
209                         }
210                         else
211                         {
212                             if (!listenersCopy.contains(listener))
213                             {
214                                 listenersCopy.add(listener);
215                             }
216                         }
217                     }
218                 }
219             }
220         }
221 
222         return event;
223     }
224 
225 
226 }