Author: kwright
Date: Mon Sep 10 23:21:53 2012
New Revision: 1383150
URL: http://svn.apache.org/viewvc?rev=1383150&view=rev
Log:
Revamp login sequence to complete and parse each request before firing off the
next one.
Modified:
manifoldcf/branches/CONNECTORS-518/connectors/wiki/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/wiki/WikiConnector.java
Modified:
manifoldcf/branches/CONNECTORS-518/connectors/wiki/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/wiki/WikiConnector.java
URL:
http://svn.apache.org/viewvc/manifoldcf/branches/CONNECTORS-518/connectors/wiki/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/wiki/WikiConnector.java?rev=1383150&r1=1383149&r2=1383150&view=diff
==============================================================================
---
manifoldcf/branches/CONNECTORS-518/connectors/wiki/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/wiki/WikiConnector.java
(original)
+++
manifoldcf/branches/CONNECTORS-518/connectors/wiki/connector/src/main/java/org/apache/manifoldcf/crawler/connectors/wiki/WikiConnector.java
Mon Sep 10 23:21:53 2012
@@ -137,7 +137,7 @@ public class WikiConnector extends org.a
// Set up connection manager
connectionManager = new MultiThreadedHttpConnectionManager();
- connectionManager.getParams().setMaxTotalConnections(20);
+ connectionManager.getParams().setMaxTotalConnections(1);
httpClient = new HttpClient(connectionManager);
@@ -155,24 +155,26 @@ public class WikiConnector extends org.a
protected void loginToAPI()
throws ManifoldCFException, ServiceInterruption
{
+ // Grab the httpclient, and use the same one throughout.
HttpClient client = getInitializedClient();
+
+ // First step in login process: get the token
+ Map<String, String> loginParams = new HashMap<String, String>();
+
+ String token = null;
+
String loginURL = baseURL + "action=login";
- HashMap<String, String> loginParams = new HashMap<String, String>();
loginParams.put("action", "login");
loginParams.put("lgname", serverLogin);
loginParams.put("lgpassword", serverPass);
if (serverDomain != null && !"".equals(serverDomain)) {
loginParams.put("lgdomain", serverDomain);
}
- PostMethod method = new PostMethod(loginURL);
- for (String key : loginParams.keySet()) {
- method.setParameter(key, loginParams.get(key));
- }
- method.getParams().setParameter("http.socket.timeout", new
Integer(300000));
+
+ HttpMethodBase method = getInitializedPostMethod(loginURL,loginParams);
try {
- APILoginResult result = new APILoginResult();
- ExecuteAPILoginThread t = new ExecuteAPILoginThread(client, method,
loginURL, loginParams, result);
+ ExecuteAPILoginThread t = new ExecuteAPILoginThread(client, method);
try {
t.start();
t.join();
@@ -208,9 +210,90 @@ public class WikiConnector extends org.a
// We need the caller to abandon any connections left around, so
rethrow in a way that forces them to process the event properly.
throw e;
}
- if (!result.result) {
- throw new ManifoldCFException("WIKI API login error: " +
result.reason, null, ManifoldCFException.REPOSITORY_CONNECTION_ERROR);
+
+ // Grab the token from the first call
+ token = t.getToken();
+
+ } catch (InterruptedException e) {
+ // Drop the connection on the floor
+ method = null;
+ throw new ManifoldCFException("Interrupted: " + e.getMessage(), e,
ManifoldCFException.INTERRUPTED);
+ } catch (ManifoldCFException e) {
+ if (e.getErrorCode() == ManifoldCFException.INTERRUPTED) // Drop the
connection on the floor
+ {
+ method = null;
}
+ throw e;
+ } catch (java.net.SocketTimeoutException e) {
+ long currentTime = System.currentTimeMillis();
+ throw new ServiceInterruption("Login timed out reading from the Wiki
server: " + e.getMessage(), e, currentTime + 300000L, currentTime + 12L *
60000L, -1, false);
+ } catch (java.net.SocketException e) {
+ long currentTime = System.currentTimeMillis();
+ throw new ServiceInterruption("Login received a socket error reading
from Wiki server: " + e.getMessage(), e, currentTime + 300000L, currentTime +
12L * 60000L, -1, false);
+ } catch (org.apache.commons.httpclient.ConnectTimeoutException e) {
+ long currentTime = System.currentTimeMillis();
+ throw new ServiceInterruption("Login connection timed out reading from
Wiki server: " + e.getMessage(), e, currentTime + 300000L, currentTime + 12L *
60000L, -1, false);
+ } catch (InterruptedIOException e) {
+ method = null;
+ throw new ManifoldCFException("Interrupted: " + e.getMessage(), e,
ManifoldCFException.INTERRUPTED);
+ } catch (IOException e) {
+ throw new ManifoldCFException("Login had an IO failure: " +
e.getMessage(), e);
+ } finally {
+ if (method != null) {
+ method.releaseConnection();
+ }
+ }
+
+ if (token == null) {
+ throw new ManifoldCFException("WIKI API login returned a null token!");
+ }
+
+ // First request is finished. Fire off the second one.
+
+ APILoginResult result = new APILoginResult();
+
+ loginParams.put("lgtoken", token);
+
+ method = getInitializedPostMethod(loginURL,loginParams);
+ try {
+ ExecuteTokenAPILoginThread t = new ExecuteTokenAPILoginThread(client,
method, result);
+ try {
+ t.start();
+ t.join();
+
+ Throwable thr = t.getException();
+ if (thr != null) {
+ if (thr instanceof ManifoldCFException) {
+ if (((ManifoldCFException) thr).getErrorCode() ==
ManifoldCFException.INTERRUPTED) {
+ throw new InterruptedException(thr.getMessage());
+ }
+ throw (ManifoldCFException) thr;
+ } else if (thr instanceof ServiceInterruption) {
+ throw (ServiceInterruption) thr;
+ } else if (thr instanceof IOException) {
+ throw (IOException) thr;
+ } else if (thr instanceof RuntimeException) {
+ throw (RuntimeException) thr;
+ } else {
+ throw (Error) thr;
+ }
+ }
+ } catch (ManifoldCFException e) {
+ t.interrupt();
+ throw e;
+ } catch (ServiceInterruption e) {
+ t.interrupt();
+ throw e;
+ } catch (IOException e) {
+ t.interrupt();
+ throw e;
+ } catch (InterruptedException e) {
+ t.interrupt();
+ // We need the caller to abandon any connections left around, so
rethrow in a way that forces them to process the event properly.
+ throw e;
+ }
+
+ // Fall through
} catch (InterruptedException e) {
// Drop the connection on the floor
method = null;
@@ -223,23 +306,158 @@ public class WikiConnector extends org.a
throw e;
} catch (java.net.SocketTimeoutException e) {
long currentTime = System.currentTimeMillis();
- throw new ServiceInterruption("Get namespaces timed out reading from the
Wiki server: " + e.getMessage(), e, currentTime + 300000L, currentTime + 12L *
60000L, -1, false);
+ throw new ServiceInterruption("Login timed out reading from the Wiki
server: " + e.getMessage(), e, currentTime + 300000L, currentTime + 12L *
60000L, -1, false);
} catch (java.net.SocketException e) {
long currentTime = System.currentTimeMillis();
- throw new ServiceInterruption("Get namespaces received a socket error
reading from Wiki server: " + e.getMessage(), e, currentTime + 300000L,
currentTime + 12L * 60000L, -1, false);
+ throw new ServiceInterruption("Login received a socket error reading
from Wiki server: " + e.getMessage(), e, currentTime + 300000L, currentTime +
12L * 60000L, -1, false);
} catch (org.apache.commons.httpclient.ConnectTimeoutException e) {
long currentTime = System.currentTimeMillis();
- throw new ServiceInterruption("Get namespaces connection timed out
reading from Wiki server: " + e.getMessage(), e, currentTime + 300000L,
currentTime + 12L * 60000L, -1, false);
+ throw new ServiceInterruption("Login connection timed out reading from
Wiki server: " + e.getMessage(), e, currentTime + 300000L, currentTime + 12L *
60000L, -1, false);
} catch (InterruptedIOException e) {
method = null;
throw new ManifoldCFException("Interrupted: " + e.getMessage(), e,
ManifoldCFException.INTERRUPTED);
} catch (IOException e) {
- throw new ManifoldCFException("Get namespaces had an IO failure: " +
e.getMessage(), e);
+ throw new ManifoldCFException("Login had an IO failure: " +
e.getMessage(), e);
} finally {
if (method != null) {
method.releaseConnection();
}
}
+
+ // Check result
+ if (!result.result)
+ throw new ManifoldCFException("WIKI API login error: " + result.reason,
null, ManifoldCFException.REPOSITORY_CONNECTION_ERROR);
+ }
+
+ /**
+ * Thread to execute a "login" operation. This thread both executes
+ * the operation and parses the result.
+ */
+ protected class ExecuteAPILoginThread extends Thread {
+
+ protected HttpClient client;
+ protected HttpMethodBase executeMethod;
+ protected Throwable exception = null;
+ protected String token = null;
+
+ public ExecuteAPILoginThread(HttpClient client, HttpMethodBase
executeMethod) {
+ super();
+ setDaemon(true);
+ this.client = client;
+ this.executeMethod = executeMethod;
+ }
+
+ public void run() {
+ try {
+ // Call the execute method appropriately
+ int rval = client.executeMethod(executeMethod);
+ if (rval != 200) {
+ throw new ManifoldCFException("Unexpected response code " + rval +
": " + executeMethod.getResponseBodyAsString());
+ }
+
+ // Read response and make sure it's valid
+ InputStream is = executeMethod.getResponseBodyAsStream();
+ try {
+ // Parse the document. This will cause various things to occur,
within the instantiated XMLContext class.
+ //<api>
+ // <login
+ // result="NeedToken"
+ // token="b5780b6e2f27e20b450921d9461010b4"
+ // cookieprefix="enwiki"
+ // sessionid="17ab96bd8ffbe8ca58a78657a918558e"
+ // />
+ //</api>
+ XMLStream x = new XMLStream();
+ WikiLoginAPIContext c = new WikiLoginAPIContext(x);
+ x.setContext(c);
+ try {
+ try {
+ x.parse(is);
+ token = c.getToken();
+ }
+ catch (IOException e)
+ {
+ long time = System.currentTimeMillis();
+ throw new ServiceInterruption(e.getMessage(),e,time +
300000L,time + 12L * 60000L,-1,false);
+ }
+ } finally {
+ x.cleanup();
+ }
+ } finally {
+ try {
+ is.close();
+ } catch (IllegalStateException e) {
+ // Ignore this error
+ }
+ }
+ } catch (Throwable e) {
+ this.exception = e;
+ }
+ }
+
+ public Throwable getException() {
+ return exception;
+ }
+
+ public String getToken()
+ {
+ return token;
+ }
+ }
+
+ /**
+ * Class representing the "api" context of a "login" response
+ */
+ protected class WikiLoginAPIContext extends SingleLevelContext {
+
+ protected String token = null;
+
+ public WikiLoginAPIContext(XMLStream theStream) {
+ super(theStream, "api");
+ }
+
+ protected BaseProcessingContext createChild(String namespaceURI, String
localName, String qName, Attributes atts) {
+ return new WikiLoginAPIResultAPIContext(theStream, namespaceURI,
localName, qName, atts);
+ }
+
+ protected void finishChild(BaseProcessingContext child)
+ throws ManifoldCFException {
+ token = ((WikiLoginAPIResultAPIContext)child).getToken();
+ }
+
+ public String getToken()
+ {
+ return token;
+ }
+ }
+
+ /**
+ * Class representing the "api/result" context of a "login"
+ * response
+ */
+ protected class WikiLoginAPIResultAPIContext extends BaseProcessingContext {
+
+ protected String token = null;
+
+ public WikiLoginAPIResultAPIContext(XMLStream theStream, String
namespaceURI, String localName, String qName, Attributes atts) {
+ super(theStream, namespaceURI, localName, qName, atts);
+ }
+
+ protected XMLContext beginTag(String namespaceURI, String localName,
String qName, Attributes atts)
+ throws ManifoldCFException, ServiceInterruption {
+ if (qName.equals("login")) {
+ String loginResult = atts.getValue("result");
+ if ("NeedToken".equals(loginResult)) {
+ token = atts.getValue("token");
+ }
+ }
+ return super.beginTag(namespaceURI, localName, qName, atts);
+ }
+
+ public String getToken()
+ {
+ return token;
+ }
}
protected class APILoginResult {
@@ -249,26 +467,22 @@ public class WikiConnector extends org.a
}
/**
- * Thread to execute a "get namespaces" operation. This thread both executes
+ * Thread to finish a "login" operation. This thread both executes
* the operation and parses the result.
*/
- protected class ExecuteAPILoginThread extends Thread {
+ protected class ExecuteTokenAPILoginThread extends Thread {
protected HttpClient client;
protected HttpMethodBase executeMethod;
protected Throwable exception = null;
- protected String baseUrl;
- protected HashMap<String, String> loginParams;
protected APILoginResult result;
- public ExecuteAPILoginThread(HttpClient client, HttpMethodBase
executeMethod, String baseUrl, HashMap<String, String> loginParams,
APILoginResult result) {
+ public ExecuteTokenAPILoginThread(HttpClient client, HttpMethodBase
executeMethod, APILoginResult result) {
super();
setDaemon(true);
this.client = client;
this.executeMethod = executeMethod;
- this.baseUrl = baseUrl;
this.result = result;
- this.loginParams = loginParams;
}
public void run() {
@@ -292,14 +506,16 @@ public class WikiConnector extends org.a
// />
//</api>
XMLStream x = new XMLStream();
- WikiLoginAPIContext c = new WikiLoginAPIContext(x, client, baseUrl,
loginParams, result);
+ WikiTokenLoginAPIContext c = new WikiTokenLoginAPIContext(x,result);
x.setContext(c);
try {
try {
x.parse(is);
- } catch (IOException e) {
+ }
+ catch (IOException e)
+ {
long time = System.currentTimeMillis();
- throw new ServiceInterruption(e.getMessage(), e, time + 300000L,
time + 12L * 60000L, -1, false);
+ throw new ServiceInterruption(e.getMessage(),e,time +
300000L,time + 12L * 60000L,-1,false);
}
} finally {
x.cleanup();
@@ -322,119 +538,45 @@ public class WikiConnector extends org.a
}
/**
- * Class representing the "api" context of a "get namespaces" response
+ * Class representing the "api" context of a "login" response
*/
- protected class WikiLoginAPIContext extends SingleLevelContext {
+ protected class WikiTokenLoginAPIContext extends SingleLevelContext {
- protected HttpClient client;
- protected String baseUrl;
protected APILoginResult result;
- protected HashMap<String, String> loginParams;
-
- public WikiLoginAPIContext(XMLStream theStream, HttpClient client, String
baseUrl, HashMap<String, String> loginParams, APILoginResult result) {
+
+ public WikiTokenLoginAPIContext(XMLStream theStream, APILoginResult
result) {
super(theStream, "api");
- this.client = client;
- this.baseUrl = baseUrl;
this.result = result;
- this.loginParams = loginParams;
}
protected BaseProcessingContext createChild(String namespaceURI, String
localName, String qName, Attributes atts) {
- return new WikiLoginAPIResultAPIContext(theStream, namespaceURI,
localName, qName, atts, client, baseUrl, loginParams, result);
+ return new WikiTokenLoginAPIResultAPIContext(theStream, namespaceURI,
localName, qName, atts, result);
}
protected void finishChild(BaseProcessingContext child)
throws ManifoldCFException {
}
+
}
/**
- * Class representing the "api/query/pages/page" context of a "get doc info"
+ * Class representing the "api/result" context of a "login"
* response
*/
- protected class WikiLoginAPIResultAPIContext extends BaseProcessingContext {
+ protected class WikiTokenLoginAPIResultAPIContext extends
BaseProcessingContext {
- protected HttpClient client;
- protected String baseUrl;
protected APILoginResult result;
- protected HashMap<String, String> loginParams;
-
- public WikiLoginAPIResultAPIContext(XMLStream theStream, String
namespaceURI, String localName, String qName, Attributes atts, HttpClient
client, String baseUrl, HashMap<String, String> loginParams, APILoginResult
result) {
+
+ public WikiTokenLoginAPIResultAPIContext(XMLStream theStream, String
namespaceURI, String localName, String qName, Attributes atts, APILoginResult
result) {
super(theStream, namespaceURI, localName, qName, atts);
- this.client = client;
- this.baseUrl = baseUrl;
this.result = result;
- this.loginParams = loginParams;
}
protected XMLContext beginTag(String namespaceURI, String localName,
String qName, Attributes atts)
throws ManifoldCFException, ServiceInterruption {
if (qName.equals("login")) {
String loginResult = atts.getValue("result");
- if ("NeedToken".equals(loginResult)) {
- String token = atts.getValue("token");
- try {
- loginParams.put("lgtoken", token);
- PostMethod method = new PostMethod(baseUrl);
- for (String key : loginParams.keySet()) {
- method.setParameter(key, loginParams.get(key));
- }
- method.getParams().setParameter("http.socket.timeout", new
Integer(300000));
-
- int rval = client.executeMethod(method);
- if (rval != 200) {
- throw new ManifoldCFException("Unexpected response code " + rval
+ ": " + method.getResponseBodyAsString());
- }
-
- // Read response and make sure it's valid
- InputStream is = method.getResponseBodyAsStream();
- try {
- XMLStream x = new XMLStream();
- WikiLoginAPIContext c = new WikiLoginAPIContext(x, client,
baseUrl, loginParams, result);
- x.setContext(c);
- try {
- try {
- x.parse(is);
- } catch (IOException e) {
- long time = System.currentTimeMillis();
- throw new ServiceInterruption(e.getMessage(), e, time +
300000L, time + 12L * 60000L, -1, false);
- }
- } finally {
- x.cleanup();
- }
- } finally {
- try {
- is.close();
- } catch (IllegalStateException e) {
- // Ignore this error
- }
- }
- method.releaseConnection();
- }
- catch (java.net.SocketTimeoutException e)
- {
- long currentTime = System.currentTimeMillis();
- throw new ServiceInterruption("Login timed out reading from the
Wiki server: "+e.getMessage(),e,currentTime+300000L,currentTime+12L *
60000L,-1,false);
- }
- catch (java.net.SocketException e)
- {
- long currentTime = System.currentTimeMillis();
- throw new ServiceInterruption("Login received a socket error
reading from Wiki server:
"+e.getMessage(),e,currentTime+300000L,currentTime+12L * 60000L,-1,false);
- }
- catch (org.apache.commons.httpclient.ConnectTimeoutException e)
- {
- long currentTime = System.currentTimeMillis();
- throw new ServiceInterruption("Login connection timed out reading
from Wiki server: "+e.getMessage(),e,currentTime+300000L,currentTime+12L *
60000L,-1,false);
- }
- catch (InterruptedIOException e)
- {
- throw new ManifoldCFException("Interrupted:
"+e.getMessage(),e,ManifoldCFException.INTERRUPTED);
- }
- catch (IOException e)
- {
- throw new ManifoldCFException("Login had an IO failure:
"+e.getMessage(),e);
- }
- } else if ("Success".equals(loginResult)) {
+ if ("Success".equals(loginResult)) {
result.result = true;
} else {
result.reason = loginResult;
@@ -443,7 +585,7 @@ public class WikiConnector extends org.a
return super.beginTag(namespaceURI, localName, qName, atts);
}
}
-
+
/** Check status of connection.
*/
@Override
@@ -1472,6 +1614,17 @@ public class WikiConnector extends org.a
return method;
}
+ /** Create an initialize a post method */
+ protected HttpMethodBase getInitializedPostMethod(String URL,
Map<String,String> params)
+ {
+ PostMethod method = new PostMethod(URL);
+ for (String key : params.keySet()) {
+ method.setParameter(key, params.get(key));
+ }
+ method.getParams().setParameter("http.socket.timeout", new
Integer(300000));
+ return method;
+ }
+
// -- Methods and classes to perform a "check" operation. --
/** Do the check operation. This throws an exception if anything is wrong.