>From 1620930495120be94f0d06b0aca7a485ce592bce Mon Sep 17 00:00:00 2001
From: Christina Fu <cfu@redhat.com>
Date: Wed, 5 Mar 2014 15:59:04 -0800
Subject: [PATCH] trac ticket 862: TPS rewrite: provide connector service for
 JAVA-based TPS subsystem. -- review comments from edewata addressed

---
 .../certsrv/connector/IRemoteAuthority.java        |   8 ++
 .../netscape/cmscore/connector/HttpConnection.java | 129 +++++----------------
 .../cmscore/connector/RemoteAuthority.java         |  16 ++-
 .../server/tps/cms/ConnectionManager.java          |  80 ++++++-------
 4 files changed, 88 insertions(+), 145 deletions(-)

diff --git a/base/common/src/com/netscape/certsrv/connector/IRemoteAuthority.java b/base/common/src/com/netscape/certsrv/connector/IRemoteAuthority.java
index 286e388..1e66daa 100644
--- a/base/common/src/com/netscape/certsrv/connector/IRemoteAuthority.java
+++ b/base/common/src/com/netscape/certsrv/connector/IRemoteAuthority.java
@@ -68,4 +68,12 @@ public interface IRemoteAuthority {
      * @return In with remote Authority timeout value.
      */
     public int getTimeout();
+
+    /**
+     * Retrieves the Content-Type value of the connection to the Remote Authority.
+     *
+     * @return String with Content-Type, if it was set
+     * @return
+     */
+    public String getContentType();
 }
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java
index 1e694e1..9d4b433 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/HttpConnection.java
@@ -61,7 +61,7 @@ public class HttpConnection implements IHttpConnection {
     }
 
     public HttpConnection(IRemoteAuthority dest, ISocketFactory factory) {
-        this(dest, factory, "");
+        this(dest, factory, null);
     }
 
     /*
@@ -75,7 +75,7 @@ public class HttpConnection implements IHttpConnection {
             Debug.trace("Created HttpClient");
         try {
             mHttpreq.setMethod("POST");
-            if ((op == null) || (op.equals("")))
+            if (op == null)
                 mHttpreq.setURI(mDest.getURI());
             else
                 mHttpreq.setURI(mDest.getURI(op));
@@ -105,7 +105,7 @@ public class HttpConnection implements IHttpConnection {
 
     // Inserted by beomsuk
     public HttpConnection(IRemoteAuthority dest, ISocketFactory factory, int timeout) {
-        this(dest, factory, timeout, "");
+        this(dest, factory, timeout, null);
     }
 
     /*
@@ -118,11 +118,15 @@ public class HttpConnection implements IHttpConnection {
         CMS.debug("HttpConn:Created HttpConnection: factory " + factory + "client " + mHttpClient);
         try {
             mHttpreq.setMethod("POST");
-            if ((op == null) || (op.equals("")))
+            if (op == null)
                 mHttpreq.setURI(mDest.getURI());
             else {
                 mHttpreq.setURI(mDest.getURI(op));
-                mHttpreq.setHeader("Content-Type", "application/x-www-form-urlencoded" );
+                String contentType = dest.getContentType();
+                if ((contentType != null) && (!contentType.equals(""))) {
+                    CMS.debug("HttpConnection: setting Content-Type");
+                    mHttpreq.setHeader("Content-Type", contentType );
+                }
             }
 
             mHttpreq.setHeader("Connection", "Keep-Alive");
@@ -146,6 +150,7 @@ public class HttpConnection implements IHttpConnection {
     public IPKIMessage send(IPKIMessage tomsg)
             throws EBaseException {
         IPKIMessage replymsg = null;
+        HttpResponse resp = null;
 
         CMS.debug("in HttpConnection.send " + this);
         if (Debug.ON)
@@ -163,92 +168,11 @@ public class HttpConnection implements IHttpConnection {
             Debug.trace(content);
             Debug.trace("--------------------------");
         }
-        boolean reconnect = false;
-
-        mHttpreq.setHeader("Content-Length",
-                Integer.toString(content.length()));
-        if (Debug.ON)
-            Debug.trace("request encoded length " + content.length());
-        mHttpreq.setContent(content);
-
-        HttpResponse p = null;
-
-        try {
-            if (!mHttpClient.connected()) {
-                mHttpClient.connect(mDest.getHost(), mDest.getPort());
-                CMS.debug("HttpConn:reconnected to " + mDest.getHost() + ":" + mDest.getPort());
-                reconnect = true;
-            }
-        } catch (IOException e) {
-            if (e.getMessage().indexOf("Peer's certificate issuer has been marked as not trusted") != -1) {
-                throw new EBaseException(
-                        CMS.getUserMessage(
-                                "CMS_BASE_CONN_FAILED",
-                                "(This local authority cannot connect to the remote authority. The local authority's signing certificate must chain to a CA certificate trusted for client authentication in the certificate database. Use the certificate manager, or command line tool such as certutil to verify that the trust permissions of the local authority's issuer cert have 'CT' setting in the SSL client auth field.)"));
-            }
-            CMS.debug("HttpConn:Couldn't reconnect " + e);
-            throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "Couldn't reconnect " + e));
-        }
-
-        // if remote closed connection want to reconnect and resend.
-        while (p == null) {
-            try {
-                if (Debug.ON)
-                    Debug.trace("sending request");
-                p = mHttpClient.send(mHttpreq);
-            } catch (IOException e) {
-                CMS.debug("HttpConn: mHttpClient.send failed " + e.toString());
-                if (reconnect) {
-                    CMS.debug("HttpConn:resend failed again. " + e);
-                    throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "resend failed again. " + e));
-                }
-                try {
-                    CMS.debug("HttpConn: trying a reconnect ");
-                    mHttpClient.connect(mDest.getHost(), mDest.getPort());
-                } catch (IOException ex) {
-                    CMS.debug("reconnect for resend failed. " + ex);
-                    throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "reconnect for resend failed."
-                            + ex));
-                }
-                reconnect = true;
-            }
-        }
-
-        // got reply; check status
-        String statusStr = p.getStatusCode();
-
-        CMS.debug("HttpConn:server returned status " + statusStr);
-        int statuscode = -1;
-
-        try {
-            statuscode = Integer.parseInt(statusStr);
-        } catch (NumberFormatException e) {
-            statuscode = -1;
-        }
-
-        /* HttpServletResponse.SC_OK = 200 */
-        if (statuscode != 200) {
-
-            /* HttpServletResponse.SC_UNAUTHORIZED = 401 */
-            if (statuscode == 401) {
-                // XXX what to do here.
-                String msg = "request no good " + statuscode + " " + p.getReasonPhrase();
-
-                if (Debug.ON)
-                    Debug.trace(msg);
-                throw new EBaseException(CMS.getUserMessage("CMS_BASE_AUTHENTICATE_FAILED", msg));
-            } else {
-                // XXX what to do here.
-                String msg = "HttpConn:request no good " + statuscode + " " + p.getReasonPhrase();
-
-                CMS.debug(msg);
-                throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", msg));
-            }
-        }
+        resp = doSend(content);
 
         // decode reply.
         // if reply is bad, error is thrown and request will be resent
-        String pcontent = p.getContent();
+        String pcontent = resp.getContent();
 
         if (Debug.ON) {
             Debug.trace("Server returned\n");
@@ -256,6 +180,7 @@ public class HttpConnection implements IHttpConnection {
             Debug.trace(pcontent);
             Debug.trace("-------");
         }
+        CMS.debug("HttpConnection.send response: " + pcontent);
 
         try {
             replymsg = (IPKIMessage) mReqEncoder.decode(pcontent);
@@ -273,24 +198,31 @@ public class HttpConnection implements IHttpConnection {
      */
     public HttpResponse send(String content)
             throws EBaseException {
+        HttpResponse resp = null;
         if ((content == null) || content.equals("")) {
             CMS.debug("HttpConnection.send: with String content: null or empty");
-            // throw later
-            return null;
+            throw new EBaseException("HttpConnection.send: with String content: null or empty");
         }
         // CMS.debug("HttpConnection.send: with String content: " + content);
+
+        resp = doSend(content);
+        return resp;
+    }
+
+    private HttpResponse doSend(String content)
+            throws EBaseException {
+        HttpResponse resp = null;
         boolean reconnect = false;
 
         mHttpreq.setHeader("Content-Length",
                 Integer.toString(content.length()));
-        CMS.debug("HttpConnection.send: with String content length: " + Integer.toString(content.length()));
+        CMS.debug("HttpConnection.doSend: with String content length: " + Integer.toString(content.length()));
         mHttpreq.setContent(content);
 
-        HttpResponse resp = null;
         try {
             if (!mHttpClient.connected()) {
                 mHttpClient.connect(mDest.getHost(), mDest.getPort());
-                CMS.debug("HttpConnection.send: reconnected to " + mDest.getHost() + ":" + mDest.getPort());
+                CMS.debug("HttpConnection.doSend: reconnected to " + mDest.getHost() + ":" + mDest.getPort());
                 reconnect = true;
             }
         } catch (IOException e) {
@@ -307,19 +239,19 @@ public class HttpConnection implements IHttpConnection {
         // if remote closed connection want to reconnect and resend.
         while (resp == null) {
             try {
-                CMS.debug("HttpConnection.send: sending request");
+                CMS.debug("HttpConnection.doSend: sending request");
                 resp = mHttpClient.send(mHttpreq);
             } catch (IOException e) {
                 CMS.debug("HttpConn: mHttpClient.send failed " + e.toString());
                 if (reconnect) {
-                    CMS.debug("HttpConnection.send:resend failed again. " + e);
+                    CMS.debug("HttpConnection.doSend:resend failed again. " + e);
                     throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "resend failed again. " + e));
                 }
                 try {
-                    CMS.debug("HttpConnection.send: trying a reconnect ");
+                    CMS.debug("HttpConnection.doSend: trying a reconnect ");
                     mHttpClient.connect(mDest.getHost(), mDest.getPort());
                 } catch (IOException ex) {
-                    CMS.debug("HttpConnection.send: reconnect for resend failed. " + ex);
+                    CMS.debug("HttpConnection.doSend: reconnect for resend failed. " + ex);
                     throw new EBaseException(CMS.getUserMessage("CMS_BASE_CONN_FAILED", "reconnect for resend failed."
                             + ex));
                 }
@@ -330,7 +262,7 @@ public class HttpConnection implements IHttpConnection {
         // got reply; check status
         String statusStr = resp.getStatusCode();
 
-        CMS.debug("HttpConnection.send:server returned status " + statusStr);
+        CMS.debug("HttpConnection.doSend:server returned status " + statusStr);
         int statuscode = -1;
 
         try {
@@ -357,7 +289,6 @@ public class HttpConnection implements IHttpConnection {
                 throw new EBaseException(CMS.getUserMessage("CMS_BASE_INVALID_ATTRIBUTE", msg));
             }
         }
-
         return resp;
     }
 }
diff --git a/base/server/cmscore/src/com/netscape/cmscore/connector/RemoteAuthority.java b/base/server/cmscore/src/com/netscape/cmscore/connector/RemoteAuthority.java
index 52cbea4..078821f 100644
--- a/base/server/cmscore/src/com/netscape/cmscore/connector/RemoteAuthority.java
+++ b/base/server/cmscore/src/com/netscape/cmscore/connector/RemoteAuthority.java
@@ -18,6 +18,7 @@
 package com.netscape.cmscore.connector;
 
 import java.util.Hashtable;
+
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IConfigStore;
 import com.netscape.certsrv.connector.IRemoteAuthority;
@@ -27,6 +28,7 @@ public class RemoteAuthority implements IRemoteAuthority {
     int mPort = -1;
     String mURI = null;
     Hashtable<String, String> mURIs = new Hashtable<String, String>();
+    String mContentType = null;
     int mTimeout = 0;
 
     /**
@@ -49,6 +51,14 @@ public class RemoteAuthority implements IRemoteAuthority {
         mTimeout = timeout;
     }
 
+    public RemoteAuthority(String host, int port, Hashtable<String, String>uris, int timeout, String contentType) {
+        mHost = host;
+        mPort = port;
+        mURIs = uris;
+        mTimeout = timeout;
+        mContentType = contentType;
+    }
+
     public RemoteAuthority() {
     }
 
@@ -74,7 +84,7 @@ public class RemoteAuthority implements IRemoteAuthority {
     }
 
     public String getURI(String name) {
-        return (String) mURIs.get(name);
+        return mURIs.get(name);
     }
 
     public Hashtable<String, String> getURIs() {
@@ -84,4 +94,8 @@ public class RemoteAuthority implements IRemoteAuthority {
     public int getTimeout() {
         return mTimeout;
     }
+
+    public String getContentType() {
+        return mContentType;
+    }
 }
diff --git a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/ConnectionManager.java b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/ConnectionManager.java
index ac0f41e..a6d2762 100644
--- a/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/ConnectionManager.java
+++ b/base/tps-tomcat/src/org/dogtagpki/server/tps/cms/ConnectionManager.java
@@ -18,17 +18,19 @@
 
 package org.dogtagpki.server.tps.cms;
 
+import java.io.ByteArrayInputStream;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
 import org.dogtagpki.server.tps.TPSSubsystem;
-import com.netscape.cmscore.connector.HttpConnector;
-import com.netscape.cmscore.connector.RemoteAuthority;
+
+import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.base.EBaseException;
 import com.netscape.certsrv.base.IConfigStore;
-import com.netscape.certsrv.apps.CMS;
 import com.netscape.certsrv.connector.IConnector;
-import java.util.Enumeration;
-import java.util.Hashtable;
+import com.netscape.cmscore.connector.HttpConnector;
+import com.netscape.cmscore.connector.RemoteAuthority;
 import com.netscape.cmsutil.xml.XMLObject;
-import java.io.ByteArrayInputStream;
 
 /**
  * ConnectionManager is a class for connection management
@@ -37,6 +39,7 @@ import java.io.ByteArrayInputStream;
  */
 public class ConnectionManager
 {
+    public String HTTP_CONTENT_TYPE_APP_URLENCODED = "application/x-www-form-urlencoded";
     private Hashtable<String, IConnector> connectors;
 
     public ConnectionManager() {
@@ -66,7 +69,7 @@ public class ConnectionManager
      *   tps.connector.ca1.uri.unrevoke=/ca/ee/subsystem/ca/doUnrevoke
      */
     public void initConnectors() throws EBaseException {
-        CMS.debug("TPSSubsystem: initConnectors(): begins.");
+        CMS.debug("ConnectionManager: initConnectors(): begins.");
         TPSSubsystem subsystem =
             (TPSSubsystem)CMS.getSubsystem(TPSSubsystem.ID);
         IConfigStore conf = subsystem.getConfigStore();
@@ -75,33 +78,26 @@ public class ConnectionManager
         connectors = new Hashtable<String, IConnector>();
         while (connector_enu.hasMoreElements()) {
             String connectorID = connector_enu.nextElement();
-            CMS.debug("TPSSubsystem: initConnectors(): initializing connector "+connectorID);
+            CMS.debug("ConnectionManager: initConnectors(): initializing connector "+connectorID);
             IConfigStore connectorConfig =
                 connectorSubstore.getSubStore(connectorID);
             IConnector conn = null;
             boolean enable = connectorConfig.getBoolean("enable", true);
             if (!enable) {
-                CMS.debug("TPSSubsystem: initConnectors(): connector disabled.");
+                CMS.debug("ConnectionManager: initConnectors(): connector disabled.");
                 continue;
             }
-            CMS.debug("TPSSubsystem: initConnectors(): connector enabled.");
+            CMS.debug("ConnectionManager: initConnectors(): connector enabled.");
             conn = createConnector(connectorConfig);
 
-            if (conn!= null) {
-                connectors.put(connectorID, conn);
-                /* start is for resender only.  no Resender for TPS
+            connectors.put(connectorID, conn);
+            /* start is for resender only.  no Resender for TPS
                 conn.start();
-                */
-                CMS.debug("TPSSubsystem: initConnectors(): connector "+connectorID+
+             */
+            CMS.debug("ConnectionManager: initConnectors(): connector "+connectorID+
                     " initialized.");
-            } else {
-                CMS.debug("TPSSubsystem: initConnectors(): connector "+connectorID+
-                " not initialized.");
-                throw new EBaseException("Connector failed to be created.  Check configuration");
-            }
-
         }
-        CMS.debug("TPSSubsystem: initConnectors(): ends.");
+        CMS.debug("ConnectionManager: initConnectors(): ends.");
     }
 
     /*
@@ -114,15 +110,15 @@ public class ConnectionManager
             throws EBaseException {
         IConnector connector = null;
 
-        CMS.debug("TPSSubsystem: createConnector(): begins.");
+        CMS.debug("ConnectionManager: createConnector(): begins.");
         if (conf== null || conf.size() <= 0) {
-            CMS.debug("TPSSubsystem: createConnector(): conf null or empty.");
+            CMS.debug("ConnectionManager: createConnector(): conf null or empty.");
             throw new EBaseException("called with null config store");
         }
 
         String host = conf.getString("host");
         if (host == null) {
-            CMS.debug("TPSSubsystem: createConnector(): host not found in config.");
+            CMS.debug("ConnectionManager: createConnector(): host not found in config.");
             throw new EBaseException("host not found in config");
         }
         // port doesn't have to contain anything if failover supplied in host
@@ -131,22 +127,22 @@ public class ConnectionManager
         Hashtable<String, String> uris = new Hashtable<String, String>();
         IConfigStore uriSubstore = conf.getSubStore("uri");
         if (uriSubstore == null) {
-            CMS.debug("TPSSubsystem: createConnector(): uri(s) not found in config.");
+            CMS.debug("ConnectionManager: createConnector(): uri(s) not found in config.");
             throw new EBaseException("uri(s) not found in config");
         }
-        CMS.debug("TPSSubsystem: createConnector(): uriSubstore name="+uriSubstore.getName()+" size =" +uriSubstore.size());
+        CMS.debug("ConnectionManager: createConnector(): uriSubstore name="+uriSubstore.getName()+" size =" +uriSubstore.size());
 
         Enumeration<String> uri_enu = uriSubstore.getPropertyNames();
         while (uri_enu.hasMoreElements()) {
             String op = uri_enu.nextElement();
             if ((op != null) && !op.equals(""))
-                CMS.debug("TPSSubsystem: createConnector(): op name="+op);
+                CMS.debug("ConnectionManager: createConnector(): op name="+op);
             else
                 continue;
 
             String uriValue = uriSubstore.getString(op);
             if ((uriValue != null) && !uriValue.equals(""))
-                CMS.debug("TPSSubsystem: createConnector(): uri value="+uriValue);
+                CMS.debug("ConnectionManager: createConnector(): uri value="+uriValue);
             else
                 continue;
             uris.put(op, uriValue);
@@ -154,9 +150,9 @@ public class ConnectionManager
 
         String nickname = conf.getString("nickName", null);
         if (nickname != null)
-            CMS.debug("TPSSubsystem: createConnector(): nickName="+nickname);
+            CMS.debug("ConnectionManager: createConnector(): nickName="+nickname);
         else {
-            CMS.debug("TPSSubsystem: createConnector(): nickName not found in config");
+            CMS.debug("ConnectionManager: createConnector(): nickName not found in config");
             throw new EBaseException("nickName not found in config");
         }
 
@@ -164,9 +160,9 @@ public class ConnectionManager
         int resendInterval = -1;
         int timeout = conf.getInteger("timeout", 0);
         RemoteAuthority remauthority =
-            new RemoteAuthority(host, port, uris, timeout);
+            new RemoteAuthority(host, port, uris, timeout, HTTP_CONTENT_TYPE_APP_URLENCODED);
 
-        CMS.debug("TPSSubsystem: createConnector(): establishing HttpConnector");
+        CMS.debug("ConnectionManager: createConnector(): establishing HttpConnector");
         if (timeout == 0) {
             connector =
                 new HttpConnector(null, nickname, remauthority, resendInterval, conf);
@@ -175,7 +171,7 @@ public class ConnectionManager
                 new HttpConnector(null, nickname, remauthority, resendInterval, conf, timeout);
         }
 
-        CMS.debug("TPSSubsystem: createConnector(): ends.");
+        CMS.debug("ConnectionManager: createConnector(): ends.");
         return connector;
     }
 
@@ -213,26 +209,20 @@ public class ConnectionManager
      * @param text XML in text
      * @return XMLObject the parser
      */
-    public XMLObject getXMLparser(String text) {
-        XMLObject parser = null;
+    public XMLObject getXMLParser(String text) {
         if (text == null) {
             return null;
         } else {
-            CMS.debug("TPSSubsystem: getXMLparser(): parsing: "+ text);
+            CMS.debug("ConnectionManager: getXMLparser(): parsing: "+ text);
         }
         try {
             ByteArrayInputStream bis =
                 new ByteArrayInputStream(text.getBytes());
-            try {
-                parser = new XMLObject(bis);
-            } catch (Exception e) {
-                CMS.debug("TPSSubsystem: getXMLparser(): new XMLObject failed: "+ e.toString());
-            }
+            return new XMLObject(bis);
         } catch (Exception e) {
-            CMS.debug("TPSSubsystem: getXMLparser(): failed: "+ e.toString());
+            CMS.debug("ConnectionManager: getXMLparser(): failed: "+ e);
+            throw new RuntimeException(e);
         }
-
-        return parser;
     }
 
 }
-- 
1.8.4.2

