From 50d68d60901ac651748c597378d76fcdfc5e1568 Mon Sep 17 00:00:00 2001 From: jamesagnew Date: Fri, 27 Jun 2014 09:05:51 -0400 Subject: [PATCH] Fix a few parsing issues and add multi server support to tester --- hapi-fhir-base/src/changes/changes.xml | 4 + .../ca/uhn/fhir/model/primitive/XhtmlDt.java | 6 +- .../rest/client/BaseHttpClientInvocation.java | 6 + .../server/tester/RestfulTesterServlet.java | 51 +- .../rest/server/tester/RestfulTester.html | 20 +- .../fhir/rest/server/tester/css/tester.css | 4 +- .../rest/server/tester/js/RestfulTester.js | 35 +- .../ca/uhn/fhir/parser/JsonParserTest.java | 21 + .../ca/uhn/fhir/parser/XmlParserTest.java | 1 - .../src/test/resources/failing-hi-bundle.json | 3371 +++++++++++++++++ .../java/ca/uhn/fhir/jpa/test/JpaTestApp.java | 8 +- 11 files changed, 3498 insertions(+), 29 deletions(-) create mode 100644 hapi-fhir-base/src/test/resources/failing-hi-bundle.json diff --git a/hapi-fhir-base/src/changes/changes.xml b/hapi-fhir-base/src/changes/changes.xml index 4da33c07a3a..432008964f4 100644 --- a/hapi-fhir-base/src/changes/changes.xml +++ b/hapi-fhir-base/src/changes/changes.xml @@ -56,6 +56,10 @@ Add support for paging responses from RESTful servers. + + Don't fail on narrative blocks in JSON resources with only an XML declaration but no content (these are + produced by the Health Intersections server) + diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/XhtmlDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/XhtmlDt.java index 8a7f5584c3c..9e88ebf5348 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/XhtmlDt.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/primitive/XhtmlDt.java @@ -80,6 +80,10 @@ public class XhtmlDt extends BasePrimitive> { if (!val.startsWith("<")) { val = "
" + val + "
"; } + if (val.startsWith("")) { + myValue = null; + return; + } try { ArrayList value = new ArrayList(); @@ -99,7 +103,7 @@ public class XhtmlDt extends BasePrimitive> { setValue(value); } catch (XMLStreamException e) { - throw new DataFormatException("String does not appear to be valid XML/XHTML: "+e.getMessage(), e); + throw new DataFormatException("String does not appear to be valid XML/XHTML (error is \""+e.getMessage() + "\"): " + theValue, e); } catch (FactoryConfigurationError e) { throw new ConfigurationException(e); } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseHttpClientInvocation.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseHttpClientInvocation.java index 0d31045e091..b6b560d88fe 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseHttpClientInvocation.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/client/BaseHttpClientInvocation.java @@ -32,6 +32,7 @@ import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.message.BasicHeader; import ca.uhn.fhir.rest.server.EncodingEnum; +import ca.uhn.fhir.util.VersionUtil; public abstract class BaseHttpClientInvocation { @@ -87,6 +88,11 @@ public abstract class BaseHttpClientInvocation { theHttpRequest.addHeader(next); } } + + theHttpRequest.addHeader("User-Agent", "HAPI-FHIR/" + VersionUtil.getVersion() + " (FHIR Client)"); + theHttpRequest.addHeader("Accept-Charset", "utf-8"); + theHttpRequest.addHeader("Accept-Encoding", "gzip"); + } } diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/tester/RestfulTesterServlet.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/tester/RestfulTesterServlet.java index 95760b7a9d7..8e66ff38a36 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/tester/RestfulTesterServlet.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/server/tester/RestfulTesterServlet.java @@ -32,6 +32,7 @@ import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.HashSet; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; @@ -46,7 +47,10 @@ import javax.servlet.http.HttpServletResponse; import org.apache.commons.io.IOUtils; import org.apache.commons.lang3.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.Validate; import org.apache.http.Header; +import org.apache.http.HttpEntity; +import org.apache.http.HttpEntityEnclosingRequest; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.entity.ContentType; @@ -93,7 +97,8 @@ public class RestfulTesterServlet extends HttpServlet { private static final String PUBLIC_TESTER_RESULT_HTML = "/PublicTesterResult.html"; private static final long serialVersionUID = 1L; private FhirContext myCtx; - private String myServerBase; + private LinkedHashMap myIdToServerName = new LinkedHashMap(); + private LinkedHashMap myIdToServerBase = new LinkedHashMap(); private HashMap myStaticResources; private TemplateEngine myTemplateEngine; @@ -191,10 +196,15 @@ public class RestfulTesterServlet extends HttpServlet { myTemplateEngine.initialize(); } - public void setServerBase(String theServerBase) { - myServerBase = theServerBase; + public void addServerBase(String theId, String theDisplayName, String theServerBase) { + Validate.notBlank(theId, "theId can not be blank"); + Validate.notBlank(theDisplayName, "theDisplayName can not be blank"); + Validate.notBlank(theServerBase, "theServerBase can not be blank"); + myIdToServerBase.put(theId, theServerBase); + myIdToServerName.put(theId, theDisplayName); } + private RuntimeResourceDefinition getResourceType(HttpServletRequest theReq) throws ServletException { String resourceName = StringUtils.defaultString(theReq.getParameter(PARAM_RESOURCE)); RuntimeResourceDefinition def = myCtx.getResourceDefinition(resourceName); @@ -214,9 +224,9 @@ public class RestfulTesterServlet extends HttpServlet { RESOURCE, BUNDLE, TAGLIST, NONE } - private void processAction(HttpServletRequest theReq, WebContext theContext) { + private void processAction(HttpServletRequest theReq, WebContext theContext, IGenericClient theClient, String theServerBase) { - GenericClient client = (GenericClient) myCtx.newRestfulGenericClient(myServerBase); + GenericClient client = (GenericClient) theClient; client.setKeepResponses(true); ResultType returnsResource; long latency = 0; @@ -285,7 +295,7 @@ public class RestfulTesterServlet extends HttpServlet { } else if ("page".equals(method)) { String url = defaultString(theReq.getParameter("page-url")); - if (!url.startsWith(myServerBase)) { + if (!url.startsWith(theServerBase)) { theContext.getVariables().put("errorMsg", "Invalid page URL: " + url); return; } @@ -453,6 +463,13 @@ public class RestfulTesterServlet extends HttpServlet { String resultStatus = client.getLastResponse() != null ? client.getLastResponse().getStatusLine().toString() : null; String resultBody = client.getLastResponseBody(); + if (lastRequest instanceof HttpEntityEnclosingRequest) { + HttpEntity entity = ((HttpEntityEnclosingRequest) lastRequest).getEntity(); + if (entity.isRepeatable()) { + requestBody = IOUtils.toString(entity.getContent()); + } + } + HttpResponse lastResponse = client.getLastResponse(); ContentType ct = lastResponse != null ? ContentType.get(lastResponse.getEntity()) : null; String mimeType = ct != null ? ct.getMimeType() : null; @@ -591,7 +608,7 @@ public class RestfulTesterServlet extends HttpServlet { if (nextChar == ':') { inValue = true; b.append(nextChar); - } else if (nextChar == '[' || nextChar == '[') { + } else if (nextChar == '[' || nextChar == '{') { b.append(""); b.append(nextChar); b.append(""); @@ -694,7 +711,18 @@ public class RestfulTesterServlet extends HttpServlet { return; } - IGenericClient client = myCtx.newRestfulGenericClient(myServerBase); + String serverId = theReq.getParameter("server-id"); + String serverBase; + String serverName; + if (isBlank(serverId) && !myIdToServerBase.containsKey(serverId)) { + serverBase = myIdToServerBase.entrySet().iterator().next().getValue(); + serverName = myIdToServerName.entrySet().iterator().next().getValue(); + }else { + serverBase = myIdToServerBase.get(serverId); + serverName = myIdToServerName.get(serverId); + } + + IGenericClient client = myCtx.newRestfulGenericClient(serverBase); Conformance conformance = client.conformance(); WebContext ctx = new WebContext(theReq, theResp, theReq.getServletContext(), theReq.getLocale()); @@ -736,16 +764,19 @@ public class RestfulTesterServlet extends HttpServlet { } } + ctx.setVariable("serverId", serverId); ctx.setVariable("resourceCounts", resourceCounts); ctx.setVariable("conf", conformance); - ctx.setVariable("base", myServerBase); + ctx.setVariable("base", serverBase); + ctx.setVariable("baseName", serverName); + ctx.setVariable("serverEntries", myIdToServerName.entrySet()); String resourceName = defaultString(theReq.getParameter(PARAM_RESOURCE)); ctx.setVariable("resourceName", resourceName); ctx.setVariable("jsonEncodedConf", myCtx.newJsonParser().encodeResourceToString(conformance)); addStandardVariables(ctx, theReq.getParameterMap()); if (isNotBlank(theReq.getParameter("action"))) { - processAction(theReq, ctx); + processAction(theReq, ctx, client, serverBase); } if (isNotBlank(resourceName)) { diff --git a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/rest/server/tester/RestfulTester.html b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/rest/server/tester/RestfulTester.html index 8083d8f9293..58026cdfd1e 100644 --- a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/rest/server/tester/RestfulTester.html +++ b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/rest/server/tester/RestfulTester.html @@ -40,6 +40,7 @@
+