You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by tm...@apache.org on 2006/11/05 15:22:55 UTC
svn commit: r471435 - in /struts/struts2/trunk/core/src:
main/java/org/apache/struts2/ main/java/org/apache/struts2/config/
main/java/org/apache/struts2/dispatcher/mapper/
main/resources/org/apache/struts2/
test/java/org/apache/struts2/dispatcher/mapper/
Author: tmjee
Date: Sun Nov 5 06:22:54 2006
New Revision: 471435
URL: http://svn.apache.org/viewvc?view=rev&rev=471435
Log:
WW-1490
- Have a composite ActionMapper that decides which ActionMapper it contains should be used
Added:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapper.java
struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapperTest.java
Modified:
struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Settings.java
struts/struts2/trunk/core/src/main/resources/org/apache/struts2/default.properties
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java?view=diff&rev=471435&r1=471434&r2=471435
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/StrutsConstants.java Sun Nov 5 06:22:54 2006
@@ -17,6 +17,8 @@
*/
package org.apache.struts2;
+import org.apache.struts2.dispatcher.mapper.CompositeActionMapper;
+
/**
* This class provides a central location for framework configuration keys
* used to retrieve and store Struts configuration settings.
@@ -134,4 +136,6 @@
/** Whether slashes in action names are allowed or not */
public static final String STRUTS_ENABLE_SLASHES_IN_ACTION_NAMES = "struts.enable.SlashesInActionNames";
+ /** Prefix used by {@link CompositeActionMapper} to identified its containing {@link ActionMapper} class. */
+ public static final String STRUTS_MAPPER_COMPOSITE = "struts.mapper.composite.";
}
Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Settings.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Settings.java?view=diff&rev=471435&r1=471434&r2=471435
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Settings.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Settings.java Sun Nov 5 06:22:54 2006
@@ -135,7 +135,7 @@
return val;
}
-
+
/**
* Returns an Iterator of all properties names.
*
Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapper.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapper.java?view=auto&rev=471435
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapper.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapper.java Sun Nov 5 06:22:54 2006
@@ -0,0 +1,254 @@
+/*
+ * $Id: ActionMapper.java 449367 2006-09-24 06:49:04Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.dispatcher.mapper;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.config.Settings;
+
+import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.config.ConfigurationManager;
+import com.opensymphony.xwork2.util.FileManager;
+
+/**
+ * A composite action mapper that is capable of delegating to a series of {@link ActionMapper} if the former
+ * failed to obtained a valid {@link ActionMapping} or uri.
+ * <p/>
+ * It is configured through struts.properties.
+ * <p/>
+ * For example, with the following entries in struts.properties
+ * <pre>
+ * struts.mapper.class=org.apache.struts2.dispatcher.mapper.CompositeActionMapper
+ * struts.mapper.composite.1=org.apache.struts2.dispatcher.mapper.DefaultActionMapper
+ * struts.mapper.composite.2=org.apache.struts2.dispatcher.mapper.RestfulActionMapper
+ * struts.mapper.composite.3=org.apache.struts2.dispatcher.mapper.Restful2ActionMapper
+ * </pre>
+ * When {@link CompositeActionMapper#getMapping(HttpServletRequest, ConfigurationManager)} or
+ * {@link CompositeActionMapper#getUriFromActionMapping(ActionMapping)} is invoked,
+ * {@link CompositeActionMapper} would go through these {@link ActionMapper}s in sequence
+ * starting from {@link ActionMapper} identified by 'struts.mapper.composite.1', followed by
+ * 'struts.mapper.composite.2' and finally 'struts.mapper.composite.3' (in this case) until either
+ * one of the {@link ActionMapper} return a valid result (not null) or it runs out of {@link ActionMapper}
+ * in which case it will just return null for both
+ * {@link CompositeActionMapper#getMapping(HttpServletRequest, ConfigurationManager)} and
+ * {@link CompositeActionMapper#getUriFromActionMapping(ActionMapping)} methods.
+ *
+ * <p/>
+ *
+ * @see ActionMapper
+ * @see ActionMapperFactory
+ * @see ActionMapping
+ * @see IndividualActionMapperEntry
+ *
+ * @version $Date$ $Id$
+ */
+public class CompositeActionMapper implements ActionMapper {
+
+ private static final Log LOG = LogFactory.getLog(CompositeActionMapper.class);
+
+ protected List<IndividualActionMapperEntry> orderedActionMappers;
+
+
+ public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
+
+ for (IndividualActionMapperEntry actionMapperEntry: getOrderedActionMapperEntries()) {
+ ActionMapping actionMapping = actionMapperEntry.actionMapper.getMapping(request, configManager);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Using ActionMapper from entry ["+actionMapperEntry.propertyName+"="+actionMapperEntry.propertyValue+"]");
+ }
+ if (actionMapping == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("ActionMapper from entry ["+actionMapperEntry.propertyName+"="+actionMapperEntry.propertyValue+"] failed to return an ActionMapping (null)");
+ }
+ }
+ else {
+ return actionMapping;
+ }
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("exhausted from ActionMapper that could return an ActionMapping");
+ }
+ return null;
+ }
+
+ public String getUriFromActionMapping(ActionMapping mapping) {
+
+ for (IndividualActionMapperEntry actionMapperEntry: getOrderedActionMapperEntries()) {
+ String uri = actionMapperEntry.actionMapper.getUriFromActionMapping(mapping);
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("Using ActionMapper from entry ["+actionMapperEntry.propertyName+"="+actionMapperEntry.propertyValue+"]");
+ }
+ if (uri == null) {
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("ActionMapper from entry ["+actionMapperEntry.propertyName+"="+actionMapperEntry.propertyValue+"] failed to return a uri (null)");
+ }
+ }
+ else {
+ return uri;
+ }
+ }
+ if (LOG.isDebugEnabled()) {
+ LOG.debug("exhausted from ActionMapper that could return a uri");
+ }
+ return null;
+ }
+
+
+ protected List<IndividualActionMapperEntry> getOrderedActionMapperEntries() {
+ if (this.orderedActionMappers == null || FileManager.isReloadingConfigs()) {
+
+ List<IndividualActionMapperEntry> actionMapperEntriesContainer = new ArrayList<IndividualActionMapperEntry>();
+ Iterator settings = Settings.list();
+ while(settings.hasNext()) {
+ String setting = settings.next().toString();
+ if (setting.startsWith(StrutsConstants.STRUTS_MAPPER_COMPOSITE)) {
+ try {
+ int order = Integer.valueOf(setting.substring(StrutsConstants.STRUTS_MAPPER_COMPOSITE.length(), setting.length()));
+ String propertyValue = Settings.get(setting);
+ if (propertyValue != null && propertyValue.trim().length() > 0) {
+ actionMapperEntriesContainer.add(
+ new IndividualActionMapperEntry(order, setting, propertyValue));
+ }
+ else {
+ LOG.warn("Ignoring property "+setting+" that contains no value");
+ }
+ }
+ catch(NumberFormatException e) {
+ LOG.warn("Ignoring malformed property "+setting);
+ }
+ }
+ }
+
+ Collections.sort(actionMapperEntriesContainer, new Comparator<IndividualActionMapperEntry>() {
+ public int compare(IndividualActionMapperEntry o1, IndividualActionMapperEntry o2) {
+ return o1.compareTo(o2);
+ }
+ });
+
+
+ ObjectFactory objectFactory = ObjectFactory.getObjectFactory();
+ List<IndividualActionMapperEntry> result = new ArrayList<IndividualActionMapperEntry>();
+ for (IndividualActionMapperEntry entry: actionMapperEntriesContainer) {
+ String actionMapperClassName = entry.propertyValue;
+ try {
+ // Let us get ClassCastException if it does not implement ActionMapper
+ ActionMapper actionMapper = (ActionMapper) objectFactory.buildBean(actionMapperClassName, null);
+ result.add(new IndividualActionMapperEntry(entry.order, entry.propertyName, entry.propertyValue, actionMapper));
+ }
+ catch(Exception e) {
+ LOG.warn("failed to create action mapper "+actionMapperClassName+", ignoring it", e);
+ }
+ }
+
+ this.orderedActionMappers = result;
+ }
+
+ return this.orderedActionMappers;
+ }
+
+
+ /**
+ * A value object (holder) that holds information regarding {@link ActionMapper} this {@link CompositeActionMapper}
+ * is capable of delegating to.
+ * <p/>
+ * The information stored are :-
+ * <ul>
+ * <li> order</li>
+ * <li> propertyValue</li>
+ * <li> propertyName</li>
+ * <li> actionMapper</li>
+ * </ul>
+ *
+ * eg. if we have the following entry in struts.properties
+ * <pre>
+ * struts.mapper.composite.1=foo.bar.ActionMapper1
+ * struts.mapper.composite.2=foo.bar.ActionMapper2
+ * struts.mapper.composite.3=foo.bar.ActionMapper3
+ * </pre>
+ *
+ * <table border="1">
+ * <tr>
+ * <td>order</td>
+ * <td>propertyName</td>
+ * <td>propertyValue</td>
+ * <td>actionMapper</td>
+ * </tr>
+ * <tr>
+ * <td>1</td>
+ * <td>struts.mapper.composite.1</td>
+ * <td>foo.bar.ActionMapper1</td>
+ * <td>instance of foo.bar.ActionMapper1</td>
+ * </tr>
+ * <tr>
+ * <td>2</td>
+ * <td>struts.mapper.composite.2</td>
+ * <td>foo.bar.ActionMapper2</td>
+ * <td>instance of foo.bar.ActionMapper2</td>
+ * </tr>
+ * <tr>
+ * <td>3</td>
+ * <td>struts.mapper.composite.3</td>
+ * <td>foo.bar.ActionMapper3</td>
+ * <td>instance of foo.bar.ActionMapper3</td>
+ * </tr>
+ * </table>
+ *
+ * @version $Date$ $Id$
+ */
+ public class IndividualActionMapperEntry implements Comparable<IndividualActionMapperEntry> {
+
+ public Integer order;
+ public String propertyValue;
+ public String propertyName;
+ public ActionMapper actionMapper;
+
+
+ private IndividualActionMapperEntry(Integer order, String propertyName, String propertyValue) {
+ assert(order != null);
+ assert(propertyValue != null);
+ assert(propertyName != null);
+ this.order = order;
+ this.propertyValue = propertyValue;
+ this.propertyName = propertyName;
+ }
+
+ public IndividualActionMapperEntry(Integer order, String propertyName, String propertyValue, ActionMapper actionMapper) {
+ assert(order != null);
+ assert(propertyValue != null);
+ assert(propertyName != null);
+ assert(actionMapper != null);
+ this.order = order;
+ this.propertyValue = propertyValue;
+ this.propertyName = propertyName;
+ this.actionMapper = actionMapper;
+ }
+
+ public int compareTo(IndividualActionMapperEntry o) {
+ return order - o.order;
+ }
+ }
+}
Modified: struts/struts2/trunk/core/src/main/resources/org/apache/struts2/default.properties
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/resources/org/apache/struts2/default.properties?view=diff&rev=471435&r1=471434&r2=471435
==============================================================================
--- struts/struts2/trunk/core/src/main/resources/org/apache/struts2/default.properties (original)
+++ struts/struts2/trunk/core/src/main/resources/org/apache/struts2/default.properties Sun Nov 5 06:22:54 2006
@@ -49,6 +49,15 @@
### How request URLs are mapped to and from actions
struts.mapper.class=org.apache.struts2.dispatcher.mapper.DefaultActionMapper
+### The above line is to be commented and following are to be uncommented to
+### enable CompositeActionMapper
+### - With CompositeActionMapper one could specified many ActionMapper instance, where
+### each of them will be chosen according to the order. Lower order number has
+### higher precedence
+#struts.mapper.class=org.apache.struts2.dispatcher.mapper.CompositeActionMapper
+#struts.mapper.composite.1=org.apache.struts2.dispatcher.mapper.DefaultActionMapper
+#struts.mapper.composite.2=foo.bar.MyActionMapper
+#struts.mapper.composite.3=foo.bar.MyAnotherActionMapper
### Used by the DefaultActionMapper
### You may provide a comma separated list, e.g. struts.action.extension=action,jnlp,do
Added: struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapperTest.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapperTest.java?view=auto&rev=471435
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapperTest.java (added)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/dispatcher/mapper/CompositeActionMapperTest.java Sun Nov 5 06:22:54 2006
@@ -0,0 +1,347 @@
+/*
+ * $Id: ActionMapper.java 449367 2006-09-24 06:49:04Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.dispatcher.mapper;
+
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletRequest;
+
+import org.apache.struts2.StrutsConstants;
+import org.apache.struts2.config.Settings;
+import org.apache.struts2.dispatcher.mapper.CompositeActionMapper.IndividualActionMapperEntry;
+import org.springframework.mock.web.MockHttpServletRequest;
+
+import com.opensymphony.xwork2.config.ConfigurationManager;
+
+import junit.framework.TestCase;
+
+/**
+ *
+ * @version $Date$ $Id$
+ */
+public class CompositeActionMapperTest extends TestCase {
+
+ /**
+ * Test with empty settings (settings with no entries of interest)
+ *
+ * @throws Exception
+ */
+ public void testGetOrderActionMapperEntries1() throws Exception {
+ CompositeActionMapper compositeActionMapper = new CompositeActionMapper();
+ List<IndividualActionMapperEntry> result =
+ compositeActionMapper.getOrderedActionMapperEntries();
+
+ assertEquals(result.size(), 0);
+ }
+
+ /**
+ * Test with a normal settings.
+ *
+ * @throws Exception
+ */
+ public void testGetOrderActionMapperEntries2() throws Exception {
+ CompositeActionMapper compositeActionMapper = new CompositeActionMapper();
+
+ Settings old = Settings.getInstance();
+ try {
+ Settings.setInstance(new InnerSettings());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"1", InnerActionMapper1.class.getName());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"2", InnerActionMapper2.class.getName());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"3", InnerActionMapper3.class.getName());
+
+ List<IndividualActionMapperEntry> result =
+ compositeActionMapper.getOrderedActionMapperEntries();
+
+ assertEquals(result.size(), 3);
+
+ IndividualActionMapperEntry e = null;
+ Iterator<IndividualActionMapperEntry> i = result.iterator();
+
+ // 1
+ e = i.next();
+
+ assertEquals(e.order, new Integer(1));
+ assertEquals(e.propertyName, StrutsConstants.STRUTS_MAPPER_COMPOSITE+"1");
+ assertEquals(e.propertyValue, InnerActionMapper1.class.getName());
+ assertEquals(e.actionMapper.getClass(), InnerActionMapper1.class);
+
+ // 2
+ e = i.next();
+
+ assertEquals(e.order, new Integer(2));
+ assertEquals(e.propertyName, StrutsConstants.STRUTS_MAPPER_COMPOSITE+"2");
+ assertEquals(e.propertyValue, InnerActionMapper2.class.getName());
+ assertEquals(e.actionMapper.getClass(), InnerActionMapper2.class);
+
+ // 3
+ e = i.next();
+ assertEquals(e.order, new Integer(3));
+ assertEquals(e.propertyName, StrutsConstants.STRUTS_MAPPER_COMPOSITE+"3");
+ assertEquals(e.propertyValue, InnerActionMapper3.class.getName());
+ assertEquals(e.actionMapper.getClass(), InnerActionMapper3.class);
+ }
+ finally {
+ Settings.setInstance(old);
+ }
+ }
+
+ /**
+ * Test with settings where entries are out-of-order, it needs to be able to retrieve them
+ * back in proper order.
+ *
+ * @throws Exception
+ */
+ public void testGetOrderActionMapperEntries3() throws Exception {
+ CompositeActionMapper compositeActionMapper = new CompositeActionMapper();
+
+ Settings old = Settings.getInstance();
+ try {
+ Settings.setInstance(new InnerSettings());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"3", InnerActionMapper3.class.getName());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"2", InnerActionMapper2.class.getName());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"1", InnerActionMapper1.class.getName());
+
+ List<IndividualActionMapperEntry> result =
+ compositeActionMapper.getOrderedActionMapperEntries();
+
+ assertEquals(result.size(), 3);
+
+ IndividualActionMapperEntry e = null;
+ Iterator<IndividualActionMapperEntry> i = result.iterator();
+
+ // 1
+ e = i.next();
+
+ assertEquals(e.order, new Integer(1));
+ assertEquals(e.propertyName, StrutsConstants.STRUTS_MAPPER_COMPOSITE+"1");
+ assertEquals(e.propertyValue, InnerActionMapper1.class.getName());
+ assertEquals(e.actionMapper.getClass(), InnerActionMapper1.class);
+
+ // 2
+ e = i.next();
+
+ assertEquals(e.order, new Integer(2));
+ assertEquals(e.propertyName, StrutsConstants.STRUTS_MAPPER_COMPOSITE+"2");
+ assertEquals(e.propertyValue, InnerActionMapper2.class.getName());
+ assertEquals(e.actionMapper.getClass(), InnerActionMapper2.class);
+
+ // 3
+ e = i.next();
+ assertEquals(e.order, new Integer(3));
+ assertEquals(e.propertyName, StrutsConstants.STRUTS_MAPPER_COMPOSITE+"3");
+ assertEquals(e.propertyValue, InnerActionMapper3.class.getName());
+ assertEquals(e.actionMapper.getClass(), InnerActionMapper3.class);
+ }
+ finally {
+ Settings.setInstance(old);
+ }
+ }
+
+ /**
+ * Test with a bad entry
+ *
+ * @throws Exception
+ */
+ public void testGetOrderActionMapperEntries4() throws Exception {
+ CompositeActionMapper compositeActionMapper = new CompositeActionMapper();
+
+ Settings old = Settings.getInstance();
+ try {
+ Settings.setInstance(new InnerSettings());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"1", InnerActionMapper1.class.getName());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"NotANumber", InnerActionMapper2.class.getName());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"3", InnerActionMapper3.class.getName());
+
+ List<IndividualActionMapperEntry> result =
+ compositeActionMapper.getOrderedActionMapperEntries();
+
+ assertEquals(result.size(), 2);
+
+ IndividualActionMapperEntry e = null;
+ Iterator<IndividualActionMapperEntry> i = result.iterator();
+
+ // 1
+ e = i.next();
+
+ assertEquals(e.order, new Integer(1));
+ assertEquals(e.propertyName, StrutsConstants.STRUTS_MAPPER_COMPOSITE+"1");
+ assertEquals(e.propertyValue, InnerActionMapper1.class.getName());
+ assertEquals(e.actionMapper.getClass(), InnerActionMapper1.class);
+
+ // 2
+ e = i.next();
+ assertEquals(e.order, new Integer(3));
+ assertEquals(e.propertyName, StrutsConstants.STRUTS_MAPPER_COMPOSITE+"3");
+ assertEquals(e.propertyValue, InnerActionMapper3.class.getName());
+ assertEquals(e.actionMapper.getClass(), InnerActionMapper3.class);
+ }
+ finally {
+ Settings.setInstance(old);
+ }
+ }
+
+ /**
+ * Test with an entry where the action mapper class is bogus.
+ * @throws Exception
+ */
+ public void testGetOrderActionMapperEntries5() throws Exception {
+ CompositeActionMapper compositeActionMapper = new CompositeActionMapper();
+
+ Settings old = Settings.getInstance();
+ try {
+ Settings.setInstance(new InnerSettings());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"1", InnerActionMapper1.class.getName());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"2", "bogus.class.name");
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"3", InnerActionMapper3.class.getName());
+
+ List<IndividualActionMapperEntry> result =
+ compositeActionMapper.getOrderedActionMapperEntries();
+
+ assertEquals(result.size(), 2);
+
+ IndividualActionMapperEntry e = null;
+ Iterator<IndividualActionMapperEntry> i = result.iterator();
+
+ // 1
+ e = i.next();
+
+ assertEquals(e.order, new Integer(1));
+ assertEquals(e.propertyName, StrutsConstants.STRUTS_MAPPER_COMPOSITE+"1");
+ assertEquals(e.propertyValue, InnerActionMapper1.class.getName());
+ assertEquals(e.actionMapper.getClass(), InnerActionMapper1.class);
+
+
+ // 2
+ e = i.next();
+ assertEquals(e.order, new Integer(3));
+ assertEquals(e.propertyName, StrutsConstants.STRUTS_MAPPER_COMPOSITE+"3");
+ assertEquals(e.propertyValue, InnerActionMapper3.class.getName());
+ assertEquals(e.actionMapper.getClass(), InnerActionMapper3.class);
+ }
+ finally {
+ Settings.setInstance(old);
+ }
+ }
+
+
+
+ public void testGetActionMappingAndUri1() throws Exception {
+ CompositeActionMapper compositeActionMapper = new CompositeActionMapper();
+
+ Settings old = Settings.getInstance();
+ try {
+ Settings.setInstance(new InnerSettings());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"1", InnerActionMapper1.class.getName());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"2", InnerActionMapper2.class.getName());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"3", InnerActionMapper3.class.getName());
+
+
+ ActionMapping actionMapping = compositeActionMapper.getMapping(new MockHttpServletRequest(), new ConfigurationManager());
+ String uri = compositeActionMapper.getUriFromActionMapping(new ActionMapping());
+
+ assertNotNull(actionMapping);
+ assertNotNull(uri);
+ assertTrue(actionMapping == InnerActionMapper3.actionMapping);
+ assertTrue(uri == InnerActionMapper3.uri);
+ }
+ finally {
+ Settings.setInstance(old);
+ }
+ }
+
+ public void testGetActionMappingAndUri2() throws Exception {
+ CompositeActionMapper compositeActionMapper = new CompositeActionMapper();
+
+ Settings old = Settings.getInstance();
+ try {
+ Settings.setInstance(new InnerSettings());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"1", InnerActionMapper1.class.getName());
+ Settings.set(StrutsConstants.STRUTS_MAPPER_COMPOSITE+"2", InnerActionMapper2.class.getName());
+
+
+ ActionMapping actionMapping = compositeActionMapper.getMapping(new MockHttpServletRequest(), new ConfigurationManager());
+ String uri = compositeActionMapper.getUriFromActionMapping(new ActionMapping());
+
+ assertNull(actionMapping);
+ assertNull(uri);
+ }
+ finally {
+ Settings.setInstance(old);
+ }
+ }
+
+
+ public static class InnerActionMapper1 implements ActionMapper {
+ public static ActionMapping actionMapping = new ActionMapping();
+ public static String uri="uri1";
+
+ public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
+ return null;
+ }
+ public String getUriFromActionMapping(ActionMapping mapping) {
+ return null;
+ }
+ }
+ public static class InnerActionMapper2 implements ActionMapper {
+ public static ActionMapping actionMapping = new ActionMapping();
+ public static String uri="uri2";
+
+ public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
+ return null;
+ }
+ public String getUriFromActionMapping(ActionMapping mapping) {
+ return null;
+ }
+ }
+ public static class InnerActionMapper3 implements ActionMapper {
+ public static ActionMapping actionMapping = new ActionMapping();
+ public static String uri = "uri3";
+
+ public ActionMapping getMapping(HttpServletRequest request, ConfigurationManager configManager) {
+ return actionMapping;
+ }
+ public String getUriFromActionMapping(ActionMapping mapping) {
+ return uri;
+ }
+ }
+
+ class InnerSettings extends Settings {
+ private Map<String, String> _impl = new LinkedHashMap<String, String>();
+
+ @Override
+ public boolean isSetImpl(String name) {
+ return _impl.containsKey(name);
+ }
+ @Override
+ public void setImpl(String name, String value) throws IllegalArgumentException, UnsupportedOperationException {
+ _impl.put(name, value);
+ }
+ @Override
+ public String getImpl(String name) throws IllegalArgumentException {
+ return (String) _impl.get(name);
+ }
+ @Override
+ public Iterator listImpl() {
+ return _impl.keySet().iterator();
+ }
+ }
+
+}