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 org.apache.wicket.MetaDataKey;
020import org.apache.wicket.core.request.handler.IPageRequestHandler;
021import org.apache.wicket.request.IRequestHandler;
022import org.apache.wicket.request.IRequestHandlerDelegate;
023
024/**
025 * Registers and retrieves first and last executed {@link IPageRequestHandler} in a request cycle.
026 * Can be used to find out what is the requested page and what is the actual response page.
027 * <p>
028 * To use it an application needs to register it with:
029 *     <pre><code>
030 *          application.getRequestCycleListeners().add(new PageRequestHandlerTracker());
031 *     </code></pre>
032 * <p>
033 * The result can then be accessed at the end of each {@link RequestCycle} with:
034 *     <pre><code>
035 *          IPageRequestHandler first = PageRequestHandlerTracker.getFirstHandler(RequestCycle.get());
036 *          IPageRequestHandler last = PageRequestHandlerTracker.getLastHandler(RequestCycle.get());
037 *     </code></pre>
038 *
039 * @since 1.5.8
040 */
041public class PageRequestHandlerTracker implements IRequestCycleListener
042{
043        /**
044         * The key for the first handler
045         */
046        public static final  MetaDataKey<IPageRequestHandler> FIRST_HANDLER_KEY = new MetaDataKey<>() {};
047
048        /**
049         * The key for the last handler
050         */
051        public static final MetaDataKey<IPageRequestHandler> LAST_HANDLER_KEY = new MetaDataKey<>() {};
052
053        @Override
054        public void onRequestHandlerResolved(RequestCycle cycle, IRequestHandler handler)
055        {
056                registerFirstHandler(cycle,handler);
057                registerLastHandler(cycle,handler);
058        }
059
060        /**
061         * Registers pagerequesthandler when it's resolved ,keeps up with the most recent handler resolved
062         *
063         * @param cycle
064         *      the current request cycle
065         * @param handler
066         *      the request handler to register
067         */
068        private void registerLastHandler(RequestCycle cycle, IRequestHandler handler)
069        {
070                final IPageRequestHandler pageRequestHandler = findPageRequestHandler(handler);
071                if (pageRequestHandler != null)
072                {
073                        cycle.setMetaData(LAST_HANDLER_KEY, pageRequestHandler);
074                }
075        }
076
077        /**
078         * Registers firsthandler if it's not already registered
079         *
080         * @param cycle
081         *      the current request cycle
082         * @param handler
083         *      the request handler to register
084         */
085        private void registerFirstHandler(RequestCycle cycle, IRequestHandler handler)
086        {
087                if (getFirstHandler(cycle) == null)
088                {
089                        final IPageRequestHandler pageRequestHandler = findPageRequestHandler(handler);
090                        if (pageRequestHandler != null)
091                        {
092                                cycle.setMetaData(FIRST_HANDLER_KEY, pageRequestHandler);
093                        }
094                }
095        }
096
097        /**
098         * Looking for IPageRequestHandler 
099         * 
100         * @param handler
101         * @return IPageRequestHandler if exist otherwise null
102         */
103        private IPageRequestHandler findPageRequestHandler(IRequestHandler handler)
104        {
105                if (handler instanceof IPageRequestHandler)
106                {
107                        return (IPageRequestHandler)handler;
108                }
109            if (handler instanceof IRequestHandlerDelegate)
110            {
111                return findPageRequestHandler(((IRequestHandlerDelegate)handler).getDelegateHandler());
112            }
113            return null;
114        }
115
116   /**
117        * retrieves last handler from request cycle
118        *
119        * @param cycle
120        * @return last handler
121        */
122        public static IPageRequestHandler getLastHandler(RequestCycle cycle)
123        {
124                return cycle.getMetaData(LAST_HANDLER_KEY);
125        }
126
127        /**
128         * retrieves first handler from the request cycle
129         *
130         * @param cycle
131         * @return first handler
132         */
133        public static IPageRequestHandler getFirstHandler(RequestCycle cycle)
134        {
135                return cycle.getMetaData(FIRST_HANDLER_KEY);
136        }
137}