Merge branch 'master' of github.com:jamesagnew/hapi-fhir

This commit is contained in:
jamesagnew 2017-12-04 22:35:43 -05:00
commit ae9ab6c109
53 changed files with 2078 additions and 2092 deletions

View File

@ -59,6 +59,13 @@
<groupId>com.phloc</groupId>
<artifactId>phloc-commons</artifactId>
<optional>true</optional>
<exclusions>
<exclusion>
<!-- Guava brings in a newer replacement for this dependency called com.google.code.findbugs:jsr305 -->
<groupId>com.google.code.findbugs</groupId>
<artifactId>annotations</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- <dependency> <groupId>xerces</groupId> <artifactId>xercesImpl</artifactId>
@ -77,6 +84,10 @@
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</dependency>
<!-- Logging -->
<dependency>

View File

@ -138,19 +138,6 @@ public class ParameterUtil {
return b.toString();
}
/**
* Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping
* Section</a>
*/
public static String escapeAndUrlEncode(String theValue) {
if (theValue == null) {
return null;
}
String escaped = escape(theValue);
return UrlUtil.escape(escaped);
}
/**
* Escapes a string according to the rules for parameter escaping specified in the <a href="http://www.hl7.org/implement/standards/fhir/search.html#escaping">FHIR Specification Escaping
* Section</a>

View File

@ -1,16 +1,20 @@
package ca.uhn.fhir.util;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.isBlank;
import java.io.UnsupportedEncodingException;
import java.net.*;
import java.util.*;
import java.util.Map.Entry;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import com.google.common.escape.Escaper;
import com.google.common.net.PercentEscaper;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.util.*;
import java.util.Map.Entry;
import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
import static org.apache.commons.lang3.StringUtils.isBlank;
/*
* #%L
@ -35,6 +39,10 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
public class UrlUtil {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(UrlUtil.class);
private static final String URL_FORM_PARAMETER_OTHER_SAFE_CHARS = "-_.*";
private static final Escaper PARAMETER_ESCAPER = new PercentEscaper(URL_FORM_PARAMETER_OTHER_SAFE_CHARS, false);
/**
* Resolve a relative URL - THIS METHOD WILL NOT FAIL but will log a warning and return theEndpoint if the input is invalid.
*/
@ -88,19 +96,24 @@ public class UrlUtil {
}
/**
* URL encode a value
* URL encode a value according to RFC 3986
* <p>
* This method is intended to be applied to an individual parameter
* name or value. For example, if you are creating the URL
* <code>http://example.com/fhir/Patient?key=føø</code>
* it would be appropriate to pass the string "føø" to this method,
* but not appropriate to pass the entire URL since characters
* such as "/" and "?" would also be escaped.
* </P>
*/
public static String escape(String theValue) {
if (theValue == null) {
public static String escapeUrlParam(String theUnescaped) {
if (theUnescaped == null) {
return null;
}
try {
return URLEncoder.encode(theValue, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new Error("UTF-8 not supported on this platform");
}
return PARAMETER_ESCAPER.escape(theUnescaped);
}
public static boolean isAbsolute(String theValue) {
String value = theValue.toLowerCase();
return value.startsWith("http://") || value.startsWith("https://");
@ -147,7 +160,7 @@ public class UrlUtil {
}
public static void main(String[] args) {
System.out.println(escape("http://snomed.info/sct?fhir_vs=isa/126851005"));
System.out.println(escapeUrlParam("http://snomed.info/sct?fhir_vs=isa/126851005"));
}
public static Map<String, String[]> parseQueryString(String theQueryString) {
@ -156,36 +169,20 @@ public class UrlUtil {
return toQueryStringMap(map);
}
public static Map<String, String[]> parseQueryStrings(String... theQueryString) {
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
for (String next : theQueryString) {
parseQueryString(next, map);
}
return toQueryStringMap(map);
}
private static Map<String, String[]> toQueryStringMap(HashMap<String, List<String>> map) {
HashMap<String, String[]> retVal = new HashMap<String, String[]>();
for (Entry<String, List<String>> nextEntry : map.entrySet()) {
retVal.put(nextEntry.getKey(), nextEntry.getValue().toArray(new String[nextEntry.getValue().size()]));
}
return retVal;
}
private static void parseQueryString(String theQueryString, HashMap<String, List<String>> map) {
String query = theQueryString;
if (query.startsWith("?")) {
query = query.substring(1);
}
StringTokenizer tok = new StringTokenizer(query, "&");
while (tok.hasMoreTokens()) {
String nextToken = tok.nextToken();
if (isBlank(nextToken)) {
continue;
}
int equalsIndex = nextToken.indexOf('=');
String nextValue;
String nextKey;
@ -196,21 +193,28 @@ public class UrlUtil {
nextKey = nextToken.substring(0, equalsIndex);
nextValue = nextToken.substring(equalsIndex + 1);
}
nextKey = unescape(nextKey);
nextValue = unescape(nextValue);
List<String> list = map.get(nextKey);
if (list == null) {
list = new ArrayList<String>();
list = new ArrayList<>();
map.put(nextKey, list);
}
list.add(nextValue);
}
}
//@formatter:off
/**
public static Map<String, String[]> parseQueryStrings(String... theQueryString) {
HashMap<String, List<String>> map = new HashMap<String, List<String>>();
for (String next : theQueryString) {
parseQueryString(next, map);
}
return toQueryStringMap(map);
}
/**
* Parse a URL in one of the following forms:
* <ul>
* <li>[Resource Type]?[Search Params]
@ -278,6 +282,16 @@ public class UrlUtil {
}
//@formatter:off
private static Map<String, String[]> toQueryStringMap(HashMap<String, List<String>> map) {
HashMap<String, String[]> retVal = new HashMap<String, String[]>();
for (Entry<String, List<String>> nextEntry : map.entrySet()) {
retVal.put(nextEntry.getKey(), nextEntry.getValue().toArray(new String[nextEntry.getValue().size()]));
}
return retVal;
}
public static String unescape(String theString) {
if (theString == null) {
return null;
@ -305,30 +319,30 @@ public class UrlUtil {
return myParams;
}
public String getResourceId() {
return myResourceId;
}
public String getResourceType() {
return myResourceType;
}
public String getVersionId() {
return myVersionId;
}
public void setParams(String theParams) {
myParams = theParams;
}
public String getResourceId() {
return myResourceId;
}
public void setResourceId(String theResourceId) {
myResourceId = theResourceId;
}
public String getResourceType() {
return myResourceType;
}
public void setResourceType(String theResourceType) {
myResourceType = theResourceType;
}
public String getVersionId() {
return myVersionId;
}
public void setVersionId(String theVersionId) {
myVersionId = theVersionId;
}

View File

@ -1,20 +1,42 @@
package ca.uhn.fhir.util;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import static org.junit.Assert.*;
public class UrlUtilTest {
@Test
public void testConstructAbsoluteUrl() {
assertEquals("http://foo/bar/baz", UrlUtil.constructAbsoluteUrl(null, "http://foo/bar/baz"));
assertEquals("http://foo/bar/baz", UrlUtil.constructAbsoluteUrl("http://foo/bar/", "baz"));
assertEquals("http://foo/bar/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/", "baz/"));
assertEquals("http://foo/bar/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/", "./baz/"));
assertEquals("http://foo/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/", "../baz/"));
assertEquals("http://foo/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/", "/baz/"));
}
@Test
public void testConstructRelativeUrl() {
assertEquals("http://foo/bar/baz", UrlUtil.constructRelativeUrl("http://boo/far/faz", "http://foo/bar/baz"));
assertEquals("http://foo/bar/baz", UrlUtil.constructRelativeUrl("http://foo/far/faz", "http://foo/bar/baz"));
assertEquals("baz", UrlUtil.constructRelativeUrl("http://foo/bar/boo", "http://foo/bar/baz"));
}
@Test
public void testEscape() {
assertEquals("A%20B", UrlUtil.escapeUrlParam("A B"));
assertEquals("A%2BB", UrlUtil.escapeUrlParam("A+B"));
}
@Test
public void testIsValid() {
assertTrue(UrlUtil.isValid("http://foo"));
assertTrue(UrlUtil.isValid("https://foo"));
assertTrue(UrlUtil.isValid("HTTP://Foo"));
assertTrue(UrlUtil.isValid("HTTPS://Foo"));
assertFalse(UrlUtil.isValid("file://foo"));
assertFalse(UrlUtil.isValid("://foo"));
assertFalse(UrlUtil.isValid("http:/ss"));
@ -24,7 +46,7 @@ public class UrlUtilTest {
assertFalse(UrlUtil.isValid(""));
assertFalse(UrlUtil.isValid(null));
}
@Test
public void testParseUrl() {
assertEquals("ConceptMap", UrlUtil.parseUrl("http://hl7.org/fhir/ConceptMap/ussgfht-loincde").getResourceType());
@ -36,25 +58,5 @@ public class UrlUtilTest {
assertEquals("a=b", UrlUtil.parseUrl("ConceptMap/ussgfht-loincde?a=b").getParams());
}
@Test
public void testConstructAbsoluteUrl() {
assertEquals("http://foo/bar/baz", UrlUtil.constructAbsoluteUrl(null, "http://foo/bar/baz"));
assertEquals("http://foo/bar/baz", UrlUtil.constructAbsoluteUrl("http://foo/bar/","baz"));
assertEquals("http://foo/bar/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/","baz/"));
assertEquals("http://foo/bar/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/","./baz/"));
assertEquals("http://foo/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/","../baz/"));
assertEquals("http://foo/baz/", UrlUtil.constructAbsoluteUrl("http://foo/bar/","/baz/"));
}
@Test
public void testConstructRelativeUrl() {
assertEquals("http://foo/bar/baz", UrlUtil.constructRelativeUrl("http://boo/far/faz", "http://foo/bar/baz"));
assertEquals("http://foo/bar/baz", UrlUtil.constructRelativeUrl("http://foo/far/faz", "http://foo/bar/baz"));
assertEquals("baz", UrlUtil.constructRelativeUrl("http://foo/bar/boo", "http://foo/bar/baz"));
}
}

View File

@ -20,13 +20,6 @@ package ca.uhn.fhir.rest.client.impl;
* #L%
*/
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
@ -34,6 +27,12 @@ import ca.uhn.fhir.rest.client.api.Header;
import ca.uhn.fhir.rest.client.api.IHttpClient;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.api.IRestfulClientFactory;
import ca.uhn.fhir.util.UrlUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
public abstract class BaseHttpClientInvocation {
@ -115,13 +114,9 @@ public abstract class BaseHttpClientInvocation {
} else {
theUrlBuilder.append('&');
}
try {
theUrlBuilder.append(URLEncoder.encode(next.getKey(), "UTF-8"));
theUrlBuilder.append('=');
theUrlBuilder.append(URLEncoder.encode(nextValue, "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new Error("UTF-8 not supported - This should not happen");
}
theUrlBuilder.append(UrlUtil.escapeUrlParam(next.getKey()));
theUrlBuilder.append('=');
theUrlBuilder.append(UrlUtil.escapeUrlParam(nextValue));
}
}
}

View File

@ -354,7 +354,7 @@ public class GenericClient extends BaseClient implements IGenericClient {
case '?':
case '$':
case ':':
b.append(UrlUtil.escape(Character.toString(nextChar)));
b.append(UrlUtil.escapeUrlParam(Character.toString(nextChar)));
break;
default:
b.append(nextChar);

View File

@ -20,21 +20,18 @@ package ca.uhn.fhir.rest.client.method;
* #L%
*/
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import org.apache.commons.lang3.StringUtils;
import ca.uhn.fhir.context.ConfigurationException;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.RequestTypeEnum;
import ca.uhn.fhir.rest.client.api.IHttpRequest;
import ca.uhn.fhir.rest.client.impl.BaseHttpClientInvocation;
import ca.uhn.fhir.util.UrlUtil;
import org.apache.commons.lang3.StringUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
/**
* @author James Agnew
@ -51,51 +48,40 @@ public class HttpGetClientInvocation extends BaseHttpClientInvocation {
myUrlPath = StringUtils.join(theUrlFragments, '/');
}
public HttpGetClientInvocation(FhirContext theContext, Map<String, List<String>> theParameters, List<String> theUrlFragments) {
super(theContext);
myParameters = theParameters;
myUrlPath = StringUtils.join(theUrlFragments, '/');
}
public HttpGetClientInvocation(FhirContext theContext, String theUrlPath) {
super(theContext);
myParameters = new HashMap<String, List<String>>();
myParameters = new HashMap<>();
myUrlPath = theUrlPath;
}
public HttpGetClientInvocation(FhirContext theContext, String... theUrlFragments) {
super(theContext);
myParameters = new HashMap<String, List<String>>();
myUrlPath = StringUtils.join(theUrlFragments, '/');
}
private boolean addQueryParameter(StringBuilder b, boolean first, String nextKey, String nextValue) {
boolean retVal = first;
if (retVal) {
b.append('?');
retVal = false;
} else {
b.append('&');
}
b.append(UrlUtil.escapeUrlParam(nextKey));
b.append('=');
b.append(UrlUtil.escapeUrlParam(nextValue));
public HttpGetClientInvocation(FhirContext theContext, List<String> theUrlFragments) {
super(theContext);
myParameters = new HashMap<String, List<String>>();
myUrlPath = StringUtils.join(theUrlFragments, '/');
}
public Map<String, List<String>> getParameters() {
return myParameters;
}
public String getUrlPath() {
return myUrlPath;
return retVal;
}
@Override
public IHttpRequest asHttpRequest(String theUrlBase, Map<String, List<String>> theExtraParams, EncodingEnum theEncoding, Boolean thePrettyPrint) {
StringBuilder b = new StringBuilder();
if (!myUrlPath.contains("://")) {
b.append(theUrlBase);
if (!theUrlBase.endsWith("/") && !myUrlPath.startsWith("/")) {
b.append('/');
}
}
b.append(myUrlPath);
b.append(theUrlBase);
if (!theUrlBase.endsWith("/") && !myUrlPath.startsWith("/")) {
b.append('/');
}
}
b.append(myUrlPath);
boolean first = b.indexOf("?") == -1;
for (Entry<String, List<String>> next : myParameters.entrySet()) {
if (next.getValue() == null || next.getValue().isEmpty()) {
@ -112,22 +98,12 @@ public class HttpGetClientInvocation extends BaseHttpClientInvocation {
return super.createHttpRequest(b.toString(), theEncoding, RequestTypeEnum.GET);
}
private boolean addQueryParameter(StringBuilder b, boolean first, String nextKey, String nextValue) {
boolean retVal = first;
if (retVal) {
b.append('?');
retVal = false;
} else {
b.append('&');
}
try {
b.append(URLEncoder.encode(nextKey, "UTF-8"));
b.append('=');
b.append(URLEncoder.encode(nextValue, "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new ConfigurationException("Could not find UTF-8 encoding. This shouldn't happen.", e);
}
return retVal;
public Map<String, List<String>> getParameters() {
return myParameters;
}
public String getUrlPath() {
return myUrlPath;
}
}

View File

@ -209,9 +209,9 @@ public class MethodUtil {
for (String nextValue : nextEntry.getValue()) {
b.append(haveQuestionMark ? '&' : '?');
haveQuestionMark = true;
b.append(UrlUtil.escape(nextEntry.getKey()));
b.append(UrlUtil.escapeUrlParam(nextEntry.getKey()));
b.append('=');
b.append(UrlUtil.escape(nextValue));
b.append(UrlUtil.escapeUrlParam(nextValue));
}
}
return b;

View File

@ -35,7 +35,6 @@ import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.XhtmlDt;
import ca.uhn.fhir.model.valueset.BundleEntryTransactionMethodEnum;
import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.parser.IParser;
@ -229,14 +228,14 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
ArrayList<String> nextChoicesList = new ArrayList<>();
partsChoices.add(nextChoicesList);
String key = UrlUtil.escape(nextCompositeOf.getName());
String key = UrlUtil.escapeUrlParam(nextCompositeOf.getName());
if (paramsListForCompositePart != null) {
for (BaseResourceIndexedSearchParam nextParam : paramsListForCompositePart) {
if (nextParam.getParamName().equals(nextCompositeOf.getName())) {
IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType();
String value = nextParamAsClientParam.getValueAsQueryToken(getContext());
if (isNotBlank(value)) {
value = UrlUtil.escape(value);
value = UrlUtil.escapeUrlParam(value);
nextChoicesList.add(key + "=" + value);
}
}
@ -246,7 +245,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> implements IDao {
for (ResourceLink nextLink : linksForCompositePart) {
String value = nextLink.getTargetResource().getIdDt().toUnqualifiedVersionless().getValue();
if (isNotBlank(value)) {
value = UrlUtil.escape(value);
value = UrlUtil.escapeUrlParam(value);
nextChoicesList.add(key + "=" + value);
}
}

View File

@ -60,7 +60,6 @@ import org.hibernate.ScrollMode;
import org.hibernate.ScrollableResults;
import org.hibernate.query.Query;
import org.hl7.fhir.dstu3.model.BaseResource;
import org.hl7.fhir.dstu3.model.Reference;
import org.hl7.fhir.instance.model.api.IAnyResource;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
@ -175,7 +174,7 @@ public class SearchBuilder implements ISearchBuilder {
if (valueBuilder.length() > 0) {
valueBuilder.append(',');
}
valueBuilder.append(UrlUtil.escape(next.getValueAsQueryToken(myContext)));
valueBuilder.append(UrlUtil.escapeUrlParam(next.getValueAsQueryToken(myContext)));
targetResourceType = next.getTargetResourceType();
owningParameter = next.getOwningFieldName();
parameterName = next.getParameterName();
@ -185,7 +184,7 @@ public class SearchBuilder implements ISearchBuilder {
continue;
}
String matchUrl = targetResourceType + '?' + UrlUtil.escape(parameterName) + '=' + valueBuilder.toString();
String matchUrl = targetResourceType + '?' + UrlUtil.escapeUrlParam(parameterName) + '=' + valueBuilder.toString();
RuntimeResourceDefinition targetResourceDefinition;
try {
targetResourceDefinition = myContext.getResourceDefinition(targetResourceType);
@ -1272,13 +1271,13 @@ public class SearchBuilder implements ISearchBuilder {
List<List<String>> params = new ArrayList<>();
for (Entry<String, List<List<? extends IQueryParameterType>>> nextParamNameToValues : theParams.entrySet()) {
String nextParamName = nextParamNameToValues.getKey();
nextParamName = UrlUtil.escape(nextParamName);
nextParamName = UrlUtil.escapeUrlParam(nextParamName);
for (List<? extends IQueryParameterType> nextAnd : nextParamNameToValues.getValue()) {
ArrayList<String> nextValueList = new ArrayList<>();
params.add(nextValueList);
for (IQueryParameterType nextOr : nextAnd) {
String nextOrValue = nextOr.getValueAsQueryToken(myContext);
nextOrValue = UrlUtil.escape(nextOrValue);
nextOrValue = UrlUtil.escapeUrlParam(nextOrValue);
nextValueList.add(nextParamName + "=" + nextOrValue);
}
}

View File

@ -1,6 +1,5 @@
package ca.uhn.fhir.jpa.dao;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/*
@ -24,7 +23,6 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
*/
import java.util.*;
import ca.uhn.fhir.rest.param.ReferenceParam;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.builder.ToStringBuilder;
@ -138,9 +136,9 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
addUrlParamSeparator(b);
b.append(paramName);
b.append('=');
b.append(UrlUtil.escape(nextInclude.getParamType()));
b.append(UrlUtil.escapeUrlParam(nextInclude.getParamType()));
b.append(':');
b.append(UrlUtil.escape(nextInclude.getParamName()));
b.append(UrlUtil.escapeUrlParam(nextInclude.getParamName()));
if (isNotBlank(nextInclude.getParamTargetType())) {
b.append(':');
b.append(nextInclude.getParamTargetType());
@ -314,7 +312,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
for (List<IQueryParameterType> nextValuesAnd : nextValuesAndsOut) {
addUrlParamSeparator(b);
IQueryParameterType firstValue = nextValuesAnd.get(0);
b.append(UrlUtil.escape(nextKey));
b.append(UrlUtil.escapeUrlParam(nextKey));
if (firstValue.getMissing() != null) {
b.append(Constants.PARAMQUALIFIER_MISSING);
@ -340,7 +338,7 @@ public class SearchParameterMap extends LinkedHashMap<String, List<List<? extend
}
String valueAsQueryToken = nextValueOr.getValueAsQueryToken(theCtx);
// b.append(ParameterUtil.escapeAndUrlEncode(valueAsQueryToken));
b.append(UrlUtil.escape(valueAsQueryToken));
b.append(UrlUtil.escapeUrlParam(valueAsQueryToken));
}
}

View File

@ -676,7 +676,7 @@ public class FhirSystemDaoDstu3 extends BaseHapiFhirSystemDao<Bundle, Meta> {
String nextReplacementIdPart = nextReplacementId.getValueAsString();
if (nextTemporaryId.isUrn() && nextTemporaryIdPart.length() > IdType.URN_PREFIX.length()) {
matchUrl = matchUrl.replace(nextTemporaryIdPart, nextReplacementIdPart);
matchUrl = matchUrl.replace(UrlUtil.escape(nextTemporaryIdPart), nextReplacementIdPart);
matchUrl = matchUrl.replace(UrlUtil.escapeUrlParam(nextTemporaryIdPart), nextReplacementIdPart);
}
}
}

View File

@ -667,7 +667,7 @@ public class FhirSystemDaoR4 extends BaseHapiFhirSystemDao<Bundle, Meta> {
String nextReplacementIdPart = nextReplacementId.getValueAsString();
if (nextTemporaryId.isUrn() && nextTemporaryIdPart.length() > IdType.URN_PREFIX.length()) {
matchUrl = matchUrl.replace(nextTemporaryIdPart, nextReplacementIdPart);
matchUrl = matchUrl.replace(UrlUtil.escape(nextTemporaryIdPart), nextReplacementIdPart);
matchUrl = matchUrl.replace(UrlUtil.escapeUrlParam(nextTemporaryIdPart), nextReplacementIdPart);
}
}
}

View File

@ -593,6 +593,9 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
shouldSync = true;
}
// If no abort was requested, bail out
Validate.isTrue(myAbortRequested == false, "Abort has been requested");
if (shouldSync) {
saveUnsynced(theResultIterator);
}
@ -605,10 +608,11 @@ public class SearchCoordinatorSvcImpl implements ISearchCoordinatorSvc {
}
}
// Check if an abort got requested
Validate.isTrue(myAbortRequested == false, "Abort has been requested");
}
// If no abort was requested, bail out
Validate.isTrue(myAbortRequested == false, "Abort has been requested");
saveUnsynced(theResultIterator);
}

View File

@ -321,7 +321,7 @@ public class HapiTerminologySvcDstu3 extends BaseHapiTerminologySvc implements I
cs.setUrl(theSystem);
cs.setContent(CodeSystemContentMode.NOTPRESENT);
DaoMethodOutcome createOutcome = myCodeSystemResourceDao.create(cs, "CodeSystem?url=" + UrlUtil.escape(theSystem), theRequestDetails);
DaoMethodOutcome createOutcome = myCodeSystemResourceDao.create(cs, "CodeSystem?url=" + UrlUtil.escapeUrlParam(theSystem), theRequestDetails);
IIdType csId = createOutcome.getId().toUnqualifiedVersionless();
if (createOutcome.getCreated() != Boolean.TRUE) {
CodeSystem existing = myCodeSystemResourceDao.read(csId, theRequestDetails);

View File

@ -325,7 +325,7 @@ public class HapiTerminologySvcR4 extends BaseHapiTerminologySvc implements IVal
cs.setUrl(theSystem);
cs.setContent(CodeSystemContentMode.NOTPRESENT);
DaoMethodOutcome createOutcome = myCodeSystemResourceDao.create(cs, "CodeSystem?url=" + UrlUtil.escape(theSystem), theRequestDetails);
DaoMethodOutcome createOutcome = myCodeSystemResourceDao.create(cs, "CodeSystem?url=" + UrlUtil.escapeUrlParam(theSystem), theRequestDetails);
IIdType csId = createOutcome.getId().toUnqualifiedVersionless();
if (createOutcome.getCreated() != Boolean.TRUE) {
CodeSystem existing = myCodeSystemResourceDao.read(csId, theRequestDetails);

View File

@ -30,7 +30,7 @@ public class TestDstu2Config extends BaseJavaConfigDstu2 {
public DataSource dataSource() {
BasicDataSource retVal = new BasicDataSource();
retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());
retVal.setUrl("jdbc:derby:memory:myUnitTestDB;create=true");
retVal.setUrl("jdbc:derby:memory:myUnitTestDBDstu2;create=true");
retVal.setUsername("");
retVal.setPassword("");
return retVal;

View File

@ -90,7 +90,7 @@ public class TestDstu3Config extends BaseJavaConfigDstu3 {
};
retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());
retVal.setUrl("jdbc:derby:memory:myUnitTestDB;create=true");
retVal.setUrl("jdbc:derby:memory:myUnitTestDBDstu3;create=true");
retVal.setMaxWaitMillis(10000);
retVal.setUsername("");
retVal.setPassword("");

View File

@ -85,7 +85,7 @@ public class TestR4Config extends BaseJavaConfigR4 {
};
retVal.setDriver(new org.apache.derby.jdbc.EmbeddedDriver());
retVal.setUrl("jdbc:derby:memory:myUnitTestDB;create=true");
retVal.setUrl("jdbc:derby:memory:myUnitTestDBR4;create=true");
retVal.setMaxWaitMillis(10000);
retVal.setUsername("");
retVal.setPassword("");

View File

@ -1,38 +1,12 @@
package ca.uhn.fhir.jpa.dao;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.Callable;
import javax.persistence.EntityManager;
import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.model.dstu2.resource.Observation;
import org.apache.commons.io.IOUtils;
import org.hibernate.search.jpa.Search;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.instance.model.api.*;
import org.junit.AfterClass;
import org.junit.Before;
import org.mockito.Mockito;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.term.VersionIndependentConcept;
import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.model.dstu2.resource.Bundle;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
@ -41,6 +15,31 @@ import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.hibernate.search.jpa.Search;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.dstu3.model.Resource;
import org.hl7.fhir.instance.model.api.IBaseBundle;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.AfterClass;
import org.junit.Before;
import org.mockito.Mockito;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallback;
import org.springframework.transaction.support.TransactionTemplate;
import javax.persistence.EntityManager;
import java.io.IOException;
import java.io.InputStream;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.Callable;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public abstract class BaseJpaTest {
@ -53,13 +52,23 @@ public abstract class BaseJpaTest {
public void beforeCreateSrd() {
mySrd = mock(ServletRequestDetails.class, Mockito.RETURNS_DEEP_STUBS);
when(mySrd.getRequestOperationCallback()).thenReturn(myRequestOperationCallback);
myServerInterceptorList = new ArrayList<IServerInterceptor>();
myServerInterceptorList = new ArrayList<>();
when(mySrd.getServer().getInterceptors()).thenReturn(myServerInterceptorList);
when(mySrd.getUserData()).thenReturn(new HashMap<Object, Object>());
when(mySrd.getUserData()).thenReturn(new HashMap<>());
}
protected abstract FhirContext getContext();
/**
* Sleep until at least 1 ms has elapsed
*/
public void sleepUntilTimeChanges() throws InterruptedException {
StopWatch sw = new StopWatch();
while (sw.getMillis() == 0) {
Thread.sleep(10);
}
}
protected org.hl7.fhir.dstu3.model.Bundle toBundle(IBundleProvider theSearch) {
org.hl7.fhir.dstu3.model.Bundle bundle = new org.hl7.fhir.dstu3.model.Bundle();
for (IBaseResource next : theSearch.getResources(0, theSearch.size())) {
@ -76,11 +85,11 @@ public abstract class BaseJpaTest {
return bundle;
}
@SuppressWarnings({ "rawtypes" })
@SuppressWarnings({"rawtypes"})
protected List toList(IBundleProvider theSearch) {
return theSearch.getResources(0, theSearch.size());
}
protected List<String> toUnqualifiedIdValues(IBaseBundle theFound) {
List<String> retVal = new ArrayList<String>();
@ -214,9 +223,9 @@ public abstract class BaseJpaTest {
}
public static void purgeDatabase(final EntityManager entityManager, PlatformTransactionManager theTxManager, ISearchParamPresenceSvc theSearchParamPresenceSvc, ISearchCoordinatorSvc theSearchCoordinatorSvc, ISearchParamRegistry theSearchParamRegistry) {
theSearchCoordinatorSvc.cancelAllActiveSearches();
TransactionTemplate txTemplate = new TransactionTemplate(theTxManager);
txTemplate.setPropagationBehavior(TransactionTemplate.PROPAGATION_REQUIRED);
txTemplate.execute(new TransactionCallback<Void>() {

View File

@ -2346,7 +2346,7 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
}
@Test
public void testSortByLastUpdated() {
public void testSortByLastUpdated() throws InterruptedException {
String methodName = "testSortByLastUpdated";
Patient p = new Patient();
@ -2354,21 +2354,29 @@ public class FhirResourceDaoDstu2Test extends BaseJpaDstu2Test {
p.addName().addFamily(methodName);
IIdType id1 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
sleepUntilTimeChanges();
p = new Patient();
p.addIdentifier().setSystem("urn:system2").setValue(methodName);
p.addName().addFamily(methodName);
IIdType id2 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
sleepUntilTimeChanges();
p = new Patient();
p.addIdentifier().setSystem("urn:system3").setValue(methodName);
p.addName().addFamily(methodName);
IIdType id3 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
sleepUntilTimeChanges();
p = new Patient();
p.addIdentifier().setSystem("urn:system4").setValue(methodName);
p.addName().addFamily(methodName);
IIdType id4 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
sleepUntilTimeChanges();
SearchParameterMap pm;
List<IIdType> actual;

View File

@ -1,14 +1,17 @@
package ca.uhn.fhir.jpa.dao.dstu3;
import static ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.*;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
import ca.uhn.fhir.jpa.util.StopWatch;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam;
import org.apache.commons.lang3.Validate;
import org.hl7.fhir.dstu3.model.Patient;
import org.hl7.fhir.instance.model.api.IIdType;
import org.junit.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.test.util.AopTestUtils;
@ -16,10 +19,11 @@ import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
import org.springframework.transaction.support.TransactionTemplate;
import ca.uhn.fhir.jpa.dao.SearchParameterMap;
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam;
import java.util.concurrent.atomic.AtomicLong;
import static ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.*;
public class FhirResourceDaoDstu3SearchPageExpiryTest extends BaseJpaDstu3Test {
private static final Logger ourLog = LoggerFactory.getLogger(FhirResourceDaoDstu3SearchPageExpiryTest.class);
@ -104,14 +108,17 @@ public class FhirResourceDaoDstu3SearchPageExpiryTest extends BaseJpaDstu3Test {
// Search just got used so it shouldn't be deleted
myStaleSearchDeletingSvc.pollForStaleSearchesAndDeleteThem();
final AtomicLong search3timestamp = new AtomicLong();
newTxTemplate().execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus theArg0) {
assertNotNull(mySearchEntityDao.findByUuid(searchUuid3));
Search search3 = mySearchEntityDao.findByUuid(searchUuid3);
assertNotNull(search3);
search3timestamp.set(search3.getCreated().getTime());
}
});
StaleSearchDeletingSvcImpl.setNowForUnitTests(start + 1400);
StaleSearchDeletingSvcImpl.setNowForUnitTests(search3timestamp.get() + 1400);
myStaleSearchDeletingSvc.pollForStaleSearchesAndDeleteThem();
newTxTemplate().execute(new TransactionCallbackWithoutResult() {
@ -127,14 +134,14 @@ public class FhirResourceDaoDstu3SearchPageExpiryTest extends BaseJpaDstu3Test {
}
});
StaleSearchDeletingSvcImpl.setNowForUnitTests(start + 2200);
StaleSearchDeletingSvcImpl.setNowForUnitTests(search3timestamp.get() + 2200);
myStaleSearchDeletingSvc.pollForStaleSearchesAndDeleteThem();
newTxTemplate().execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus theArg0) {
assertNull(mySearchEntityDao.findByUuid(searchUuid1));
assertNull(mySearchEntityDao.findByUuid(searchUuid3));
assertNull("Search 1 still exists", mySearchEntityDao.findByUuid(searchUuid1));
assertNull("Search 3 still exists", mySearchEntityDao.findByUuid(searchUuid3));
}
});

View File

@ -30,7 +30,6 @@ import ca.uhn.fhir.model.dstu2.resource.*;
import ca.uhn.fhir.model.dstu2.resource.Bundle.Entry;
import ca.uhn.fhir.model.dstu2.valueset.*;
import ca.uhn.fhir.model.primitive.*;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.client.api.IGenericClient;
@ -528,7 +527,7 @@ public class ResourceProviderDstu2Test extends BaseResourceProviderDstu2Test {
pt.addName().addFamily("FOO");
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escape("|"))));
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escapeUrlParam("|"))));
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
IdDt id2;

View File

@ -1639,7 +1639,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
myObservationDao.create(obs, mySrd);
}
String uri = ourServerBase + "/Patient?_has:Observation:subject:identifier=" + UrlUtil.escape("urn:system|FOO");
String uri = ourServerBase + "/Patient?_has:Observation:subject:identifier=" + UrlUtil.escapeUrlParam("urn:system|FOO");
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertThat(ids, contains(pid0.getValue()));
}
@ -2347,7 +2347,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
myPatientDao.create(p, mySrd);
}
String uri = ourServerBase + "/Patient?name=" + URLEncoder.encode("Jernelöv", "UTF-8") + "&_count=5&_pretty=true";
String uri = ourServerBase + "/Patient?name=" + UrlUtil.escapeUrlParam("Jernelöv") + "&_count=5&_pretty=true";
ourLog.info("URI: {}", uri);
HttpGet get = new HttpGet(uri);
CloseableHttpResponse resp = ourHttpClient.execute(get);
@ -3792,7 +3792,7 @@ public class ResourceProviderDstu3Test extends BaseResourceProviderDstu3Test {
pt.addName().setFamily("FOO");
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escape("|"))));
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escapeUrlParam("|"))));
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
IdType id2;

View File

@ -25,7 +25,7 @@ public class GraphQLProviderR4Test extends BaseResourceProviderR4Test {
initTestPatients();
String query = "{name{family,given}}";
HttpGet httpGet = new HttpGet(ourServerBase + "/Patient/" + myPatientId0.getIdPart() + "/$graphql?query=" + UrlUtil.escape(query));
HttpGet httpGet = new HttpGet(ourServerBase + "/Patient/" + myPatientId0.getIdPart() + "/$graphql?query=" + UrlUtil.escapeUrlParam(query));
CloseableHttpResponse response = ourHttpClient.execute(httpGet);
try {
@ -50,7 +50,7 @@ public class GraphQLProviderR4Test extends BaseResourceProviderR4Test {
initTestPatients();
String query = "{PatientList(given:\"given\"){name{family,given}}}";
HttpGet httpGet = new HttpGet(ourServerBase + "/$graphql?query=" + UrlUtil.escape(query));
HttpGet httpGet = new HttpGet(ourServerBase + "/$graphql?query=" + UrlUtil.escapeUrlParam(query));
CloseableHttpResponse response = ourHttpClient.execute(httpGet);
try {

View File

@ -61,7 +61,6 @@ import java.math.BigDecimal;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.*;
@ -1647,7 +1646,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
myObservationDao.create(obs, mySrd);
}
String uri = ourServerBase + "/Patient?_has:Observation:subject:identifier=" + UrlUtil.escape("urn:system|FOO");
String uri = ourServerBase + "/Patient?_has:Observation:subject:identifier=" + UrlUtil.escapeUrlParam("urn:system|FOO");
List<String> ids = searchAndReturnUnqualifiedVersionlessIdValues(uri);
assertThat(ids, contains(pid0.getValue()));
}
@ -2355,7 +2354,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
myPatientDao.create(p, mySrd);
}
String uri = ourServerBase + "/Patient?name=" + URLEncoder.encode("Jernelöv", "UTF-8") + "&_count=5&_pretty=true";
String uri = ourServerBase + "/Patient?name=" + UrlUtil.escapeUrlParam("Jernelöv") + "&_count=5&_pretty=true";
ourLog.info("URI: {}", uri);
HttpGet get = new HttpGet(uri);
CloseableHttpResponse resp = ourHttpClient.execute(get);
@ -3938,7 +3937,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
pt.addName().setFamily("FOO");
resource = myFhirCtx.newXmlParser().encodeResourceToString(pt);
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escape("|"))));
HttpPut put = new HttpPut(ourServerBase + "/Patient?identifier=" + ("http://general-hospital.co.uk/Identifiers|09832345234543876876".replace("|", UrlUtil.escapeUrlParam("|"))));
put.setEntity(new StringEntity(resource, ContentType.create(Constants.CT_FHIR_XML, "UTF-8")));
IdType id2;

View File

@ -80,13 +80,13 @@ public class AnalyticsInterceptor extends InterceptorAdapter {
b.append("&tid=").append(myAnalyticsTid);
b.append("&t=event");
b.append("&an=").append(UrlUtil.escape(myHostname)).append('+').append(UrlUtil.escape(next.getApplicationName()));
b.append("&an=").append(UrlUtil.escapeUrlParam(myHostname)).append('+').append(UrlUtil.escapeUrlParam(next.getApplicationName()));
b.append("&ec=").append(next.getResourceName());
b.append("&ea=").append(next.getRestOperation());
b.append("&cid=").append(next.getClientId());
b.append("&uip=").append(UrlUtil.escape(next.getSourceIp()));
b.append("&ua=").append(UrlUtil.escape(next.getUserAgent()));
b.append("&uip=").append(UrlUtil.escapeUrlParam(next.getSourceIp()));
b.append("&ua=").append(UrlUtil.escapeUrlParam(next.getUserAgent()));
b.append("\n");
}

View File

@ -19,34 +19,38 @@ package ca.uhn.fhir.rest.server;
* limitations under the License.
* #L%
*/
import static org.apache.commons.lang3.StringUtils.*;
import java.io.*;
import java.net.URLEncoder;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.util.BinaryUtil;
import org.hl7.fhir.instance.model.api.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.valueset.BundleTypeEnum;
import ca.uhn.fhir.parser.IParser;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.PreferReturnEnum;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.api.server.IRestfulResponse;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.method.ElementsParameter;
import ca.uhn.fhir.rest.server.method.SummaryEnumParameter;
import ca.uhn.fhir.util.BinaryUtil;
import ca.uhn.fhir.util.DateUtils;
import ca.uhn.fhir.util.UrlUtil;
import org.hl7.fhir.instance.model.api.*;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.io.Writer;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static org.apache.commons.lang3.StringUtils.*;
public class RestfulServerUtils {
static final Pattern ACCEPT_HEADER_PATTERN = Pattern.compile("\\s*([a-zA-Z0-9+.*/-]+)\\s*(;\\s*([a-zA-Z]+)\\s*=\\s*([a-zA-Z0-9.]+)\\s*)?(,?)");
@ -127,74 +131,70 @@ public class RestfulServerUtils {
}
public static String createPagingLink(Set<Include> theIncludes, String theServerBase, String theSearchId, int theOffset, int theCount, Map<String, String[]> theRequestParameters, boolean thePrettyPrint,
BundleTypeEnum theBundleType) {
try {
StringBuilder b = new StringBuilder();
b.append(theServerBase);
b.append('?');
b.append(Constants.PARAM_PAGINGACTION);
b.append('=');
b.append(URLEncoder.encode(theSearchId, "UTF-8"));
BundleTypeEnum theBundleType) {
StringBuilder b = new StringBuilder();
b.append(theServerBase);
b.append('?');
b.append(Constants.PARAM_PAGINGACTION);
b.append('=');
b.append(UrlUtil.escapeUrlParam(theSearchId));
b.append('&');
b.append(Constants.PARAM_PAGINGOFFSET);
b.append('=');
b.append(theOffset);
b.append('&');
b.append(Constants.PARAM_COUNT);
b.append('=');
b.append(theCount);
String[] strings = theRequestParameters.get(Constants.PARAM_FORMAT);
if (strings != null && strings.length > 0) {
b.append('&');
b.append(Constants.PARAM_PAGINGOFFSET);
b.append(Constants.PARAM_FORMAT);
b.append('=');
b.append(theOffset);
b.append('&');
b.append(Constants.PARAM_COUNT);
b.append('=');
b.append(theCount);
String[] strings = theRequestParameters.get(Constants.PARAM_FORMAT);
if (strings != null && strings.length > 0) {
b.append('&');
b.append(Constants.PARAM_FORMAT);
b.append('=');
String format = strings[0];
format = replace(format, " ", "+");
b.append(UrlUtil.escape(format));
}
if (thePrettyPrint) {
b.append('&');
b.append(Constants.PARAM_PRETTY);
b.append('=');
b.append(Constants.PARAM_PRETTY_VALUE_TRUE);
}
if (theIncludes != null) {
for (Include nextInclude : theIncludes) {
if (isNotBlank(nextInclude.getValue())) {
b.append('&');
b.append(Constants.PARAM_INCLUDE);
b.append('=');
b.append(URLEncoder.encode(nextInclude.getValue(), "UTF-8"));
}
}
}
if (theBundleType != null) {
b.append('&');
b.append(Constants.PARAM_BUNDLETYPE);
b.append('=');
b.append(theBundleType.getCode());
}
String paramName = Constants.PARAM_ELEMENTS;
String[] params = theRequestParameters.get(paramName);
if (params != null) {
for (String nextValue : params) {
if (isNotBlank(nextValue)) {
b.append('&');
b.append(paramName);
b.append('=');
b.append(UrlUtil.escape(nextValue));
}
}
}
return b.toString();
} catch (UnsupportedEncodingException e) {
throw new Error("UTF-8 not supported", e);// should not happen
String format = strings[0];
format = replace(format, " ", "+");
b.append(UrlUtil.escapeUrlParam(format));
}
if (thePrettyPrint) {
b.append('&');
b.append(Constants.PARAM_PRETTY);
b.append('=');
b.append(Constants.PARAM_PRETTY_VALUE_TRUE);
}
if (theIncludes != null) {
for (Include nextInclude : theIncludes) {
if (isNotBlank(nextInclude.getValue())) {
b.append('&');
b.append(Constants.PARAM_INCLUDE);
b.append('=');
b.append(UrlUtil.escapeUrlParam(nextInclude.getValue()));
}
}
}
if (theBundleType != null) {
b.append('&');
b.append(Constants.PARAM_BUNDLETYPE);
b.append('=');
b.append(theBundleType.getCode());
}
String paramName = Constants.PARAM_ELEMENTS;
String[] params = theRequestParameters.get(paramName);
if (params != null) {
for (String nextValue : params) {
if (isNotBlank(nextValue)) {
b.append('&');
b.append(paramName);
b.append('=');
b.append(UrlUtil.escapeUrlParam(nextValue));
}
}
}
return b.toString();
}
/**
@ -392,15 +392,15 @@ public class RestfulServerUtils {
try {
NarrativeModeEnum narrativeMode = NarrativeModeEnum.valueOfCaseInsensitive(narrative[0]);
switch (narrativeMode) {
case NORMAL:
retVal = Collections.singleton(SummaryEnum.FALSE);
break;
case ONLY:
retVal = Collections.singleton(SummaryEnum.TEXT);
break;
case SUPPRESS:
retVal = Collections.singleton(SummaryEnum.DATA);
break;
case NORMAL:
retVal = Collections.singleton(SummaryEnum.FALSE);
break;
case ONLY:
retVal = Collections.singleton(SummaryEnum.TEXT);
break;
case SUPPRESS:
retVal = Collections.singleton(SummaryEnum.DATA);
break;
}
} catch (IllegalArgumentException e) {
ourLog.debug("Invalid {} parameter: {}", Constants.PARAM_NARRATIVE, narrative[0]);
@ -461,13 +461,13 @@ public class RestfulServerUtils {
EncodingEnum responseEncoding = RestfulServerUtils.determineResponseEncodingWithDefault(theRequestDetails).getEncoding();
IParser parser;
switch (responseEncoding) {
case JSON:
parser = theContext.newJsonParser();
break;
case XML:
default:
parser = theContext.newXmlParser();
break;
case JSON:
parser = theContext.newJsonParser();
break;
case XML:
default:
parser = theContext.newXmlParser();
break;
}
configureResponseParser(theRequestDetails, parser);
@ -581,13 +581,13 @@ public class RestfulServerUtils {
}
public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set<SummaryEnum> theSummaryMode, int stausCode, boolean theAddContentLocationHeader,
boolean respondGzip, RequestDetails theRequestDetails) throws IOException {
boolean respondGzip, RequestDetails theRequestDetails) throws IOException {
return streamResponseAsResource(theServer, theResource, theSummaryMode, stausCode, null, theAddContentLocationHeader, respondGzip, theRequestDetails, null, null);
}
public static Object streamResponseAsResource(IRestfulServerDefaults theServer, IBaseResource theResource, Set<SummaryEnum> theSummaryMode, int theStausCode, String theStatusMessage,
boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails, IIdType theOperationResourceId, IPrimitiveType<Date> theOperationResourceLastUpdated)
throws IOException {
boolean theAddContentLocationHeader, boolean respondGzip, RequestDetails theRequestDetails, IIdType theOperationResourceId, IPrimitiveType<Date> theOperationResourceLastUpdated)
throws IOException {
IRestfulResponse response = theRequestDetails.getResponse();
// Determine response encoding
@ -706,7 +706,7 @@ public class RestfulServerUtils {
try {
return Integer.parseInt(retVal[0]);
} catch (NumberFormatException e) {
ourLog.debug("Failed to parse {} value '{}': {}", new Object[] { theParamName, retVal[0], e });
ourLog.debug("Failed to parse {} value '{}': {}", new Object[]{theParamName, retVal[0], e});
return null;
}
}
@ -752,7 +752,7 @@ public class RestfulServerUtils {
if (theContentType.equals(EncodingEnum.JSON_PLAIN_STRING) || theContentType.equals(EncodingEnum.XML_PLAIN_STRING)) {
FhirVersionEnum ctxtEnum = theCtx.getVersion().getVersion();
myNonLegacy = ctxtEnum.isNewerThan(FhirVersionEnum.DSTU3)
|| (ctxtEnum.isEquivalentTo(FhirVersionEnum.DSTU3) && !"1.4.0".equals(theCtx.getVersion().getVersion().getFhirVersionString()));
|| (ctxtEnum.isEquivalentTo(FhirVersionEnum.DSTU3) && !"1.4.0".equals(theCtx.getVersion().getVersion().getFhirVersionString()));
} else {
myNonLegacy = EncodingEnum.isNonLegacy(theContentType);
}

View File

@ -25,7 +25,6 @@ import java.io.IOException;
*/
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.Map.Entry;
@ -33,6 +32,7 @@ import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import ca.uhn.fhir.util.UrlUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.Validate;
import org.apache.commons.lang3.text.StrLookup;
@ -277,13 +277,9 @@ public class LoggingInterceptor extends InterceptorAdapter {
} else {
b.append('&');
}
try {
b.append(URLEncoder.encode(next.getKey(), "UTF-8"));
b.append('=');
b.append(URLEncoder.encode(nextValue, "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new ca.uhn.fhir.context.ConfigurationException("UTF-8 not supported", e);
}
b.append(UrlUtil.escapeUrlParam(next.getKey()));
b.append('=');
b.append(UrlUtil.escapeUrlParam(nextValue));
}
}
return b.toString();

View File

@ -92,9 +92,9 @@ public class ResponseHighlighterInterceptor extends InterceptorAdapter {
} else {
rawB.append('&');
}
rawB.append(UrlUtil.escape(next));
rawB.append(UrlUtil.escapeUrlParam(next));
rawB.append('=');
rawB.append(UrlUtil.escape(nextValue));
rawB.append(UrlUtil.escapeUrlParam(nextValue));
}
}
if (rawB.length() == 0) {

View File

@ -186,9 +186,9 @@ public abstract class BaseResourceReturningMethodBinding extends BaseMethodBindi
} else {
b.append('&');
}
b.append(UrlUtil.escape(nextParamName));
b.append(UrlUtil.escapeUrlParam(nextParamName));
b.append('=');
b.append(UrlUtil.escape(nextParamValue));
b.append(UrlUtil.escapeUrlParam(nextParamValue));
}
}
}

View File

@ -1,12 +1,15 @@
package ca.uhn.fhir.rest.server;
import static org.junit.Assert.*;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
@ -20,20 +23,11 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.model.primitive.DateTimeDt;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.param.CompositeAndListParam;
import ca.uhn.fhir.rest.param.CompositeOrListParam;
import ca.uhn.fhir.rest.param.CompositeParam;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
/**
* Created by dsotnikov on 2/25/2014.
@ -48,7 +42,7 @@ public class CompositeParameterTest {
@Test
public void testSearchWithDateValue() throws Exception {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?" + Observation.SP_NAME_VALUE_DATE + "=" + URLEncoder.encode("foo\\$bar$2001-01-01", "UTF-8"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?" + Observation.SP_NAME_VALUE_DATE + "=" + UrlUtil.escape("foo\\$bar$2001-01-01"));
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());
@ -66,7 +60,7 @@ public class CompositeParameterTest {
@Test
public void testSearchWithMultipleValue() throws Exception {
{
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?" + Observation.SP_NAME_VALUE_STRING + "=" + URLEncoder.encode("l1$r1,l2$r2", "UTF-8") + "&" + Observation.SP_NAME_VALUE_STRING + "=" + URLEncoder.encode("l3$r3,l4$r4", "UTF-8"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Observation?" + Observation.SP_NAME_VALUE_STRING + "=" + UrlUtil.escape("l1$r1,l2$r2") + "&" + Observation.SP_NAME_VALUE_STRING + "=" + UrlUtil.escape("l3$r3,l4$r4"));
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());

View File

@ -1,15 +1,14 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.hamcrest.Matchers.stringContainsInOrder;
import static org.junit.Assert.*;
import java.net.URLEncoder;
import java.util.concurrent.TimeUnit;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
@ -22,20 +21,11 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import com.google.common.net.UrlEscapers;
import java.util.concurrent.TimeUnit;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.BaseResource;
import ca.uhn.fhir.model.dstu.resource.Binary;
import ca.uhn.fhir.model.dstu.resource.Organization;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.not;
import static org.junit.Assert.*;
public class DefaultEncodingTest {

View File

@ -1,11 +1,17 @@
package ca.uhn.fhir.rest.server;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import java.net.URLEncoder;
import java.util.concurrent.TimeUnit;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.BaseResource;
import ca.uhn.fhir.model.dstu.resource.Binary;
import ca.uhn.fhir.model.dstu.resource.Organization;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
@ -20,18 +26,10 @@ import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.IdentifierDt;
import ca.uhn.fhir.model.dstu.resource.BaseResource;
import ca.uhn.fhir.model.dstu.resource.Binary;
import ca.uhn.fhir.model.dstu.resource.Organization;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.IdParam;
import ca.uhn.fhir.rest.annotation.Read;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import java.util.concurrent.TimeUnit;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
public class ReadDstu1Test {
@ -129,10 +127,10 @@ public class ReadDstu1Test {
@Test
public void testReadWithEscapedCharsInId() throws Exception {
String id = "ABC!@#$--DEF";
String idEscaped = URLEncoder.encode(id, "UTF-8");
String idEscaped = UrlUtil.escapeid);
String vid = "GHI:/:/JKL";
String vidEscaped = URLEncoder.encode(vid, "UTF-8");
String vidEscaped = UrlUtil.escape(vid);
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/" + idEscaped + "/_history/" + vidEscaped);
HttpResponse status = ourClient.execute(httpGet);

View File

@ -1,41 +1,12 @@
package ca.uhn.fhir.rest.server;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThat;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.utils.URLEncodedUtils;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.BundleEntry;
import ca.uhn.fhir.model.api.IResource;
import ca.uhn.fhir.model.dstu.composite.ResourceReferenceDt;
import ca.uhn.fhir.model.dstu.resource.Conformance;
import ca.uhn.fhir.model.dstu.resource.*;
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResource;
import ca.uhn.fhir.model.dstu.resource.Conformance.RestResourceSearchParam;
import ca.uhn.fhir.model.dstu.resource.Location;
import ca.uhn.fhir.model.dstu.resource.Observation;
import ca.uhn.fhir.model.dstu.resource.Organization;
import ca.uhn.fhir.model.dstu.resource.Patient;
import ca.uhn.fhir.model.dstu.valueset.ResourceTypeEnum;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.annotation.IdParam;
@ -47,6 +18,27 @@ import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.apache.commons.lang3.StringUtils.defaultString;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
/**
* Created by dsotnikov on 2/25/2014.
@ -105,7 +97,7 @@ public class ReferenceParameterTest {
@Test
public void testReferenceParamViewToken() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?provider.name=" + URLEncoder.encode("foo|bar", "UTF-8"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?provider.name=" + UrlUtil.escape("foo|bar"));
HttpResponse status = ourClient.execute(httpGet);
IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());

View File

@ -105,7 +105,7 @@ public class OperationServerWithSearchParamTypesDstu2_1Test {
@Test
public void testEscapedOperationName() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/%24andlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escape("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escape("VALTOK2A|VALTOK2B"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/%24andlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escapeUrlParam("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escapeUrlParam("VALTOK2A|VALTOK2B"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -118,7 +118,7 @@ public class OperationServerWithSearchParamTypesDstu2_1Test {
@Test
public void testAndListWithUrl() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$andlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escape("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escape("VALTOK2A|VALTOK2B"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$andlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escapeUrlParam("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escapeUrlParam("VALTOK2A|VALTOK2B"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -270,7 +270,7 @@ public class OperationServerWithSearchParamTypesDstu2_1Test {
}
@Test
public void testNonRepeatingWithUrl() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr=VALSTR&valtok=" + UrlUtil.escape("VALTOKA|VALTOKB"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr=VALSTR&valtok=" + UrlUtil.escapeUrlParam("VALTOKA|VALTOKB"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -290,7 +290,7 @@ public class OperationServerWithSearchParamTypesDstu2_1Test {
@Test
public void testNonRepeatingWithUrlQualified() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr:exact=VALSTR&valtok:not=" + UrlUtil.escape("VALTOKA|VALTOKB"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr:exact=VALSTR&valtok:not=" + UrlUtil.escapeUrlParam("VALTOKA|VALTOKB"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -345,7 +345,7 @@ public class OperationServerWithSearchParamTypesDstu2_1Test {
@Test
public void testOrListWithUrl() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$orlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escape("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escape("VALTOK2A|VALTOK2B"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$orlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escapeUrlParam("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escapeUrlParam("VALTOK2A|VALTOK2B"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());

View File

@ -110,8 +110,8 @@ public class OperationServerWithSearchParamTypesDstu2Test {
@Test
public void testAndListWithUrl() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$andlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escape("VALTOK1A|VALTOK1B") + "&valtok="
+ UrlUtil.escape("VALTOK2A|VALTOK2B"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$andlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escapeUrlParam("VALTOK1A|VALTOK1B") + "&valtok="
+ UrlUtil.escapeUrlParam("VALTOK2A|VALTOK2B"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -214,7 +214,7 @@ public class OperationServerWithSearchParamTypesDstu2Test {
@Test
public void testNonRepeatingWithUrl() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr=VALSTR&valtok=" + UrlUtil.escape("VALTOKA|VALTOKB"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr=VALSTR&valtok=" + UrlUtil.escapeUrlParam("VALTOKA|VALTOKB"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -234,7 +234,7 @@ public class OperationServerWithSearchParamTypesDstu2Test {
@Test
public void testNonRepeatingWithUrlQualified() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr:exact=VALSTR&valtok:not=" + UrlUtil.escape("VALTOKA|VALTOKB"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr:exact=VALSTR&valtok:not=" + UrlUtil.escapeUrlParam("VALTOKA|VALTOKB"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -289,8 +289,8 @@ public class OperationServerWithSearchParamTypesDstu2Test {
@Test
public void testOrListWithUrl() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$orlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escape("VALTOK1A|VALTOK1B") + "&valtok="
+ UrlUtil.escape("VALTOK2A|VALTOK2B"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$orlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escapeUrlParam("VALTOK1A|VALTOK1B") + "&valtok="
+ UrlUtil.escapeUrlParam("VALTOK2A|VALTOK2B"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());

View File

@ -1,12 +1,14 @@
package ca.uhn.fhir.rest.server;
import static org.junit.Assert.assertEquals;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil;
import org.apache.commons.io.IOUtils;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
@ -22,14 +24,11 @@ import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.rest.annotation.RequiredParam;
import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.param.ReferenceParam;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.util.PortUtil;
import ca.uhn.fhir.util.TestUtil;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
public class ServerSearchDstu2Test {
@ -106,7 +105,7 @@ public class ServerSearchDstu2Test {
@Test
public void testSearchWithEncodedValue() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/?param1=" + URLEncoder.encode("Jernelöv", "UTF-8"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/?param1=" + UrlUtil.escapeUrlParam("Jernelöv"));
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());
IOUtils.closeQuietly(status.getEntity().getContent());

View File

@ -14,7 +14,6 @@ import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
@ -186,7 +185,7 @@ public class ResponseHighlightingInterceptorTest {
@Test
public void testForceApplicationJsonPlusFhir() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=" + UrlUtil.escape("application/json+fhir"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=" + UrlUtil.escapeUrlParam("application/json+fhir"));
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
HttpResponse status = ourClient.execute(httpGet);
@ -225,7 +224,7 @@ public class ResponseHighlightingInterceptorTest {
@Test
public void testForceApplicationXmlPlusFhir() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=" + UrlUtil.escape("application/xml+fhir"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/1?_format=" + UrlUtil.escapeUrlParam("application/xml+fhir"));
httpGet.addHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:40.0) Gecko/20100101 Firefox/40.1");
HttpResponse status = ourClient.execute(httpGet);

View File

@ -1,122 +1,122 @@
package org.hl7.fhir.dstu3.model.codesystems;
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
// Generated on Sat, Mar 25, 2017 21:03-0400 for FHIR v3.0.0
import org.hl7.fhir.dstu3.model.EnumFactory;
public class MapTransformEnumFactory implements EnumFactory<MapTransform> {
public MapTransform fromCode(String codeString) throws IllegalArgumentException {
if (codeString == null || "".equals(codeString))
return null;
if ("create".equals(codeString))
return MapTransform.CREATE;
if ("copy".equals(codeString))
return MapTransform.COPY;
if ("truncate".equals(codeString))
return MapTransform.TRUNCATE;
if ("escape".equals(codeString))
return MapTransform.ESCAPE;
if ("cast".equals(codeString))
return MapTransform.CAST;
if ("append".equals(codeString))
return MapTransform.APPEND;
if ("translate".equals(codeString))
return MapTransform.TRANSLATE;
if ("reference".equals(codeString))
return MapTransform.REFERENCE;
if ("dateOp".equals(codeString))
return MapTransform.DATEOP;
if ("uuid".equals(codeString))
return MapTransform.UUID;
if ("pointer".equals(codeString))
return MapTransform.POINTER;
if ("evaluate".equals(codeString))
return MapTransform.EVALUATE;
if ("cc".equals(codeString))
return MapTransform.CC;
if ("c".equals(codeString))
return MapTransform.C;
if ("qty".equals(codeString))
return MapTransform.QTY;
if ("id".equals(codeString))
return MapTransform.ID;
if ("cp".equals(codeString))
return MapTransform.CP;
throw new IllegalArgumentException("Unknown MapTransform code '"+codeString+"'");
}
public String toCode(MapTransform code) {
if (code == MapTransform.CREATE)
return "create";
if (code == MapTransform.COPY)
return "copy";
if (code == MapTransform.TRUNCATE)
return "truncate";
if (code == MapTransform.ESCAPE)
return "escape";
if (code == MapTransform.CAST)
return "cast";
if (code == MapTransform.APPEND)
return "append";
if (code == MapTransform.TRANSLATE)
return "translate";
if (code == MapTransform.REFERENCE)
return "reference";
if (code == MapTransform.DATEOP)
return "dateOp";
if (code == MapTransform.UUID)
return "uuid";
if (code == MapTransform.POINTER)
return "pointer";
if (code == MapTransform.EVALUATE)
return "evaluate";
if (code == MapTransform.CC)
return "cc";
if (code == MapTransform.C)
return "c";
if (code == MapTransform.QTY)
return "qty";
if (code == MapTransform.ID)
return "id";
if (code == MapTransform.CP)
return "cp";
return "?";
}
public String toSystem(MapTransform code) {
return code.getSystem();
}
}
package org.hl7.fhir.dstu3.model.codesystems;
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
// Generated on Sat, Mar 25, 2017 21:03-0400 for FHIR v3.0.0
import org.hl7.fhir.dstu3.model.EnumFactory;
public class MapTransformEnumFactory implements EnumFactory<MapTransform> {
public MapTransform fromCode(String codeString) throws IllegalArgumentException {
if (codeString == null || "".equals(codeString))
return null;
if ("create".equals(codeString))
return MapTransform.CREATE;
if ("copy".equals(codeString))
return MapTransform.COPY;
if ("truncate".equals(codeString))
return MapTransform.TRUNCATE;
if ("escapeUrlParam".equals(codeString))
return MapTransform.ESCAPE;
if ("cast".equals(codeString))
return MapTransform.CAST;
if ("append".equals(codeString))
return MapTransform.APPEND;
if ("translate".equals(codeString))
return MapTransform.TRANSLATE;
if ("reference".equals(codeString))
return MapTransform.REFERENCE;
if ("dateOp".equals(codeString))
return MapTransform.DATEOP;
if ("uuid".equals(codeString))
return MapTransform.UUID;
if ("pointer".equals(codeString))
return MapTransform.POINTER;
if ("evaluate".equals(codeString))
return MapTransform.EVALUATE;
if ("cc".equals(codeString))
return MapTransform.CC;
if ("c".equals(codeString))
return MapTransform.C;
if ("qty".equals(codeString))
return MapTransform.QTY;
if ("id".equals(codeString))
return MapTransform.ID;
if ("cp".equals(codeString))
return MapTransform.CP;
throw new IllegalArgumentException("Unknown MapTransform code '"+codeString+"'");
}
public String toCode(MapTransform code) {
if (code == MapTransform.CREATE)
return "create";
if (code == MapTransform.COPY)
return "copy";
if (code == MapTransform.TRUNCATE)
return "truncate";
if (code == MapTransform.ESCAPE)
return "escapeUrlParam";
if (code == MapTransform.CAST)
return "cast";
if (code == MapTransform.APPEND)
return "append";
if (code == MapTransform.TRANSLATE)
return "translate";
if (code == MapTransform.REFERENCE)
return "reference";
if (code == MapTransform.DATEOP)
return "dateOp";
if (code == MapTransform.UUID)
return "uuid";
if (code == MapTransform.POINTER)
return "pointer";
if (code == MapTransform.EVALUATE)
return "evaluate";
if (code == MapTransform.CC)
return "cc";
if (code == MapTransform.C)
return "c";
if (code == MapTransform.QTY)
return "qty";
if (code == MapTransform.ID)
return "id";
if (code == MapTransform.CP)
return "cp";
return "?";
}
public String toSystem(MapTransform code) {
return code.getSystem();
}
}

View File

@ -105,7 +105,7 @@ public class OperationServerWithSearchParamTypesDstu3Test {
@Test
public void testEscapedOperationName() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/%24andlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escape("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escape("VALTOK2A|VALTOK2B"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/%24andlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escapeUrlParam("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escapeUrlParam("VALTOK2A|VALTOK2B"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -118,7 +118,7 @@ public class OperationServerWithSearchParamTypesDstu3Test {
@Test
public void testAndListWithUrl() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$andlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escape("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escape("VALTOK2A|VALTOK2B"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$andlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escapeUrlParam("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escapeUrlParam("VALTOK2A|VALTOK2B"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -270,7 +270,7 @@ public class OperationServerWithSearchParamTypesDstu3Test {
}
@Test
public void testNonRepeatingWithUrl() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr=VALSTR&valtok=" + UrlUtil.escape("VALTOKA|VALTOKB"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr=VALSTR&valtok=" + UrlUtil.escapeUrlParam("VALTOKA|VALTOKB"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -290,7 +290,7 @@ public class OperationServerWithSearchParamTypesDstu3Test {
@Test
public void testNonRepeatingWithUrlQualified() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr:exact=VALSTR&valtok:not=" + UrlUtil.escape("VALTOKA|VALTOKB"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$nonrepeating?valstr:exact=VALSTR&valtok:not=" + UrlUtil.escapeUrlParam("VALTOKA|VALTOKB"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());
@ -345,7 +345,7 @@ public class OperationServerWithSearchParamTypesDstu3Test {
@Test
public void testOrListWithUrl() throws Exception {
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$orlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escape("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escape("VALTOK2A|VALTOK2B"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/$orlist?valstr=VALSTR1A,VALSTR1B&valstr=VALSTR2A,VALSTR2B&valtok=" + UrlUtil.escapeUrlParam("VALTOK1A|VALTOK1B") + "&valtok=" + UrlUtil.escapeUrlParam("VALTOK2A|VALTOK2B"));
HttpResponse status = ourClient.execute(httpGet);
assertEquals(200, status.getStatusLine().getStatusCode());

View File

@ -137,25 +137,25 @@ public class SearchDstu3Test {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier=foo%7Cbar&_format=" + Constants.CT_FHIR_JSON_NEW);
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
assertThat(linkNext, containsString("_format=" + UrlUtil.escape(Constants.CT_FHIR_JSON_NEW)));
assertThat(linkNext, containsString("_format=" + UrlUtil.escapeUrlParam(Constants.CT_FHIR_JSON_NEW)));
// Fetch the next page
httpGet = new HttpGet(linkNext);
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
assertThat(linkNext, containsString("_format=" + UrlUtil.escape(Constants.CT_FHIR_JSON_NEW)));
assertThat(linkNext, containsString("_format=" + UrlUtil.escapeUrlParam(Constants.CT_FHIR_JSON_NEW)));
// Fetch the next page
httpGet = new HttpGet(linkNext);
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
assertThat(linkNext, containsString("_format=" + UrlUtil.escape(Constants.CT_FHIR_JSON_NEW)));
assertThat(linkNext, containsString("_format=" + UrlUtil.escapeUrlParam(Constants.CT_FHIR_JSON_NEW)));
// Fetch the next page
httpGet = new HttpGet(linkNext);
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
assertThat(linkNext, containsString("_format=" + UrlUtil.escape(Constants.CT_FHIR_JSON_NEW)));
assertThat(linkNext, containsString("_format=" + UrlUtil.escapeUrlParam(Constants.CT_FHIR_JSON_NEW)));
}

View File

@ -1,406 +1,406 @@
/*
Copyright (c) 2011+, HL7, Inc
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
package org.hl7.fhir.instance.utilities.xml;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.hl7.fhir.instance.utilities.Utilities;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
public class XMLUtil {
public static final String SPACE_CHAR = "\u00A0";
public static boolean isNMToken(String name) {
if (name == null)
return false;
for (int i = 0; i < name.length(); i++)
if (!isNMTokenChar(name.charAt(i)))
return false;
return name.length() > 0;
}
public static boolean isNMTokenChar(char c) {
return isLetter(c) || isDigit(c) || c == '.' || c == '-' || c == '_' || c == ':' || isCombiningChar(c) || isExtender(c);
}
private static boolean isDigit(char c) {
return (c >= '\u0030' && c <= '\u0039') || (c >= '\u0660' && c <= '\u0669') || (c >= '\u06F0' && c <= '\u06F9') ||
(c >= '\u0966' && c <= '\u096F') || (c >= '\u09E6' && c <= '\u09EF') || (c >= '\u0A66' && c <= '\u0A6F') ||
(c >= '\u0AE6' && c <= '\u0AEF') || (c >= '\u0B66' && c <= '\u0B6F') || (c >= '\u0BE7' && c <= '\u0BEF') ||
(c >= '\u0C66' && c <= '\u0C6F') || (c >= '\u0CE6' && c <= '\u0CEF') || (c >= '\u0D66' && c <= '\u0D6F') ||
(c >= '\u0E50' && c <= '\u0E59') || (c >= '\u0ED0' && c <= '\u0ED9') || (c >= '\u0F20' && c <= '\u0F29');
}
private static boolean isCombiningChar(char c) {
return (c >= '\u0300' && c <= '\u0345') || (c >= '\u0360' && c <= '\u0361') || (c >= '\u0483' && c <= '\u0486') ||
(c >= '\u0591' && c <= '\u05A1') || (c >= '\u05A3' && c <= '\u05B9') || (c >= '\u05BB' && c <= '\u05BD') ||
c == '\u05BF' || (c >= '\u05C1' && c <= '\u05C2') || c == '\u05C4' || (c >= '\u064B' && c <= '\u0652') ||
c == '\u0670' || (c >= '\u06D6' && c <= '\u06DC') || (c >= '\u06DD' && c <= '\u06DF') || (c >= '\u06E0' && c <= '\u06E4') ||
(c >= '\u06E7' && c <= '\u06E8') || (c >= '\u06EA' && c <= '\u06ED') || (c >= '\u0901' && c <= '\u0903') || c == '\u093C' ||
(c >= '\u093E' && c <= '\u094C') || c == '\u094D' || (c >= '\u0951' && c <= '\u0954') || (c >= '\u0962' && c <= '\u0963') ||
(c >= '\u0981' && c <= '\u0983') || c == '\u09BC' || c == '\u09BE' || c == '\u09BF' || (c >= '\u09C0' && c <= '\u09C4') ||
(c >= '\u09C7' && c <= '\u09C8') || (c >= '\u09CB' && c <= '\u09CD') || c == '\u09D7' || (c >= '\u09E2' && c <= '\u09E3') ||
c == '\u0A02' || c == '\u0A3C' || c == '\u0A3E' || c == '\u0A3F' || (c >= '\u0A40' && c <= '\u0A42') ||
(c >= '\u0A47' && c <= '\u0A48') || (c >= '\u0A4B' && c <= '\u0A4D') || (c >= '\u0A70' && c <= '\u0A71') ||
(c >= '\u0A81' && c <= '\u0A83') || c == '\u0ABC' || (c >= '\u0ABE' && c <= '\u0AC5') || (c >= '\u0AC7' && c <= '\u0AC9') ||
(c >= '\u0ACB' && c <= '\u0ACD') || (c >= '\u0B01' && c <= '\u0B03') || c == '\u0B3C' || (c >= '\u0B3E' && c <= '\u0B43') ||
(c >= '\u0B47' && c <= '\u0B48') || (c >= '\u0B4B' && c <= '\u0B4D') || (c >= '\u0B56' && c <= '\u0B57') ||
(c >= '\u0B82' && c <= '\u0B83') || (c >= '\u0BBE' && c <= '\u0BC2') || (c >= '\u0BC6' && c <= '\u0BC8') ||
(c >= '\u0BCA' && c <= '\u0BCD') || c == '\u0BD7' || (c >= '\u0C01' && c <= '\u0C03') || (c >= '\u0C3E' && c <= '\u0C44') ||
(c >= '\u0C46' && c <= '\u0C48') || (c >= '\u0C4A' && c <= '\u0C4D') || (c >= '\u0C55' && c <= '\u0C56') ||
(c >= '\u0C82' && c <= '\u0C83') || (c >= '\u0CBE' && c <= '\u0CC4') || (c >= '\u0CC6' && c <= '\u0CC8') ||
(c >= '\u0CCA' && c <= '\u0CCD') || (c >= '\u0CD5' && c <= '\u0CD6') || (c >= '\u0D02' && c <= '\u0D03') ||
(c >= '\u0D3E' && c <= '\u0D43') || (c >= '\u0D46' && c <= '\u0D48') || (c >= '\u0D4A' && c <= '\u0D4D') || c == '\u0D57' ||
c == '\u0E31' || (c >= '\u0E34' && c <= '\u0E3A') || (c >= '\u0E47' && c <= '\u0E4E') || c == '\u0EB1' ||
(c >= '\u0EB4' && c <= '\u0EB9') || (c >= '\u0EBB' && c <= '\u0EBC') || (c >= '\u0EC8' && c <= '\u0ECD') ||
(c >= '\u0F18' && c <= '\u0F19') || c == '\u0F35' || c == '\u0F37' || c == '\u0F39' || c == '\u0F3E' || c == '\u0F3F' ||
(c >= '\u0F71' && c <= '\u0F84') || (c >= '\u0F86' && c <= '\u0F8B') || (c >= '\u0F90' && c <= '\u0F95') || c == '\u0F97' ||
(c >= '\u0F99' && c <= '\u0FAD') || (c >= '\u0FB1' && c <= '\u0FB7') || c == '\u0FB9' || (c >= '\u20D0' && c <= '\u20DC') ||
c == '\u20E1' || (c >= '\u302A' && c <= '\u302F') || c == '\u3099' || c == '\u309A';
}
private static boolean isExtender(char c) {
return c == '\u00B7' || c == '\u02D0' || c == '\u02D1' || c == '\u0387' || c == '\u0640' || c == '\u0E46' ||
c == '\u0EC6' || c == '\u3005' || (c >= '\u3031' && c <= '\u3035') || (c >= '\u309D' && c <= '\u309E') ||
(c >= '\u30FC' && c <= '\u30FE');
}
private static boolean isLetter(char c) {
return isBaseChar(c) || isIdeographic(c);
}
private static boolean isBaseChar(char c) {
return (c >= '\u0041' && c <= '\u005A') || (c >= '\u0061' && c <= '\u007A') || (c >= '\u00C0' && c <= '\u00D6') ||
(c >= '\u00D8' && c <= '\u00F6') || (c >= '\u00F8' && c <= '\u00FF') || (c >= '\u0100' && c <= '\u0131') ||
(c >= '\u0134' && c <= '\u013E') || (c >= '\u0141' && c <= '\u0148') || (c >= '\u014A' && c <= '\u017E') ||
(c >= '\u0180' && c <= '\u01C3') || (c >= '\u01CD' && c <= '\u01F0') || (c >= '\u01F4' && c <= '\u01F5') ||
(c >= '\u01FA' && c <= '\u0217') || (c >= '\u0250' && c <= '\u02A8') || (c >= '\u02BB' && c <= '\u02C1') ||
c == '\u0386' || (c >= '\u0388' && c <= '\u038A') || c == '\u038C' || (c >= '\u038E' && c <= '\u03A1') ||
(c >= '\u03A3' && c <= '\u03CE') || (c >= '\u03D0' && c <= '\u03D6') || c == '\u03DA' || c == '\u03DC' || c == '\u03DE' ||
c == '\u03E0' || (c >= '\u03E2' && c <= '\u03F3') || (c >= '\u0401' && c <= '\u040C') || (c >= '\u040E' && c <= '\u044F') ||
(c >= '\u0451' && c <= '\u045C') || (c >= '\u045E' && c <= '\u0481') || (c >= '\u0490' && c <= '\u04C4') ||
(c >= '\u04C7' && c <= '\u04C8') || (c >= '\u04CB' && c <= '\u04CC') || (c >= '\u04D0' && c <= '\u04EB') ||
(c >= '\u04EE' && c <= '\u04F5') || (c >= '\u04F8' && c <= '\u04F9') || (c >= '\u0531' && c <= '\u0556') ||
c == '\u0559' || (c >= '\u0561' && c <= '\u0586') || (c >= '\u05D0' && c <= '\u05EA') || (c >= '\u05F0' && c <= '\u05F2') ||
(c >= '\u0621' && c <= '\u063A') || (c >= '\u0641' && c <= '\u064A') || (c >= '\u0671' && c <= '\u06B7') ||
(c >= '\u06BA' && c <= '\u06BE') || (c >= '\u06C0' && c <= '\u06CE') || (c >= '\u06D0' && c <= '\u06D3') ||
c == '\u06D5' || (c >= '\u06E5' && c <= '\u06E6') || (c >= '\u0905' && c <= '\u0939') || c == '\u093D' ||
(c >= '\u0958' && c <= '\u0961') || (c >= '\u0985' && c <= '\u098C') || (c >= '\u098F' && c <= '\u0990') ||
(c >= '\u0993' && c <= '\u09A8') || (c >= '\u09AA' && c <= '\u09B0') || c == '\u09B2' ||
(c >= '\u09B6' && c <= '\u09B9') || (c >= '\u09DC' && c <= '\u09DD') || (c >= '\u09DF' && c <= '\u09E1') ||
(c >= '\u09F0' && c <= '\u09F1') || (c >= '\u0A05' && c <= '\u0A0A') || (c >= '\u0A0F' && c <= '\u0A10') ||
(c >= '\u0A13' && c <= '\u0A28') || (c >= '\u0A2A' && c <= '\u0A30') || (c >= '\u0A32' && c <= '\u0A33') ||
(c >= '\u0A35' && c <= '\u0A36') || (c >= '\u0A38' && c <= '\u0A39') || (c >= '\u0A59' && c <= '\u0A5C') ||
c == '\u0A5E' || (c >= '\u0A72' && c <= '\u0A74') || (c >= '\u0A85' && c <= '\u0A8B') || c == '\u0A8D' ||
(c >= '\u0A8F' && c <= '\u0A91') || (c >= '\u0A93' && c <= '\u0AA8') || (c >= '\u0AAA' && c <= '\u0AB0') ||
(c >= '\u0AB2' && c <= '\u0AB3') || (c >= '\u0AB5' && c <= '\u0AB9') || c == '\u0ABD' || c == '\u0AE0' ||
(c >= '\u0B05' && c <= '\u0B0C') || (c >= '\u0B0F' && c <= '\u0B10') || (c >= '\u0B13' && c <= '\u0B28') ||
(c >= '\u0B2A' && c <= '\u0B30') || (c >= '\u0B32' && c <= '\u0B33') || (c >= '\u0B36' && c <= '\u0B39') ||
c == '\u0B3D' || (c >= '\u0B5C' && c <= '\u0B5D') || (c >= '\u0B5F' && c <= '\u0B61') ||
(c >= '\u0B85' && c <= '\u0B8A') || (c >= '\u0B8E' && c <= '\u0B90') || (c >= '\u0B92' && c <= '\u0B95') ||
(c >= '\u0B99' && c <= '\u0B9A') || c == '\u0B9C' || (c >= '\u0B9E' && c <= '\u0B9F') ||
(c >= '\u0BA3' && c <= '\u0BA4') || (c >= '\u0BA8' && c <= '\u0BAA') || (c >= '\u0BAE' && c <= '\u0BB5') ||
(c >= '\u0BB7' && c <= '\u0BB9') || (c >= '\u0C05' && c <= '\u0C0C') || (c >= '\u0C0E' && c <= '\u0C10') ||
(c >= '\u0C12' && c <= '\u0C28') || (c >= '\u0C2A' && c <= '\u0C33') || (c >= '\u0C35' && c <= '\u0C39') ||
(c >= '\u0C60' && c <= '\u0C61') || (c >= '\u0C85' && c <= '\u0C8C') || (c >= '\u0C8E' && c <= '\u0C90') ||
(c >= '\u0C92' && c <= '\u0CA8') || (c >= '\u0CAA' && c <= '\u0CB3') || (c >= '\u0CB5' && c <= '\u0CB9') ||
c == '\u0CDE' || (c >= '\u0CE0' && c <= '\u0CE1') || (c >= '\u0D05' && c <= '\u0D0C') ||
(c >= '\u0D0E' && c <= '\u0D10') || (c >= '\u0D12' && c <= '\u0D28') || (c >= '\u0D2A' && c <= '\u0D39') ||
(c >= '\u0D60' && c <= '\u0D61') || (c >= '\u0E01' && c <= '\u0E2E') || c == '\u0E30' ||
(c >= '\u0E32' && c <= '\u0E33') || (c >= '\u0E40' && c <= '\u0E45') || (c >= '\u0E81' && c <= '\u0E82') ||
c == '\u0E84' || (c >= '\u0E87' && c <= '\u0E88') || c == '\u0E8A' || c == '\u0E8D' || (c >= '\u0E94' && c <= '\u0E97') ||
(c >= '\u0E99' && c <= '\u0E9F') || (c >= '\u0EA1' && c <= '\u0EA3') || c == '\u0EA5' || c == '\u0EA7' ||
(c >= '\u0EAA' && c <= '\u0EAB') || (c >= '\u0EAD' && c <= '\u0EAE') || c == '\u0EB0' ||
(c >= '\u0EB2' && c <= '\u0EB3') || c == '\u0EBD' || (c >= '\u0EC0' && c <= '\u0EC4') ||
(c >= '\u0F40' && c <= '\u0F47') || (c >= '\u0F49' && c <= '\u0F69') || (c >= '\u10A0' && c <= '\u10C5') ||
(c >= '\u10D0' && c <= '\u10F6') || c == '\u1100' || (c >= '\u1102' && c <= '\u1103') ||
(c >= '\u1105' && c <= '\u1107') || c == '\u1109' || (c >= '\u110B' && c <= '\u110C') ||
(c >= '\u110E' && c <= '\u1112') || c == '\u113C' || c == '\u113E' || c == '\u1140' || c == '\u114C' ||
c == '\u114E' || c == '\u1150' || (c >= '\u1154' && c <= '\u1155') || c == '\u1159' ||
(c >= '\u115F' && c <= '\u1161') || c == '\u1163' || c == '\u1165' || c == '\u1167' || c == '\u1169' ||
(c >= '\u116D' && c <= '\u116E') || (c >= '\u1172' && c <= '\u1173') || c == '\u1175' ||
c == '\u119E' || c == '\u11A8' || c == '\u11AB' || (c >= '\u11AE' && c <= '\u11AF') ||
(c >= '\u11B7' && c <= '\u11B8') || c == '\u11BA' || (c >= '\u11BC' && c <= '\u11C2') ||
c == '\u11EB' || c == '\u11F0' || c == '\u11F9' || (c >= '\u1E00' && c <= '\u1E9B') || (c >= '\u1EA0' && c <= '\u1EF9') ||
(c >= '\u1F00' && c <= '\u1F15') || (c >= '\u1F18' && c <= '\u1F1D') || (c >= '\u1F20' && c <= '\u1F45') ||
(c >= '\u1F48' && c <= '\u1F4D') || (c >= '\u1F50' && c <= '\u1F57') || c == '\u1F59' || c == '\u1F5B' || c == '\u1F5D' ||
(c >= '\u1F5F' && c <= '\u1F7D') || (c >= '\u1F80' && c <= '\u1FB4') || (c >= '\u1FB6' && c <= '\u1FBC') ||
c == '\u1FBE' || (c >= '\u1FC2' && c <= '\u1FC4') || (c >= '\u1FC6' && c <= '\u1FCC') ||
(c >= '\u1FD0' && c <= '\u1FD3') || (c >= '\u1FD6' && c <= '\u1FDB') || (c >= '\u1FE0' && c <= '\u1FEC') ||
(c >= '\u1FF2' && c <= '\u1FF4') || (c >= '\u1FF6' && c <= '\u1FFC') || c == '\u2126' ||
(c >= '\u212A' && c <= '\u212B') || c == '\u212E' || (c >= '\u2180' && c <= '\u2182') ||
(c >= '\u3041' && c <= '\u3094') || (c >= '\u30A1' && c <= '\u30FA') || (c >= '\u3105' && c <= '\u312C') ||
(c >= '\uAC00' && c <= '\uD7A3');
}
private static boolean isIdeographic(char c) {
return (c >= '\u4E00' && c <= '\u9FA5') || c == '\u3007' || (c >= '\u3021' && c <= '\u3029');
}
public static String determineEncoding(InputStream stream) throws IOException {
stream.mark(20000);
try {
int b0 = stream.read();
int b1 = stream.read();
int b2 = stream.read();
int b3 = stream.read();
if (b0 == 0xFE && b1 == 0xFF)
return "UTF-16BE";
else if (b0 == 0xFF && b1 == 0xFE)
return "UTF-16LE";
else if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF )
return "UTF-8";
else if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F)
return "UTF-16BE";
else if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00)
return "UTF-16LE";
else if (b0 == 0x3C && b1 == 0x3F && b2 == 0x78 && b3 == 0x6D) {
// UTF-8, ISO 646, ASCII, some part of ISO 8859, Shift-JIS, EUC, or any other 7-bit, 8-bit, or mixed-width encoding
// which ensures that the characters of ASCII have their normal positions, width, and values; the actual encoding
// declaration must be read to detect which of these applies, but since all of these encodings use the same bit patterns
// for the relevant ASCII characters, the encoding declaration itself may be read reliably
InputStreamReader rdr = new InputStreamReader(stream, "US-ASCII");
String hdr = readFirstLine(rdr);
return extractEncoding(hdr);
} else
return null;
} finally {
stream.reset();
}
}
private static String extractEncoding(String hdr) {
int i = hdr.indexOf("encoding=");
if (i == -1)
return null;
hdr = hdr.substring(i+9);
char sep = hdr.charAt(0);
hdr = hdr.substring(1);
i = hdr.indexOf(sep);
if (i == -1)
return null;
return hdr.substring(0, i);
}
private static String readFirstLine(InputStreamReader rdr) throws IOException {
char[] buf = new char[1];
StringBuffer bldr = new StringBuffer();
rdr.read(buf);
while (buf[0] != '>') {
bldr.append(buf[0]);
rdr.read(buf);
}
return bldr.toString();
}
public static boolean charSetImpliesAscii(String charset) {
return charset.equals("ISO-8859-1") || charset.equals("US-ASCII");
}
/**
* Converts the raw characters to XML escape characters.
*
* @param rawContent
* @param charset Null when charset is not known, so we assume it's unicode
* @param isNoLines
* @return escape string
*/
public static String escapeXML(String rawContent, String charset, boolean isNoLines) {
if (rawContent == null)
return "";
else {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < rawContent.length(); i++) {
char ch = rawContent.charAt(i);
if (ch == '\'')
sb.append("&#39;");
else if (ch == '&')
sb.append("&amp;");
else if (ch == '"')
sb.append("&quot;");
else if (ch == '<')
sb.append("&lt;");
else if (ch == '>')
sb.append("&gt;");
else if (ch > '~' && charset != null && charSetImpliesAscii(charset))
// TODO - why is hashcode the only way to get the unicode number for the character
// in jre 5.0?
sb.append("&#x"+Integer.toHexString(new Character(ch).hashCode()).toUpperCase()+";");
else if (isNoLines) {
if (ch == '\r')
sb.append("&#xA;");
else if (ch != '\n')
sb.append(ch);
}
else
sb.append(ch);
}
return sb.toString();
}
}
public static Element getFirstChild(Element e) {
if (e == null)
return null;
Node n = e.getFirstChild();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getNextSibling();
return (Element) n;
}
public static Element getNamedChild(Element e, String name) {
Element c = getFirstChild(e);
while (c != null && !name.equals(c.getLocalName()) && !name.equals(c.getNodeName()))
c = getNextSibling(c);
return c;
}
public static Element getNextSibling(Element e) {
Node n = e.getNextSibling();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getNextSibling();
return (Element) n;
}
public static void getNamedChildren(Element e, String name, List<Element> set) {
Element c = getFirstChild(e);
while (c != null) {
if (name.equals(c.getLocalName()) || name.equals(c.getNodeName()) )
set.add(c);
c = getNextSibling(c);
}
}
public static String htmlToXmlEscapedPlainText(Element r) {
StringBuilder s = new StringBuilder();
Node n = r.getFirstChild();
boolean ws = false;
while (n != null) {
if (n.getNodeType() == Node.TEXT_NODE) {
String t = n.getTextContent().trim();
if (Utilities.noString(t))
ws = true;
else {
if (ws)
s.append(" ");
ws = false;
s.append(t);
}
}
if (n.getNodeType() == Node.ELEMENT_NODE) {
if (ws)
s.append(" ");
ws = false;
s.append(htmlToXmlEscapedPlainText((Element) n));
if (r.getNodeName().equals("br") || r.getNodeName().equals("p"))
s.append("\r\n");
}
n = n.getNextSibling();
}
return s.toString();
}
public static String htmlToXmlEscapedPlainText(String definition) throws Exception {
return htmlToXmlEscapedPlainText(parseToDom("<div>"+definition+"</div>").getDocumentElement());
}
public static String elementToString(Element el) {
if (el == null)
return "";
Document document = el.getOwnerDocument();
DOMImplementationLS domImplLS = (DOMImplementationLS) document
.getImplementation();
LSSerializer serializer = domImplLS.createLSSerializer();
return serializer.writeToString(el);
}
public static String getNamedChildValue(Element element, String name) {
Element e = getNamedChild(element, name);
return e == null ? null : e.getAttribute("value");
}
public static void getNamedChildrenWithWildcard(Element focus, String name, List<Element> children) {
Element c = getFirstChild(focus);
while (c != null) {
String n = c.getLocalName() != null ? c.getLocalName() : c.getNodeName();
if (name.equals(n) || (name.endsWith("[x]") && n.startsWith(name.substring(0, name.length()-3))))
children.add(c);
c = getNextSibling(c);
}
}
public static boolean hasNamedChild(Element e, String name) {
Element c = getFirstChild(e);
while (c != null && !name.equals(c.getLocalName()) && !name.equals(c.getNodeName()))
c = getNextSibling(c);
return c != null;
}
public static Document parseToDom(String content) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(content.getBytes()));
}
public static Element getLastChild(Element e) {
if (e == null)
return null;
Node n = e.getLastChild();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getPreviousSibling();
return (Element) n;
}
public static Element getPrevSibling(Element e) {
Node n = e.getPreviousSibling();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getPreviousSibling();
return (Element) n;
}
}
/*
Copyright (c) 2011+, HL7, Inc
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
package org.hl7.fhir.instance.utilities.xml;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.hl7.fhir.instance.utilities.Utilities;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
public class XMLUtil {
public static final String SPACE_CHAR = "\u00A0";
public static boolean isNMToken(String name) {
if (name == null)
return false;
for (int i = 0; i < name.length(); i++)
if (!isNMTokenChar(name.charAt(i)))
return false;
return name.length() > 0;
}
public static boolean isNMTokenChar(char c) {
return isLetter(c) || isDigit(c) || c == '.' || c == '-' || c == '_' || c == ':' || isCombiningChar(c) || isExtender(c);
}
private static boolean isDigit(char c) {
return (c >= '\u0030' && c <= '\u0039') || (c >= '\u0660' && c <= '\u0669') || (c >= '\u06F0' && c <= '\u06F9') ||
(c >= '\u0966' && c <= '\u096F') || (c >= '\u09E6' && c <= '\u09EF') || (c >= '\u0A66' && c <= '\u0A6F') ||
(c >= '\u0AE6' && c <= '\u0AEF') || (c >= '\u0B66' && c <= '\u0B6F') || (c >= '\u0BE7' && c <= '\u0BEF') ||
(c >= '\u0C66' && c <= '\u0C6F') || (c >= '\u0CE6' && c <= '\u0CEF') || (c >= '\u0D66' && c <= '\u0D6F') ||
(c >= '\u0E50' && c <= '\u0E59') || (c >= '\u0ED0' && c <= '\u0ED9') || (c >= '\u0F20' && c <= '\u0F29');
}
private static boolean isCombiningChar(char c) {
return (c >= '\u0300' && c <= '\u0345') || (c >= '\u0360' && c <= '\u0361') || (c >= '\u0483' && c <= '\u0486') ||
(c >= '\u0591' && c <= '\u05A1') || (c >= '\u05A3' && c <= '\u05B9') || (c >= '\u05BB' && c <= '\u05BD') ||
c == '\u05BF' || (c >= '\u05C1' && c <= '\u05C2') || c == '\u05C4' || (c >= '\u064B' && c <= '\u0652') ||
c == '\u0670' || (c >= '\u06D6' && c <= '\u06DC') || (c >= '\u06DD' && c <= '\u06DF') || (c >= '\u06E0' && c <= '\u06E4') ||
(c >= '\u06E7' && c <= '\u06E8') || (c >= '\u06EA' && c <= '\u06ED') || (c >= '\u0901' && c <= '\u0903') || c == '\u093C' ||
(c >= '\u093E' && c <= '\u094C') || c == '\u094D' || (c >= '\u0951' && c <= '\u0954') || (c >= '\u0962' && c <= '\u0963') ||
(c >= '\u0981' && c <= '\u0983') || c == '\u09BC' || c == '\u09BE' || c == '\u09BF' || (c >= '\u09C0' && c <= '\u09C4') ||
(c >= '\u09C7' && c <= '\u09C8') || (c >= '\u09CB' && c <= '\u09CD') || c == '\u09D7' || (c >= '\u09E2' && c <= '\u09E3') ||
c == '\u0A02' || c == '\u0A3C' || c == '\u0A3E' || c == '\u0A3F' || (c >= '\u0A40' && c <= '\u0A42') ||
(c >= '\u0A47' && c <= '\u0A48') || (c >= '\u0A4B' && c <= '\u0A4D') || (c >= '\u0A70' && c <= '\u0A71') ||
(c >= '\u0A81' && c <= '\u0A83') || c == '\u0ABC' || (c >= '\u0ABE' && c <= '\u0AC5') || (c >= '\u0AC7' && c <= '\u0AC9') ||
(c >= '\u0ACB' && c <= '\u0ACD') || (c >= '\u0B01' && c <= '\u0B03') || c == '\u0B3C' || (c >= '\u0B3E' && c <= '\u0B43') ||
(c >= '\u0B47' && c <= '\u0B48') || (c >= '\u0B4B' && c <= '\u0B4D') || (c >= '\u0B56' && c <= '\u0B57') ||
(c >= '\u0B82' && c <= '\u0B83') || (c >= '\u0BBE' && c <= '\u0BC2') || (c >= '\u0BC6' && c <= '\u0BC8') ||
(c >= '\u0BCA' && c <= '\u0BCD') || c == '\u0BD7' || (c >= '\u0C01' && c <= '\u0C03') || (c >= '\u0C3E' && c <= '\u0C44') ||
(c >= '\u0C46' && c <= '\u0C48') || (c >= '\u0C4A' && c <= '\u0C4D') || (c >= '\u0C55' && c <= '\u0C56') ||
(c >= '\u0C82' && c <= '\u0C83') || (c >= '\u0CBE' && c <= '\u0CC4') || (c >= '\u0CC6' && c <= '\u0CC8') ||
(c >= '\u0CCA' && c <= '\u0CCD') || (c >= '\u0CD5' && c <= '\u0CD6') || (c >= '\u0D02' && c <= '\u0D03') ||
(c >= '\u0D3E' && c <= '\u0D43') || (c >= '\u0D46' && c <= '\u0D48') || (c >= '\u0D4A' && c <= '\u0D4D') || c == '\u0D57' ||
c == '\u0E31' || (c >= '\u0E34' && c <= '\u0E3A') || (c >= '\u0E47' && c <= '\u0E4E') || c == '\u0EB1' ||
(c >= '\u0EB4' && c <= '\u0EB9') || (c >= '\u0EBB' && c <= '\u0EBC') || (c >= '\u0EC8' && c <= '\u0ECD') ||
(c >= '\u0F18' && c <= '\u0F19') || c == '\u0F35' || c == '\u0F37' || c == '\u0F39' || c == '\u0F3E' || c == '\u0F3F' ||
(c >= '\u0F71' && c <= '\u0F84') || (c >= '\u0F86' && c <= '\u0F8B') || (c >= '\u0F90' && c <= '\u0F95') || c == '\u0F97' ||
(c >= '\u0F99' && c <= '\u0FAD') || (c >= '\u0FB1' && c <= '\u0FB7') || c == '\u0FB9' || (c >= '\u20D0' && c <= '\u20DC') ||
c == '\u20E1' || (c >= '\u302A' && c <= '\u302F') || c == '\u3099' || c == '\u309A';
}
private static boolean isExtender(char c) {
return c == '\u00B7' || c == '\u02D0' || c == '\u02D1' || c == '\u0387' || c == '\u0640' || c == '\u0E46' ||
c == '\u0EC6' || c == '\u3005' || (c >= '\u3031' && c <= '\u3035') || (c >= '\u309D' && c <= '\u309E') ||
(c >= '\u30FC' && c <= '\u30FE');
}
private static boolean isLetter(char c) {
return isBaseChar(c) || isIdeographic(c);
}
private static boolean isBaseChar(char c) {
return (c >= '\u0041' && c <= '\u005A') || (c >= '\u0061' && c <= '\u007A') || (c >= '\u00C0' && c <= '\u00D6') ||
(c >= '\u00D8' && c <= '\u00F6') || (c >= '\u00F8' && c <= '\u00FF') || (c >= '\u0100' && c <= '\u0131') ||
(c >= '\u0134' && c <= '\u013E') || (c >= '\u0141' && c <= '\u0148') || (c >= '\u014A' && c <= '\u017E') ||
(c >= '\u0180' && c <= '\u01C3') || (c >= '\u01CD' && c <= '\u01F0') || (c >= '\u01F4' && c <= '\u01F5') ||
(c >= '\u01FA' && c <= '\u0217') || (c >= '\u0250' && c <= '\u02A8') || (c >= '\u02BB' && c <= '\u02C1') ||
c == '\u0386' || (c >= '\u0388' && c <= '\u038A') || c == '\u038C' || (c >= '\u038E' && c <= '\u03A1') ||
(c >= '\u03A3' && c <= '\u03CE') || (c >= '\u03D0' && c <= '\u03D6') || c == '\u03DA' || c == '\u03DC' || c == '\u03DE' ||
c == '\u03E0' || (c >= '\u03E2' && c <= '\u03F3') || (c >= '\u0401' && c <= '\u040C') || (c >= '\u040E' && c <= '\u044F') ||
(c >= '\u0451' && c <= '\u045C') || (c >= '\u045E' && c <= '\u0481') || (c >= '\u0490' && c <= '\u04C4') ||
(c >= '\u04C7' && c <= '\u04C8') || (c >= '\u04CB' && c <= '\u04CC') || (c >= '\u04D0' && c <= '\u04EB') ||
(c >= '\u04EE' && c <= '\u04F5') || (c >= '\u04F8' && c <= '\u04F9') || (c >= '\u0531' && c <= '\u0556') ||
c == '\u0559' || (c >= '\u0561' && c <= '\u0586') || (c >= '\u05D0' && c <= '\u05EA') || (c >= '\u05F0' && c <= '\u05F2') ||
(c >= '\u0621' && c <= '\u063A') || (c >= '\u0641' && c <= '\u064A') || (c >= '\u0671' && c <= '\u06B7') ||
(c >= '\u06BA' && c <= '\u06BE') || (c >= '\u06C0' && c <= '\u06CE') || (c >= '\u06D0' && c <= '\u06D3') ||
c == '\u06D5' || (c >= '\u06E5' && c <= '\u06E6') || (c >= '\u0905' && c <= '\u0939') || c == '\u093D' ||
(c >= '\u0958' && c <= '\u0961') || (c >= '\u0985' && c <= '\u098C') || (c >= '\u098F' && c <= '\u0990') ||
(c >= '\u0993' && c <= '\u09A8') || (c >= '\u09AA' && c <= '\u09B0') || c == '\u09B2' ||
(c >= '\u09B6' && c <= '\u09B9') || (c >= '\u09DC' && c <= '\u09DD') || (c >= '\u09DF' && c <= '\u09E1') ||
(c >= '\u09F0' && c <= '\u09F1') || (c >= '\u0A05' && c <= '\u0A0A') || (c >= '\u0A0F' && c <= '\u0A10') ||
(c >= '\u0A13' && c <= '\u0A28') || (c >= '\u0A2A' && c <= '\u0A30') || (c >= '\u0A32' && c <= '\u0A33') ||
(c >= '\u0A35' && c <= '\u0A36') || (c >= '\u0A38' && c <= '\u0A39') || (c >= '\u0A59' && c <= '\u0A5C') ||
c == '\u0A5E' || (c >= '\u0A72' && c <= '\u0A74') || (c >= '\u0A85' && c <= '\u0A8B') || c == '\u0A8D' ||
(c >= '\u0A8F' && c <= '\u0A91') || (c >= '\u0A93' && c <= '\u0AA8') || (c >= '\u0AAA' && c <= '\u0AB0') ||
(c >= '\u0AB2' && c <= '\u0AB3') || (c >= '\u0AB5' && c <= '\u0AB9') || c == '\u0ABD' || c == '\u0AE0' ||
(c >= '\u0B05' && c <= '\u0B0C') || (c >= '\u0B0F' && c <= '\u0B10') || (c >= '\u0B13' && c <= '\u0B28') ||
(c >= '\u0B2A' && c <= '\u0B30') || (c >= '\u0B32' && c <= '\u0B33') || (c >= '\u0B36' && c <= '\u0B39') ||
c == '\u0B3D' || (c >= '\u0B5C' && c <= '\u0B5D') || (c >= '\u0B5F' && c <= '\u0B61') ||
(c >= '\u0B85' && c <= '\u0B8A') || (c >= '\u0B8E' && c <= '\u0B90') || (c >= '\u0B92' && c <= '\u0B95') ||
(c >= '\u0B99' && c <= '\u0B9A') || c == '\u0B9C' || (c >= '\u0B9E' && c <= '\u0B9F') ||
(c >= '\u0BA3' && c <= '\u0BA4') || (c >= '\u0BA8' && c <= '\u0BAA') || (c >= '\u0BAE' && c <= '\u0BB5') ||
(c >= '\u0BB7' && c <= '\u0BB9') || (c >= '\u0C05' && c <= '\u0C0C') || (c >= '\u0C0E' && c <= '\u0C10') ||
(c >= '\u0C12' && c <= '\u0C28') || (c >= '\u0C2A' && c <= '\u0C33') || (c >= '\u0C35' && c <= '\u0C39') ||
(c >= '\u0C60' && c <= '\u0C61') || (c >= '\u0C85' && c <= '\u0C8C') || (c >= '\u0C8E' && c <= '\u0C90') ||
(c >= '\u0C92' && c <= '\u0CA8') || (c >= '\u0CAA' && c <= '\u0CB3') || (c >= '\u0CB5' && c <= '\u0CB9') ||
c == '\u0CDE' || (c >= '\u0CE0' && c <= '\u0CE1') || (c >= '\u0D05' && c <= '\u0D0C') ||
(c >= '\u0D0E' && c <= '\u0D10') || (c >= '\u0D12' && c <= '\u0D28') || (c >= '\u0D2A' && c <= '\u0D39') ||
(c >= '\u0D60' && c <= '\u0D61') || (c >= '\u0E01' && c <= '\u0E2E') || c == '\u0E30' ||
(c >= '\u0E32' && c <= '\u0E33') || (c >= '\u0E40' && c <= '\u0E45') || (c >= '\u0E81' && c <= '\u0E82') ||
c == '\u0E84' || (c >= '\u0E87' && c <= '\u0E88') || c == '\u0E8A' || c == '\u0E8D' || (c >= '\u0E94' && c <= '\u0E97') ||
(c >= '\u0E99' && c <= '\u0E9F') || (c >= '\u0EA1' && c <= '\u0EA3') || c == '\u0EA5' || c == '\u0EA7' ||
(c >= '\u0EAA' && c <= '\u0EAB') || (c >= '\u0EAD' && c <= '\u0EAE') || c == '\u0EB0' ||
(c >= '\u0EB2' && c <= '\u0EB3') || c == '\u0EBD' || (c >= '\u0EC0' && c <= '\u0EC4') ||
(c >= '\u0F40' && c <= '\u0F47') || (c >= '\u0F49' && c <= '\u0F69') || (c >= '\u10A0' && c <= '\u10C5') ||
(c >= '\u10D0' && c <= '\u10F6') || c == '\u1100' || (c >= '\u1102' && c <= '\u1103') ||
(c >= '\u1105' && c <= '\u1107') || c == '\u1109' || (c >= '\u110B' && c <= '\u110C') ||
(c >= '\u110E' && c <= '\u1112') || c == '\u113C' || c == '\u113E' || c == '\u1140' || c == '\u114C' ||
c == '\u114E' || c == '\u1150' || (c >= '\u1154' && c <= '\u1155') || c == '\u1159' ||
(c >= '\u115F' && c <= '\u1161') || c == '\u1163' || c == '\u1165' || c == '\u1167' || c == '\u1169' ||
(c >= '\u116D' && c <= '\u116E') || (c >= '\u1172' && c <= '\u1173') || c == '\u1175' ||
c == '\u119E' || c == '\u11A8' || c == '\u11AB' || (c >= '\u11AE' && c <= '\u11AF') ||
(c >= '\u11B7' && c <= '\u11B8') || c == '\u11BA' || (c >= '\u11BC' && c <= '\u11C2') ||
c == '\u11EB' || c == '\u11F0' || c == '\u11F9' || (c >= '\u1E00' && c <= '\u1E9B') || (c >= '\u1EA0' && c <= '\u1EF9') ||
(c >= '\u1F00' && c <= '\u1F15') || (c >= '\u1F18' && c <= '\u1F1D') || (c >= '\u1F20' && c <= '\u1F45') ||
(c >= '\u1F48' && c <= '\u1F4D') || (c >= '\u1F50' && c <= '\u1F57') || c == '\u1F59' || c == '\u1F5B' || c == '\u1F5D' ||
(c >= '\u1F5F' && c <= '\u1F7D') || (c >= '\u1F80' && c <= '\u1FB4') || (c >= '\u1FB6' && c <= '\u1FBC') ||
c == '\u1FBE' || (c >= '\u1FC2' && c <= '\u1FC4') || (c >= '\u1FC6' && c <= '\u1FCC') ||
(c >= '\u1FD0' && c <= '\u1FD3') || (c >= '\u1FD6' && c <= '\u1FDB') || (c >= '\u1FE0' && c <= '\u1FEC') ||
(c >= '\u1FF2' && c <= '\u1FF4') || (c >= '\u1FF6' && c <= '\u1FFC') || c == '\u2126' ||
(c >= '\u212A' && c <= '\u212B') || c == '\u212E' || (c >= '\u2180' && c <= '\u2182') ||
(c >= '\u3041' && c <= '\u3094') || (c >= '\u30A1' && c <= '\u30FA') || (c >= '\u3105' && c <= '\u312C') ||
(c >= '\uAC00' && c <= '\uD7A3');
}
private static boolean isIdeographic(char c) {
return (c >= '\u4E00' && c <= '\u9FA5') || c == '\u3007' || (c >= '\u3021' && c <= '\u3029');
}
public static String determineEncoding(InputStream stream) throws IOException {
stream.mark(20000);
try {
int b0 = stream.read();
int b1 = stream.read();
int b2 = stream.read();
int b3 = stream.read();
if (b0 == 0xFE && b1 == 0xFF)
return "UTF-16BE";
else if (b0 == 0xFF && b1 == 0xFE)
return "UTF-16LE";
else if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF )
return "UTF-8";
else if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F)
return "UTF-16BE";
else if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00)
return "UTF-16LE";
else if (b0 == 0x3C && b1 == 0x3F && b2 == 0x78 && b3 == 0x6D) {
// UTF-8, ISO 646, ASCII, some part of ISO 8859, Shift-JIS, EUC, or any other 7-bit, 8-bit, or mixed-width encoding
// which ensures that the characters of ASCII have their normal positions, width, and values; the actual encoding
// declaration must be read to detect which of these applies, but since all of these encodings use the same bit patterns
// for the relevant ASCII characters, the encoding declaration itself may be read reliably
InputStreamReader rdr = new InputStreamReader(stream, "US-ASCII");
String hdr = readFirstLine(rdr);
return extractEncoding(hdr);
} else
return null;
} finally {
stream.reset();
}
}
private static String extractEncoding(String hdr) {
int i = hdr.indexOf("encoding=");
if (i == -1)
return null;
hdr = hdr.substring(i+9);
char sep = hdr.charAt(0);
hdr = hdr.substring(1);
i = hdr.indexOf(sep);
if (i == -1)
return null;
return hdr.substring(0, i);
}
private static String readFirstLine(InputStreamReader rdr) throws IOException {
char[] buf = new char[1];
StringBuffer bldr = new StringBuffer();
rdr.read(buf);
while (buf[0] != '>') {
bldr.append(buf[0]);
rdr.read(buf);
}
return bldr.toString();
}
public static boolean charSetImpliesAscii(String charset) {
return charset.equals("ISO-8859-1") || charset.equals("US-ASCII");
}
/**
* Converts the raw characters to XML escapeUrlParam characters.
*
* @param rawContent
* @param charset Null when charset is not known, so we assume it's unicode
* @param isNoLines
* @return escapeUrlParam string
*/
public static String escapeXML(String rawContent, String charset, boolean isNoLines) {
if (rawContent == null)
return "";
else {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < rawContent.length(); i++) {
char ch = rawContent.charAt(i);
if (ch == '\'')
sb.append("&#39;");
else if (ch == '&')
sb.append("&amp;");
else if (ch == '"')
sb.append("&quot;");
else if (ch == '<')
sb.append("&lt;");
else if (ch == '>')
sb.append("&gt;");
else if (ch > '~' && charset != null && charSetImpliesAscii(charset))
// TODO - why is hashcode the only way to get the unicode number for the character
// in jre 5.0?
sb.append("&#x"+Integer.toHexString(new Character(ch).hashCode()).toUpperCase()+";");
else if (isNoLines) {
if (ch == '\r')
sb.append("&#xA;");
else if (ch != '\n')
sb.append(ch);
}
else
sb.append(ch);
}
return sb.toString();
}
}
public static Element getFirstChild(Element e) {
if (e == null)
return null;
Node n = e.getFirstChild();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getNextSibling();
return (Element) n;
}
public static Element getNamedChild(Element e, String name) {
Element c = getFirstChild(e);
while (c != null && !name.equals(c.getLocalName()) && !name.equals(c.getNodeName()))
c = getNextSibling(c);
return c;
}
public static Element getNextSibling(Element e) {
Node n = e.getNextSibling();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getNextSibling();
return (Element) n;
}
public static void getNamedChildren(Element e, String name, List<Element> set) {
Element c = getFirstChild(e);
while (c != null) {
if (name.equals(c.getLocalName()) || name.equals(c.getNodeName()) )
set.add(c);
c = getNextSibling(c);
}
}
public static String htmlToXmlEscapedPlainText(Element r) {
StringBuilder s = new StringBuilder();
Node n = r.getFirstChild();
boolean ws = false;
while (n != null) {
if (n.getNodeType() == Node.TEXT_NODE) {
String t = n.getTextContent().trim();
if (Utilities.noString(t))
ws = true;
else {
if (ws)
s.append(" ");
ws = false;
s.append(t);
}
}
if (n.getNodeType() == Node.ELEMENT_NODE) {
if (ws)
s.append(" ");
ws = false;
s.append(htmlToXmlEscapedPlainText((Element) n));
if (r.getNodeName().equals("br") || r.getNodeName().equals("p"))
s.append("\r\n");
}
n = n.getNextSibling();
}
return s.toString();
}
public static String htmlToXmlEscapedPlainText(String definition) throws Exception {
return htmlToXmlEscapedPlainText(parseToDom("<div>"+definition+"</div>").getDocumentElement());
}
public static String elementToString(Element el) {
if (el == null)
return "";
Document document = el.getOwnerDocument();
DOMImplementationLS domImplLS = (DOMImplementationLS) document
.getImplementation();
LSSerializer serializer = domImplLS.createLSSerializer();
return serializer.writeToString(el);
}
public static String getNamedChildValue(Element element, String name) {
Element e = getNamedChild(element, name);
return e == null ? null : e.getAttribute("value");
}
public static void getNamedChildrenWithWildcard(Element focus, String name, List<Element> children) {
Element c = getFirstChild(focus);
while (c != null) {
String n = c.getLocalName() != null ? c.getLocalName() : c.getNodeName();
if (name.equals(n) || (name.endsWith("[x]") && n.startsWith(name.substring(0, name.length()-3))))
children.add(c);
c = getNextSibling(c);
}
}
public static boolean hasNamedChild(Element e, String name) {
Element c = getFirstChild(e);
while (c != null && !name.equals(c.getLocalName()) && !name.equals(c.getNodeName()))
c = getNextSibling(c);
return c != null;
}
public static Document parseToDom(String content) throws Exception {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(content.getBytes()));
}
public static Element getLastChild(Element e) {
if (e == null)
return null;
Node n = e.getLastChild();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getPreviousSibling();
return (Element) n;
}
public static Element getPrevSibling(Element e) {
Node n = e.getPreviousSibling();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getPreviousSibling();
return (Element) n;
}
}

View File

@ -1,493 +1,493 @@
package org.hl7.fhir.r4.elementmodel;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import org.hl7.fhir.r4.context.IWorkerContext;
import org.hl7.fhir.r4.formats.IParser.OutputStyle;
import org.hl7.fhir.r4.model.StructureDefinition;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
/**
* This class provides special support for parsing v2 by the v2 logical model
* For the logical model, see the FHIRPath spec
*
* @author Grahame Grieve
*
*/
public class VerticalBarParser extends ParserBase {
/**
* Delimiters for a message. Note that the application rarely needs to concern
* itself with this information; it mainly exists for internal use. However if
* a message is being written to a spec that calls for non-standard delimiters,
* the application can set them here.
*
* @author Grahame
*
*/
public class Delimiters {
/**
* Hl7 defined default delimiter for a field
*/
public final static char DEFAULT_DELIMITER_FIELD = '|';
/**
* Hl7 defined default delimiter for a component
*/
public final static char DEFAULT_DELIMITER_COMPONENT = '^';
/**
* Hl7 defined default delimiter for a subcomponent
*/
public final static char DEFAULT_DELIMITER_SUBCOMPONENT = '&';
/**
* Hl7 defined default delimiter for a repeat
*/
public final static char DEFAULT_DELIMITER_REPETITION = '~';
/**
* Hl7 defined default delimiter for an escape
*/
public final static char DEFAULT_CHARACTER_ESCAPE = '\\';
/**
* defined escape character for this message
*/
private char escapeCharacter;
/**
* defined repetition character for this message
*/
private char repetitionDelimiter;
/**
* defined field character for this message
*/
private char fieldDelimiter;
/**
* defined subComponent character for this message
*/
private char subComponentDelimiter;
/**
* defined component character for this message
*/
private char componentDelimiter;
/**
* create
*
*/
public Delimiters() {
super();
reset();
}
public boolean matches(Delimiters other) {
return escapeCharacter == other.escapeCharacter &&
repetitionDelimiter == other.repetitionDelimiter &&
fieldDelimiter == other.fieldDelimiter &&
subComponentDelimiter == other.subComponentDelimiter &&
componentDelimiter == other.componentDelimiter;
}
/**
* get defined component character for this message
* @return
*/
public char getComponentDelimiter() {
return componentDelimiter;
}
/**
* set defined component character for this message
* @param componentDelimiter
*/
public void setComponentDelimiter(char componentDelimiter) {
this.componentDelimiter = componentDelimiter;
}
/**
* get defined escape character for this message
* @return
*/
public char getEscapeCharacter() {
return escapeCharacter;
}
/**
* set defined escape character for this message
* @param escapeCharacter
*/
public void setEscapeCharacter(char escapeCharacter) {
this.escapeCharacter = escapeCharacter;
}
/**
* get defined field character for this message
* @return
*/
public char getFieldDelimiter() {
return fieldDelimiter;
}
/**
* set defined field character for this message
* @param fieldDelimiter
*/
public void setFieldDelimiter(char fieldDelimiter) {
this.fieldDelimiter = fieldDelimiter;
}
/**
* get repeat field character for this message
* @return
*/
public char getRepetitionDelimiter() {
return repetitionDelimiter;
}
/**
* set repeat field character for this message
* @param repetitionDelimiter
*/
public void setRepetitionDelimiter(char repetitionDelimiter) {
this.repetitionDelimiter = repetitionDelimiter;
}
/**
* get sub-component field character for this message
* @return
*/
public char getSubComponentDelimiter() {
return subComponentDelimiter;
}
/**
* set sub-component field character for this message
* @param subComponentDelimiter
*/
public void setSubComponentDelimiter(char subComponentDelimiter) {
this.subComponentDelimiter = subComponentDelimiter;
}
/**
* reset to default HL7 values
*
*/
public void reset () {
fieldDelimiter = DEFAULT_DELIMITER_FIELD;
componentDelimiter = DEFAULT_DELIMITER_COMPONENT;
subComponentDelimiter = DEFAULT_DELIMITER_SUBCOMPONENT;
repetitionDelimiter = DEFAULT_DELIMITER_REPETITION;
escapeCharacter = DEFAULT_CHARACTER_ESCAPE;
}
/**
* check that the delimiters are valid
*
* @throws FHIRException
*/
public void check() throws FHIRException {
rule(componentDelimiter != fieldDelimiter, "Delimiter Error: \""+componentDelimiter+"\" is used for both CPComponent and CPField");
rule(subComponentDelimiter != fieldDelimiter, "Delimiter Error: \""+subComponentDelimiter+"\" is used for both CPSubComponent and CPField");
rule(subComponentDelimiter != componentDelimiter, "Delimiter Error: \""+subComponentDelimiter+"\" is used for both CPSubComponent and CPComponent");
rule(repetitionDelimiter != fieldDelimiter, "Delimiter Error: \""+repetitionDelimiter+"\" is used for both Repetition and CPField");
rule(repetitionDelimiter != componentDelimiter, "Delimiter Error: \""+repetitionDelimiter+"\" is used for both Repetition and CPComponent");
rule(repetitionDelimiter != subComponentDelimiter, "Delimiter Error: \""+repetitionDelimiter+"\" is used for both Repetition and CPSubComponent");
rule(escapeCharacter != fieldDelimiter, "Delimiter Error: \""+escapeCharacter+"\" is used for both Escape and CPField");
rule(escapeCharacter != componentDelimiter, "Delimiter Error: \""+escapeCharacter+"\" is used for both Escape and CPComponent");
rule(escapeCharacter != subComponentDelimiter, "Delimiter Error: \""+escapeCharacter+"\" is used for both Escape and CPSubComponent");
rule(escapeCharacter != repetitionDelimiter, "Delimiter Error: \""+escapeCharacter+"\" is used for both Escape and Repetition");
}
/**
* check to see whether ch is a delimiter character (vertical bar parser support)
* @param ch
* @return
*/
public boolean isDelimiter(char ch) {
return ch == escapeCharacter || ch == repetitionDelimiter || ch == fieldDelimiter || ch == subComponentDelimiter || ch == componentDelimiter;
}
/**
* check to see whether ch is a cell delimiter char (vertical bar parser support)
* @param ch
* @return
*/
public boolean isCellDelimiter(char ch) {
return ch == repetitionDelimiter || ch == fieldDelimiter || ch == subComponentDelimiter || ch == componentDelimiter;
}
/**
* get the escape for a character
* @param ch
* @return
*/
public String getEscape(char ch) {
if (ch == escapeCharacter)
return escapeCharacter + "E" + escapeCharacter;
else if (ch == fieldDelimiter)
return escapeCharacter + "F" + escapeCharacter;
else if (ch == componentDelimiter)
return escapeCharacter + "S" + escapeCharacter;
else if (ch == subComponentDelimiter)
return escapeCharacter + "T" + escapeCharacter;
else if (ch == repetitionDelimiter)
return escapeCharacter + "R" + escapeCharacter;
else
return null;
}
/**
* build the MSH-2 content
* @return
*/
public String forMSH2() {
return "" + componentDelimiter + repetitionDelimiter + escapeCharacter + subComponentDelimiter;
}
/**
* check to see whether ch represents a delimiter escape
* @param ch
* @return
*/
public boolean isDelimiterEscape(char ch) {
return ch == 'F' || ch == 'S' || ch == 'E' || ch == 'T' || ch == 'R';
}
/**
* get escape for ch in an escape
* @param ch
* @return
* @throws DefinitionException
* @throws FHIRException
*/
public char getDelimiterEscapeChar(char ch) throws DefinitionException {
if (ch == 'E')
return escapeCharacter;
else if (ch == 'F')
return fieldDelimiter;
else if (ch == 'S')
return componentDelimiter;
else if (ch == 'T')
return subComponentDelimiter;
else if (ch == 'R')
return repetitionDelimiter;
else
throw new DefinitionException("internal error in getDelimiterEscapeChar");
}
}
public class VerticalBarParserReader {
private BufferedInputStream stream;
private String charsetName;
private InputStreamReader reader = null;
private boolean finished;
private char peeked;
private char lastValue;
private int offset;
private int lineNumber;
public VerticalBarParserReader(BufferedInputStream stream, String charsetName) throws FHIRException {
super();
setStream(stream);
setCharsetName(charsetName);
open();
}
public String getCharsetName() {
return charsetName;
}
public void setCharsetName(String charsetName) {
this.charsetName = charsetName;
}
public BufferedInputStream getStream() {
return stream;
}
public void setStream(BufferedInputStream stream) {
this.stream = stream;
}
private void open() throws FHIRException {
try {
stream.mark(2048);
reader = new InputStreamReader(stream, charsetName);
offset = 0;
lineNumber = 0;
lastValue = ' ';
next();
} catch (Exception e) {
throw new FHIRException(e);
}
}
private void next() throws IOException, FHIRException {
finished = !reader.ready();
if (!finished) {
char[] temp = new char[1];
rule(reader.read(temp, 0, 1) == 1, "unable to read 1 character from the stream");
peeked = temp[0];
}
}
public String read(int charCount) throws FHIRException {
String value = "";
for (int i = 0; i < charCount; i++)
value = value + read();
return value;
}
public void skipEOL () throws FHIRException {
while (!finished && (peek() == '\r' || peek() == '\n'))
read();
}
public char read () throws FHIRException {
rule(!finished, "No more content to read");
char value = peek();
offset++;
if (value == '\r' || value == '\n') {
if (lastValue != '\r' || value != '\n')
lineNumber++;
}
lastValue = value;
try {
next();
} catch (Exception e) {
throw new FHIRException(e);
}
return value;
}
public boolean isFinished () {
return finished;
}
public char peek() throws FHIRException {
rule(!finished, "Cannot peek");
return peeked;
}
public void mark() {
stream.mark(2048);
}
public void reset() throws FHIRException {
try {
stream.reset();
} catch (IOException e) {
throw new FHIRException(e);
}
open();
}
public boolean IsEOL() throws FHIRException {
return peek() == '\r' || peek() == '\n';
}
public int getLineNumber() {
return lineNumber;
}
public int getOffset() {
return offset;
}
}
public VerticalBarParser(IWorkerContext context) {
super(context);
}
private String charset = "ASCII";
private Delimiters delimiters = new Delimiters();
@Override
public Element parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/v2/StructureDefinition/Message");
Element message = new Element("Message", new Property(context, sd.getSnapshot().getElementFirstRep(), sd));
VerticalBarParserReader reader = new VerticalBarParserReader(new BufferedInputStream(stream), charset);
preDecode(reader);
while (!reader.isFinished()) // && (getOptions().getSegmentLimit() == 0 || getOptions().getSegmentLimit() > message.getSegments().size()))
readSegment(message, reader);
return message;
}
private void preDecode(VerticalBarParserReader reader) throws FHIRException {
reader.skipEOL();
String temp = reader.read(3);
rule(temp.equals("MSH") || temp.equals("FHS"), "Found '" + temp + "' looking for 'MSH' or 'FHS'");
readDelimiters(reader);
// readVersion(message); - probably don't need to do that?
// readCharacterSet();
reader.reset(); // ready to read message now
}
private void rule(boolean test, String msg) throws FHIRException {
if (!test)
throw new FHIRException(msg);
}
private void readDelimiters(VerticalBarParserReader reader) throws FHIRException {
delimiters.setFieldDelimiter(reader.read());
if (!(reader.peek() == delimiters.getFieldDelimiter()))
delimiters.setComponentDelimiter(reader.read());
if (!(reader.peek() == delimiters.getFieldDelimiter()))
delimiters.setRepetitionDelimiter(reader.read());
if (!(reader.peek() == delimiters.getFieldDelimiter()))
delimiters.setEscapeCharacter(reader.read());
if (!(reader.peek() == delimiters.getFieldDelimiter()))
delimiters.setSubComponentDelimiter(reader.read());
delimiters.check();
}
private void readSegment(Element message, VerticalBarParserReader reader) throws FHIRException {
Element segment = new Element("segment", message.getProperty().getChild("segment"));
message.getChildren().add(segment);
Element segmentCode = new Element("code", segment.getProperty().getChild("code"));
segment.getChildren().add(segmentCode);
segmentCode.setValue(reader.read(3));
int index = 0;
while (!reader.isFinished() && !reader.IsEOL()) {
index++;
readField(reader, segment, index);
if (!reader.isFinished() && !reader.IsEOL())
rule(reader.read() == delimiters.getFieldDelimiter(), "Expected to find field delimiter");
}
if (!reader.isFinished())
reader.skipEOL();
}
private void readField(VerticalBarParserReader reader, Element segment, int index) {
// TODO Auto-generated method stub
}
@Override
public void compose(Element e, OutputStream destination, OutputStyle style, String base) {
// TODO Auto-generated method stub
}
}
package org.hl7.fhir.r4.elementmodel;
import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import org.hl7.fhir.r4.context.IWorkerContext;
import org.hl7.fhir.r4.formats.IParser.OutputStyle;
import org.hl7.fhir.r4.model.StructureDefinition;
import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
/**
* This class provides special support for parsing v2 by the v2 logical model
* For the logical model, see the FHIRPath spec
*
* @author Grahame Grieve
*
*/
public class VerticalBarParser extends ParserBase {
/**
* Delimiters for a message. Note that the application rarely needs to concern
* itself with this information; it mainly exists for internal use. However if
* a message is being written to a spec that calls for non-standard delimiters,
* the application can set them here.
*
* @author Grahame
*
*/
public class Delimiters {
/**
* Hl7 defined default delimiter for a field
*/
public final static char DEFAULT_DELIMITER_FIELD = '|';
/**
* Hl7 defined default delimiter for a component
*/
public final static char DEFAULT_DELIMITER_COMPONENT = '^';
/**
* Hl7 defined default delimiter for a subcomponent
*/
public final static char DEFAULT_DELIMITER_SUBCOMPONENT = '&';
/**
* Hl7 defined default delimiter for a repeat
*/
public final static char DEFAULT_DELIMITER_REPETITION = '~';
/**
* Hl7 defined default delimiter for an escapeUrlParam
*/
public final static char DEFAULT_CHARACTER_ESCAPE = '\\';
/**
* defined escapeUrlParam character for this message
*/
private char escapeCharacter;
/**
* defined repetition character for this message
*/
private char repetitionDelimiter;
/**
* defined field character for this message
*/
private char fieldDelimiter;
/**
* defined subComponent character for this message
*/
private char subComponentDelimiter;
/**
* defined component character for this message
*/
private char componentDelimiter;
/**
* create
*
*/
public Delimiters() {
super();
reset();
}
public boolean matches(Delimiters other) {
return escapeCharacter == other.escapeCharacter &&
repetitionDelimiter == other.repetitionDelimiter &&
fieldDelimiter == other.fieldDelimiter &&
subComponentDelimiter == other.subComponentDelimiter &&
componentDelimiter == other.componentDelimiter;
}
/**
* get defined component character for this message
* @return
*/
public char getComponentDelimiter() {
return componentDelimiter;
}
/**
* set defined component character for this message
* @param componentDelimiter
*/
public void setComponentDelimiter(char componentDelimiter) {
this.componentDelimiter = componentDelimiter;
}
/**
* get defined escapeUrlParam character for this message
* @return
*/
public char getEscapeCharacter() {
return escapeCharacter;
}
/**
* set defined escapeUrlParam character for this message
* @param escapeCharacter
*/
public void setEscapeCharacter(char escapeCharacter) {
this.escapeCharacter = escapeCharacter;
}
/**
* get defined field character for this message
* @return
*/
public char getFieldDelimiter() {
return fieldDelimiter;
}
/**
* set defined field character for this message
* @param fieldDelimiter
*/
public void setFieldDelimiter(char fieldDelimiter) {
this.fieldDelimiter = fieldDelimiter;
}
/**
* get repeat field character for this message
* @return
*/
public char getRepetitionDelimiter() {
return repetitionDelimiter;
}
/**
* set repeat field character for this message
* @param repetitionDelimiter
*/
public void setRepetitionDelimiter(char repetitionDelimiter) {
this.repetitionDelimiter = repetitionDelimiter;
}
/**
* get sub-component field character for this message
* @return
*/
public char getSubComponentDelimiter() {
return subComponentDelimiter;
}
/**
* set sub-component field character for this message
* @param subComponentDelimiter
*/
public void setSubComponentDelimiter(char subComponentDelimiter) {
this.subComponentDelimiter = subComponentDelimiter;
}
/**
* reset to default HL7 values
*
*/
public void reset () {
fieldDelimiter = DEFAULT_DELIMITER_FIELD;
componentDelimiter = DEFAULT_DELIMITER_COMPONENT;
subComponentDelimiter = DEFAULT_DELIMITER_SUBCOMPONENT;
repetitionDelimiter = DEFAULT_DELIMITER_REPETITION;
escapeCharacter = DEFAULT_CHARACTER_ESCAPE;
}
/**
* check that the delimiters are valid
*
* @throws FHIRException
*/
public void check() throws FHIRException {
rule(componentDelimiter != fieldDelimiter, "Delimiter Error: \""+componentDelimiter+"\" is used for both CPComponent and CPField");
rule(subComponentDelimiter != fieldDelimiter, "Delimiter Error: \""+subComponentDelimiter+"\" is used for both CPSubComponent and CPField");
rule(subComponentDelimiter != componentDelimiter, "Delimiter Error: \""+subComponentDelimiter+"\" is used for both CPSubComponent and CPComponent");
rule(repetitionDelimiter != fieldDelimiter, "Delimiter Error: \""+repetitionDelimiter+"\" is used for both Repetition and CPField");
rule(repetitionDelimiter != componentDelimiter, "Delimiter Error: \""+repetitionDelimiter+"\" is used for both Repetition and CPComponent");
rule(repetitionDelimiter != subComponentDelimiter, "Delimiter Error: \""+repetitionDelimiter+"\" is used for both Repetition and CPSubComponent");
rule(escapeCharacter != fieldDelimiter, "Delimiter Error: \""+escapeCharacter+"\" is used for both Escape and CPField");
rule(escapeCharacter != componentDelimiter, "Delimiter Error: \""+escapeCharacter+"\" is used for both Escape and CPComponent");
rule(escapeCharacter != subComponentDelimiter, "Delimiter Error: \""+escapeCharacter+"\" is used for both Escape and CPSubComponent");
rule(escapeCharacter != repetitionDelimiter, "Delimiter Error: \""+escapeCharacter+"\" is used for both Escape and Repetition");
}
/**
* check to see whether ch is a delimiter character (vertical bar parser support)
* @param ch
* @return
*/
public boolean isDelimiter(char ch) {
return ch == escapeCharacter || ch == repetitionDelimiter || ch == fieldDelimiter || ch == subComponentDelimiter || ch == componentDelimiter;
}
/**
* check to see whether ch is a cell delimiter char (vertical bar parser support)
* @param ch
* @return
*/
public boolean isCellDelimiter(char ch) {
return ch == repetitionDelimiter || ch == fieldDelimiter || ch == subComponentDelimiter || ch == componentDelimiter;
}
/**
* get the escapeUrlParam for a character
* @param ch
* @return
*/
public String getEscape(char ch) {
if (ch == escapeCharacter)
return escapeCharacter + "E" + escapeCharacter;
else if (ch == fieldDelimiter)
return escapeCharacter + "F" + escapeCharacter;
else if (ch == componentDelimiter)
return escapeCharacter + "S" + escapeCharacter;
else if (ch == subComponentDelimiter)
return escapeCharacter + "T" + escapeCharacter;
else if (ch == repetitionDelimiter)
return escapeCharacter + "R" + escapeCharacter;
else
return null;
}
/**
* build the MSH-2 content
* @return
*/
public String forMSH2() {
return "" + componentDelimiter + repetitionDelimiter + escapeCharacter + subComponentDelimiter;
}
/**
* check to see whether ch represents a delimiter escapeUrlParam
* @param ch
* @return
*/
public boolean isDelimiterEscape(char ch) {
return ch == 'F' || ch == 'S' || ch == 'E' || ch == 'T' || ch == 'R';
}
/**
* get escapeUrlParam for ch in an escapeUrlParam
* @param ch
* @return
* @throws DefinitionException
* @throws FHIRException
*/
public char getDelimiterEscapeChar(char ch) throws DefinitionException {
if (ch == 'E')
return escapeCharacter;
else if (ch == 'F')
return fieldDelimiter;
else if (ch == 'S')
return componentDelimiter;
else if (ch == 'T')
return subComponentDelimiter;
else if (ch == 'R')
return repetitionDelimiter;
else
throw new DefinitionException("internal error in getDelimiterEscapeChar");
}
}
public class VerticalBarParserReader {
private BufferedInputStream stream;
private String charsetName;
private InputStreamReader reader = null;
private boolean finished;
private char peeked;
private char lastValue;
private int offset;
private int lineNumber;
public VerticalBarParserReader(BufferedInputStream stream, String charsetName) throws FHIRException {
super();
setStream(stream);
setCharsetName(charsetName);
open();
}
public String getCharsetName() {
return charsetName;
}
public void setCharsetName(String charsetName) {
this.charsetName = charsetName;
}
public BufferedInputStream getStream() {
return stream;
}
public void setStream(BufferedInputStream stream) {
this.stream = stream;
}
private void open() throws FHIRException {
try {
stream.mark(2048);
reader = new InputStreamReader(stream, charsetName);
offset = 0;
lineNumber = 0;
lastValue = ' ';
next();
} catch (Exception e) {
throw new FHIRException(e);
}
}
private void next() throws IOException, FHIRException {
finished = !reader.ready();
if (!finished) {
char[] temp = new char[1];
rule(reader.read(temp, 0, 1) == 1, "unable to read 1 character from the stream");
peeked = temp[0];
}
}
public String read(int charCount) throws FHIRException {
String value = "";
for (int i = 0; i < charCount; i++)
value = value + read();
return value;
}
public void skipEOL () throws FHIRException {
while (!finished && (peek() == '\r' || peek() == '\n'))
read();
}
public char read () throws FHIRException {
rule(!finished, "No more content to read");
char value = peek();
offset++;
if (value == '\r' || value == '\n') {
if (lastValue != '\r' || value != '\n')
lineNumber++;
}
lastValue = value;
try {
next();
} catch (Exception e) {
throw new FHIRException(e);
}
return value;
}
public boolean isFinished () {
return finished;
}
public char peek() throws FHIRException {
rule(!finished, "Cannot peek");
return peeked;
}
public void mark() {
stream.mark(2048);
}
public void reset() throws FHIRException {
try {
stream.reset();
} catch (IOException e) {
throw new FHIRException(e);
}
open();
}
public boolean IsEOL() throws FHIRException {
return peek() == '\r' || peek() == '\n';
}
public int getLineNumber() {
return lineNumber;
}
public int getOffset() {
return offset;
}
}
public VerticalBarParser(IWorkerContext context) {
super(context);
}
private String charset = "ASCII";
private Delimiters delimiters = new Delimiters();
@Override
public Element parse(InputStream stream) throws IOException, FHIRFormatError, DefinitionException, FHIRException {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/v2/StructureDefinition/Message");
Element message = new Element("Message", new Property(context, sd.getSnapshot().getElementFirstRep(), sd));
VerticalBarParserReader reader = new VerticalBarParserReader(new BufferedInputStream(stream), charset);
preDecode(reader);
while (!reader.isFinished()) // && (getOptions().getSegmentLimit() == 0 || getOptions().getSegmentLimit() > message.getSegments().size()))
readSegment(message, reader);
return message;
}
private void preDecode(VerticalBarParserReader reader) throws FHIRException {
reader.skipEOL();
String temp = reader.read(3);
rule(temp.equals("MSH") || temp.equals("FHS"), "Found '" + temp + "' looking for 'MSH' or 'FHS'");
readDelimiters(reader);
// readVersion(message); - probably don't need to do that?
// readCharacterSet();
reader.reset(); // ready to read message now
}
private void rule(boolean test, String msg) throws FHIRException {
if (!test)
throw new FHIRException(msg);
}
private void readDelimiters(VerticalBarParserReader reader) throws FHIRException {
delimiters.setFieldDelimiter(reader.read());
if (!(reader.peek() == delimiters.getFieldDelimiter()))
delimiters.setComponentDelimiter(reader.read());
if (!(reader.peek() == delimiters.getFieldDelimiter()))
delimiters.setRepetitionDelimiter(reader.read());
if (!(reader.peek() == delimiters.getFieldDelimiter()))
delimiters.setEscapeCharacter(reader.read());
if (!(reader.peek() == delimiters.getFieldDelimiter()))
delimiters.setSubComponentDelimiter(reader.read());
delimiters.check();
}
private void readSegment(Element message, VerticalBarParserReader reader) throws FHIRException {
Element segment = new Element("segment", message.getProperty().getChild("segment"));
message.getChildren().add(segment);
Element segmentCode = new Element("code", segment.getProperty().getChild("code"));
segment.getChildren().add(segmentCode);
segmentCode.setValue(reader.read(3));
int index = 0;
while (!reader.isFinished() && !reader.IsEOL()) {
index++;
readField(reader, segment, index);
if (!reader.isFinished() && !reader.IsEOL())
rule(reader.read() == delimiters.getFieldDelimiter(), "Expected to find field delimiter");
}
if (!reader.isFinished())
reader.skipEOL();
}
private void readField(VerticalBarParserReader reader, Element segment, int index) {
// TODO Auto-generated method stub
}
@Override
public void compose(Element e, OutputStream destination, OutputStyle style, String base) {
// TODO Auto-generated method stub
}
}

View File

@ -1,21 +1,35 @@
package ca.uhn.fhir.rest.client;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.InputStream;
import java.io.StringReader;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.SummaryEnum;
import ca.uhn.fhir.rest.client.apache.ApacheHttpRequest;
import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil;
import com.google.common.base.Charsets;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.http.*;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.*;
import org.apache.http.client.methods.HttpDelete;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hamcrest.core.StringContains;
@ -23,29 +37,23 @@ import org.hamcrest.core.StringEndsWith;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Bundle.BundleEntryComponent;
import org.junit.*;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import com.google.common.base.Charsets;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.*;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.annotation.ResourceDef;
import ca.uhn.fhir.model.base.resource.BaseConformance;
import ca.uhn.fhir.rest.annotation.*;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.apache.ApacheHttpRequest;
import ca.uhn.fhir.rest.client.api.IBasicClient;
import ca.uhn.fhir.rest.client.api.ServerValidationModeEnum;
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ClientR4Test {
@ -569,7 +577,7 @@ public class ClientR4Test {
DateParam date = new DateParam("2001-01-01");
client.getObservationByNameValueDate(new CompositeParam<StringParam, DateParam>(str, date));
assertEquals("http://foo/Observation?" + Observation.SP_CODE_VALUE_DATE + "=" + URLEncoder.encode("FOO\\$BAR$2001-01-01", "UTF-8"), capt.getValue().getURI().toString());
assertEquals("http://foo/Observation?" + Observation.SP_CODE_VALUE_DATE + "=" + UrlUtil.escapeUrlParam("FOO\\$BAR$2001-01-01"), capt.getValue().getURI().toString());
}

View File

@ -1,45 +1,6 @@
package ca.uhn.fhir.rest.client;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.*;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.*;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.*;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hamcrest.Matchers;
import org.hamcrest.core.StringContains;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
import org.junit.*;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.model.primitive.UriDt;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.api.IGenericClient;
@ -49,7 +10,43 @@ import ca.uhn.fhir.rest.client.impl.BaseClient;
import ca.uhn.fhir.rest.client.impl.GenericClient;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.util.*;
import ca.uhn.fhir.util.BundleUtil;
import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.io.input.ReaderInputStream;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicStatusLine;
import org.hamcrest.Matchers;
import org.hamcrest.core.StringContains;
import org.hl7.fhir.r4.model.*;
import org.hl7.fhir.r4.model.Bundle.BundleType;
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
import org.junit.*;
import org.mockito.ArgumentCaptor;
import org.mockito.internal.stubbing.defaultanswers.ReturnsDeepStubs;
import org.mockito.invocation.InvocationOnMock;
import org.mockito.stubbing.Answer;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.nio.charset.Charset;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class GenericClientTest {
@ -782,7 +779,7 @@ public class GenericClientTest {
.returnBundle(Bundle.class)
.execute();
assertEquals("http://foo/Observation?" + Observation.SP_CODE_VALUE_DATE + "=" + URLEncoder.encode("FOO\\$BAR$2001-01-01", "UTF-8"), capt.getValue().getURI().toString());
assertEquals("http://foo/Observation?" + Observation.SP_CODE_VALUE_DATE + "=" + UrlUtil.escapeUrlParam("FOO\\$BAR$2001-01-01"), capt.getValue().getURI().toString());
}
@ -1025,7 +1022,7 @@ public class GenericClientTest {
.returnBundle(Bundle.class)
.execute();
assertEquals("http://example.com/fhir/Patient?name=" + URLEncoder.encode("AAA,BBB,C\\,C", "UTF-8"), capt.getAllValues().get(1).getURI().toString());
assertEquals("http://example.com/fhir/Patient?name=" + UrlUtil.escapeUrlParam("AAA,BBB,C\\,C"), capt.getAllValues().get(1).getURI().toString());
}
@ -1116,7 +1113,7 @@ public class GenericClientTest {
.returnBundle(Bundle.class)
.execute();
assertEquals("http://example.com/fhir/Patient?identifier=" + URLEncoder.encode("A|B,C|D", "UTF-8"), capt.getAllValues().get(2).getURI().toString());
assertEquals("http://example.com/fhir/Patient?identifier=" + UrlUtil.escapeUrlParam("A|B,C|D"), capt.getAllValues().get(2).getURI().toString());
}
@ -1152,7 +1149,7 @@ public class GenericClientTest {
String url = capt.getAllValues().get(index).getURI().toString();
assertThat(url, Matchers.startsWith(wantPrefix));
assertEquals(wantValue, UrlUtil.unescape(url.substring(wantPrefix.length())));
assertEquals(UrlUtil.escape(wantValue), url.substring(wantPrefix.length()));
assertEquals(UrlUtil.escapeUrlParam(wantValue), url.substring(wantPrefix.length()));
index++;
response = client.search()
@ -1164,7 +1161,7 @@ public class GenericClientTest {
url = capt.getAllValues().get(index).getURI().toString();
assertThat(url, Matchers.startsWith(wantPrefix));
assertEquals(wantValue, UrlUtil.unescape(url.substring(wantPrefix.length())));
assertEquals(UrlUtil.escape(wantValue), url.substring(wantPrefix.length()));
assertEquals(UrlUtil.escapeUrlParam(wantValue), url.substring(wantPrefix.length()));
index++;
}
@ -1234,8 +1231,8 @@ public class GenericClientTest {
.execute();
assertThat(capt.getValue().getURI().toString(), containsString("http://example.com/fhir/Patient?"));
assertThat(capt.getValue().getURI().toString(), containsString("_include=" + UrlUtil.escape(Patient.INCLUDE_ORGANIZATION.getValue())));
assertThat(capt.getValue().getURI().toString(), containsString("_include%3Arecurse=" + UrlUtil.escape(Patient.INCLUDE_LINK.getValue())));
assertThat(capt.getValue().getURI().toString(), containsString("_include=" + UrlUtil.escapeUrlParam(Patient.INCLUDE_ORGANIZATION.getValue())));
assertThat(capt.getValue().getURI().toString(), containsString("_include%3Arecurse=" + UrlUtil.escapeUrlParam(Patient.INCLUDE_LINK.getValue())));
assertThat(capt.getValue().getURI().toString(), containsString("_include=*"));
}

View File

@ -54,7 +54,7 @@ public class GraphQLR4ProviderTest {
@Test
public void testGraphInstance() throws Exception {
String query = "{name{family,given}}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escape(query));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escapeUrlParam(query));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
@ -80,7 +80,7 @@ public class GraphQLR4ProviderTest {
@Test
public void testGraphInstanceWithFhirpath() throws Exception {
String query = "{name(fhirpath:\"family.exists()\"){text,given,family}}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escape(query));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escapeUrlParam(query));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
@ -104,7 +104,7 @@ public class GraphQLR4ProviderTest {
@Test
public void testGraphSystemInstance() throws Exception {
String query = "{Patient(id:123){id,name{given,family}}}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escape(query));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escapeUrlParam(query));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
@ -132,7 +132,7 @@ public class GraphQLR4ProviderTest {
@Test
public void testGraphSystemList() throws Exception {
String query = "{PatientList(name:\"pet\"){name{family,given}}}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escape(query));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escapeUrlParam(query));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);

View File

@ -91,7 +91,7 @@ public class GraphQLR4RawTest {
ourNextRetVal = "{\"foo\"}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escape("{name{family,given}}"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escapeUrlParam("{name{family,given}}"));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
@ -114,7 +114,7 @@ public class GraphQLR4RawTest {
ourNextRetVal = "{\"foo\"}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Condition/123/$graphql?query=" + UrlUtil.escape("{name{family,given}}"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Condition/123/$graphql?query=" + UrlUtil.escapeUrlParam("{name{family,given}}"));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
@ -132,7 +132,7 @@ public class GraphQLR4RawTest {
ourNextRetVal = "{\"foo\"}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escape("{name{family,given}}"));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escapeUrlParam("{name{family,given}}"));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);

View File

@ -131,25 +131,25 @@ public class SearchR4Test {
httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?identifier=foo%7Cbar&_format=" + Constants.CT_FHIR_JSON_NEW);
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
assertThat(linkNext, containsString("_format=" + UrlUtil.escape(Constants.CT_FHIR_JSON_NEW)));
assertThat(linkNext, containsString("_format=" + UrlUtil.escapeUrlParam(Constants.CT_FHIR_JSON_NEW)));
// Fetch the next page
httpGet = new HttpGet(linkNext);
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
assertThat(linkNext, containsString("_format=" + UrlUtil.escape(Constants.CT_FHIR_JSON_NEW)));
assertThat(linkNext, containsString("_format=" + UrlUtil.escapeUrlParam(Constants.CT_FHIR_JSON_NEW)));
// Fetch the next page
httpGet = new HttpGet(linkNext);
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
assertThat(linkNext, containsString("_format=" + UrlUtil.escape(Constants.CT_FHIR_JSON_NEW)));
assertThat(linkNext, containsString("_format=" + UrlUtil.escapeUrlParam(Constants.CT_FHIR_JSON_NEW)));
// Fetch the next page
httpGet = new HttpGet(linkNext);
bundle = executeAndReturnLinkNext(httpGet, EncodingEnum.JSON);
linkNext = bundle.getLink(Constants.LINK_NEXT).getUrl();
assertThat(linkNext, containsString("_format=" + UrlUtil.escape(Constants.CT_FHIR_JSON_NEW)));
assertThat(linkNext, containsString("_format=" + UrlUtil.escapeUrlParam(Constants.CT_FHIR_JSON_NEW)));
}

View File

@ -1,6 +1,6 @@
package ca.uhn.fhir.rest.server;
import static ca.uhn.fhir.util.UrlUtil.escape;
import static ca.uhn.fhir.util.UrlUtil.escapeUrlParam;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.hamcrest.Matchers.containsString;
import static org.hamcrest.Matchers.empty;
@ -110,10 +110,10 @@ public class SearchSearchServerDstu1Test {
b.append("http://localhost:");
b.append(ourPort);
b.append("/Patient?");
b.append(escape("findPatientWithAndList")).append('=').append(escape("NE\\,NE,NE\\,NE")).append('&');
b.append(escape("findPatientWithAndList")).append('=').append(escape("NE\\\\NE")).append('&');
b.append(escape("findPatientWithAndList:exact")).append('=').append(escape("E\\$E")).append('&');
b.append(escape("findPatientWithAndList:exact")).append('=').append(escape("E\\|E")).append('&');
b.append(escapeUrlParam("findPatientWithAndList")).append('=').append(escapeUrlParam("NE\\,NE,NE\\,NE")).append('&');
b.append(escapeUrlParam("findPatientWithAndList")).append('=').append(escapeUrlParam("NE\\\\NE")).append('&');
b.append(escapeUrlParam("findPatientWithAndList:exact")).append('=').append(escapeUrlParam("E\\$E")).append('&');
b.append(escapeUrlParam("findPatientWithAndList:exact")).append('=').append(escapeUrlParam("E\\|E")).append('&');
HttpGet httpGet = new HttpGet(b.toString());
@ -416,7 +416,7 @@ public class SearchSearchServerDstu1Test {
@Test
public void testSearchWithTokenParameter() throws Exception {
String token = UrlUtil.escape("http://www.dmix.gov/vista/2957|301");
String token = UrlUtil.escapeUrlParam("http://www.dmix.gov/vista/2957|301");
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient?tokenParam=" + token);
HttpResponse status = ourClient.execute(httpGet);
String responseContent = IOUtils.toString(status.getEntity().getContent());

View File

@ -1,472 +1,472 @@
/*
Copyright (c) 2011+, HL7, Inc
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
package org.hl7.fhir.utilities.xml;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.Utilities;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.SAXException;
public class XMLUtil {
public static final String SPACE_CHAR = "\u00A0";
public static boolean isNMToken(String name) {
if (name == null)
return false;
for (int i = 0; i < name.length(); i++)
if (!isNMTokenChar(name.charAt(i)))
return false;
return name.length() > 0;
}
public static boolean isNMTokenChar(char c) {
return isLetter(c) || isDigit(c) || c == '.' || c == '-' || c == '_' || c == ':' || isCombiningChar(c) || isExtender(c);
}
private static boolean isDigit(char c) {
return (c >= '\u0030' && c <= '\u0039') || (c >= '\u0660' && c <= '\u0669') || (c >= '\u06F0' && c <= '\u06F9') ||
(c >= '\u0966' && c <= '\u096F') || (c >= '\u09E6' && c <= '\u09EF') || (c >= '\u0A66' && c <= '\u0A6F') ||
(c >= '\u0AE6' && c <= '\u0AEF') || (c >= '\u0B66' && c <= '\u0B6F') || (c >= '\u0BE7' && c <= '\u0BEF') ||
(c >= '\u0C66' && c <= '\u0C6F') || (c >= '\u0CE6' && c <= '\u0CEF') || (c >= '\u0D66' && c <= '\u0D6F') ||
(c >= '\u0E50' && c <= '\u0E59') || (c >= '\u0ED0' && c <= '\u0ED9') || (c >= '\u0F20' && c <= '\u0F29');
}
private static boolean isCombiningChar(char c) {
return (c >= '\u0300' && c <= '\u0345') || (c >= '\u0360' && c <= '\u0361') || (c >= '\u0483' && c <= '\u0486') ||
(c >= '\u0591' && c <= '\u05A1') || (c >= '\u05A3' && c <= '\u05B9') || (c >= '\u05BB' && c <= '\u05BD') ||
c == '\u05BF' || (c >= '\u05C1' && c <= '\u05C2') || c == '\u05C4' || (c >= '\u064B' && c <= '\u0652') ||
c == '\u0670' || (c >= '\u06D6' && c <= '\u06DC') || (c >= '\u06DD' && c <= '\u06DF') || (c >= '\u06E0' && c <= '\u06E4') ||
(c >= '\u06E7' && c <= '\u06E8') || (c >= '\u06EA' && c <= '\u06ED') || (c >= '\u0901' && c <= '\u0903') || c == '\u093C' ||
(c >= '\u093E' && c <= '\u094C') || c == '\u094D' || (c >= '\u0951' && c <= '\u0954') || (c >= '\u0962' && c <= '\u0963') ||
(c >= '\u0981' && c <= '\u0983') || c == '\u09BC' || c == '\u09BE' || c == '\u09BF' || (c >= '\u09C0' && c <= '\u09C4') ||
(c >= '\u09C7' && c <= '\u09C8') || (c >= '\u09CB' && c <= '\u09CD') || c == '\u09D7' || (c >= '\u09E2' && c <= '\u09E3') ||
c == '\u0A02' || c == '\u0A3C' || c == '\u0A3E' || c == '\u0A3F' || (c >= '\u0A40' && c <= '\u0A42') ||
(c >= '\u0A47' && c <= '\u0A48') || (c >= '\u0A4B' && c <= '\u0A4D') || (c >= '\u0A70' && c <= '\u0A71') ||
(c >= '\u0A81' && c <= '\u0A83') || c == '\u0ABC' || (c >= '\u0ABE' && c <= '\u0AC5') || (c >= '\u0AC7' && c <= '\u0AC9') ||
(c >= '\u0ACB' && c <= '\u0ACD') || (c >= '\u0B01' && c <= '\u0B03') || c == '\u0B3C' || (c >= '\u0B3E' && c <= '\u0B43') ||
(c >= '\u0B47' && c <= '\u0B48') || (c >= '\u0B4B' && c <= '\u0B4D') || (c >= '\u0B56' && c <= '\u0B57') ||
(c >= '\u0B82' && c <= '\u0B83') || (c >= '\u0BBE' && c <= '\u0BC2') || (c >= '\u0BC6' && c <= '\u0BC8') ||
(c >= '\u0BCA' && c <= '\u0BCD') || c == '\u0BD7' || (c >= '\u0C01' && c <= '\u0C03') || (c >= '\u0C3E' && c <= '\u0C44') ||
(c >= '\u0C46' && c <= '\u0C48') || (c >= '\u0C4A' && c <= '\u0C4D') || (c >= '\u0C55' && c <= '\u0C56') ||
(c >= '\u0C82' && c <= '\u0C83') || (c >= '\u0CBE' && c <= '\u0CC4') || (c >= '\u0CC6' && c <= '\u0CC8') ||
(c >= '\u0CCA' && c <= '\u0CCD') || (c >= '\u0CD5' && c <= '\u0CD6') || (c >= '\u0D02' && c <= '\u0D03') ||
(c >= '\u0D3E' && c <= '\u0D43') || (c >= '\u0D46' && c <= '\u0D48') || (c >= '\u0D4A' && c <= '\u0D4D') || c == '\u0D57' ||
c == '\u0E31' || (c >= '\u0E34' && c <= '\u0E3A') || (c >= '\u0E47' && c <= '\u0E4E') || c == '\u0EB1' ||
(c >= '\u0EB4' && c <= '\u0EB9') || (c >= '\u0EBB' && c <= '\u0EBC') || (c >= '\u0EC8' && c <= '\u0ECD') ||
(c >= '\u0F18' && c <= '\u0F19') || c == '\u0F35' || c == '\u0F37' || c == '\u0F39' || c == '\u0F3E' || c == '\u0F3F' ||
(c >= '\u0F71' && c <= '\u0F84') || (c >= '\u0F86' && c <= '\u0F8B') || (c >= '\u0F90' && c <= '\u0F95') || c == '\u0F97' ||
(c >= '\u0F99' && c <= '\u0FAD') || (c >= '\u0FB1' && c <= '\u0FB7') || c == '\u0FB9' || (c >= '\u20D0' && c <= '\u20DC') ||
c == '\u20E1' || (c >= '\u302A' && c <= '\u302F') || c == '\u3099' || c == '\u309A';
}
private static boolean isExtender(char c) {
return c == '\u00B7' || c == '\u02D0' || c == '\u02D1' || c == '\u0387' || c == '\u0640' || c == '\u0E46' ||
c == '\u0EC6' || c == '\u3005' || (c >= '\u3031' && c <= '\u3035') || (c >= '\u309D' && c <= '\u309E') ||
(c >= '\u30FC' && c <= '\u30FE');
}
private static boolean isLetter(char c) {
return isBaseChar(c) || isIdeographic(c);
}
private static boolean isBaseChar(char c) {
return (c >= '\u0041' && c <= '\u005A') || (c >= '\u0061' && c <= '\u007A') || (c >= '\u00C0' && c <= '\u00D6') ||
(c >= '\u00D8' && c <= '\u00F6') || (c >= '\u00F8' && c <= '\u00FF') || (c >= '\u0100' && c <= '\u0131') ||
(c >= '\u0134' && c <= '\u013E') || (c >= '\u0141' && c <= '\u0148') || (c >= '\u014A' && c <= '\u017E') ||
(c >= '\u0180' && c <= '\u01C3') || (c >= '\u01CD' && c <= '\u01F0') || (c >= '\u01F4' && c <= '\u01F5') ||
(c >= '\u01FA' && c <= '\u0217') || (c >= '\u0250' && c <= '\u02A8') || (c >= '\u02BB' && c <= '\u02C1') ||
c == '\u0386' || (c >= '\u0388' && c <= '\u038A') || c == '\u038C' || (c >= '\u038E' && c <= '\u03A1') ||
(c >= '\u03A3' && c <= '\u03CE') || (c >= '\u03D0' && c <= '\u03D6') || c == '\u03DA' || c == '\u03DC' || c == '\u03DE' ||
c == '\u03E0' || (c >= '\u03E2' && c <= '\u03F3') || (c >= '\u0401' && c <= '\u040C') || (c >= '\u040E' && c <= '\u044F') ||
(c >= '\u0451' && c <= '\u045C') || (c >= '\u045E' && c <= '\u0481') || (c >= '\u0490' && c <= '\u04C4') ||
(c >= '\u04C7' && c <= '\u04C8') || (c >= '\u04CB' && c <= '\u04CC') || (c >= '\u04D0' && c <= '\u04EB') ||
(c >= '\u04EE' && c <= '\u04F5') || (c >= '\u04F8' && c <= '\u04F9') || (c >= '\u0531' && c <= '\u0556') ||
c == '\u0559' || (c >= '\u0561' && c <= '\u0586') || (c >= '\u05D0' && c <= '\u05EA') || (c >= '\u05F0' && c <= '\u05F2') ||
(c >= '\u0621' && c <= '\u063A') || (c >= '\u0641' && c <= '\u064A') || (c >= '\u0671' && c <= '\u06B7') ||
(c >= '\u06BA' && c <= '\u06BE') || (c >= '\u06C0' && c <= '\u06CE') || (c >= '\u06D0' && c <= '\u06D3') ||
c == '\u06D5' || (c >= '\u06E5' && c <= '\u06E6') || (c >= '\u0905' && c <= '\u0939') || c == '\u093D' ||
(c >= '\u0958' && c <= '\u0961') || (c >= '\u0985' && c <= '\u098C') || (c >= '\u098F' && c <= '\u0990') ||
(c >= '\u0993' && c <= '\u09A8') || (c >= '\u09AA' && c <= '\u09B0') || c == '\u09B2' ||
(c >= '\u09B6' && c <= '\u09B9') || (c >= '\u09DC' && c <= '\u09DD') || (c >= '\u09DF' && c <= '\u09E1') ||
(c >= '\u09F0' && c <= '\u09F1') || (c >= '\u0A05' && c <= '\u0A0A') || (c >= '\u0A0F' && c <= '\u0A10') ||
(c >= '\u0A13' && c <= '\u0A28') || (c >= '\u0A2A' && c <= '\u0A30') || (c >= '\u0A32' && c <= '\u0A33') ||
(c >= '\u0A35' && c <= '\u0A36') || (c >= '\u0A38' && c <= '\u0A39') || (c >= '\u0A59' && c <= '\u0A5C') ||
c == '\u0A5E' || (c >= '\u0A72' && c <= '\u0A74') || (c >= '\u0A85' && c <= '\u0A8B') || c == '\u0A8D' ||
(c >= '\u0A8F' && c <= '\u0A91') || (c >= '\u0A93' && c <= '\u0AA8') || (c >= '\u0AAA' && c <= '\u0AB0') ||
(c >= '\u0AB2' && c <= '\u0AB3') || (c >= '\u0AB5' && c <= '\u0AB9') || c == '\u0ABD' || c == '\u0AE0' ||
(c >= '\u0B05' && c <= '\u0B0C') || (c >= '\u0B0F' && c <= '\u0B10') || (c >= '\u0B13' && c <= '\u0B28') ||
(c >= '\u0B2A' && c <= '\u0B30') || (c >= '\u0B32' && c <= '\u0B33') || (c >= '\u0B36' && c <= '\u0B39') ||
c == '\u0B3D' || (c >= '\u0B5C' && c <= '\u0B5D') || (c >= '\u0B5F' && c <= '\u0B61') ||
(c >= '\u0B85' && c <= '\u0B8A') || (c >= '\u0B8E' && c <= '\u0B90') || (c >= '\u0B92' && c <= '\u0B95') ||
(c >= '\u0B99' && c <= '\u0B9A') || c == '\u0B9C' || (c >= '\u0B9E' && c <= '\u0B9F') ||
(c >= '\u0BA3' && c <= '\u0BA4') || (c >= '\u0BA8' && c <= '\u0BAA') || (c >= '\u0BAE' && c <= '\u0BB5') ||
(c >= '\u0BB7' && c <= '\u0BB9') || (c >= '\u0C05' && c <= '\u0C0C') || (c >= '\u0C0E' && c <= '\u0C10') ||
(c >= '\u0C12' && c <= '\u0C28') || (c >= '\u0C2A' && c <= '\u0C33') || (c >= '\u0C35' && c <= '\u0C39') ||
(c >= '\u0C60' && c <= '\u0C61') || (c >= '\u0C85' && c <= '\u0C8C') || (c >= '\u0C8E' && c <= '\u0C90') ||
(c >= '\u0C92' && c <= '\u0CA8') || (c >= '\u0CAA' && c <= '\u0CB3') || (c >= '\u0CB5' && c <= '\u0CB9') ||
c == '\u0CDE' || (c >= '\u0CE0' && c <= '\u0CE1') || (c >= '\u0D05' && c <= '\u0D0C') ||
(c >= '\u0D0E' && c <= '\u0D10') || (c >= '\u0D12' && c <= '\u0D28') || (c >= '\u0D2A' && c <= '\u0D39') ||
(c >= '\u0D60' && c <= '\u0D61') || (c >= '\u0E01' && c <= '\u0E2E') || c == '\u0E30' ||
(c >= '\u0E32' && c <= '\u0E33') || (c >= '\u0E40' && c <= '\u0E45') || (c >= '\u0E81' && c <= '\u0E82') ||
c == '\u0E84' || (c >= '\u0E87' && c <= '\u0E88') || c == '\u0E8A' || c == '\u0E8D' || (c >= '\u0E94' && c <= '\u0E97') ||
(c >= '\u0E99' && c <= '\u0E9F') || (c >= '\u0EA1' && c <= '\u0EA3') || c == '\u0EA5' || c == '\u0EA7' ||
(c >= '\u0EAA' && c <= '\u0EAB') || (c >= '\u0EAD' && c <= '\u0EAE') || c == '\u0EB0' ||
(c >= '\u0EB2' && c <= '\u0EB3') || c == '\u0EBD' || (c >= '\u0EC0' && c <= '\u0EC4') ||
(c >= '\u0F40' && c <= '\u0F47') || (c >= '\u0F49' && c <= '\u0F69') || (c >= '\u10A0' && c <= '\u10C5') ||
(c >= '\u10D0' && c <= '\u10F6') || c == '\u1100' || (c >= '\u1102' && c <= '\u1103') ||
(c >= '\u1105' && c <= '\u1107') || c == '\u1109' || (c >= '\u110B' && c <= '\u110C') ||
(c >= '\u110E' && c <= '\u1112') || c == '\u113C' || c == '\u113E' || c == '\u1140' || c == '\u114C' ||
c == '\u114E' || c == '\u1150' || (c >= '\u1154' && c <= '\u1155') || c == '\u1159' ||
(c >= '\u115F' && c <= '\u1161') || c == '\u1163' || c == '\u1165' || c == '\u1167' || c == '\u1169' ||
(c >= '\u116D' && c <= '\u116E') || (c >= '\u1172' && c <= '\u1173') || c == '\u1175' ||
c == '\u119E' || c == '\u11A8' || c == '\u11AB' || (c >= '\u11AE' && c <= '\u11AF') ||
(c >= '\u11B7' && c <= '\u11B8') || c == '\u11BA' || (c >= '\u11BC' && c <= '\u11C2') ||
c == '\u11EB' || c == '\u11F0' || c == '\u11F9' || (c >= '\u1E00' && c <= '\u1E9B') || (c >= '\u1EA0' && c <= '\u1EF9') ||
(c >= '\u1F00' && c <= '\u1F15') || (c >= '\u1F18' && c <= '\u1F1D') || (c >= '\u1F20' && c <= '\u1F45') ||
(c >= '\u1F48' && c <= '\u1F4D') || (c >= '\u1F50' && c <= '\u1F57') || c == '\u1F59' || c == '\u1F5B' || c == '\u1F5D' ||
(c >= '\u1F5F' && c <= '\u1F7D') || (c >= '\u1F80' && c <= '\u1FB4') || (c >= '\u1FB6' && c <= '\u1FBC') ||
c == '\u1FBE' || (c >= '\u1FC2' && c <= '\u1FC4') || (c >= '\u1FC6' && c <= '\u1FCC') ||
(c >= '\u1FD0' && c <= '\u1FD3') || (c >= '\u1FD6' && c <= '\u1FDB') || (c >= '\u1FE0' && c <= '\u1FEC') ||
(c >= '\u1FF2' && c <= '\u1FF4') || (c >= '\u1FF6' && c <= '\u1FFC') || c == '\u2126' ||
(c >= '\u212A' && c <= '\u212B') || c == '\u212E' || (c >= '\u2180' && c <= '\u2182') ||
(c >= '\u3041' && c <= '\u3094') || (c >= '\u30A1' && c <= '\u30FA') || (c >= '\u3105' && c <= '\u312C') ||
(c >= '\uAC00' && c <= '\uD7A3');
}
private static boolean isIdeographic(char c) {
return (c >= '\u4E00' && c <= '\u9FA5') || c == '\u3007' || (c >= '\u3021' && c <= '\u3029');
}
public static String determineEncoding(InputStream stream) throws IOException {
stream.mark(20000);
try {
int b0 = stream.read();
int b1 = stream.read();
int b2 = stream.read();
int b3 = stream.read();
if (b0 == 0xFE && b1 == 0xFF)
return "UTF-16BE";
else if (b0 == 0xFF && b1 == 0xFE)
return "UTF-16LE";
else if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF )
return "UTF-8";
else if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F)
return "UTF-16BE";
else if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00)
return "UTF-16LE";
else if (b0 == 0x3C && b1 == 0x3F && b2 == 0x78 && b3 == 0x6D) {
// UTF-8, ISO 646, ASCII, some part of ISO 8859, Shift-JIS, EUC, or any other 7-bit, 8-bit, or mixed-width encoding
// which ensures that the characters of ASCII have their normal positions, width, and values; the actual encoding
// declaration must be read to detect which of these applies, but since all of these encodings use the same bit patterns
// for the relevant ASCII characters, the encoding declaration itself may be read reliably
InputStreamReader rdr = new InputStreamReader(stream, "US-ASCII");
String hdr = readFirstLine(rdr);
return extractEncoding(hdr);
} else
return null;
} finally {
stream.reset();
}
}
private static String extractEncoding(String hdr) {
int i = hdr.indexOf("encoding=");
if (i == -1)
return null;
hdr = hdr.substring(i+9);
char sep = hdr.charAt(0);
hdr = hdr.substring(1);
i = hdr.indexOf(sep);
if (i == -1)
return null;
return hdr.substring(0, i);
}
private static String readFirstLine(InputStreamReader rdr) throws IOException {
char[] buf = new char[1];
StringBuffer bldr = new StringBuffer();
rdr.read(buf);
while (buf[0] != '>') {
bldr.append(buf[0]);
rdr.read(buf);
}
return bldr.toString();
}
public static boolean charSetImpliesAscii(String charset) {
return charset.equals("ISO-8859-1") || charset.equals("US-ASCII");
}
/**
* Converts the raw characters to XML escape characters.
*
* @param rawContent
* @param charset Null when charset is not known, so we assume it's unicode
* @param isNoLines
* @return escape string
*/
public static String escapeXML(String rawContent, String charset, boolean isNoLines) {
if (rawContent == null)
return "";
else {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < rawContent.length(); i++) {
char ch = rawContent.charAt(i);
if (ch == '\'')
sb.append("&#39;");
else if (ch == '&')
sb.append("&amp;");
else if (ch == '"')
sb.append("&quot;");
else if (ch == '<')
sb.append("&lt;");
else if (ch == '>')
sb.append("&gt;");
else if (ch > '~' && charset != null && charSetImpliesAscii(charset))
// TODO - why is hashcode the only way to get the unicode number for the character
// in jre 5.0?
sb.append("&#x"+Integer.toHexString(ch).toUpperCase()+";");
else if (isNoLines) {
if (ch == '\r')
sb.append("&#xA;");
else if (ch != '\n')
sb.append(ch);
}
else
sb.append(ch);
}
return sb.toString();
}
}
public static Element getFirstChild(Element e) {
if (e == null)
return null;
Node n = e.getFirstChild();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getNextSibling();
return (Element) n;
}
public static Element getNamedChild(Element e, String name) {
Element c = getFirstChild(e);
while (c != null && !name.equals(c.getLocalName()) && !name.equals(c.getNodeName()))
c = getNextSibling(c);
return c;
}
public static Element getNextSibling(Element e) {
Node n = e.getNextSibling();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getNextSibling();
return (Element) n;
}
public static void getNamedChildren(Element e, String name, List<Element> set) {
Element c = getFirstChild(e);
while (c != null) {
if (name.equals(c.getLocalName()) || name.equals(c.getNodeName()) )
set.add(c);
c = getNextSibling(c);
}
}
public static String htmlToXmlEscapedPlainText(Element r) {
StringBuilder s = new StringBuilder();
Node n = r.getFirstChild();
boolean ws = false;
while (n != null) {
if (n.getNodeType() == Node.TEXT_NODE) {
String t = n.getTextContent().trim();
if (Utilities.noString(t))
ws = true;
else {
if (ws)
s.append(" ");
ws = false;
s.append(t);
}
}
if (n.getNodeType() == Node.ELEMENT_NODE) {
if (ws)
s.append(" ");
ws = false;
s.append(htmlToXmlEscapedPlainText((Element) n));
if (r.getNodeName().equals("br") || r.getNodeName().equals("p"))
s.append("\r\n");
}
n = n.getNextSibling();
}
return s.toString();
}
public static String htmlToXmlEscapedPlainText(String definition) throws ParserConfigurationException, SAXException, IOException {
return htmlToXmlEscapedPlainText(parseToDom("<div>"+definition+"</div>").getDocumentElement());
}
public static String elementToString(Element el) {
if (el == null)
return "";
Document document = el.getOwnerDocument();
DOMImplementationLS domImplLS = (DOMImplementationLS) document
.getImplementation();
LSSerializer serializer = domImplLS.createLSSerializer();
return serializer.writeToString(el);
}
public static String getNamedChildValue(Element element, String name) {
Element e = getNamedChild(element, name);
return e == null ? null : e.getAttribute("value");
}
public static void setNamedChildValue(Element element, String name, String value) throws FHIRException {
Element e = getNamedChild(element, name);
if (e == null)
throw new FHIRException("unable to find element "+name);
e.setAttribute("value", value);
}
public static void getNamedChildrenWithWildcard(Element focus, String name, List<Element> children) {
Element c = getFirstChild(focus);
while (c != null) {
String n = c.getLocalName() != null ? c.getLocalName() : c.getNodeName();
if (name.equals(n) || (name.endsWith("[x]") && n.startsWith(name.substring(0, name.length()-3))))
children.add(c);
c = getNextSibling(c);
}
}
public static void getNamedChildrenWithTails(Element focus, String name, List<Element> children, Set<String> typeTails) {
Element c = getFirstChild(focus);
while (c != null) {
String n = c.getLocalName() != null ? c.getLocalName() : c.getNodeName();
if (n.equals(name) || (!n.equals("responseCode") && (n.startsWith(name) && typeTails.contains(n.substring(name.length())))))
children.add(c);
c = getNextSibling(c);
}
}
public static boolean hasNamedChild(Element e, String name) {
Element c = getFirstChild(e);
while (c != null && !name.equals(c.getLocalName()) && !name.equals(c.getNodeName()))
c = getNextSibling(c);
return c != null;
}
public static Document parseToDom(String content) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(content.getBytes()));
}
public static Document parseFileToDom(String filename) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new FileInputStream(filename));
}
public static Element getLastChild(Element e) {
if (e == null)
return null;
Node n = e.getLastChild();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getPreviousSibling();
return (Element) n;
}
public static Element getPrevSibling(Element e) {
Node n = e.getPreviousSibling();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getPreviousSibling();
return (Element) n;
}
public static String getNamedChildAttribute(Element element, String name, String aname) {
Element e = getNamedChild(element, name);
return e == null ? null : e.getAttribute(aname);
}
public static void writeDomToFile(Document doc, String filename) throws TransformerException {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult streamResult = new StreamResult(new File(filename));
transformer.transform(source, streamResult);
}
public static String getXsiType(org.w3c.dom.Element element) {
Attr a = element.getAttributeNodeNS("http://www.w3.org/2001/XMLSchema-instance", "type");
return (a == null ? null : a.getTextContent());
}
public static String getDirectText(org.w3c.dom.Element node) {
Node n = node.getFirstChild();
StringBuilder b = new StringBuilder();
while (n != null) {
if (n.getNodeType() == Node.TEXT_NODE)
b.append(n.getTextContent());
n = n.getNextSibling();
}
return b.toString().trim();
}
}
/*
Copyright (c) 2011+, HL7, Inc
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific
prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
*/
package org.hl7.fhir.utilities.xml;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.List;
import java.util.Set;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.utilities.Utilities;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.ls.DOMImplementationLS;
import org.w3c.dom.ls.LSSerializer;
import org.xml.sax.SAXException;
public class XMLUtil {
public static final String SPACE_CHAR = "\u00A0";
public static boolean isNMToken(String name) {
if (name == null)
return false;
for (int i = 0; i < name.length(); i++)
if (!isNMTokenChar(name.charAt(i)))
return false;
return name.length() > 0;
}
public static boolean isNMTokenChar(char c) {
return isLetter(c) || isDigit(c) || c == '.' || c == '-' || c == '_' || c == ':' || isCombiningChar(c) || isExtender(c);
}
private static boolean isDigit(char c) {
return (c >= '\u0030' && c <= '\u0039') || (c >= '\u0660' && c <= '\u0669') || (c >= '\u06F0' && c <= '\u06F9') ||
(c >= '\u0966' && c <= '\u096F') || (c >= '\u09E6' && c <= '\u09EF') || (c >= '\u0A66' && c <= '\u0A6F') ||
(c >= '\u0AE6' && c <= '\u0AEF') || (c >= '\u0B66' && c <= '\u0B6F') || (c >= '\u0BE7' && c <= '\u0BEF') ||
(c >= '\u0C66' && c <= '\u0C6F') || (c >= '\u0CE6' && c <= '\u0CEF') || (c >= '\u0D66' && c <= '\u0D6F') ||
(c >= '\u0E50' && c <= '\u0E59') || (c >= '\u0ED0' && c <= '\u0ED9') || (c >= '\u0F20' && c <= '\u0F29');
}
private static boolean isCombiningChar(char c) {
return (c >= '\u0300' && c <= '\u0345') || (c >= '\u0360' && c <= '\u0361') || (c >= '\u0483' && c <= '\u0486') ||
(c >= '\u0591' && c <= '\u05A1') || (c >= '\u05A3' && c <= '\u05B9') || (c >= '\u05BB' && c <= '\u05BD') ||
c == '\u05BF' || (c >= '\u05C1' && c <= '\u05C2') || c == '\u05C4' || (c >= '\u064B' && c <= '\u0652') ||
c == '\u0670' || (c >= '\u06D6' && c <= '\u06DC') || (c >= '\u06DD' && c <= '\u06DF') || (c >= '\u06E0' && c <= '\u06E4') ||
(c >= '\u06E7' && c <= '\u06E8') || (c >= '\u06EA' && c <= '\u06ED') || (c >= '\u0901' && c <= '\u0903') || c == '\u093C' ||
(c >= '\u093E' && c <= '\u094C') || c == '\u094D' || (c >= '\u0951' && c <= '\u0954') || (c >= '\u0962' && c <= '\u0963') ||
(c >= '\u0981' && c <= '\u0983') || c == '\u09BC' || c == '\u09BE' || c == '\u09BF' || (c >= '\u09C0' && c <= '\u09C4') ||
(c >= '\u09C7' && c <= '\u09C8') || (c >= '\u09CB' && c <= '\u09CD') || c == '\u09D7' || (c >= '\u09E2' && c <= '\u09E3') ||
c == '\u0A02' || c == '\u0A3C' || c == '\u0A3E' || c == '\u0A3F' || (c >= '\u0A40' && c <= '\u0A42') ||
(c >= '\u0A47' && c <= '\u0A48') || (c >= '\u0A4B' && c <= '\u0A4D') || (c >= '\u0A70' && c <= '\u0A71') ||
(c >= '\u0A81' && c <= '\u0A83') || c == '\u0ABC' || (c >= '\u0ABE' && c <= '\u0AC5') || (c >= '\u0AC7' && c <= '\u0AC9') ||
(c >= '\u0ACB' && c <= '\u0ACD') || (c >= '\u0B01' && c <= '\u0B03') || c == '\u0B3C' || (c >= '\u0B3E' && c <= '\u0B43') ||
(c >= '\u0B47' && c <= '\u0B48') || (c >= '\u0B4B' && c <= '\u0B4D') || (c >= '\u0B56' && c <= '\u0B57') ||
(c >= '\u0B82' && c <= '\u0B83') || (c >= '\u0BBE' && c <= '\u0BC2') || (c >= '\u0BC6' && c <= '\u0BC8') ||
(c >= '\u0BCA' && c <= '\u0BCD') || c == '\u0BD7' || (c >= '\u0C01' && c <= '\u0C03') || (c >= '\u0C3E' && c <= '\u0C44') ||
(c >= '\u0C46' && c <= '\u0C48') || (c >= '\u0C4A' && c <= '\u0C4D') || (c >= '\u0C55' && c <= '\u0C56') ||
(c >= '\u0C82' && c <= '\u0C83') || (c >= '\u0CBE' && c <= '\u0CC4') || (c >= '\u0CC6' && c <= '\u0CC8') ||
(c >= '\u0CCA' && c <= '\u0CCD') || (c >= '\u0CD5' && c <= '\u0CD6') || (c >= '\u0D02' && c <= '\u0D03') ||
(c >= '\u0D3E' && c <= '\u0D43') || (c >= '\u0D46' && c <= '\u0D48') || (c >= '\u0D4A' && c <= '\u0D4D') || c == '\u0D57' ||
c == '\u0E31' || (c >= '\u0E34' && c <= '\u0E3A') || (c >= '\u0E47' && c <= '\u0E4E') || c == '\u0EB1' ||
(c >= '\u0EB4' && c <= '\u0EB9') || (c >= '\u0EBB' && c <= '\u0EBC') || (c >= '\u0EC8' && c <= '\u0ECD') ||
(c >= '\u0F18' && c <= '\u0F19') || c == '\u0F35' || c == '\u0F37' || c == '\u0F39' || c == '\u0F3E' || c == '\u0F3F' ||
(c >= '\u0F71' && c <= '\u0F84') || (c >= '\u0F86' && c <= '\u0F8B') || (c >= '\u0F90' && c <= '\u0F95') || c == '\u0F97' ||
(c >= '\u0F99' && c <= '\u0FAD') || (c >= '\u0FB1' && c <= '\u0FB7') || c == '\u0FB9' || (c >= '\u20D0' && c <= '\u20DC') ||
c == '\u20E1' || (c >= '\u302A' && c <= '\u302F') || c == '\u3099' || c == '\u309A';
}
private static boolean isExtender(char c) {
return c == '\u00B7' || c == '\u02D0' || c == '\u02D1' || c == '\u0387' || c == '\u0640' || c == '\u0E46' ||
c == '\u0EC6' || c == '\u3005' || (c >= '\u3031' && c <= '\u3035') || (c >= '\u309D' && c <= '\u309E') ||
(c >= '\u30FC' && c <= '\u30FE');
}
private static boolean isLetter(char c) {
return isBaseChar(c) || isIdeographic(c);
}
private static boolean isBaseChar(char c) {
return (c >= '\u0041' && c <= '\u005A') || (c >= '\u0061' && c <= '\u007A') || (c >= '\u00C0' && c <= '\u00D6') ||
(c >= '\u00D8' && c <= '\u00F6') || (c >= '\u00F8' && c <= '\u00FF') || (c >= '\u0100' && c <= '\u0131') ||
(c >= '\u0134' && c <= '\u013E') || (c >= '\u0141' && c <= '\u0148') || (c >= '\u014A' && c <= '\u017E') ||
(c >= '\u0180' && c <= '\u01C3') || (c >= '\u01CD' && c <= '\u01F0') || (c >= '\u01F4' && c <= '\u01F5') ||
(c >= '\u01FA' && c <= '\u0217') || (c >= '\u0250' && c <= '\u02A8') || (c >= '\u02BB' && c <= '\u02C1') ||
c == '\u0386' || (c >= '\u0388' && c <= '\u038A') || c == '\u038C' || (c >= '\u038E' && c <= '\u03A1') ||
(c >= '\u03A3' && c <= '\u03CE') || (c >= '\u03D0' && c <= '\u03D6') || c == '\u03DA' || c == '\u03DC' || c == '\u03DE' ||
c == '\u03E0' || (c >= '\u03E2' && c <= '\u03F3') || (c >= '\u0401' && c <= '\u040C') || (c >= '\u040E' && c <= '\u044F') ||
(c >= '\u0451' && c <= '\u045C') || (c >= '\u045E' && c <= '\u0481') || (c >= '\u0490' && c <= '\u04C4') ||
(c >= '\u04C7' && c <= '\u04C8') || (c >= '\u04CB' && c <= '\u04CC') || (c >= '\u04D0' && c <= '\u04EB') ||
(c >= '\u04EE' && c <= '\u04F5') || (c >= '\u04F8' && c <= '\u04F9') || (c >= '\u0531' && c <= '\u0556') ||
c == '\u0559' || (c >= '\u0561' && c <= '\u0586') || (c >= '\u05D0' && c <= '\u05EA') || (c >= '\u05F0' && c <= '\u05F2') ||
(c >= '\u0621' && c <= '\u063A') || (c >= '\u0641' && c <= '\u064A') || (c >= '\u0671' && c <= '\u06B7') ||
(c >= '\u06BA' && c <= '\u06BE') || (c >= '\u06C0' && c <= '\u06CE') || (c >= '\u06D0' && c <= '\u06D3') ||
c == '\u06D5' || (c >= '\u06E5' && c <= '\u06E6') || (c >= '\u0905' && c <= '\u0939') || c == '\u093D' ||
(c >= '\u0958' && c <= '\u0961') || (c >= '\u0985' && c <= '\u098C') || (c >= '\u098F' && c <= '\u0990') ||
(c >= '\u0993' && c <= '\u09A8') || (c >= '\u09AA' && c <= '\u09B0') || c == '\u09B2' ||
(c >= '\u09B6' && c <= '\u09B9') || (c >= '\u09DC' && c <= '\u09DD') || (c >= '\u09DF' && c <= '\u09E1') ||
(c >= '\u09F0' && c <= '\u09F1') || (c >= '\u0A05' && c <= '\u0A0A') || (c >= '\u0A0F' && c <= '\u0A10') ||
(c >= '\u0A13' && c <= '\u0A28') || (c >= '\u0A2A' && c <= '\u0A30') || (c >= '\u0A32' && c <= '\u0A33') ||
(c >= '\u0A35' && c <= '\u0A36') || (c >= '\u0A38' && c <= '\u0A39') || (c >= '\u0A59' && c <= '\u0A5C') ||
c == '\u0A5E' || (c >= '\u0A72' && c <= '\u0A74') || (c >= '\u0A85' && c <= '\u0A8B') || c == '\u0A8D' ||
(c >= '\u0A8F' && c <= '\u0A91') || (c >= '\u0A93' && c <= '\u0AA8') || (c >= '\u0AAA' && c <= '\u0AB0') ||
(c >= '\u0AB2' && c <= '\u0AB3') || (c >= '\u0AB5' && c <= '\u0AB9') || c == '\u0ABD' || c == '\u0AE0' ||
(c >= '\u0B05' && c <= '\u0B0C') || (c >= '\u0B0F' && c <= '\u0B10') || (c >= '\u0B13' && c <= '\u0B28') ||
(c >= '\u0B2A' && c <= '\u0B30') || (c >= '\u0B32' && c <= '\u0B33') || (c >= '\u0B36' && c <= '\u0B39') ||
c == '\u0B3D' || (c >= '\u0B5C' && c <= '\u0B5D') || (c >= '\u0B5F' && c <= '\u0B61') ||
(c >= '\u0B85' && c <= '\u0B8A') || (c >= '\u0B8E' && c <= '\u0B90') || (c >= '\u0B92' && c <= '\u0B95') ||
(c >= '\u0B99' && c <= '\u0B9A') || c == '\u0B9C' || (c >= '\u0B9E' && c <= '\u0B9F') ||
(c >= '\u0BA3' && c <= '\u0BA4') || (c >= '\u0BA8' && c <= '\u0BAA') || (c >= '\u0BAE' && c <= '\u0BB5') ||
(c >= '\u0BB7' && c <= '\u0BB9') || (c >= '\u0C05' && c <= '\u0C0C') || (c >= '\u0C0E' && c <= '\u0C10') ||
(c >= '\u0C12' && c <= '\u0C28') || (c >= '\u0C2A' && c <= '\u0C33') || (c >= '\u0C35' && c <= '\u0C39') ||
(c >= '\u0C60' && c <= '\u0C61') || (c >= '\u0C85' && c <= '\u0C8C') || (c >= '\u0C8E' && c <= '\u0C90') ||
(c >= '\u0C92' && c <= '\u0CA8') || (c >= '\u0CAA' && c <= '\u0CB3') || (c >= '\u0CB5' && c <= '\u0CB9') ||
c == '\u0CDE' || (c >= '\u0CE0' && c <= '\u0CE1') || (c >= '\u0D05' && c <= '\u0D0C') ||
(c >= '\u0D0E' && c <= '\u0D10') || (c >= '\u0D12' && c <= '\u0D28') || (c >= '\u0D2A' && c <= '\u0D39') ||
(c >= '\u0D60' && c <= '\u0D61') || (c >= '\u0E01' && c <= '\u0E2E') || c == '\u0E30' ||
(c >= '\u0E32' && c <= '\u0E33') || (c >= '\u0E40' && c <= '\u0E45') || (c >= '\u0E81' && c <= '\u0E82') ||
c == '\u0E84' || (c >= '\u0E87' && c <= '\u0E88') || c == '\u0E8A' || c == '\u0E8D' || (c >= '\u0E94' && c <= '\u0E97') ||
(c >= '\u0E99' && c <= '\u0E9F') || (c >= '\u0EA1' && c <= '\u0EA3') || c == '\u0EA5' || c == '\u0EA7' ||
(c >= '\u0EAA' && c <= '\u0EAB') || (c >= '\u0EAD' && c <= '\u0EAE') || c == '\u0EB0' ||
(c >= '\u0EB2' && c <= '\u0EB3') || c == '\u0EBD' || (c >= '\u0EC0' && c <= '\u0EC4') ||
(c >= '\u0F40' && c <= '\u0F47') || (c >= '\u0F49' && c <= '\u0F69') || (c >= '\u10A0' && c <= '\u10C5') ||
(c >= '\u10D0' && c <= '\u10F6') || c == '\u1100' || (c >= '\u1102' && c <= '\u1103') ||
(c >= '\u1105' && c <= '\u1107') || c == '\u1109' || (c >= '\u110B' && c <= '\u110C') ||
(c >= '\u110E' && c <= '\u1112') || c == '\u113C' || c == '\u113E' || c == '\u1140' || c == '\u114C' ||
c == '\u114E' || c == '\u1150' || (c >= '\u1154' && c <= '\u1155') || c == '\u1159' ||
(c >= '\u115F' && c <= '\u1161') || c == '\u1163' || c == '\u1165' || c == '\u1167' || c == '\u1169' ||
(c >= '\u116D' && c <= '\u116E') || (c >= '\u1172' && c <= '\u1173') || c == '\u1175' ||
c == '\u119E' || c == '\u11A8' || c == '\u11AB' || (c >= '\u11AE' && c <= '\u11AF') ||
(c >= '\u11B7' && c <= '\u11B8') || c == '\u11BA' || (c >= '\u11BC' && c <= '\u11C2') ||
c == '\u11EB' || c == '\u11F0' || c == '\u11F9' || (c >= '\u1E00' && c <= '\u1E9B') || (c >= '\u1EA0' && c <= '\u1EF9') ||
(c >= '\u1F00' && c <= '\u1F15') || (c >= '\u1F18' && c <= '\u1F1D') || (c >= '\u1F20' && c <= '\u1F45') ||
(c >= '\u1F48' && c <= '\u1F4D') || (c >= '\u1F50' && c <= '\u1F57') || c == '\u1F59' || c == '\u1F5B' || c == '\u1F5D' ||
(c >= '\u1F5F' && c <= '\u1F7D') || (c >= '\u1F80' && c <= '\u1FB4') || (c >= '\u1FB6' && c <= '\u1FBC') ||
c == '\u1FBE' || (c >= '\u1FC2' && c <= '\u1FC4') || (c >= '\u1FC6' && c <= '\u1FCC') ||
(c >= '\u1FD0' && c <= '\u1FD3') || (c >= '\u1FD6' && c <= '\u1FDB') || (c >= '\u1FE0' && c <= '\u1FEC') ||
(c >= '\u1FF2' && c <= '\u1FF4') || (c >= '\u1FF6' && c <= '\u1FFC') || c == '\u2126' ||
(c >= '\u212A' && c <= '\u212B') || c == '\u212E' || (c >= '\u2180' && c <= '\u2182') ||
(c >= '\u3041' && c <= '\u3094') || (c >= '\u30A1' && c <= '\u30FA') || (c >= '\u3105' && c <= '\u312C') ||
(c >= '\uAC00' && c <= '\uD7A3');
}
private static boolean isIdeographic(char c) {
return (c >= '\u4E00' && c <= '\u9FA5') || c == '\u3007' || (c >= '\u3021' && c <= '\u3029');
}
public static String determineEncoding(InputStream stream) throws IOException {
stream.mark(20000);
try {
int b0 = stream.read();
int b1 = stream.read();
int b2 = stream.read();
int b3 = stream.read();
if (b0 == 0xFE && b1 == 0xFF)
return "UTF-16BE";
else if (b0 == 0xFF && b1 == 0xFE)
return "UTF-16LE";
else if (b0 == 0xEF && b1 == 0xBB && b2 == 0xBF )
return "UTF-8";
else if (b0 == 0x00 && b1 == 0x3C && b2 == 0x00 && b3 == 0x3F)
return "UTF-16BE";
else if (b0 == 0x3C && b1 == 0x00 && b2 == 0x3F && b3 == 0x00)
return "UTF-16LE";
else if (b0 == 0x3C && b1 == 0x3F && b2 == 0x78 && b3 == 0x6D) {
// UTF-8, ISO 646, ASCII, some part of ISO 8859, Shift-JIS, EUC, or any other 7-bit, 8-bit, or mixed-width encoding
// which ensures that the characters of ASCII have their normal positions, width, and values; the actual encoding
// declaration must be read to detect which of these applies, but since all of these encodings use the same bit patterns
// for the relevant ASCII characters, the encoding declaration itself may be read reliably
InputStreamReader rdr = new InputStreamReader(stream, "US-ASCII");
String hdr = readFirstLine(rdr);
return extractEncoding(hdr);
} else
return null;
} finally {
stream.reset();
}
}
private static String extractEncoding(String hdr) {
int i = hdr.indexOf("encoding=");
if (i == -1)
return null;
hdr = hdr.substring(i+9);
char sep = hdr.charAt(0);
hdr = hdr.substring(1);
i = hdr.indexOf(sep);
if (i == -1)
return null;
return hdr.substring(0, i);
}
private static String readFirstLine(InputStreamReader rdr) throws IOException {
char[] buf = new char[1];
StringBuffer bldr = new StringBuffer();
rdr.read(buf);
while (buf[0] != '>') {
bldr.append(buf[0]);
rdr.read(buf);
}
return bldr.toString();
}
public static boolean charSetImpliesAscii(String charset) {
return charset.equals("ISO-8859-1") || charset.equals("US-ASCII");
}
/**
* Converts the raw characters to XML escapeUrlParam characters.
*
* @param rawContent
* @param charset Null when charset is not known, so we assume it's unicode
* @param isNoLines
* @return escapeUrlParam string
*/
public static String escapeXML(String rawContent, String charset, boolean isNoLines) {
if (rawContent == null)
return "";
else {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < rawContent.length(); i++) {
char ch = rawContent.charAt(i);
if (ch == '\'')
sb.append("&#39;");
else if (ch == '&')
sb.append("&amp;");
else if (ch == '"')
sb.append("&quot;");
else if (ch == '<')
sb.append("&lt;");
else if (ch == '>')
sb.append("&gt;");
else if (ch > '~' && charset != null && charSetImpliesAscii(charset))
// TODO - why is hashcode the only way to get the unicode number for the character
// in jre 5.0?
sb.append("&#x"+Integer.toHexString(ch).toUpperCase()+";");
else if (isNoLines) {
if (ch == '\r')
sb.append("&#xA;");
else if (ch != '\n')
sb.append(ch);
}
else
sb.append(ch);
}
return sb.toString();
}
}
public static Element getFirstChild(Element e) {
if (e == null)
return null;
Node n = e.getFirstChild();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getNextSibling();
return (Element) n;
}
public static Element getNamedChild(Element e, String name) {
Element c = getFirstChild(e);
while (c != null && !name.equals(c.getLocalName()) && !name.equals(c.getNodeName()))
c = getNextSibling(c);
return c;
}
public static Element getNextSibling(Element e) {
Node n = e.getNextSibling();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getNextSibling();
return (Element) n;
}
public static void getNamedChildren(Element e, String name, List<Element> set) {
Element c = getFirstChild(e);
while (c != null) {
if (name.equals(c.getLocalName()) || name.equals(c.getNodeName()) )
set.add(c);
c = getNextSibling(c);
}
}
public static String htmlToXmlEscapedPlainText(Element r) {
StringBuilder s = new StringBuilder();
Node n = r.getFirstChild();
boolean ws = false;
while (n != null) {
if (n.getNodeType() == Node.TEXT_NODE) {
String t = n.getTextContent().trim();
if (Utilities.noString(t))
ws = true;
else {
if (ws)
s.append(" ");
ws = false;
s.append(t);
}
}
if (n.getNodeType() == Node.ELEMENT_NODE) {
if (ws)
s.append(" ");
ws = false;
s.append(htmlToXmlEscapedPlainText((Element) n));
if (r.getNodeName().equals("br") || r.getNodeName().equals("p"))
s.append("\r\n");
}
n = n.getNextSibling();
}
return s.toString();
}
public static String htmlToXmlEscapedPlainText(String definition) throws ParserConfigurationException, SAXException, IOException {
return htmlToXmlEscapedPlainText(parseToDom("<div>"+definition+"</div>").getDocumentElement());
}
public static String elementToString(Element el) {
if (el == null)
return "";
Document document = el.getOwnerDocument();
DOMImplementationLS domImplLS = (DOMImplementationLS) document
.getImplementation();
LSSerializer serializer = domImplLS.createLSSerializer();
return serializer.writeToString(el);
}
public static String getNamedChildValue(Element element, String name) {
Element e = getNamedChild(element, name);
return e == null ? null : e.getAttribute("value");
}
public static void setNamedChildValue(Element element, String name, String value) throws FHIRException {
Element e = getNamedChild(element, name);
if (e == null)
throw new FHIRException("unable to find element "+name);
e.setAttribute("value", value);
}
public static void getNamedChildrenWithWildcard(Element focus, String name, List<Element> children) {
Element c = getFirstChild(focus);
while (c != null) {
String n = c.getLocalName() != null ? c.getLocalName() : c.getNodeName();
if (name.equals(n) || (name.endsWith("[x]") && n.startsWith(name.substring(0, name.length()-3))))
children.add(c);
c = getNextSibling(c);
}
}
public static void getNamedChildrenWithTails(Element focus, String name, List<Element> children, Set<String> typeTails) {
Element c = getFirstChild(focus);
while (c != null) {
String n = c.getLocalName() != null ? c.getLocalName() : c.getNodeName();
if (n.equals(name) || (!n.equals("responseCode") && (n.startsWith(name) && typeTails.contains(n.substring(name.length())))))
children.add(c);
c = getNextSibling(c);
}
}
public static boolean hasNamedChild(Element e, String name) {
Element c = getFirstChild(e);
while (c != null && !name.equals(c.getLocalName()) && !name.equals(c.getNodeName()))
c = getNextSibling(c);
return c != null;
}
public static Document parseToDom(String content) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new ByteArrayInputStream(content.getBytes()));
}
public static Document parseFileToDom(String filename) throws ParserConfigurationException, SAXException, IOException {
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(false);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder.parse(new FileInputStream(filename));
}
public static Element getLastChild(Element e) {
if (e == null)
return null;
Node n = e.getLastChild();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getPreviousSibling();
return (Element) n;
}
public static Element getPrevSibling(Element e) {
Node n = e.getPreviousSibling();
while (n != null && n.getNodeType() != Node.ELEMENT_NODE)
n = n.getPreviousSibling();
return (Element) n;
}
public static String getNamedChildAttribute(Element element, String name, String aname) {
Element e = getNamedChild(element, name);
return e == null ? null : e.getAttribute(aname);
}
public static void writeDomToFile(Document doc, String filename) throws TransformerException {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource source = new DOMSource(doc);
StreamResult streamResult = new StreamResult(new File(filename));
transformer.transform(source, streamResult);
}
public static String getXsiType(org.w3c.dom.Element element) {
Attr a = element.getAttributeNodeNS("http://www.w3.org/2001/XMLSchema-instance", "type");
return (a == null ? null : a.getTextContent());
}
public static String getDirectText(org.w3c.dom.Element node) {
Node n = node.getFirstChild();
StringBuilder b = new StringBuilder();
while (n != null) {
if (n.getNodeType() == Node.TEXT_NODE)
b.append(n.getTextContent());
n = n.getNextSibling();
}
return b.toString().trim();
}
}

View File

@ -57,7 +57,7 @@ public class GraphQLDstu3ProviderTest {
@Ignore
public void testGraphInstance() throws Exception {
String query = "{name{family,given}}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escape(query));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escapeUrlParam(query));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
@ -84,7 +84,7 @@ public class GraphQLDstu3ProviderTest {
@Ignore
public void testGraphInstanceWithFhirpath() throws Exception {
String query = "{name(fhirpath:\"family.exists()\"){text,given,family}}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escape(query));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/Patient/123/$graphql?query=" + UrlUtil.escapeUrlParam(query));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
@ -109,7 +109,7 @@ public class GraphQLDstu3ProviderTest {
@org.junit.Ignore
public void testGraphSystemInstance() throws Exception {
String query = "{Patient(id:123){id,name{given,family}}}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escape(query));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escapeUrlParam(query));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);
@ -138,7 +138,7 @@ public class GraphQLDstu3ProviderTest {
@Ignore
public void testGraphSystemList() throws Exception {
String query = "{PatientList(name:\"pet\"){name{family,given}}}";
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escape(query));
HttpGet httpGet = new HttpGet("http://localhost:" + ourPort + "/$graphql?query=" + UrlUtil.escapeUrlParam(query));
CloseableHttpResponse status = ourClient.execute(httpGet);
try {
String responseContent = IOUtils.toString(status.getEntity().getContent(), StandardCharsets.UTF_8);

View File

@ -11,6 +11,12 @@
Fix a crash in JPA server when performing a recursive
<![CDATA[<code>_include</code>]]> which doesn't actually find any matches.
</action>
<action type="fix" issue="796">
When encoding URL parameter values, HAPI FHIR would incorrectly escape
a space (" ") as a plus ("+") insetad of as "%20" as required by
RFC 3986. This affects client calls, as well as URLs generated by
the server (e.g. REST HOOK calls). Thanks to James Daily for reporting!
</action>
</release>
<release version="3.1.0" date="2017-11-23">
<action type="add">