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 }