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;
018
019import org.apache.wicket.request.cycle.RequestCycle;
020
021/**
022 * Holds thread local state for Wicket data.
023 * 
024 * @author Matej Knopp
025 */
026public class ThreadContext
027{
028        private Application application;
029
030        private RequestCycle requestCycle;
031
032        private Session session;
033
034        private static final ThreadLocal<ThreadContext> threadLocal = new ThreadLocal<ThreadContext>();
035
036        /**
037         * INTERNAL METHOD
038         * 
039         * @param createIfDoesNotExist
040         * @return ThreadContext
041         */
042        public static ThreadContext get(boolean createIfDoesNotExist)
043        {
044                ThreadContext context = threadLocal.get();
045                if (context == null)
046                {
047                        if (createIfDoesNotExist)
048                        {
049                                context = new ThreadContext();
050                                threadLocal.set(context);
051                        }
052                        else
053                        {
054                                /*
055                                 * There is no ThreadContext set, but the threadLocal.get() operation has registered
056                                 * the threadLocal in this Thread's ThreadLocal map. We must now remove it.
057                                 */
058                                threadLocal.remove();
059                        }
060                }
061                return context;
062        }
063
064        /**
065         * Checks if {@link ThreadContext} exists for the current thread
066         * 
067         * @return {@code true} if {@link ThreadContext} exists for the current thread
068         */
069        public static boolean exists()
070        {
071                return get(false) != null;
072        }
073
074        /**
075         * @return {@link Application} bound to current thread
076         */
077        public static Application getApplication()
078        {
079                ThreadContext context = get(false);
080                return context != null ? context.application : null;
081        }
082
083        /**
084         * Binds the specified application to current thread.
085         * 
086         * @param application
087         */
088        public static void setApplication(Application application)
089        {
090                ThreadContext context = get(true);
091                context.application = application;
092        }
093
094        /**
095         * @return {@link RequestCycle} bound to current thrad
096         */
097        public static RequestCycle getRequestCycle()
098        {
099                ThreadContext context = get(false);
100                return context != null ? context.requestCycle : null;
101        }
102
103        /**
104         * Binds the {@link RequestCycle} to current thread.
105         * 
106         * @param requestCycle
107         */
108        public static void setRequestCycle(RequestCycle requestCycle)
109        {
110                ThreadContext context = get(true);
111                context.requestCycle = requestCycle;
112        }
113
114        /**
115         * @return {@link Session} bound to current thread
116         */
117        public static Session getSession()
118        {
119                ThreadContext context = get(false);
120                return context != null ? context.session : null;
121        }
122
123        /**
124         * Binds the session to current thread.
125         * 
126         * @param session
127         */
128        public static void setSession(Session session)
129        {
130                ThreadContext context = get(true);
131                context.session = session;
132        }
133
134        /**
135         * Cleans the {@link ThreadContext} and returns previous context.
136         * 
137         * @return old {@link ThreadContext}
138         */
139        public static ThreadContext detach()
140        {
141                ThreadContext value = threadLocal.get();
142                threadLocal.remove();
143                return value;
144        }
145
146        /**
147         * Restores the context
148         * 
149         * @param threadContext
150         * @see #detach()
151         */
152        public static void restore(ThreadContext threadContext)
153        {
154                if (threadContext == null)
155                {
156                        threadLocal.remove();
157                }
158                else
159                {
160                        threadLocal.set(threadContext);
161                }
162        }
163
164        /**
165         * Construct.
166         */
167        private ThreadContext()
168        {
169        }
170}