##### Coverage Report - org.seasar.cubby.internal.controller.ThreadContext

Classes in this File | Line Coverage | Branch Coverage | Complexity
ThreadContext |
93% | 40/43
81% | 13/16
| 2.3333333333333335;2.333
ThreadContext$Command |
N/A | N/A
N/A | N/A
| 2.3333333333333335;2.333

1 |  |
     /*
2 |  |
      * Copyright 2004-2009 the Seasar Foundation and the Others.
3 |  |
      *
4 |  |
      * Licensed under the Apache License, Version 2.0 (the "License");
5 |  |
      * you may not use this file except in compliance with the License.
6 |  |
      * You may obtain a copy of the License at
7 |  |
      *
8 |  |
      *     http://www.apache.org/licenses/LICENSE-2.0
9 |  |
      *
10 |  |
      * Unless required by applicable law or agreed to in writing, software
11 |  |
      * distributed under the License is distributed on an "AS IS" BASIS,
12 |  |
      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
13 |  |
      * either express or implied. See the License for the specific language
14 |  |
      * governing permissions and limitations under the License.
15 |  |
      */
16 |  |
     package org.seasar.cubby.internal.controller;
17 |  |
18 |  |
     import java.util.Map;
19 |  |
     import java.util.ResourceBundle;
20 |  |
21 |  |
     import javax.servlet.http.HttpServletRequest;
22 |  |
     import javax.servlet.http.HttpServletResponse;
23 |  |
24 |  |
     import org.seasar.cubby.controller.MessagesBehaviour;
25 |  |
     import org.seasar.cubby.spi.ContainerProvider;
26 |  |
     import org.seasar.cubby.spi.ProviderFactory;
27 |  |
     import org.seasar.cubby.spi.container.Container;
28 |  |
29 |  |
     /**
30 |  |
      * 実行スレッドのコンテキスト情報です。
31 |  |
      *
32 |  |
      * @author baba
33 |  |
      */
34 |  |
     public class ThreadContext {
35 |  |
36 |  |
             /** ThreadContext を保存するスレッドローカル。 */
37 | 1 |
             private static final ThreadLocal<ThreadContext> THREAD_LOCAL = new ThreadLocal<ThreadContext>();
38 |  |
39 |  |
             /** 要求。 */
40 |  |
             private final HttpServletRequest request;
41 |  |
42 |  |
             /** 応答 */
43 |  |
             private final HttpServletResponse response;
44 |  |
45 |  |
             /** メッセージのリソースバンドル。 */
46 | 21 |
             private ResourceBundle messagesResourceBundle = null;
47 |  |
48 |  |
             /** メッセージの {@link Map} */
49 | 21 |
             private Map<String, Object> messages = null;
50 |  |
51 |  |
             /** メッセージ表示用リソースバンドルの振る舞い。 */
52 |  |
             private MessagesBehaviour messagesBehaviour;
53 |  |
54 |  |
             /**
55 |  |
              * インスタンス化します。
56 |  |
              *
57 |  |
              * @param request
58 |  |
              *            要求
59 |  |
              * @param response
60 |  |
              *            応答
61 |  |
              */
62 |  |
             private ThreadContext(final HttpServletRequest request,
63 | 21 |
                             final HttpServletResponse response) {
64 | 21 |
                     this.request = request;
65 | 21 |
                     this.response = response;
66 | 21 |
             }
67 |  |
68 |  |
             /**
69 |  |
              * スレッドローカル変数からコンテキストを取得します。
70 |  |
              *
71 |  |
              * @return コンテキスト
72 |  |
              */
73 |  |
             private static ThreadContext getContext() {
74 | 119 |
                     final ThreadContext context = THREAD_LOCAL.get();
75 | 119 |
                     if (context == null) {
76 | 9 |
                             throw new IllegalStateException(
77 |  |
                                             "Could not get context from ThreadLocal. run in context scope.");
78 |  |
                     }
79 | 110 |
                     return context;
80 |  |
             }
81 |  |
82 |  |
             /**
83 |  |
              * 現在の実行スレッドに関連付けられた要求を取得します。
84 |  |
              *
85 |  |
              * @return 要求
86 |  |
              */
87 |  |
             public static HttpServletRequest getRequest() {
88 | 21 |
                     return getContext().request;
89 |  |
             }
90 |  |
91 |  |
             /**
92 |  |
              * 現在の実行スレッドに関連付けられた応答を取得します。
93 |  |
              *
94 |  |
              * @return 応答
95 |  |
              */
96 |  |
             public static HttpServletResponse getResponse() {
97 | 9 |
                     return getContext().response;
98 |  |
             }
99 |  |
100 |  |
             /**
101 |  |
              * 現在の実行スレッドに関連付けられた要求に対応するメッセージ用の {@link ResourceBundle} を取得します。
102 |  |
              *
103 |  |
              * @return リソースバンドル
104 |  |
              */
105 |  |
             public static ResourceBundle getMessagesResourceBundle() {
106 | 85 |
                     final ThreadContext context = getContext();
107 | 85 |
                     if (context.messagesResourceBundle == null) {
108 | 8 |
                             final MessagesBehaviour messagesBehaviour = getMessagesBehaviour(context);
109 | 8 |
                             context.messagesResourceBundle = messagesBehaviour
110 |  |
                                             .getBundle(context.request.getLocale());
111 |  |
                     }
112 | 85 |
                     return context.messagesResourceBundle;
113 |  |
             }
114 |  |
115 |  |
             /**
116 |  |
              * {@link #getMessagesResourceBundle()} で取得できる {@link ResourceBundle} を変換した
117 |  |
              * {@link Map} を取得します。
118 |  |
              *
119 |  |
              * @return メッセージの {@link Map}
120 |  |
              */
121 |  |
             public static Map<String, Object> getMessagesMap() {
122 | 4 |
                     final ThreadContext context = getContext();
123 | 4 |
                     if (context.messages == null) {
124 | 3 |
                             final ResourceBundle bundle = getMessagesResourceBundle();
125 | 3 |
                             final MessagesBehaviour messagesBehaviour = getMessagesBehaviour(context);
126 | 3 |
                             context.messages = messagesBehaviour.toMap(bundle);
127 |  |
                     }
128 | 4 |
                     return context.messages;
129 |  |
             }
130 |  |
131 |  |
             /**
132 |  |
              * メッセージ表示用リソースバンドルの振る舞いを取得します。
133 |  |
              *
134 |  |
              * @param context
135 |  |
              *            実行スレッドのコンテキスト情報
136 |  |
              * @return メッセージ表示用リソースバンドルの振る舞い
137 |  |
              */
138 |  |
             private static MessagesBehaviour getMessagesBehaviour(
139 |  |
                             final ThreadContext context) {
140 | 11 |
                     if (context.messagesBehaviour == null) {
141 | 8 |
                             final Container container = ProviderFactory.get(
142 |  |
                                             ContainerProvider.class).getContainer();
143 | 8 |
                             context.messagesBehaviour = container
144 |  |
                                             .lookup(MessagesBehaviour.class);
145 |  |
                     }
146 | 11 |
                     return context.messagesBehaviour;
147 |  |
             }
148 |  |
149 |  |
             /**
150 |  |
              * 指定されたコマンドを新しいコンテキスト内で実行します。
151 |  |
              *
152 |  |
              * @param request
153 |  |
              *            要求
154 |  |
              * @param response
155 |  |
              *            応答
156 |  |
              * @param command
157 |  |
              *            コンテキスト内で実行するコマンド
158 |  |
              * @throws Exception
159 |  |
              *             コマンドの実行中に例外が発生した場合
160 |  |
              */
161 |  |
             public static void runInContext(final HttpServletRequest request,
162 |  |
                             final HttpServletResponse response, final Command command)
163 |  |
                             throws Exception {
164 | 21 |
                     if (request == null) {
165 | 0 |
                             throw new NullPointerException("request");
166 |  |
                     }
167 | 21 |
                     if (response == null) {
168 | 0 |
                             throw new NullPointerException("response");
169 |  |
                     }
170 | 21 |
                     if (command == null) {
171 | 0 |
                             throw new NullPointerException("command");
172 |  |
                     }
173 |  |
174 | 21 |
                     final ThreadContext previous = THREAD_LOCAL.get();
175 | 21 |
                     final ThreadContext context = new ThreadContext(request, response);
176 | 21 |
                     THREAD_LOCAL.set(context);
177 |  |
                     try {
178 | 21 |
                             command.execute(request, response);
179 |  |
                     } finally {
180 | 21 |
                             if (previous == null) {
181 | 19 |
                                     THREAD_LOCAL.remove();
182 |  |
                             } else {
183 | 2 |
                                     THREAD_LOCAL.set(previous);
184 |  |
                             }
185 | 1 |
                     }
186 | 19 |
             }
187 |  |
188 |  |
             /**
189 |  |
              * コンテキスト内で実行するコマンドのインターフェイスです。
190 |  |
              *
191 |  |
              * @author baba
192 |  |
              */
193 |  |
             public interface Command {
194 |  |
195 |  |
                     /**
196 |  |
                      * コマンドを実行します。
197 |  |
                      *
198 |  |
                      * @param request
199 |  |
                      *            要求
200 |  |
                      * @param response
201 |  |
                      *            応答
202 |  |
                      * @throws Exception
203 |  |
                      *             コマンドの実行中に例外が発生した場合
204 |  |
                      */
205 |  |
                     void execute(HttpServletRequest request, HttpServletResponse response)
206 |  |
                                     throws Exception;
207 |  |
208 |  |
             }
209 |  |
210 |  |
     }