All Downloads are FREE. Search and download functionalities are using the official Maven repository.

ca.uhn.fhir.util.UrlUtil Maven / Gradle / Ivy

There is a newer version: 7.6.1
Show newest version
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