| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You 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. |
| */ |
| |
| package org.apache.openejb.util; |
| |
| import java.io.UnsupportedEncodingException; |
| import java.net.URI; |
| import java.net.URISyntaxException; |
| import java.net.URLDecoder; |
| import java.net.URLEncoder; |
| import java.util.ArrayList; |
| import java.util.Arrays; |
| import java.util.Collections; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.LinkedHashMap; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| |
| /** |
| * Swiped verbatim from ActiveMQ... the URI kings. |
| * <p/> |
| * URI relativize(URI, URI) added afterwards to deal with the |
| * non-functional URI.relativize(URI) method |
| */ |
| public class URISupport { |
| |
| /** |
| * URI absoluteA = new URI("/Users/dblevins/work/openejb3/container/openejb-jee/apple/"); |
| * URI absoluteB = new URI("/Users/dblevins/work/openejb3/container/openejb-core/foo.jar"); |
| * <p/> |
| * URI relativeB = URISupport.relativize(absoluteA, absoluteB); |
| * <p/> |
| * assertEquals("../../openejb-core/foo.jar", relativeB.toString()); |
| * <p/> |
| * URI resolvedB = absoluteA.resolve(relativeB); |
| * assertTrue(resolvedB.equals(absoluteB)); |
| * |
| * @param a |
| * @param b |
| * @return relative b |
| */ |
| public static URI relativize(final URI a, URI b) { |
| if (a == null || b == null) { |
| return b; |
| } |
| |
| if (!a.isAbsolute() && b.isAbsolute()) { |
| return b; |
| } |
| |
| if (!b.isAbsolute()) { |
| b = a.resolve(b); |
| } |
| |
| final List<String> pathA = Arrays.asList(a.getPath().split("/")); |
| final List<String> pathB = Arrays.asList(b.getPath().split("/")); |
| |
| final int limit = Math.min(pathA.size(), pathB.size()); |
| |
| |
| int lastMatch = 0; |
| while (lastMatch < limit) { |
| final String aa = pathA.get(lastMatch); |
| final String bb = pathB.get(lastMatch); |
| if (aa.equals(bb)) { |
| lastMatch++; |
| } else { |
| break; |
| } |
| } |
| |
| final List<String> path = new ArrayList<String>(); |
| for (int x = pathA.size() - lastMatch; x > 0; x--) { |
| path.add(".."); |
| } |
| |
| final List<String> remaining = pathB.subList(lastMatch, pathB.size()); |
| path.addAll(remaining); |
| |
| try { |
| return new URI(null, null, Join.join("/", path), b.getQuery(), b.getFragment()); |
| } catch (final URISyntaxException e) { |
| throw new IllegalArgumentException(e); |
| } |
| } |
| |
| public static class CompositeData { |
| String scheme; |
| String path; |
| URI[] components; |
| Map parameters; |
| String fragment; |
| public String host; |
| |
| public URI[] getComponents() { |
| return components; |
| } |
| |
| public String getFragment() { |
| return fragment; |
| } |
| |
| public Map getParameters() { |
| return parameters; |
| } |
| |
| public String getScheme() { |
| return scheme; |
| } |
| |
| public String getPath() { |
| return path; |
| } |
| |
| public String getHost() { |
| return host; |
| } |
| |
| public URI toURI() throws URISyntaxException { |
| final StringBuilder sb = new StringBuilder(); |
| if (scheme != null) { |
| sb.append(scheme); |
| sb.append(':'); |
| } |
| |
| if (host != null && host.length() != 0) { |
| sb.append(host); |
| } else { |
| sb.append('('); |
| for (int i = 0; i < components.length; i++) { |
| if (i != 0) { |
| sb.append(','); |
| } |
| sb.append(components[i].toString()); |
| } |
| sb.append(')'); |
| } |
| |
| if (path != null) { |
| sb.append('/'); |
| sb.append(path); |
| } |
| if (!parameters.isEmpty()) { |
| sb.append("?"); |
| sb.append(createQueryString(parameters)); |
| } |
| if (fragment != null) { |
| sb.append("#"); |
| sb.append(fragment); |
| } |
| return URLs.uri(sb.toString()); |
| } |
| } |
| |
| public static Map<String, String> parseQuery(final String uri) throws URISyntaxException { |
| try { |
| final Map<String, String> rc = new LinkedHashMap<String, String>(); |
| if (uri != null) { |
| final String[] parameters = uri.split("&"); |
| for (int i = 0; i < parameters.length; i++) { |
| final int p = parameters[i].indexOf("="); |
| if (p >= 0) { |
| final String name = URLDecoder.decode(parameters[i].substring(0, p), "UTF-8"); |
| final String value = URLDecoder.decode(parameters[i].substring(p + 1), "UTF-8"); |
| rc.put(name, value); |
| } else { |
| rc.put(parameters[i], null); |
| } |
| } |
| } |
| return rc; |
| } catch (final UnsupportedEncodingException e) { |
| throw (URISyntaxException) new URISyntaxException(e.toString(), "Invalid encoding").initCause(e); |
| } |
| } |
| |
| public static Map<String, String> parseParamters(final URI uri) throws URISyntaxException { |
| return uri.getQuery() == null ? Collections.EMPTY_MAP : parseQuery(stripPrefix(uri.getQuery(), "?")); |
| } |
| |
| /** |
| * Removes any URI query from the given uri |
| */ |
| public static URI removeQuery(final URI uri) throws URISyntaxException { |
| return createURIWithQuery(uri, null); |
| } |
| |
| /** |
| * Creates a URI with the given query |
| */ |
| public static URI createURIWithQuery(final URI uri, final String query) throws URISyntaxException { |
| return new URI(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), uri.getPath(), query, uri.getFragment()); |
| } |
| |
| public static CompositeData parseComposite(final URI uri) throws URISyntaxException { |
| |
| final CompositeData rc = new CompositeData(); |
| rc.scheme = uri.getScheme(); |
| final String ssp = stripPrefix(uri.getSchemeSpecificPart().trim(), "//").trim(); |
| |
| parseComposite(uri, rc, ssp); |
| |
| rc.fragment = uri.getFragment(); |
| return rc; |
| } |
| |
| private static void parseComposite(final URI uri, final CompositeData rc, final String ssp) throws URISyntaxException { |
| final String componentString; |
| final String params; |
| |
| if (!checkParenthesis(ssp)) { |
| throw new URISyntaxException(uri.toString(), "Not a matching number of '(' and ')' parenthesis"); |
| } |
| |
| int p; |
| final int intialParen = ssp.indexOf("("); |
| if (intialParen == 0) { |
| rc.host = ssp.substring(0, intialParen); |
| p = rc.host.indexOf("/"); |
| if (p >= 0) { |
| rc.path = rc.host.substring(p); |
| rc.host = rc.host.substring(0, p); |
| } |
| p = ssp.lastIndexOf(")"); |
| componentString = ssp.substring(intialParen + 1, p); |
| params = ssp.substring(p + 1).trim(); |
| |
| } else { |
| componentString = ssp; |
| params = ""; |
| } |
| |
| final String[] components = splitComponents(componentString); |
| rc.components = new URI[components.length]; |
| for (int i = 0; i < components.length; i++) { |
| rc.components[i] = new URI(components[i].trim()); |
| } |
| |
| p = params.indexOf("?"); |
| if (p >= 0) { |
| if (p > 0) { |
| rc.path = stripPrefix(params.substring(0, p), "/"); |
| } |
| rc.parameters = parseQuery(params.substring(p + 1)); |
| } else { |
| if (params.length() > 0) { |
| rc.path = stripPrefix(params, "/"); |
| } |
| rc.parameters = new LinkedHashMap(); |
| } |
| } |
| |
| private static String[] splitComponents(final String str) { |
| final ArrayList<String> l = new ArrayList<String>(); |
| |
| int last = 0; |
| int depth = 0; |
| final char[] chars = str.toCharArray(); |
| for (int i = 0; i < chars.length; i++) { |
| switch (chars[i]) { |
| case '(': |
| depth++; |
| break; |
| case ')': |
| depth--; |
| break; |
| case ',': |
| if (depth == 0) { |
| final String s = str.substring(last, i); |
| l.add(s); |
| last = i + 1; |
| } |
| } |
| } |
| |
| final String s = str.substring(last); |
| if (s.length() != 0) { |
| l.add(s); |
| } |
| |
| final String[] rc = new String[l.size()]; |
| l.toArray(rc); |
| return rc; |
| } |
| |
| public static String stripPrefix(final String value, final String prefix) { |
| if (value.startsWith(prefix)) { |
| return value.substring(prefix.length()); |
| } |
| return value; |
| } |
| |
| public static URI stripScheme(final URI uri) throws URISyntaxException { |
| return URLs.uri(stripPrefix(uri.getRawSchemeSpecificPart().trim(), "//")); |
| } |
| |
| public static String createQueryString(final Map options) throws URISyntaxException { |
| try { |
| if (options.size() > 0) { |
| final StringBuilder rc = new StringBuilder(); |
| boolean first = true; |
| for (final Iterator iter = options.keySet().iterator(); iter.hasNext(); ) { |
| if (first) { |
| first = false; |
| } else { |
| rc.append("&"); |
| } |
| |
| final String key = (String) iter.next(); |
| final String value = (String) options.get(key); |
| rc.append(URLEncoder.encode(key, "UTF-8")); |
| rc.append("="); |
| rc.append(URLEncoder.encode(value, "UTF-8")); |
| } |
| return rc.toString(); |
| } else { |
| return ""; |
| } |
| } catch (final UnsupportedEncodingException e) { |
| throw (URISyntaxException) new URISyntaxException(e.toString(), "Invalid encoding").initCause(e); |
| } |
| } |
| |
| /** |
| * Creates a URI from the original URI and the remaining paramaters |
| * |
| * @throws URISyntaxException |
| */ |
| public static URI createRemainingURI(final URI originalURI, final Map params) throws URISyntaxException { |
| String s = createQueryString(params); |
| if (s.length() == 0) { |
| s = null; |
| } |
| return createURIWithQuery(originalURI, s); |
| } |
| |
| public static URI changeScheme(final URI bindAddr, final String scheme) throws URISyntaxException { |
| return new URI(scheme, bindAddr.getUserInfo(), bindAddr.getHost(), bindAddr.getPort(), bindAddr.getPath(), bindAddr.getQuery(), bindAddr.getFragment()); |
| } |
| |
| public static boolean checkParenthesis(final String str) { |
| boolean result = true; |
| if (str != null) { |
| int open = 0; |
| int closed = 0; |
| |
| int i = 0; |
| while ((i = str.indexOf('(', i)) >= 0) { |
| i++; |
| open++; |
| } |
| i = 0; |
| while ((i = str.indexOf(')', i)) >= 0) { |
| i++; |
| closed++; |
| } |
| result = open == closed; |
| } |
| return result; |
| } |
| |
| public int indexOfParenthesisMatch(final String str) { |
| final int result = -1; |
| |
| return result; |
| } |
| |
| /** |
| * This method adds new parameters to a URI. Any parameters provided that already exist in the URI will *not* be replaced. |
| * @param uri The URI to add parameters to |
| * @param newParameters The parameters to add |
| * @return The URI with the new parameters added |
| * @throws URISyntaxException If there is a syntax error with the provided URI. |
| */ |
| public static URI addParameters(final URI uri, final Map<String, String> newParameters) throws URISyntaxException { |
| if (newParameters == null || newParameters.size() == 0) { |
| return uri; |
| } |
| |
| final Map<String, String> parameters = new HashMap<String, String>(parseParamters(uri)); |
| |
| final Set<String> keys = newParameters.keySet(); |
| for (final String key : keys) { |
| if (! parameters.containsKey(key)) { |
| parameters.put(key, newParameters.get(key)); |
| } |
| } |
| |
| return createRemainingURI(uri, parameters); |
| } |
| } |