001: /**
002: *
003: * Licensed to the Apache Software Foundation (ASF) under one or more
004: * contributor license agreements. See the NOTICE file distributed with
005: * this work for additional information regarding copyright ownership.
006: * The ASF licenses this file to You under the Apache License, Version 2.0
007: * (the "License"); you may not use this file except in compliance with
008: * the License. You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */package org.apache.openejb.util;
018:
019: import java.io.UnsupportedEncodingException;
020: import java.net.URI;
021: import java.net.URISyntaxException;
022: import java.net.URLDecoder;
023: import java.net.URLEncoder;
024: import java.util.ArrayList;
025: import java.util.Arrays;
026: import java.util.Collections;
027: import java.util.HashMap;
028: import java.util.Iterator;
029: import java.util.LinkedHashMap;
030: import java.util.List;
031: import java.util.Map;
032:
033: /**
034: * Swiped verbatim from ActiveMQ... the URI kings.
035: *
036: * URI relativize(URI, URI) added afterwards to deal with the
037: * non-functional URI.relativize(URI) method
038: */
039: public class URISupport {
040:
041: /**
042: * URI absoluteA = new URI("/Users/dblevins/work/openejb3/container/openejb-jee/apple/");
043: * URI absoluteB = new URI("/Users/dblevins/work/openejb3/container/openejb-core/foo.jar");
044: *
045: * URI relativeB = URISupport.relativize(absoluteA, absoluteB);
046: *
047: * assertEquals("../../openejb-core/foo.jar", relativeB.toString());
048: *
049: * URI resolvedB = absoluteA.resolve(relativeB);
050: * assertTrue(resolvedB.equals(absoluteB));
051: *
052: * @param a
053: * @param b
054: * @return relative b
055: */
056: public static URI relativize(URI a, URI b) {
057: if (a == null || b == null)
058: return b;
059:
060: if (!a.isAbsolute() && b.isAbsolute())
061: return b;
062:
063: if (!b.isAbsolute())
064: b = a.resolve(b);
065:
066: List<String> pathA = Arrays.asList(a.getPath().split("/"));
067: List<String> pathB = Arrays.asList(b.getPath().split("/"));
068:
069: int limit = Math.min(pathA.size(), pathB.size());
070:
071: int lastMatch = 0;
072: while (lastMatch < limit) {
073: String aa = pathA.get(lastMatch);
074: String bb = pathB.get(lastMatch);
075: if (aa.equals(bb))
076: lastMatch++;
077: else
078: break;
079: }
080:
081: List<String> path = new ArrayList<String>();
082: for (int x = pathA.size() - lastMatch; x > 0; x--) {
083: path.add("..");
084: }
085:
086: List<String> remaining = pathB.subList(lastMatch, pathB.size());
087: path.addAll(remaining);
088:
089: try {
090: return new URI(null, null, Join.join("/", path), b
091: .getQuery(), b.getFragment());
092: } catch (URISyntaxException e) {
093: throw new IllegalArgumentException(e);
094: }
095: }
096:
097: public static class CompositeData {
098: String scheme;
099: String path;
100: URI components[];
101: Map parameters;
102: String fragment;
103: public String host;
104:
105: public URI[] getComponents() {
106: return components;
107: }
108:
109: public String getFragment() {
110: return fragment;
111: }
112:
113: public Map getParameters() {
114: return parameters;
115: }
116:
117: public String getScheme() {
118: return scheme;
119: }
120:
121: public String getPath() {
122: return path;
123: }
124:
125: public String getHost() {
126: return host;
127: }
128:
129: public URI toURI() throws URISyntaxException {
130: StringBuffer sb = new StringBuffer();
131: if (scheme != null) {
132: sb.append(scheme);
133: sb.append(':');
134: }
135:
136: if (host != null && host.length() != 0) {
137: sb.append(host);
138: } else {
139: sb.append('(');
140: for (int i = 0; i < components.length; i++) {
141: if (i != 0)
142: sb.append(',');
143: sb.append(components[i].toString());
144: }
145: sb.append(')');
146: }
147:
148: if (path != null) {
149: sb.append('/');
150: sb.append(path);
151: }
152: if (!parameters.isEmpty()) {
153: sb.append("?");
154: sb.append(createQueryString(parameters));
155: }
156: if (fragment != null) {
157: sb.append("#");
158: sb.append(fragment);
159: }
160: return new URI(sb.toString());
161: }
162: }
163:
164: public static Map<String, String> parseQuery(String uri)
165: throws URISyntaxException {
166: try {
167: Map<String, String> rc = new LinkedHashMap<String, String>();
168: if (uri != null) {
169: String[] parameters = uri.split("&");
170: for (int i = 0; i < parameters.length; i++) {
171: int p = parameters[i].indexOf("=");
172: if (p >= 0) {
173: String name = URLDecoder.decode(parameters[i]
174: .substring(0, p), "UTF-8");
175: String value = URLDecoder.decode(parameters[i]
176: .substring(p + 1), "UTF-8");
177: rc.put(name, value);
178: } else {
179: rc.put(parameters[i], null);
180: }
181: }
182: }
183: return rc;
184: } catch (UnsupportedEncodingException e) {
185: throw (URISyntaxException) new URISyntaxException(e
186: .toString(), "Invalid encoding").initCause(e);
187: }
188: }
189:
190: public static Map<String, String> parseParamters(URI uri)
191: throws URISyntaxException {
192: return uri.getQuery() == null ? Collections.EMPTY_MAP
193: : parseQuery(stripPrefix(uri.getQuery(), "?"));
194: }
195:
196: /**
197: * Removes any URI query from the given uri
198: */
199: public static URI removeQuery(URI uri) throws URISyntaxException {
200: return createURIWithQuery(uri, null);
201: }
202:
203: /**
204: * Creates a URI with the given query
205: */
206: public static URI createURIWithQuery(URI uri, String query)
207: throws URISyntaxException {
208: return new URI(uri.getScheme(), uri.getUserInfo(), uri
209: .getHost(), uri.getPort(), uri.getPath(), query, uri
210: .getFragment());
211: }
212:
213: public static CompositeData parseComposite(URI uri)
214: throws URISyntaxException {
215:
216: CompositeData rc = new CompositeData();
217: rc.scheme = uri.getScheme();
218: String ssp = stripPrefix(uri.getSchemeSpecificPart().trim(),
219: "//").trim();
220:
221: parseComposite(uri, rc, ssp);
222:
223: rc.fragment = uri.getFragment();
224: return rc;
225: }
226:
227: private static void parseComposite(URI uri, CompositeData rc,
228: String ssp) throws URISyntaxException {
229: String componentString;
230: String params;
231:
232: if (!checkParenthesis(ssp)) {
233: throw new URISyntaxException(uri.toString(),
234: "Not a matching number of '(' and ')' parenthesis");
235: }
236:
237: int p;
238: int intialParen = ssp.indexOf("(");
239: if (intialParen == 0) {
240: rc.host = ssp.substring(0, intialParen);
241: p = rc.host.indexOf("/");
242: if (p >= 0) {
243: rc.path = rc.host.substring(p);
244: rc.host = rc.host.substring(0, p);
245: }
246: p = ssp.lastIndexOf(")");
247: componentString = ssp.substring(intialParen + 1, p);
248: params = ssp.substring(p + 1).trim();
249:
250: } else {
251: componentString = ssp;
252: params = "";
253: }
254:
255: String components[] = splitComponents(componentString);
256: rc.components = new URI[components.length];
257: for (int i = 0; i < components.length; i++) {
258: rc.components[i] = new URI(components[i].trim());
259: }
260:
261: p = params.indexOf("?");
262: if (p >= 0) {
263: if (p > 0) {
264: rc.path = stripPrefix(params.substring(0, p), "/");
265: }
266: rc.parameters = parseQuery(params.substring(p + 1));
267: } else {
268: if (params.length() > 0)
269: rc.path = stripPrefix(params, "/");
270: rc.parameters = new LinkedHashMap();
271: }
272: }
273:
274: private static String[] splitComponents(String str) {
275: ArrayList<String> l = new ArrayList<String>();
276:
277: int last = 0;
278: int depth = 0;
279: char chars[] = str.toCharArray();
280: for (int i = 0; i < chars.length; i++) {
281: switch (chars[i]) {
282: case '(':
283: depth++;
284: break;
285: case ')':
286: depth--;
287: break;
288: case ',':
289: if (depth == 0) {
290: String s = str.substring(last, i);
291: l.add(s);
292: last = i + 1;
293: }
294: }
295: }
296:
297: String s = str.substring(last);
298: if (s.length() != 0)
299: l.add(s);
300:
301: String rc[] = new String[l.size()];
302: l.toArray(rc);
303: return rc;
304: }
305:
306: public static String stripPrefix(String value, String prefix) {
307: if (value.startsWith(prefix))
308: return value.substring(prefix.length());
309: return value;
310: }
311:
312: public static URI stripScheme(URI uri) throws URISyntaxException {
313: return new URI(stripPrefix(uri.getRawSchemeSpecificPart()
314: .trim(), "//"));
315: }
316:
317: public static String createQueryString(Map options)
318: throws URISyntaxException {
319: try {
320: if (options.size() > 0) {
321: StringBuffer rc = new StringBuffer();
322: boolean first = true;
323: for (Iterator iter = options.keySet().iterator(); iter
324: .hasNext();) {
325: if (first)
326: first = false;
327: else
328: rc.append("&");
329:
330: String key = (String) iter.next();
331: String value = (String) options.get(key);
332: rc.append(URLEncoder.encode(key, "UTF-8"));
333: rc.append("=");
334: rc.append(URLEncoder.encode(value, "UTF-8"));
335: }
336: return rc.toString();
337: } else {
338: return "";
339: }
340: } catch (UnsupportedEncodingException e) {
341: throw (URISyntaxException) new URISyntaxException(e
342: .toString(), "Invalid encoding").initCause(e);
343: }
344: }
345:
346: /**
347: * Creates a URI from the original URI and the remaining paramaters
348: * @throws URISyntaxException
349: */
350: public static URI createRemainingURI(URI originalURI, Map params)
351: throws URISyntaxException {
352: String s = createQueryString(params);
353: if (s.length() == 0)
354: s = null;
355: return createURIWithQuery(originalURI, s);
356: }
357:
358: static public URI changeScheme(URI bindAddr, String scheme)
359: throws URISyntaxException {
360: return new URI(scheme, bindAddr.getUserInfo(), bindAddr
361: .getHost(), bindAddr.getPort(), bindAddr.getPath(),
362: bindAddr.getQuery(), bindAddr.getFragment());
363: }
364:
365: public static boolean checkParenthesis(String str) {
366: boolean result = true;
367: if (str != null) {
368: int open = 0;
369: int closed = 0;
370:
371: int i = 0;
372: while ((i = str.indexOf('(', i)) >= 0) {
373: i++;
374: open++;
375: }
376: i = 0;
377: while ((i = str.indexOf(')', i)) >= 0) {
378: i++;
379: closed++;
380: }
381: result = open == closed;
382: }
383: return result;
384: }
385:
386: public int indexOfParenthesisMatch(String str) {
387: int result = -1;
388:
389: return result;
390: }
391: }
|