View Javadoc

1   /*
2    *
3    * The Seasar Software License, Version 1.1
4    *
5    * Copyright (c) 2003-2004 The Seasar Project. All rights reserved.
6    *
7    * Redistribution and use in source and binary forms, with or
8    * without modification, are permitted provided that the following
9    * conditions are met:
10   *
11   * 1. Redistributions of source code must retain the above
12   *    copyright notice, this list of conditions and the following
13   *    disclaimer.
14   *
15   * 2. Redistributions in binary form must reproduce the above
16   *    copyright notice, this list of conditions and the following
17   *    disclaimer in the documentation and/or other materials provided
18   *    with the distribution.
19   *
20   * 3. The end-user documentation included with the redistribution,
21   *    if any, must include the following acknowledgement:
22   *    "This product includes software developed by the
23   *    Seasar Project (http://www.seasar.org/)."
24   *    Alternately, this acknowledgement may appear in the software
25   *    itself, if and wherever such third-party acknowledgements
26   *    normally appear.
27   *
28   * 4. Neither the name "The Seasar Project" nor the names of its
29   *    contributors may be used to endorse or promote products derived
30   *    from this software without specific prior written permission of
31   *    the Seasar Project.
32   *
33   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR
34   * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
35   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
36   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE SEASAR PROJECT
37   * OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
38   * INCIDENTAL,SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
39   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
40   * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
41   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
42   * WHETHER IN CONTRACT, STRICT LIABILITY,OR TORT (INCLUDING
43   * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
44   * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
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      //class fields
81      private final static Logger logger = Logger.getLogger(Deployer.class);
82  
83      //instance fields
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>&lt;meta name="s2axis:deploy"&gt;</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>&lt;meta name="s2axis:service"&gt;</code>
182      * または <code>&lt;meta name="s2axis:handler"&gt;</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>&lt;service&gt;</code> 要素を返します。
257      * 
258      * @param wsddFileName
259      *            WSDDファイルのパス名
260      * @return <code>&lt;service&gt;</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 }