portals-portalapps-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From woon...@apache.org
Subject svn commit: r1631349 - in /portals/applications/webcontent/trunk: portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/ portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/ reverse-proxy/src/main/java/...
Date Mon, 13 Oct 2014 11:32:32 GMT
Author: woonsan
Date: Mon Oct 13 11:32:31 2014
New Revision: 1631349

URL: http://svn.apache.org/r1631349
Log:
More extensibility in dealing with proxy commands in a chain and http client/context creation
for more advanced use cases such as sso proxy portlets (see JS2-1305, etc.)

Added:
    portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/ProxyProcessingChainIndexingAdditionRemovalTest.java
Modified:
    portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/WebContentPortlet.java
    portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/SimpleReverseProxyPortlet.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/command/InitHttpRequestCommand.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/filter/SimpleReverseProxyFilter.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/ProxyProcessingChain.java
    portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/servlet/SimpleReverseProxyServlet.java

Modified: portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/WebContentPortlet.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/WebContentPortlet.java?rev=1631349&r1=1631348&r2=1631349&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/WebContentPortlet.java
(original)
+++ portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/WebContentPortlet.java
Mon Oct 13 11:32:31 2014
@@ -61,6 +61,7 @@ import org.apache.http.client.methods.Cl
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpPost;
 import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.protocol.HttpClientContext;
 import org.apache.http.client.utils.URIBuilder;
 import org.apache.http.cookie.Cookie;
 import org.apache.http.entity.ContentType;
@@ -380,7 +381,7 @@ public class WebContentPortlet extends G
                 httpRequest = createHttpRequest(httpClient, methodName, sourceAttr, sourceParams,
null, request);
             }
 
-            byte[] result = doPreemptiveAuthentication(httpClient, httpRequest, request,
response);
+            byte[] result = doPreemptiveAuthentication(httpClient, cookieStore, httpRequest,
request, response);
 
             // ...get, cache, and return the content
             if (result == null) 
@@ -434,8 +435,16 @@ public class WebContentPortlet extends G
 
         try
         {
-            // ...set up URL and HttpClient stuff
-            httpResponse = httpClient.execute(httpRequest);
+            HttpClientContext httpClientContext = getHttpClientContext(request, httpRequest);
+
+            if (httpClientContext == null)
+            {
+                httpResponse = httpClient.execute(httpRequest);
+            }
+            else
+            {
+                httpResponse = httpClient.execute(httpRequest, httpClientContext);
+            }
 
             // ...reset base URL with fully resolved path (e.g. if a directory, path will
end with a /, which it may not have in the call to this method)
             rewriter.setBaseUrl( rewriter.getBaseRelativeUrl( httpRequest.getURI().getPath()
)) ;
@@ -474,7 +483,7 @@ public class WebContentPortlet extends G
             {
                 if ( responseCode == 401 )
                 {
-                    if (retryCount++ < 1 && doRequestedAuthentication( httpClient,
httpRequest, request, response))
+                    if (retryCount++ < 1 && doRequestedAuthentication(httpClient,
cookieStore, httpRequest, request, response))
                     {
                         // try again, now that we are authorizied
                         return doHttpWebContent(httpClient, cookieStore, httpRequest, retryCount,
request, response, rewriter);
@@ -562,13 +571,13 @@ public class WebContentPortlet extends G
         }
     }
 
-    protected byte[] doPreemptiveAuthentication(CloseableHttpClient clent, HttpRequestBase
httpRequest, RenderRequest request, RenderResponse response)
+    protected byte[] doPreemptiveAuthentication(CloseableHttpClient client, CookieStore cookieStore,
HttpRequestBase httpRequest, RenderRequest request, RenderResponse response)
     {
         // derived class responsibilty - return true, if credentials have been set
         return null ;
     }
-    
-    protected boolean doRequestedAuthentication(CloseableHttpClient clent, HttpRequestBase
httpRequest, RenderRequest request, RenderResponse response)
+
+    protected boolean doRequestedAuthentication(CloseableHttpClient client, CookieStore cookieStore,
HttpRequestBase httpRequest, RenderRequest request, RenderResponse response)
     {
         // derived class responsibilty - return true, if credentials have been set
         return false ;
@@ -594,10 +603,7 @@ public class WebContentPortlet extends G
         return rewriter;
     }
 
-    protected CloseableHttpClient getHttpClient(RenderRequest request, CookieStore cookieStore)
throws IOException
-    {
-        // derived class hook (e.g. to set up Basic Authentication)
-
+    protected HttpClientBuilder getHttpClientBuilder(PortletRequest request, CookieStore
cookieStore) {
         HttpClientBuilder builder = 
                         HttpClients.custom()
                         .setRedirectStrategy(new LaxRedirectStrategy());
@@ -633,9 +639,26 @@ public class WebContentPortlet extends G
             builder.setDefaultCookieStore(cookieStore);
         }
 
+        return builder;
+    }
+
+    protected CloseableHttpClient getHttpClient(RenderRequest request, CookieStore cookieStore)
throws IOException
+    {
+        HttpClientBuilder builder = getHttpClientBuilder(request, cookieStore);
         return builder.build();
     }
 
+    /**
+     * Override this method to give a custom <code>HttpClientContext</code>
+     * when executing <code>HttpClient</code>.
+     * @param request
+     * @return
+     */
+    protected HttpClientContext getHttpClientContext(PortletRequest request, HttpRequestBase
httpRequest)
+    {
+        return null;
+    }
+
     protected HttpRequestBase createHttpRequest(CloseableHttpClient client, String method,
String uri, Map<String, String []> queryParams, Map<String, String []> formPostParams,
RenderRequest request) throws IOException, URISyntaxException
     {
         // formMethod = FORM_MULTIPART_METHOD;

Modified: portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/SimpleReverseProxyPortlet.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/SimpleReverseProxyPortlet.java?rev=1631349&r1=1631348&r2=1631349&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/SimpleReverseProxyPortlet.java
(original)
+++ portals/applications/webcontent/trunk/portlets/src/main/java/org/apache/portals/applications/webcontent2/portlet/proxy/SimpleReverseProxyPortlet.java
Mon Oct 13 11:32:31 2014
@@ -63,7 +63,7 @@ public class SimpleReverseProxyPortlet e
     {
         super.init(portletConfig);
 
-        proxyServiceCommand = ProxyServices.createDefault().build(getProxyMappingRegistry(),
getHttpClientBuilder(), getHttpClientContextBuilder());
+        proxyServiceCommand = createProxyServiceCommand();
         ProxyCommandUtils.initializeAllCommands(proxyServiceCommand);
 
         DefaultReverseProxyService proxyService = new DefaultReverseProxyService(proxyServiceCommand);
@@ -118,6 +118,10 @@ public class SimpleReverseProxyPortlet e
         super.destroy();
     }
 
+    protected ProxyProcessingChain createProxyServiceCommand() {
+        return ProxyServices.createDefault().build(getProxyMappingRegistry(), getHttpClientBuilder(),
getHttpClientContextBuilder());
+    }
+
     protected ProxyMapping getProxyMapping()
     {
         PortletAnyProxyMapping portletAnyProxyMapping = new PortletAnyProxyMapping(getPortletConfig());

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/command/InitHttpRequestCommand.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/command/InitHttpRequestCommand.java?rev=1631349&r1=1631348&r2=1631349&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/command/InitHttpRequestCommand.java
(original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/command/InitHttpRequestCommand.java
Mon Oct 13 11:32:31 2014
@@ -44,6 +44,13 @@ public class InitHttpRequestCommand exte
     @Override
     protected boolean executeInternal(final ProxyContext context) throws ReverseProxyException,
IOException
     {
+        HttpRequestBase httpRequest = createHttpRequest(context);
+        context.setHttpRequest(httpRequest);
+        return false;
+    }
+
+    protected HttpRequestBase createHttpRequest(final ProxyContext context) throws ReverseProxyException,
IOException
+    {
         HttpRequestBase httpRequest = null;
 
         String method = context.getRequestContext().getMethod();
@@ -97,9 +104,6 @@ public class InitHttpRequestCommand exte
             throw new ReverseProxyException(HttpServletResponse.SC_METHOD_NOT_ALLOWED, "Unsupported
method: " + method);
         }
 
-        context.setHttpRequest(httpRequest);
-
-        return false;
+        return httpRequest;
     }
-
 }

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/filter/SimpleReverseProxyFilter.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/filter/SimpleReverseProxyFilter.java?rev=1631349&r1=1631348&r2=1631349&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/filter/SimpleReverseProxyFilter.java
(original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/filter/SimpleReverseProxyFilter.java
Mon Oct 13 11:32:31 2014
@@ -50,7 +50,7 @@ public class SimpleReverseProxyFilter ex
     {
         super.init(filterConfig);
 
-        proxyServiceCommand = ProxyServices.createDefault().build(getProxyMappingRegistry(),
getHttpClientBuilder(), getHttpClientContextBuilder());
+        proxyServiceCommand = createProxyServiceCommand();
         ProxyCommandUtils.initializeAllCommands(proxyServiceCommand);
 
         DefaultReverseProxyService proxyService = new DefaultReverseProxyService(proxyServiceCommand);
@@ -106,4 +106,8 @@ public class SimpleReverseProxyFilter ex
         ProxyCommandUtils.destroyAllCommands(proxyServiceCommand);
         super.destroy();
     }
+
+    protected ProxyProcessingChain createProxyServiceCommand() {
+        return ProxyServices.createDefault().build(getProxyMappingRegistry(), getHttpClientBuilder(),
getHttpClientContextBuilder());
+    }
 }

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/ProxyProcessingChain.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/ProxyProcessingChain.java?rev=1631349&r1=1631348&r2=1631349&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/ProxyProcessingChain.java
(original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/impl/ProxyProcessingChain.java
Mon Oct 13 11:32:31 2014
@@ -21,11 +21,16 @@ import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 
+import org.apache.commons.chain.Chain;
 import org.apache.commons.chain.Command;
 import org.apache.commons.chain.Context;
 import org.apache.commons.chain.impl.ChainBase;
+import org.apache.commons.lang.ArrayUtils;
 import org.apache.portals.applications.webcontent2.proxy.ReverseProxyException;
 
+/**
+ * <p>Convenience base class for reverse proxy processing {@link Chain} implementation.</p>
+ */
 public class ProxyProcessingChain extends ChainBase
 {
 
@@ -49,6 +54,150 @@ public class ProxyProcessingChain extend
         super(commands);
     }
 
+    /**
+     * Return the size of command list.
+     * @return
+     */
+    public int getCommandCount() {
+        return commands.length;
+    }
+
+    /**
+     * Return the index of the given <code>command</code> in the command list.
+     * If not found, return -1.
+     * @param command
+     * @return
+     */
+    public int getCommandIndex(Command command) {
+        return ArrayUtils.indexOf(commands, command);
+    }
+
+    public int getCommandIndex(Class<? extends Command> commandType) {
+        if (commands == null) {
+            return -1;
+        }
+
+        if (commandType == null) {
+            return -1;
+        }
+
+        for (int i = 0; i < commands.length; i++) {
+            if (commands[i] != null && commandType.isAssignableFrom(commands[i].getClass()))
{
+                return i;
+            }
+        }
+
+        return -1;
+    }
+
+    /**
+     * Find and return the command at the given <code>index</code> of the command
list.
+     * @param index
+     * @return
+     */
+    public Command getCommand(int index) {
+        if (index < 0 || index > commands.length) {
+            throw new IllegalArgumentException();
+        }
+
+        return commands[index];
+    }
+
+    /**
+     * <p>Add a {@link Command} at the given <code>index</code> of the
list of 
+     * {@link Command}s that will be called in turn when this {@link Chain}'s 
+     * <code>execute()</code> method is called.
+     * Once <code>execute()</code> has been called
+     * at least once, it is no longer possible to add additional
+     * {@link Command}s; instead, an exception will be thrown.</p>
+
+     * @param index The index at which the command should be inserted
+     * @param command The {@link Command} to be added
+     * @exception IllegalArgumentException if <code>command</code>
+     *  is <code>null</code>, or 
+     *  <code>index</code> is negative or greater than the size of the command
list.
+     * @exception IllegalStateException if this {@link Chain} has already
+     *  been executed at least once, so no further configuration is allowed
+     */
+    public void addCommand(int index, Command command) {
+        if (index < 0 || index > commands.length) {
+            throw new IllegalArgumentException();
+        }
+
+        if (command == null) {
+            throw new IllegalArgumentException();
+        }
+
+        if (frozen) {
+            throw new IllegalStateException();
+        }
+
+        Command[] results = new Command[commands.length + 1];
+        System.arraycopy(commands, 0, results, 0, index);
+        System.arraycopy(commands, index, results, index + 1, commands.length - index);
+        results[index] = command;
+        commands = results;
+    }
+
+    /**
+     * <p>Remove the {@link Command} at the given <code>index</code> of
the list of 
+     * {@link Command}s that will be called in turn when this {@link Chain}'s 
+     * <code>execute()</code> method is called.
+     * Once <code>execute()</code> has been called
+     * at least once, it is no longer possible to add additional
+     * {@link Command}s; instead, an exception will be thrown.</p>
+
+     * @param index The index to add in the command list
+     * @return true if successfully removed.
+     * @exception IllegalArgumentException if <code>index</code> is out of bound.
+     * @exception IllegalStateException if this {@link Chain} has already
+     *  been executed at least once, so no further configuration is allowed
+     */
+    public boolean removeCommand(int index) {
+        if (index < 0 || index > commands.length) {
+            throw new IllegalArgumentException();
+        }
+
+        if (frozen) {
+            throw new IllegalStateException();
+        }
+
+        Command[] results = new Command[commands.length - 1];
+        System.arraycopy(commands, 0, results, 0, index);
+        System.arraycopy(commands, index + 1, results, index, commands.length - index - 1);
+        commands = results;
+
+        return true;
+    }
+
+    /**
+     * <p>Remove the {@link Command} from the list of 
+     * {@link Command}s that will be called in turn when this {@link Chain}'s 
+     * <code>execute()</code> method is called.
+     * Once <code>execute()</code> has been called
+     * at least once, it is no longer possible to add additional
+     * {@link Command}s; instead, an exception will be thrown.</p>
+
+     * @param command The {@link Command} to be added
+     * @return true if successfully removed.
+     * @exception IllegalArgumentException if <code>index</code> is out of bound.
+     * @exception IllegalStateException if this {@link Chain} has already
+     *  been executed at least once, so no further configuration is allowed
+     */
+    public boolean removeCommand(Command command) {
+        if (command == null) {
+            throw new IllegalArgumentException();
+        }
+
+        int index = getCommandIndex(command);
+
+        if (index != -1) {
+            return removeCommand(index);
+        }
+
+        return false;
+    }
+
     @Override
     public boolean execute(Context context) throws ReverseProxyException, IOException
     {
@@ -64,6 +213,11 @@ public class ProxyProcessingChain extend
         return false;
     }
 
+    /**
+     * Return a list including all the descendant commands, type of which is <code>AbstractProxyCommand</code>
+     * in this proxy processing chain.
+     * @return
+     */
     public List<AbstractProxyCommand> getAllProxyCommands()
     {
         List<AbstractProxyCommand> allCommands = new LinkedList<AbstractProxyCommand>();

Modified: portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/servlet/SimpleReverseProxyServlet.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/servlet/SimpleReverseProxyServlet.java?rev=1631349&r1=1631348&r2=1631349&view=diff
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/servlet/SimpleReverseProxyServlet.java
(original)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/main/java/org/apache/portals/applications/webcontent2/proxy/servlet/SimpleReverseProxyServlet.java
Mon Oct 13 11:32:31 2014
@@ -55,7 +55,7 @@ public class SimpleReverseProxyServlet e
     {
         super.init(servletConfig);
 
-        proxyServiceCommand = ProxyServices.createDefault().build(getProxyMappingRegistry(),
getHttpClientBuilder(), getHttpClientContextBuilder());
+        proxyServiceCommand = createProxyServiceCommand();
         ProxyCommandUtils.initializeAllCommands(proxyServiceCommand);
 
         DefaultReverseProxyService proxyService = new DefaultReverseProxyService(proxyServiceCommand);
@@ -111,4 +111,8 @@ public class SimpleReverseProxyServlet e
         ProxyCommandUtils.destroyAllCommands(proxyServiceCommand);
         super.destroy();
     }
+
+    protected ProxyProcessingChain createProxyServiceCommand() {
+        return ProxyServices.createDefault().build(getProxyMappingRegistry(), getHttpClientBuilder(),
getHttpClientContextBuilder());
+    }
 }

Added: portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/ProxyProcessingChainIndexingAdditionRemovalTest.java
URL: http://svn.apache.org/viewvc/portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/ProxyProcessingChainIndexingAdditionRemovalTest.java?rev=1631349&view=auto
==============================================================================
--- portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/ProxyProcessingChainIndexingAdditionRemovalTest.java
(added)
+++ portals/applications/webcontent/trunk/reverse-proxy/src/test/java/org/apache/portals/applications/webcontent2/proxy/impl/ProxyProcessingChainIndexingAdditionRemovalTest.java
Mon Oct 13 11:32:31 2014
@@ -0,0 +1,99 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.portals.applications.webcontent2.proxy.impl;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertSame;
+
+import org.apache.commons.chain.Command;
+import org.apache.portals.applications.webcontent2.proxy.command.CleanupCommand;
+import org.apache.portals.applications.webcontent2.proxy.command.ExecuteHttpClientCommand;
+import org.apache.portals.applications.webcontent2.proxy.command.InitializationCommand;
+import org.apache.portals.applications.webcontent2.proxy.command.SerializeHttpEntityContentCommand;
+import org.junit.Test;
+
+public class ProxyProcessingChainIndexingAdditionRemovalTest
+{
+
+    @Test
+    public void testCommandIndexing() throws Exception {
+        Command [] commands =  new Command [] {
+            new InitializationCommand(), 
+            new ExecuteHttpClientCommand(), 
+            new CleanupCommand()
+        };
+
+        ProxyProcessingChain chain = new ProxyProcessingChain();
+
+        for (Command command : commands) {
+            chain.addCommand(command);
+        }
+
+        assertEquals(3, chain.getCommandCount());
+
+        for (int i = 0; i < chain.getCommandCount(); i++) {
+            assertSame(commands[i], chain.getCommand(i));
+            assertSame(i, chain.getCommandIndex(commands[i]));
+        }
+
+        assertEquals(0, chain.getCommandIndex(Command.class));
+        assertEquals(0, chain.getCommandIndex(InitializationCommand.class));
+        assertEquals(1, chain.getCommandIndex(ExecuteHttpClientCommand.class));
+        assertEquals(2, chain.getCommandIndex(CleanupCommand.class));
+        assertEquals(-1, chain.getCommandIndex(SerializeHttpEntityContentCommand.class));
+    }
+
+    @Test
+    public void testCommandAdditionRemoval() throws Exception {
+        ProxyProcessingChain chain = new ProxyProcessingChain();
+
+        assertEquals(0, chain.getCommandCount());
+
+        Command serializeHttpEntityContentCommand = new SerializeHttpEntityContentCommand();
+        chain.addCommand(serializeHttpEntityContentCommand);
+        assertEquals(1, chain.getCommandCount());
+        assertSame(serializeHttpEntityContentCommand, chain.getCommand(0));
+        assertSame(0, chain.getCommandIndex(serializeHttpEntityContentCommand));
+
+        Command initializationCommand = new InitializationCommand();
+        chain.addCommand(0, initializationCommand);
+        assertEquals(2, chain.getCommandCount());
+        assertSame(initializationCommand, chain.getCommand(0));
+        assertSame(0, chain.getCommandIndex(initializationCommand));
+
+        Command executeHttpClientCommand = new ExecuteHttpClientCommand();
+        chain.addCommand(chain.getCommandIndex(serializeHttpEntityContentCommand), executeHttpClientCommand);
+        assertEquals(3, chain.getCommandCount());
+        assertSame(executeHttpClientCommand, chain.getCommand(1));
+        assertSame(1, chain.getCommandIndex(executeHttpClientCommand));
+
+        Command cleanupCommand = new CleanupCommand();
+        chain.addCommand(chain.getCommandCount(), cleanupCommand);
+        assertEquals(4, chain.getCommandCount());
+        assertSame(cleanupCommand, chain.getCommand(3));
+        assertSame(3, chain.getCommandIndex(cleanupCommand));
+
+        assertSame(initializationCommand, chain.getCommand(0));
+        assertSame(0, chain.getCommandIndex(initializationCommand));
+        assertSame(executeHttpClientCommand, chain.getCommand(1));
+        assertSame(1, chain.getCommandIndex(executeHttpClientCommand));
+        assertSame(serializeHttpEntityContentCommand, chain.getCommand(2));
+        assertSame(2, chain.getCommandIndex(serializeHttpEntityContentCommand));
+        assertSame(cleanupCommand, chain.getCommand(3));
+        assertSame(3, chain.getCommandIndex(cleanupCommand));
+    }
+}



Mime
View raw message