
ca.uhn.fhir.util.UrlUtil Maven / Gradle / Ivy
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.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.server.Constants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
/*
* #%L
* HAPI FHIR - Core Library
* %%
* Copyright (C) 2014 - 2016 University Health Network
* %%
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* #L%
*/
public class UrlUtil {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(UrlUtil.class);
/**
* Resolve a relative URL - THIS METHOD WILL NOT FAIL but will log a warning and return theEndpoint if the input is invalid.
*/
public static String constructAbsoluteUrl(String theBase, String theEndpoint) {
if (theEndpoint == null) {
return null;
}
if (isAbsolute(theEndpoint)) {
return theEndpoint;
}
if (theBase == null) {
return theEndpoint;
}
try {
return new URL(new URL(theBase), theEndpoint).toString();
} catch (MalformedURLException e) {
ourLog.warn("Failed to resolve relative URL[" + theEndpoint + "] against absolute base[" + theBase + "]", e);
return theEndpoint;
}
}
public static String constructRelativeUrl(String theParentExtensionUrl, String theExtensionUrl) {
if (theParentExtensionUrl == null) {
return theExtensionUrl;
}
if (theExtensionUrl == null) {
return theExtensionUrl;
}
int parentLastSlashIdx = theParentExtensionUrl.lastIndexOf('/');
int childLastSlashIdx = theExtensionUrl.lastIndexOf('/');
if (parentLastSlashIdx == -1 || childLastSlashIdx == -1) {
return theExtensionUrl;
}
if (parentLastSlashIdx != childLastSlashIdx) {
return theExtensionUrl;
}
if (!theParentExtensionUrl.substring(0, parentLastSlashIdx).equals(theExtensionUrl.substring(0, parentLastSlashIdx))) {
return theExtensionUrl;
}
if (theExtensionUrl.length() > parentLastSlashIdx) {
return theExtensionUrl.substring(parentLastSlashIdx + 1);
}
return theExtensionUrl;
}
/**
* URL encode a value
*/
public static String escape(String theValue) {
if (theValue == null) {
return null;
}
try {
return URLEncoder.encode(theValue, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new Error("UTF-8 not supported on this platform");
}
}
public static boolean isAbsolute(String theValue) {
String value = theValue.toLowerCase();
return value.startsWith("http://") || value.startsWith("https://");
}
public static boolean isValid(String theUrl) {
if (theUrl == null || theUrl.length() < 8) {
return false;
}
String url = theUrl.toLowerCase();
if (url.charAt(0) != 'h') {
return false;
}
if (url.charAt(1) != 't') {
return false;
}
if (url.charAt(2) != 't') {
return false;
}
if (url.charAt(3) != 'p') {
return false;
}
int slashOffset;
if (url.charAt(4) == ':') {
slashOffset = 5;
} else if (url.charAt(4) == 's') {
if (url.charAt(5) != ':') {
return false;
}
slashOffset = 6;
} else {
return false;
}
if (url.charAt(slashOffset) != '/') {
return false;
}
if (url.charAt(slashOffset + 1) != '/') {
return false;
}
return true;
}
public static void main(String[] args) {
System.out.println(escape("http://snomed.info/sct?fhir_vs=isa/126851005"));
}
public static Map parseQueryString(String theQueryString) {
HashMap> map = new HashMap>();
parseQueryString(theQueryString, map);
return toQueryStringMap(map);
}
public static Map parseQueryStrings(String... theQueryString) {
HashMap> map = new HashMap>();
for (String next : theQueryString) {
parseQueryString(next, map);
}
return toQueryStringMap(map);
}
private static Map toQueryStringMap(HashMap> map) {
HashMap retVal = new HashMap();
for (Entry> nextEntry : map.entrySet()) {
retVal.put(nextEntry.getKey(), nextEntry.getValue().toArray(new String[nextEntry.getValue().size()]));
}
return retVal;
}
private static void parseQueryString(String theQueryString, HashMap> 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;
if (equalsIndex == -1) {
nextKey = nextToken;
nextValue = "";
} else {
nextKey = nextToken.substring(0, equalsIndex);
nextValue = nextToken.substring(equalsIndex + 1);
}
nextKey = unescape(nextKey);
nextValue = unescape(nextValue);
List list = map.get(nextKey);
if (list == null) {
list = new ArrayList();
map.put(nextKey, list);
}
list.add(nextValue);
}
}
//@formatter:off
/**
* Parse a URL in one of the following forms:
*
* - [Resource Type]?[Search Params]
*
- [Resource Type]/[Resource ID]
*
- [Resource Type]/[Resource ID]/_history/[Version ID]
*
*/
//@formatter:on
public static UrlParts parseUrl(String theUrl) {
String url = theUrl;
UrlParts retVal = new UrlParts();
if (url.startsWith("http")) {
if (url.startsWith("/")) {
url = url.substring(1);
}
int qmIdx = url.indexOf('?');
if (qmIdx != -1) {
retVal.setParams(defaultIfBlank(url.substring(qmIdx + 1), null));
url = url.substring(0, qmIdx);
}
IdDt id = new IdDt(url);
retVal.setResourceType(id.getResourceType());
retVal.setResourceId(id.getIdPart());
retVal.setVersionId(id.getVersionIdPart());
return retVal;
} else {
if (url.matches("\\/[a-zA-Z]+\\?.*")) {
url = url.substring(1);
}
int nextStart = 0;
boolean nextIsHistory = false;
for (int idx = 0; idx < url.length(); idx++) {
char nextChar = url.charAt(idx);
boolean atEnd = (idx + 1) == url.length();
if (nextChar == '?' || nextChar == '/' || atEnd) {
int endIdx = (atEnd && nextChar != '?') ? idx + 1 : idx;
String nextSubstring = url.substring(nextStart, endIdx);
if (retVal.getResourceType() == null) {
retVal.setResourceType(nextSubstring);
} else if (retVal.getResourceId() == null) {
retVal.setResourceId(nextSubstring);
} else if (nextIsHistory) {
retVal.setVersionId(nextSubstring);
} else {
if (nextSubstring.equals(Constants.URL_TOKEN_HISTORY)) {
nextIsHistory = true;
} else {
throw new InvalidRequestException("Invalid FHIR resource URL: " + url);
}
}
if (nextChar == '?') {
if (url.length() > idx + 1) {
retVal.setParams(url.substring(idx + 1, url.length()));
}
break;
}
nextStart = idx + 1;
}
}
return retVal;
}
}
public static String unescape(String theString) {
if (theString == null) {
return null;
}
for (int i = 0; i < theString.length(); i++) {
char nextChar = theString.charAt(i);
if (nextChar == '%' || nextChar == '+') {
try {
return URLDecoder.decode(theString, "UTF-8");
} catch (UnsupportedEncodingException e) {
throw new Error("UTF-8 not supported, this shouldn't happen", e);
}
}
}
return theString;
}
public static class UrlParts {
private String myParams;
private String myResourceId;
private String myResourceType;
private String myVersionId;
public String getParams() {
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 void setResourceId(String theResourceId) {
myResourceId = theResourceId;
}
public void setResourceType(String theResourceType) {
myResourceType = theResourceType;
}
public void setVersionId(String theVersionId) {
myVersionId = theVersionId;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy