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 }