View Javadoc

1   /*
2    * $Id: CompositeActionMapper.java 478625 2006-11-23 17:31:52Z wsmoak $
3    *
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  package org.apache.struts2.dispatcher.mapper;
22  
23  import java.util.ArrayList;
24  import java.util.Collections;
25  import java.util.Comparator;
26  import java.util.Iterator;
27  import java.util.List;
28  
29  import javax.servlet.http.HttpServletRequest;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.apache.struts2.StrutsConstants;
34  
35  import com.opensymphony.xwork2.ObjectFactory;
36  import com.opensymphony.xwork2.config.ConfigurationManager;
37  import com.opensymphony.xwork2.inject.Container;
38  import com.opensymphony.xwork2.inject.Inject;
39  import com.opensymphony.xwork2.util.FileManager;
40  
41  /***
42   * <!-- START SNIPPET: description -->
43   *
44   * A composite action mapper that is capable of delegating to a series of {@link ActionMapper} if the former
45   * failed to obtained a valid {@link ActionMapping} or uri.
46   * <p/>
47   * It is configured through struts.properties.
48   * <p/>
49   * For example, with the following entries in struts.properties
50   * <p/>
51   * <pre>
52   * &lt;bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="struts" 
53   *       class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper" /&gt;
54   * &lt;constant name="struts.mapper.composite" 
55   *       value="org.apache.struts2.dispatcher.mapper.DefaultActionMapper,org.apache.struts2.dispatcher.mapper.RestfulActionMapperorg.apache.struts2.dispatcher.mapper.Restful2ActionMapper" /&gt;
56   * </pre>
57   * <p/>
58   * When {@link CompositeActionMapper#getMapping(HttpServletRequest, ConfigurationManager)} or
59   * {@link CompositeActionMapper#getUriFromActionMapping(ActionMapping)} is invoked,
60   * {@link CompositeActionMapper} would go through these {@link ActionMapper}s in sequence
61   * starting from {@link ActionMapper} identified by 'struts.mapper.composite.1', followed by
62   * 'struts.mapper.composite.2' and finally 'struts.mapper.composite.3' (in this case) until either
63   * one of the {@link ActionMapper} return a valid result (not null) or it runs out of {@link ActionMapper}
64   * in which case it will just return null for both
65   * {@link CompositeActionMapper#getMapping(HttpServletRequest, ConfigurationManager)} and
66   * {@link CompositeActionMapper#getUriFromActionMapping(ActionMapping)} methods.
67   * <p/>
68   *
69   * For example with the following in struts-*.xml :-
70   * <pre>
71   *    &lt;bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="struts" 
72   *       class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper" /&gt;
73   *    &lt;constant name="struts.mapper.composite" 
74   *       value="org.apache.struts2.dispatcher.mapper.DefaultActionMapper,foo.bar.MyActionMapper,foo.bar.MyAnotherActionMapper" /&gt;
75   * </pre>
76   * <p/>
77   * <code>CompositeActionMapper</code> will be configured with 3 ActionMapper, namely
78   * "DefaultActionMapper", "MyActionMapper" and "MyAnotherActionMapper".
79   * <code>CompositeActionMapper</code> would consult each of them in order described above.
80   *
81   * <!-- END SNIPPET: description -->
82   *
83   * @see ActionMapper
84   * @see ActionMapperFactory
85   * @see ActionMapping
86   * @see IndividualActionMapperEntry
87   *
88   * @version $Date: 2006-11-23 18:31:52 +0100 (Do, 23 Nov 2006) $ $Id: CompositeActionMapper.java 478625 2006-11-23 17:31:52Z wsmoak $
89   */
90  public class CompositeActionMapper implements ActionMapper {
91  
92      private static final Log LOG = LogFactory.getLog(CompositeActionMapper.class);
93  
94      protected Container container;
95      
96      protected List<ActionMapper> actionMappers = new ArrayList<ActionMapper>();
97      
98      @Inject
99      public void setContainer(Container container) {
100         this.container = container;
101     }
102     
103     @Inject(StrutsConstants.STRUTS_MAPPER_COMPOSITE)
104     public void setActionMappers(String list) {
105         if (list != null) {
106             String[] arr = list.split(",");
107             for (String name : arr) {
108                 Object obj = container.getInstance(ActionMapper.class, name);
109                 if (obj != null) {
110                     actionMappers.add((ActionMapper) obj);
111                 }
112             }
113         }
114     }
115 
116 
117     public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
118 
119         for (ActionMapper actionMapper : actionMappers) {
120             ActionMapping actionMapping = actionMapper.getMapping(request, configManager);
121             if (LOG.isDebugEnabled()) {
122                 LOG.debug("Using ActionMapper "+actionMapper);
123             }
124             if (actionMapping == null) {
125                 if (LOG.isDebugEnabled()) {
126                     LOG.debug("ActionMapper "+actionMapper+" failed to return an ActionMapping (null)");
127                 }
128             }
129             else {
130                 return actionMapping;
131             }
132         }
133         if (LOG.isDebugEnabled()) {
134             LOG.debug("exhausted from ActionMapper that could return an ActionMapping");
135         }
136         return null;
137     }
138 
139     public String getUriFromActionMapping(ActionMapping mapping) {
140 
141         for (ActionMapper actionMapper : actionMappers) {
142             String uri = actionMapper.getUriFromActionMapping(mapping);
143             if (LOG.isDebugEnabled()) {
144                 LOG.debug("Using ActionMapper "+actionMapper);
145             }
146             if (uri == null) {
147                 if (LOG.isDebugEnabled()) {
148                     LOG.debug("ActionMapper "+actionMapper+" failed to return an ActionMapping (null)");
149                 }
150             }
151             else {
152                 return uri;
153             }
154         }
155         if (LOG.isDebugEnabled()) {
156             LOG.debug("exhausted from ActionMapper that could return a uri");
157         }
158         return null;
159     }
160 }