1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package org.seasar.remoting.axis.deployer;
47
48 import java.util.ArrayList;
49 import java.util.List;
50 import java.util.regex.Matcher;
51 import java.util.regex.Pattern;
52
53 import javax.servlet.ServletContext;
54
55 import org.apache.axis.AxisEngine;
56 import org.apache.axis.WSDDEngineConfiguration;
57 import org.apache.axis.client.Service;
58 import org.apache.axis.deployment.wsdd.WSDDDeployment;
59 import org.seasar.framework.container.ComponentDef;
60 import org.seasar.framework.container.MetaDef;
61 import org.seasar.framework.container.MetaDefAware;
62 import org.seasar.framework.container.S2Container;
63 import org.seasar.framework.message.MessageFormatter;
64 import org.seasar.remoting.axis.DeployFailedException;
65 import org.seasar.remoting.axis.S2AxisConstants;
66 import org.seasar.remoting.common.deployer.Deployer;
67
68 /***
69 * diconファイル中に記述されたコンポーネントをAxisにデプロイします。
70 *
71 * @author koichik
72 */
73 public class AxisDeployer implements Deployer {
74
75 /***
76 * <code><meta></code> 要素の <code>name</code>
77 * 属性に指定される名前を取得するための正規表現です。 <br>
78 * S2Axis-V1.0.0-RC2以降は接頭辞 <code>axis-</code> の後にローカル名が続きます。 <br>
79 * S2Axis-V1.0.0-RC1以前との互換性のため、接頭辞 <code>s2-axis:</code> も使えるようにしています。
80 */
81 protected static final Pattern META_NAME_PATTERN = Pattern.compile("(?:s2-axis:|axis-)(.+)");
82
83
84 protected S2Container container;
85 protected ServletContext servletContext;
86
87 protected ItemDeployer serviceDeployer = new ServiceDeployer(this);
88 protected ItemDeployer handlerDeployer = new HandlerDeployer(this);
89 protected ItemDeployer wsddDeployer = new WSDDDeployer(this);
90
91 /***
92 * S2コンテナを設定します。
93 *
94 * @param container
95 * S2コンテナ
96 */
97 public void setContainer(final S2Container container) {
98 this.container = container;
99 }
100
101 /***
102 * サーブレットコンテキストを設定します。
103 *
104 * @param servletContext
105 * サーブレットコンテキスト
106 */
107 public void setServletContext(final ServletContext servletContext) {
108 this.servletContext = servletContext;
109 }
110
111 /***
112 * コンテナに登録されているサービスやハンドラをデプロイします。
113 */
114 public void deploy() {
115 forEach(container.getRoot());
116 }
117
118 /***
119 * コンテナの階層をたどって全てのコンテナとコンポーネント定義を走査します。 <br>
120 * 走査する順序は次の通りです。
121 * <ol>
122 * <li>コンテナ自身</li>
123 * <li>子のコンポーネント定義</li>
124 * <li>子のコンテナを再起的に</li>
125 * </ol>
126 *
127 * @param container
128 * 起点となるコンテナ
129 */
130 protected void forEach(final S2Container container) {
131 process(container);
132
133 final int componentDefSize = container.getComponentDefSize();
134 for (int i = 0; i < componentDefSize; ++i) {
135 process(container.getComponentDef(i));
136 }
137
138 final int childContainerSize = container.getChildSize();
139 for (int i = 0; i < childContainerSize; ++i) {
140 forEach(container.getChild(i));
141 }
142 }
143
144 /***
145 * S2コンテナにS2Axisのメタデータ <code><meta name="axis-deploy"></code>
146 * が指定されていれば、そのWSDDをAxisにデプロイします。
147 *
148 * @param container
149 * S2コンテナ
150 */
151 protected void process(final S2Container container) {
152 final MetaDef[] metaDefs = getMetaDefs(container, S2AxisConstants.META_DEPLOY);
153 for (int i = 0; metaDefs != null && i < metaDefs.length; ++i) {
154 wsddDeployer.deploy(null, metaDefs[i]);
155 }
156 }
157
158 /***
159 * コンポーネント定義にS2Axisのメタデータ <code><meta name="axis-service"></code>
160 * または <code><meta name="axis-handler"></code>
161 * が指定されていれば、そのコンポーネントをサービスまたはハンドラとしてAxisにデプロイします。
162 *
163 * @param componentDef
164 * コンポーネント定義
165 */
166 protected void process(final ComponentDef componentDef) {
167 final MetaDef serviceMetaDef = getMetaDef(componentDef, S2AxisConstants.META_SERVICE);
168 if (serviceMetaDef != null) {
169 serviceDeployer.deploy(componentDef, serviceMetaDef);
170 }
171
172 final MetaDef handlerMetaDef = getMetaDef(componentDef, S2AxisConstants.META_HANDLER);
173 if (handlerMetaDef != null) {
174 handlerDeployer.deploy(componentDef, handlerMetaDef);
175 }
176 }
177
178 /***
179 * WSDDデプロイメントを返します。
180 *
181 * @param container
182 * コンテナ
183 * @return WSDDデプロイメント
184 */
185 protected WSDDDeployment getDeployment(final S2Container container) {
186 return ((WSDDEngineConfiguration) getEngine(container).getConfig()).getDeployment();
187 }
188
189 /***
190 * Axisエンジンを返します。 <br>
191 * Axisエンジンは、コンテナに名前 <code>axis-engine</code> を持つ
192 * <code><meta></code> 要素が指定されていれば、その内容文字列から次のように決定されます。
193 * <dl>
194 * <dt>未定義の場合</dt>
195 * <dd><code>"default"</code> が指定されたものとしてAxisエンジンを決定します。</dd>
196 * <dt><code>"default"</code></dt>
197 * <dd>コンテナにサーブレットコンテキストが設定されていれば <code>"default-server"</code> 、そうでなければ
198 * <code>"default-client"</code> が指定されたものとしてAxisエンジンを決定します。</dd>
199 * <dt><code>"default-client"</code></dt>
200 * <dd>コンテナから <code>javax.xml.rpc.Service</code>
201 * を実装したコンポーネントを取得し、そのエンジンを使用します。</dd>
202 * <dt><code>"default-server"</code></dt>
203 * <dd>サーブレットコンテキストに設定されているAxisエンジンを使用します。 <br>
204 * 最初に {@link S2AxisConstants#AXIS_SERVLET}と
205 * {@link S2AxisConstants#ATTR_AXIS_ENGINE}を連結した文字列をキーとして
206 * サーブレットコンテキストからAxisエンジンを取得します。 <br>
207 * 見つからなかった場合は{S2AxisConstants#ATTR_AXIS_ENGINE}を
208 * キーとしてサーブレットコンテキストから取得したAxisエンジンを取得します。 <br>
209 * </dd>
210 * <dt><code>"servlet:"</code> で始まる文字列</dt>
211 * <dd><code>"servlet:"</code> の後ろの文字列をキーとしてサーブレットコンテキストから
212 * 取得したAxisエンジンを使用します。
213 * <dd>
214 * <dt><code>"s2:"</code> で始まる文字列</dt>
215 * <dd><code>"s2:"</code> の後ろの文字列をキーとしてS2コンテナから
216 * 取得したコンポーネントをAxisエンジンを使用します。</dd>
217 * <dt>その他</dt>
218 * <dd>キーとしてS2コンテナから取得したコンポーネントをAxisエンジンとして使用します。</dd>
219 * </dl>
220 *
221 * @param container
222 * コンテナ
223 * @return Axisエンジン
224 */
225 protected AxisEngine getEngine(final S2Container container) {
226 String engineName = S2AxisConstants.ENGINE_DEFAULT;
227
228 final MetaDef metadata = getMetaDef(container, S2AxisConstants.META_ENGINE);
229 if (metadata != null) {
230 engineName = (String) metadata.getValue();
231 }
232
233 if (S2AxisConstants.ENGINE_DEFAULT.equals(engineName)) {
234 if (servletContext == null) {
235 engineName = S2AxisConstants.ENGINE_DEFAULT_CLIENT;
236 }
237 else {
238 engineName = S2AxisConstants.ENGINE_DEFAULT_SERVER;
239 }
240 }
241
242 AxisEngine engine = null;
243 if (S2AxisConstants.ENGINE_DEFAULT_CLIENT.equals(engineName)) {
244 final Service service = (Service) container.getComponent(javax.xml.rpc.Service.class);
245 engine = service.getEngine();
246 }
247 else if (S2AxisConstants.ENGINE_DEFAULT_SERVER.equals(engineName)) {
248 engine = (AxisEngine) servletContext.getAttribute(S2AxisConstants.AXIS_SERVLET
249 + S2AxisConstants.ATTR_AXIS_ENGINE);
250 if (engine == null) {
251 engine = (AxisEngine) servletContext.getAttribute(S2AxisConstants.ATTR_AXIS_ENGINE);
252 }
253 }
254 else if (engineName.startsWith(S2AxisConstants.ENGINE_FROM_SERVLET)) {
255 final String servletName = engineName.substring(S2AxisConstants.ENGINE_FROM_SERVLET
256 .length());
257 engine = (AxisEngine) servletContext.getAttribute(servletName
258 + S2AxisConstants.ATTR_AXIS_ENGINE);
259 }
260 else if (engineName.startsWith(S2AxisConstants.ENGINE_FROM_S2CONTAINER)) {
261 final String componentName = engineName
262 .substring(S2AxisConstants.ENGINE_FROM_S2CONTAINER.length());
263 engine = (AxisEngine) container.getComponent(componentName);
264 }
265 else {
266 engine = (AxisEngine) container.getComponent(engineName);
267 }
268
269 if (engine == null) {
270 throw new DeployFailedException(MessageFormatter.getSimpleMessage("EAXS0007", null));
271 }
272 return engine;
273 }
274
275 /***
276 * <code>S2Container</code> または <code>ComponentDef</code> が名前
277 * <code>"axis-<var>localName</var></code> の <code><meta></code>
278 * 要素を持っていれば、その <code>MetaDef</code> を返します。 <br>
279 * <code>S2Container</code> または <code>ComponentDef</code> に該当する
280 * メタデータが複数定義されている場合は最初に見つかったメタデータを返します。
281 *
282 * @param metaDefSupport
283 * <code>S2Container</code> または <code>ComponentDef</code>
284 * @param localName
285 * 接頭辞 <code>axis-</code> に続くメタデータの名前
286 * @return 指定された名前を持つ <code>MetaDef</code> 。存在しない場合は <code>null</code>
287 */
288 protected MetaDef getMetaDef(final MetaDefAware metaDefSupport, final String localName) {
289 for (int i = 0; i < metaDefSupport.getMetaDefSize(); ++i) {
290 final MetaDef metaDef = metaDefSupport.getMetaDef(i);
291 if (localName.equals(getLocalName(metaDef))) {
292 return metaDef;
293 }
294 }
295 return null;
296 }
297
298 /***
299 * <code>S2Container</code> または <code>ComponentDef</code> が名前
300 * <code>"axis-<var>localName</var></code> の <code><meta></code>
301 * 要素を持っていれば、その <code>MetaDef</code> を全て返します。 <br>
302 *
303 * @param metaDefSupport
304 * <code>S2Container</code> または <code>ComponentDef</code>
305 * @param localName
306 * 接頭辞 <code>axis-</code> に続くメタデータの名前
307 * @return 指定された名前を持つ <code>MetaDef</code> の配列
308 */
309 protected MetaDef[] getMetaDefs(final MetaDefAware metaDefSupport, final String localName) {
310 final List result = new ArrayList();
311 for (int i = 0; i < metaDefSupport.getMetaDefSize(); ++i) {
312 final MetaDef metaDef = metaDefSupport.getMetaDef(i);
313 if (localName.equals(getLocalName(metaDef))) {
314 result.add(metaDef);
315 }
316 }
317 return (MetaDef[]) result.toArray(new MetaDef[result.size()]);
318 }
319
320 /***
321 * メタデータの名前がS2Axisで使用する接頭辞で始まっていれば、接頭辞の後ろのローカル名を返します。
322 *
323 * @param metaDef
324 * メタデータ定義
325 * @return ローカル名
326 */
327 protected String getLocalName(final MetaDef metaDef) {
328 final Matcher matcher = META_NAME_PATTERN.matcher(metaDef.getName());
329 return matcher.matches() ? matcher.group(1) : null;
330 }
331 }