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.axis.server.deployment;
47
48 import java.io.InputStream;
49 import java.util.ArrayList;
50 import java.util.List;
51
52 import javax.servlet.ServletContext;
53
54 import org.apache.axis.WSDDEngineConfiguration;
55 import org.apache.axis.deployment.wsdd.WSDDConstants;
56 import org.apache.axis.deployment.wsdd.WSDDDeployment;
57 import org.apache.axis.deployment.wsdd.WSDDDocument;
58 import org.apache.axis.deployment.wsdd.WSDDException;
59 import org.apache.axis.server.AxisServer;
60 import org.apache.axis.utils.XMLUtils;
61 import org.seasar.axis.S2AxisConstants;
62 import org.seasar.axis.server.DeployFailedException;
63 import org.seasar.axis.server.ServiceDef;
64 import org.seasar.framework.container.ComponentDef;
65 import org.seasar.framework.container.MetaDef;
66 import org.seasar.framework.container.S2Container;
67 import org.seasar.framework.log.Logger;
68 import org.seasar.framework.message.MessageFormatter;
69 import org.seasar.framework.util.ResourceUtil;
70 import org.w3c.dom.Element;
71 import org.w3c.dom.Node;
72 import org.w3c.dom.NodeList;
73
74 /***
75 * diconファイル中に記述されたコンポーネントをAxisにデプロイします。
76 *
77 * @author koichik
78 */
79 public class Deployer {
80
81 private final static Logger logger = Logger.getLogger(Deployer.class);
82
83
84 protected S2Container container;
85 protected ServletContext servletContext;
86 protected AxisServer axisEngine;
87 protected WSDDEngineConfiguration configuration;
88 protected WSDDDeployment deployment;
89
90 /***
91 * S2コンテナを設定します。
92 *
93 * @param container
94 * S2コンテナ
95 */
96 public void setContainer(final S2Container container) {
97 this.container = container;
98 }
99
100 /***
101 * サーブレットコンテキストを設定します。
102 *
103 * @param servletContext
104 * サーブレットコンテキスト
105 */
106 public void setServletContext(final ServletContext servletContext) {
107 this.servletContext = servletContext;
108 }
109
110 /***
111 * Axisエンジンを取得し,コンテナに登録されているサービスやハンドラをデプロイします。
112 */
113 public void deploy() {
114 setupAxis();
115 forEach(container.getRoot());
116 }
117
118 /***
119 * Axisにデプロイするためのセットアップを行います。
120 */
121 protected void setupAxis() {
122 axisEngine = (AxisServer) servletContext.getAttribute(S2AxisConstants.ATTR_AXIS_ENGINE);
123 configuration = (WSDDEngineConfiguration) axisEngine.getConfig();
124 deployment = configuration.getDeployment();
125 }
126
127 /***
128 * コンテナの階層をたどって全てのコンテナとコンポーネント定義を走査します。 <br>
129 * 走査する順序は次の通りです。
130 * <ol>
131 * <li>コンテナ自身</li>
132 * <li>子のコンポーネント定義</li>
133 * <li>子のコンテナを再起的に</li>
134 * </ol>
135 *
136 * @param container
137 * 起点となるコンテナ
138 */
139 protected void forEach(final S2Container container) {
140 process(container);
141
142 final int componentDefSize = container.getComponentDefSize();
143 for (int i = 0; i < componentDefSize; ++i) {
144 process(container.getComponentDef(i));
145 }
146
147 final int childContainerSize = container.getChildSize();
148 for (int i = 0; i < childContainerSize; ++i) {
149 forEach(container.getChild(i));
150 }
151 }
152
153 /***
154 * S2コンテナにS2Axisのメタデータ <code><meta name="s2axis:deploy"></code>
155 * が指定されていれば、そのWSDDをAxisにデプロイします。
156 *
157 * @param container
158 * S2コンテナ
159 */
160 protected void process(final S2Container container) {
161 final MetaDef[] metadataArray = container.getMetaDefs(S2AxisConstants.META_S2AXIS_DEPLOY);
162 if (metadataArray != null) {
163 for (int i = 0; i < metadataArray.length; ++i) {
164 final Object value = metadataArray[i].getValue();
165 if (value instanceof String) {
166 final String wsddFileName = (String) value;
167 deployWSDD(wsddFileName);
168 if (logger.isDebugEnabled()) {
169 logger.log("DAXS0001", new Object[] { wsddFileName });
170 }
171 }
172 else {
173 throw new DeployFailedException(MessageFormatter.getSimpleMessage("EAXS0002",
174 new Object[] { value }));
175 }
176 }
177 }
178 }
179
180 /***
181 * コンポーネント定義にS2Axisのメタデータ <code><meta name="s2axis:service"></code>
182 * または <code><meta name="s2axis:handler"></code>
183 * が指定されていれば、そのコンポーネントをサービスまたはハンドラとしてAxisにデプロイします。
184 *
185 * @param componentDef
186 * コンポーネント定義
187 */
188 protected void process(final ComponentDef componentDef) {
189 final MetaDef serviceMetaDef = componentDef.getMetaDef(S2AxisConstants.META_S2AXIS_SERVICE);
190 if (serviceMetaDef != null) {
191 final WSDDS2Service service = createWSDDS2Service(componentDef, serviceMetaDef);
192 deployment.deployService(service);
193 if (logger.isDebugEnabled()) {
194 logger.log("DAXS0003", new Object[] { service.getQName() });
195 }
196 }
197
198 final MetaDef handlerMetaDef = componentDef.getMetaDef(S2AxisConstants.META_S2AXIS_HANDLER);
199 if (handlerMetaDef != null) {
200 final WSDDS2Handler handler = new WSDDS2Handler(componentDef);
201 deployment.deployHandler(handler);
202 if (logger.isDebugEnabled()) {
203 logger.log("DAXS0004", new Object[] { handler.getQName() });
204 }
205 }
206 }
207
208 /***
209 * WSDDファイルををファイルシステムまたはクラスパスから読み込み、Axisにデプロイします。
210 *
211 * @param wsddFileName
212 * WSDDファイルのパス名
213 */
214 protected void deployWSDD(final String wsddFileName) {
215 try {
216 final InputStream is = ResourceUtil.getResourceAsStream(wsddFileName);
217 final WSDDDocument wsddDocument = new WSDDDocument(XMLUtils.newDocument(is));
218 wsddDocument.deploy(deployment);
219 }
220 catch (final Exception e) {
221 throw new DeployFailedException(e);
222 }
223 }
224
225 /***
226 * <code>WSDDS2Service</code> をインスタンス化して返します。 <br>
227 * メタデータの指定に従い、 <code>ServiceDef</code> またはWSDDファイルから
228 * <code>WSDDS2Service</code> をインスタンス化します。
229 *
230 * @param componentDef
231 * コンポーネント定義
232 * @param metaDef
233 * メタデータ定義
234 * @return <code>WSDDS2Service</code>
235 */
236 public WSDDS2Service createWSDDS2Service(final ComponentDef componentDef, final MetaDef metaDef) {
237 try {
238 Object metadata = metaDef.getValue();
239 if (metadata == null) {
240 return new WSDDS2Service(componentDef);
241 }
242 else if (metadata instanceof ServiceDef) {
243 return new WSDDS2Service(componentDef, (ServiceDef) metadata);
244 }
245 else if (metadata instanceof String) {
246 return new WSDDS2Service(componentDef, getServiceElement((String) metadata));
247 }
248 throw new DeployFailedException();
249 }
250 catch (final WSDDException e) {
251 throw new DeployFailedException(e);
252 }
253 }
254
255 /***
256 * WSDDファイルをファイルシステムまたはクラスパスから読み込み、 <code><service></code> 要素を返します。
257 *
258 * @param wsddFileName
259 * WSDDファイルのパス名
260 * @return <code><service></code> 要素
261 */
262 protected Element getServiceElement(final String wsddFileName) {
263 try {
264 final InputStream is = ResourceUtil.getResourceAsStream(wsddFileName);
265 final Element documentElement = XMLUtils.newDocument(is).getDocumentElement();
266 final Element[] serviceElements = getChildElements(documentElement,
267 WSDDConstants.ELEM_WSDD_SERVICE);
268 if (serviceElements.length != 1) {
269 throw new DeployFailedException(MessageFormatter.getSimpleMessage("EAXS0005",
270 new Object[] { wsddFileName }));
271 }
272 return serviceElements[0];
273 }
274 catch (final DeployFailedException e) {
275 throw e;
276 }
277 catch (final Exception e) {
278 throw new DeployFailedException(e);
279 }
280 }
281
282 /***
283 * 指定されたローカル名を持つ子要素の配列を返します。
284 *
285 * @param parent
286 * 親要素
287 * @param name
288 * 子要素のローカル名
289 * @return 指定されたローカル名を持つ子要素の配列。該当する子要素が存在しない場合は空の配列。
290 */
291 protected Element[] getChildElements(final Element parent, final String name) {
292 final List result = new ArrayList();
293 final NodeList children = parent.getChildNodes();
294 for (int i = 0; i < children.getLength(); i++) {
295 final Node thisNode = children.item(i);
296 if (thisNode instanceof Element) {
297 final Element element = (Element) thisNode;
298 if (element.getLocalName().equals(name)) {
299 result.add(element);
300 }
301 }
302 }
303 return (Element[]) result.toArray(new Element[result.size()]);
304 }
305 }