001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.wicket.request.cycle; 018 019import java.util.ArrayList; 020import java.util.List; 021 022import org.apache.wicket.request.IRequestHandler; 023import org.apache.wicket.request.Url; 024import org.apache.wicket.util.listener.ListenerCollection; 025import org.slf4j.Logger; 026import org.slf4j.LoggerFactory; 027 028/** 029 * Composite {@link IRequestCycleListener} that notifies all registered listeners with each 030 * IRequestCycleListener event. 031 * <p> 032 * Order of notification 033 * 034 * {@link #onBeginRequest(RequestCycle)}, {@link #onRequestHandlerScheduled(RequestCycle, IRequestHandler)} and 035 * {@link #onRequestHandlerResolved(RequestCycle, IRequestHandler)} are notified in first in, first out order. 036 * <p> 037 * {@link #onEndRequest(RequestCycle)} and {@link #onDetach(RequestCycle)} are notified in last in 038 * first out order (i.e. reversed order). So for these events the collection functions as a stack. 039 * <p> 040 * Exception handling 041 * 042 * The {@code RequestCycleListenerCollection} will use the first exception handler that is returned 043 * from all listeners in {@link #onException(RequestCycle, Exception)} 044 */ 045public class RequestCycleListenerCollection extends ListenerCollection<IRequestCycleListener> 046 implements 047 IRequestCycleListener 048{ 049 private static final Logger logger = LoggerFactory.getLogger(RequestCycleListenerCollection.class); 050 private static final long serialVersionUID = 1L; 051 052 /** 053 * Notifies all registered listeners of the onBeginRequest event in first in first out order, 054 * i.e. the listener that is the first element of this collection is the first listener to be 055 * notified of {@code onBeginRequest}. 056 */ 057 @Override 058 public void onBeginRequest(final RequestCycle cycle) 059 { 060 notify(new INotifier<IRequestCycleListener>() 061 { 062 @Override 063 public void notify(IRequestCycleListener listener) 064 { 065 listener.onBeginRequest(cycle); 066 } 067 }); 068 } 069 070 /** 071 * Notifies all registered listeners of the {@code onEndRequest} event in first in last out 072 * order (i.e. the last listener that received an {@code #onBeginRequest} will be the first to 073 * get notified of an {@code onEndRequest}. 074 * 075 * @see IRequestCycleListener#onEndRequest(RequestCycle) 076 */ 077 @Override 078 public void onEndRequest(final RequestCycle cycle) 079 { 080 reversedNotify(new INotifier<IRequestCycleListener>() 081 { 082 @Override 083 public void notify(IRequestCycleListener listener) 084 { 085 listener.onEndRequest(cycle); 086 } 087 }); 088 } 089 090 /** 091 * Notifies all registered listeners of the {@code onDetach} event in first in last out order 092 * (i.e. the last listener that received an {@code #onBeginRequest} will be the first to get 093 * notified of an {@code onDetach}. 094 * 095 * @see IRequestCycleListener#onDetach(RequestCycle) 096 */ 097 @Override 098 public void onDetach(final RequestCycle cycle) 099 { 100 reversedNotifyIgnoringExceptions(new INotifier<IRequestCycleListener>() 101 { 102 @Override 103 public void notify(IRequestCycleListener listener) 104 { 105 listener.onDetach(cycle); 106 } 107 }); 108 } 109 110 /** 111 * Notifies all registered listeners of the exception and calls the first handler that was 112 * returned by the listeners. 113 * 114 * @see IRequestCycleListener#onException(RequestCycle, Exception) 115 */ 116 @Override 117 public IRequestHandler onException(final RequestCycle cycle, final Exception ex) 118 { 119 final List<IRequestHandler> handlers = new ArrayList<IRequestHandler>(); 120 121 notify(new INotifier<IRequestCycleListener>() 122 { 123 @Override 124 public void notify(IRequestCycleListener listener) 125 { 126 IRequestHandler handler = listener.onException(cycle, ex); 127 if (handler != null) 128 { 129 handlers.add(handler); 130 } 131 } 132 }); 133 134 if (handlers.isEmpty()) 135 { 136 return null; 137 } 138 if (handlers.size() > 1) 139 { 140 logger.debug( 141 "{} exception handlers available for exception {}, using the first handler", 142 handlers.size(), ex); 143 } 144 return handlers.get(0); 145 } 146 147 @Override 148 public void onRequestHandlerResolved(final RequestCycle cycle, final IRequestHandler handler) 149 { 150 notify(new INotifier<IRequestCycleListener>() 151 { 152 @Override 153 public void notify(IRequestCycleListener listener) 154 { 155 listener.onRequestHandlerResolved(cycle, handler); 156 } 157 }); 158 } 159 160 @Override 161 public void onExceptionRequestHandlerResolved(final RequestCycle cycle, 162 final IRequestHandler handler, final Exception exception) 163 { 164 notify(new INotifier<IRequestCycleListener>() 165 { 166 @Override 167 public void notify(IRequestCycleListener listener) 168 { 169 listener.onExceptionRequestHandlerResolved(cycle, handler, exception); 170 } 171 }); 172 } 173 174 @Override 175 public void onRequestHandlerScheduled(final RequestCycle cycle, final IRequestHandler handler) 176 { 177 notify(new INotifier<IRequestCycleListener>() 178 { 179 @Override 180 public void notify(IRequestCycleListener listener) 181 { 182 listener.onRequestHandlerScheduled(cycle, handler); 183 } 184 }); 185 } 186 187 @Override 188 public void onRequestHandlerExecuted(final RequestCycle cycle, final IRequestHandler handler) 189 { 190 notify(new INotifier<IRequestCycleListener>() 191 { 192 @Override 193 public void notify(IRequestCycleListener listener) 194 { 195 listener.onRequestHandlerExecuted(cycle, handler); 196 } 197 }); 198 } 199 200 @Override 201 public void onUrlMapped(final RequestCycle cycle, final IRequestHandler handler, final Url url) 202 { 203 notify(new INotifier<IRequestCycleListener>() 204 { 205 @Override 206 public void notify(IRequestCycleListener listener) 207 { 208 listener.onUrlMapped(cycle, handler, url); 209 } 210 }); 211 212 } 213}