001: /*
002: * $Id: CompositeActionMapper.java 478625 2006-11-23 17:31:52Z wsmoak $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts2.dispatcher.mapper;
022:
023: import java.util.ArrayList;
024: import java.util.Collections;
025: import java.util.Comparator;
026: import java.util.Iterator;
027: import java.util.List;
028:
029: import javax.servlet.http.HttpServletRequest;
030:
031: import org.apache.commons.logging.Log;
032: import org.apache.commons.logging.LogFactory;
033: import org.apache.struts2.StrutsConstants;
034:
035: import com.opensymphony.xwork2.ObjectFactory;
036: import com.opensymphony.xwork2.config.ConfigurationManager;
037: import com.opensymphony.xwork2.inject.Container;
038: import com.opensymphony.xwork2.inject.Inject;
039: import com.opensymphony.xwork2.util.FileManager;
040:
041: /**
042: * <!-- START SNIPPET: description -->
043: *
044: * A composite action mapper that is capable of delegating to a series of {@link ActionMapper} if the former
045: * failed to obtained a valid {@link ActionMapping} or uri.
046: * <p/>
047: * It is configured through struts.properties.
048: * <p/>
049: * For example, with the following entries in struts.properties
050: * <p/>
051: * <pre>
052: * <bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="struts"
053: * class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper" />
054: * <constant name="struts.mapper.composite"
055: * value="org.apache.struts2.dispatcher.mapper.DefaultActionMapper,org.apache.struts2.dispatcher.mapper.RestfulActionMapperorg.apache.struts2.dispatcher.mapper.Restful2ActionMapper" />
056: * </pre>
057: * <p/>
058: * When {@link CompositeActionMapper#getMapping(HttpServletRequest, ConfigurationManager)} or
059: * {@link CompositeActionMapper#getUriFromActionMapping(ActionMapping)} is invoked,
060: * {@link CompositeActionMapper} would go through these {@link ActionMapper}s in sequence
061: * starting from {@link ActionMapper} identified by 'struts.mapper.composite.1', followed by
062: * 'struts.mapper.composite.2' and finally 'struts.mapper.composite.3' (in this case) until either
063: * one of the {@link ActionMapper} return a valid result (not null) or it runs out of {@link ActionMapper}
064: * in which case it will just return null for both
065: * {@link CompositeActionMapper#getMapping(HttpServletRequest, ConfigurationManager)} and
066: * {@link CompositeActionMapper#getUriFromActionMapping(ActionMapping)} methods.
067: * <p/>
068: *
069: * For example with the following in struts-*.xml :-
070: * <pre>
071: * <bean type="org.apache.struts2.dispatcher.mapper.ActionMapper" name="struts"
072: * class="org.apache.struts2.dispatcher.mapper.CompositeActionMapper" />
073: * <constant name="struts.mapper.composite"
074: * value="org.apache.struts2.dispatcher.mapper.DefaultActionMapper,foo.bar.MyActionMapper,foo.bar.MyAnotherActionMapper" />
075: * </pre>
076: * <p/>
077: * <code>CompositeActionMapper</code> will be configured with 3 ActionMapper, namely
078: * "DefaultActionMapper", "MyActionMapper" and "MyAnotherActionMapper".
079: * <code>CompositeActionMapper</code> would consult each of them in order described above.
080: *
081: * <!-- END SNIPPET: description -->
082: *
083: * @see ActionMapper
084: * @see ActionMapperFactory
085: * @see ActionMapping
086: * @see IndividualActionMapperEntry
087: *
088: * @version $Date: 2006-11-23 12:31:52 -0500 (Thu, 23 Nov 2006) $ $Id: CompositeActionMapper.java 478625 2006-11-23 17:31:52Z wsmoak $
089: */
090: public class CompositeActionMapper implements ActionMapper {
091:
092: private static final Log LOG = LogFactory
093: .getLog(CompositeActionMapper.class);
094:
095: protected Container container;
096:
097: protected List<ActionMapper> actionMappers = new ArrayList<ActionMapper>();
098:
099: @Inject
100: public void setContainer(Container container) {
101: this .container = container;
102: }
103:
104: @Inject(StrutsConstants.STRUTS_MAPPER_COMPOSITE)
105: public void setActionMappers(String list) {
106: if (list != null) {
107: String[] arr = list.split(",");
108: for (String name : arr) {
109: Object obj = container.getInstance(ActionMapper.class,
110: name);
111: if (obj != null) {
112: actionMappers.add((ActionMapper) obj);
113: }
114: }
115: }
116: }
117:
118: public ActionMapping getMapping(HttpServletRequest request,
119: ConfigurationManager configManager) {
120:
121: for (ActionMapper actionMapper : actionMappers) {
122: ActionMapping actionMapping = actionMapper.getMapping(
123: request, configManager);
124: if (LOG.isDebugEnabled()) {
125: LOG.debug("Using ActionMapper " + actionMapper);
126: }
127: if (actionMapping == null) {
128: if (LOG.isDebugEnabled()) {
129: LOG
130: .debug("ActionMapper "
131: + actionMapper
132: + " failed to return an ActionMapping (null)");
133: }
134: } else {
135: return actionMapping;
136: }
137: }
138: if (LOG.isDebugEnabled()) {
139: LOG
140: .debug("exhausted from ActionMapper that could return an ActionMapping");
141: }
142: return null;
143: }
144:
145: public String getUriFromActionMapping(ActionMapping mapping) {
146:
147: for (ActionMapper actionMapper : actionMappers) {
148: String uri = actionMapper.getUriFromActionMapping(mapping);
149: if (LOG.isDebugEnabled()) {
150: LOG.debug("Using ActionMapper " + actionMapper);
151: }
152: if (uri == null) {
153: if (LOG.isDebugEnabled()) {
154: LOG
155: .debug("ActionMapper "
156: + actionMapper
157: + " failed to return an ActionMapping (null)");
158: }
159: } else {
160: return uri;
161: }
162: }
163: if (LOG.isDebugEnabled()) {
164: LOG
165: .debug("exhausted from ActionMapper that could return a uri");
166: }
167: return null;
168: }
169: }
|