From 5584e83f4b8d6c66999048dafcb9ce6999808894 Mon Sep 17 00:00:00 2001 From: "Niels Erik G. Nielsen" Date: Sun, 12 May 2013 13:49:16 -0400 Subject: [PATCH] More error handling/reporting. Normalizing auth resp Parses HTML reponses where XML were expected, for instance HTML pages returned when domain is not found or HTML error pages from servlet container when service-proxy app not found. Also normalizes auth responses, renaming the document element 'response' to 'auth' before handing the XML string to the parser (other responses are named by their corresponding command, which is what the parser expects). Thie original auth response is still preserved, though. --- .../mkjsf/pazpar2/ClientCommandResponse.java | 24 +++++++++++++++++ .../java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java | 4 +-- .../com/indexdata/mkjsf/pazpar2/Pz2Client.java | 8 +++--- .../mkjsf/pazpar2/ServiceProxyClient.java | 27 +++++++++++++++----- .../mkjsf/pazpar2/ServiceProxyExtensions.java | 24 ++++++++++------- .../indexdata/mkjsf/pazpar2/data/CommandError.java | 6 +++-- .../mkjsf/pazpar2/data/ResponseParser.java | 12 +++++---- 7 files changed, 77 insertions(+), 28 deletions(-) diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/ClientCommandResponse.java b/src/main/java/com/indexdata/mkjsf/pazpar2/ClientCommandResponse.java index 6e0d9e3..e33ce1e 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/ClientCommandResponse.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/ClientCommandResponse.java @@ -11,6 +11,7 @@ public class ClientCommandResponse implements HttpResponseWrapper { private String contentType; private byte[] content = null; private String contentString = null; + private byte[] bytesForParsing = null; public ClientCommandResponse(Pazpar2HttpResponse pz2response, ByteArrayOutputStream content) { this.content = content.toByteArray(); @@ -58,7 +59,30 @@ public class ClientCommandResponse implements HttpResponseWrapper { public byte[] getBytes() { return content; } + + public void setResponseToParse(String parseString) { + try { + this.bytesForParsing = parseString.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + } + } + public byte[] getResponseToParse() { + if (bytesForParsing != null) { + return bytesForParsing; + } else if (content != null) { + return content; + } else { + try { + return contentString.getBytes("UTF-8"); + } catch (UnsupportedEncodingException e) { + e.printStackTrace(); + return null; + } + } + } + @Override public boolean isBinary() { return !contentType.contains("xml"); diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java b/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java index 902a497..4faef7b 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Bean.java @@ -161,9 +161,9 @@ public class Pz2Bean implements Pz2Interface, StateListener, Configurable, Seria } for (CommandThread thread : threadList) { String commandName = thread.getCommand().getCommandName(); - HttpResponseWrapper response = thread.getCommandResponse(); + ClientCommandResponse response = (ClientCommandResponse) thread.getCommandResponse(); responseLogger.debug("Response was: " + response.getResponseString()); - ResponseDataObject responseObject = ResponseParser.getParser().getDataObject(response.getResponseString()); + ResponseDataObject responseObject = ResponseParser.getParser().getDataObject(response); if (ResponseParser.docTypes.contains(responseObject.getType())) { pzresp.put(commandName, responseObject); } else { diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Client.java b/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Client.java index cbdcf6b..fc919f3 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Client.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/Pz2Client.java @@ -101,22 +101,22 @@ public class Pz2Client implements SearchClient { commandResponse = new ClientCommandResponse(pz2HttpResponse,baos); } else if (pz2HttpResponse.getStatusCode()==417) { logger.error("Pazpar2 status code 417: " + baos.toString("UTF-8")); - commandResponse = new ClientCommandResponse(pz2HttpResponse.getStatusCode(),CommandError.insertPazpar2ErrorXml(command.getCommandName(), "Pazpar2: Expectation failed (417)", baos.toString("UTF-8")),"text/xml"); + commandResponse = new ClientCommandResponse(pz2HttpResponse.getStatusCode(),CommandError.insertErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()) ,"Pazpar2: Expectation failed (417)", baos.toString("UTF-8")),"text/xml"); } else { String resp = baos.toString("UTF-8"); logger.error("Pazpar2 status code was " + pz2HttpResponse.getStatusCode() + ": " + resp); - commandResponse = new ClientCommandResponse(pz2HttpResponse.getStatusCode(),CommandError.insertPazpar2ErrorXml(command.getCommandName(), "Pazpar2 error occurred", baos.toString("UTF-8")),"text/xml"); + commandResponse = new ClientCommandResponse(pz2HttpResponse.getStatusCode(),CommandError.insertErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()), "Pazpar2 error occurred", baos.toString("UTF-8")),"text/xml"); throw new Pazpar2ErrorException(resp,pz2HttpResponse.getStatusCode(),resp,null); } } catch (IOException e) { logger.error(e.getMessage()); e.printStackTrace(); - commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml(command.getCommandName(), "io", e.getMessage()),"text/xml"); + commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()), "io", e.getMessage()),"text/xml"); } catch (Pazpar2ErrorException e) { logger.error(e.getMessage()); e.printStackTrace(); logger.error("Creating error XML"); - commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml(command.getCommandName(), "io", e.getMessage()),"text/xml"); + commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml(command.getCommandName(), String.valueOf(pz2HttpResponse.getStatusCode()), "io", e.getMessage()),"text/xml"); } long end = System.currentTimeMillis(); logger.debug("Executed " + command.getCommandName() + " in " + (end-start) + " ms." ); diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/ServiceProxyClient.java b/src/main/java/com/indexdata/mkjsf/pazpar2/ServiceProxyClient.java index 9493e49..51afab2 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/ServiceProxyClient.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/ServiceProxyClient.java @@ -100,15 +100,30 @@ public class ServiceProxyClient implements SearchClient { byte[] response = null; try { response = client.execute(httpget, handler); - if (handler.getStatusCode()==200) { + if (handler.getStatusCode()==200 && handler.getContentType().contains("xml")) { commandResponse = new ClientCommandResponse(handler.getStatusCode(),response,handler.getContentType()); } else { logger.error("Service Proxy status code: " + handler.getStatusCode()); - commandResponse = new ClientCommandResponse(handler.getStatusCode(),CommandError.insertPazpar2ErrorXml(command.getCommandName(), "Service Proxy error occurred", new String(response,"UTF-8")),"text/xml"); + String errorXml = ""; + if (handler.getContentType().contains("xml")) { + errorXml = CommandError.insertErrorXml(command.getCommandName(), String.valueOf(handler.getStatusCode()), "Service Proxy error: "+handler.getStatusCode(), new String(response,"UTF-8")); + } else { + if (handler.getContentType().contains("html")) { + String htmlStrippedOfTags = (new String(response,"UTF-8")).replaceAll("\\<[^>]*>",""); + if (htmlStrippedOfTags.toLowerCase().contains("domain")) { + errorXml = CommandError.createErrorXml(command.getCommandName(), String.valueOf(handler.getStatusCode()), "Error: Expected XML response from Service Proxy, got HTML with word 'domain' in, probably domain not found.", htmlStrippedOfTags); + } else { + errorXml = CommandError.createErrorXml(command.getCommandName(), String.valueOf(handler.getStatusCode()), "Error: Expected XML response from Service Proxy, got HTML", htmlStrippedOfTags); + } + } else { + errorXml = CommandError.createErrorXml(command.getCommandName(), String.valueOf(handler.getStatusCode()), "Error: Expected XML response from Service Proxy, got: "+handler.getContentType(), new String(response,"UTF-8")); + } + commandResponse = new ClientCommandResponse(handler.getStatusCode(),errorXml,handler.getContentType()); + } } } catch (Exception e) { e.printStackTrace(); - commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml(command.getCommandName(), e.getClass().getSimpleName(), (e.getMessage()!= null ? e.getMessage() : "") + (e.getCause()!=null ? e.getCause().getMessage() : "")),"text/xml"); + commandResponse = new ClientCommandResponse(handler.getStatusCode(),CommandError.createErrorXml(command.getCommandName(), String.valueOf(handler.getStatusCode()), e.getClass().getSimpleName(), (e.getMessage()!= null ? e.getMessage() : "") + (e.getCause()!=null ? e.getCause().getMessage() : "")),handler.getContentType()); } return commandResponse; } @@ -218,16 +233,16 @@ public class ServiceProxyClient implements SearchClient { commandResponse = new ClientCommandResponse(handler.getStatusCode(),response,handler.getContentType()); } else { logger.error("Service Proxy status code: " + handler.getStatusCode()); - commandResponse = new ClientCommandResponse(handler.getStatusCode(),CommandError.insertPazpar2ErrorXml("init", "Service Proxy error occurred", new String(response,"UTF-8")),"text/xml"); + commandResponse = new ClientCommandResponse(handler.getStatusCode(),CommandError.insertErrorXml("init", String.valueOf(handler.getStatusCode()), "Service Proxy error: "+handler.getStatusCode(), new String(response,"UTF-8")),"text/xml"); } } catch (ClientProtocolException e) { logger.error(e.getMessage()); e.printStackTrace(); - commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml("init", "client protocol exception", e.getMessage()),"text/xml"); + commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml("init", String.valueOf(handler.getStatusCode()), "client protocol exception", e.getMessage()),"text/xml"); } catch (IOException e) { logger.error(e.getMessage()); e.printStackTrace(); - commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml("init", "IO", e.getMessage()),"text/xml"); + commandResponse = new ClientCommandResponse(-1,CommandError.createErrorXml("init", String.valueOf(handler.getStatusCode()), "IO", e.getMessage()),"text/xml"); } return commandResponse; } diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/ServiceProxyExtensions.java b/src/main/java/com/indexdata/mkjsf/pazpar2/ServiceProxyExtensions.java index 0ee2825..dae3a17 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/ServiceProxyExtensions.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/ServiceProxyExtensions.java @@ -69,7 +69,9 @@ public class ServiceProxyExtensions implements ServiceProxyInterface, Serializab new CommandParameter("username","=",user.getName()), new CommandParameter("password","=",user.getPassword())); ClientCommandResponse commandResponse = pz2.getSpClient().send(auth); - AuthResponse responseObject = (AuthResponse) (ResponseParser.getParser().getDataObject(commandResponse.getResponseString())); + String renamedResponse = renameResponseElement(commandResponse.getResponseString(), "auth"); + commandResponse.setResponseToParse(renamedResponse); + AuthResponse responseObject = (AuthResponse) ResponseParser.getParser().getDataObject(commandResponse); if (ResponseParser.docTypes.contains(responseObject.getType())) { pzresp.put(auth.getCommandName(), responseObject); } @@ -93,8 +95,10 @@ public class ServiceProxyExtensions implements ServiceProxyInterface, Serializab pzresp.resetAllSessionData(); AuthCommand auth = pzreq.getSp().getAuth(); auth.setParameterInState(new CommandParameter("action","=","ipAuth")); - ClientCommandResponse commandResponse = pz2.getSpClient().send(auth); - AuthResponse responseObject = (AuthResponse) (ResponseParser.getParser().getDataObject(commandResponse.getResponseString())); + ClientCommandResponse commandResponse = pz2.getSpClient().send(auth); + String renamedResponse = renameResponseElement(commandResponse.getResponseString(), "auth"); + commandResponse.setResponseToParse(renamedResponse); + ResponseDataObject responseObject = ResponseParser.getParser().getDataObject(commandResponse); if (ResponseParser.docTypes.contains(responseObject.getType())) { pzresp.put(auth.getCommandName(), responseObject); } @@ -107,6 +111,12 @@ public class ServiceProxyExtensions implements ServiceProxyInterface, Serializab } } } + + private String renameResponseElement(String responseString, String newName) { + responseString = responseString.replace("", "<" + newName + ">"); + responseString = responseString.replace("", ""); + return responseString; + } public String getInitDocPath () { return pz2.getSpClient().getConfiguration().get("INIT_DOC_PATH"); @@ -156,8 +166,8 @@ public class ServiceProxyExtensions implements ServiceProxyInterface, Serializab } public void submitInitDoc () throws IOException { - HttpResponseWrapper response = initDocUpload.submit(); - ResponseDataObject responseObject = ResponseParser.getParser().getDataObject(response.getResponseString()); + ClientCommandResponse response = (ClientCommandResponse) initDocUpload.submit(); + ResponseDataObject responseObject = ResponseParser.getParser().getDataObject(response); logger.info("Putting init response to : " + Utils.objectId(pzresp)); pzresp.put("init", responseObject); } @@ -175,8 +185,4 @@ public class ServiceProxyExtensions implements ServiceProxyInterface, Serializab public InitDocUpload getInitDocUpload () { return initDocUpload; } - - - - } diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/data/CommandError.java b/src/main/java/com/indexdata/mkjsf/pazpar2/data/CommandError.java index e3fd7b7..9fbe0d0 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/data/CommandError.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/data/CommandError.java @@ -70,11 +70,12 @@ public class CommandError extends ResponseDataObject implements ErrorInterface { * @param errorMessage * @return */ - public static String createErrorXml (String commandName, String exceptionName, String errorMessage) { + public static String createErrorXml (String commandName, String statusCode, String exceptionName, String errorMessage) { StringBuilder errorXml = new StringBuilder(""); errorXml.append("<" + commandName + ">"+nl); errorXml.append(" "+nl); errorXml.append(" " + commandName + ""+nl); + errorXml.append(" " + statusCode + ""+nl); errorXml.append(" " + (exceptionName != null ? XmlUtils.escape(exceptionName) : "") + ""+nl); errorXml.append(" " + (errorMessage != null ? XmlUtils.escape(errorMessage) : "") + ""+nl); errorXml.append(" "+nl); @@ -94,11 +95,12 @@ public class CommandError extends ResponseDataObject implements ErrorInterface { * by the Pazpar2 client itself. * @return */ - public static String insertPazpar2ErrorXml (String commandName, String exceptionName, String pazpar2ErrorXml) { + public static String insertErrorXml (String commandName, String statusCode, String exceptionName, String pazpar2ErrorXml) { StringBuilder errorXml = new StringBuilder(""); errorXml.append("<" + commandName + ">"+nl); errorXml.append(" "+nl); errorXml.append(" " + commandName + ""+nl); + errorXml.append(" " + statusCode + ""+nl); errorXml.append(" " + XmlUtils.escape(exceptionName) + ""+nl); errorXml.append(xmlDeclaration.matcher(pazpar2ErrorXml).replaceAll("")+nl); errorXml.append(" "+nl); diff --git a/src/main/java/com/indexdata/mkjsf/pazpar2/data/ResponseParser.java b/src/main/java/com/indexdata/mkjsf/pazpar2/data/ResponseParser.java index 29a5fb7..852ebb1 100644 --- a/src/main/java/com/indexdata/mkjsf/pazpar2/data/ResponseParser.java +++ b/src/main/java/com/indexdata/mkjsf/pazpar2/data/ResponseParser.java @@ -18,6 +18,8 @@ import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; +import com.indexdata.mkjsf.pazpar2.ClientCommandResponse; + public class ResponseParser extends DefaultHandler { private XMLReader xmlReader = null; @@ -28,7 +30,7 @@ public class ResponseParser extends DefaultHandler { private static Logger logger = Logger.getLogger(ResponseParser.class); public static List docTypes = Arrays.asList( "bytarget","termlist","show","stat","record","search","init", - /* SP extras */ "response" ); + /* SP extras */ "auth" ); public ResponseParser() { try { @@ -61,10 +63,10 @@ public class ResponseParser extends DefaultHandler { * @param response XML response string from Pazpar2 * @return Response data object */ - public ResponseDataObject getDataObject (String response) { - this.xml = response; + public ResponseDataObject getDataObject (ClientCommandResponse response) { + this.xml = response.getResponseString(); try { - xmlReader.parse(new InputSource(new ByteArrayInputStream(response.getBytes("UTF-8")))); + xmlReader.parse(new InputSource(new ByteArrayInputStream(response.getResponseToParse()))); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } catch (IOException e) { @@ -116,7 +118,7 @@ public class ResponseParser extends DefaultHandler { currentElement = new CommandError(); } else if (localName.equals("error") && dataElements.peek().getType().equals("applicationerror")) { currentElement = new Pazpar2Error(); - } else if (localName.equals("response")) { // Note, document element not named 'auth' + } else if (localName.equals("auth")) { currentElement = new AuthResponse(); } else { currentElement = new ResponseDataObject(); -- 1.7.10.4