/* * Copyright 2000-2014 JetBrains s.r.o. * * 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. */ package com.intellij.rt.coverage.util; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * @author anna * @since 02-Mar-2010 */ public class URLsUtil { public static final String FILE = "file"; public static final String PROTOCOL_DELIMITER = ":"; public static final String JAR_DELIMITER = "!"; public static boolean startsWithChar(CharSequence s, char prefix) { return s != null && s.length() != 0 && s.charAt(0) == prefix; } public static String extractRoot(URL resourceURL, String resourcePath) { if (!(startsWithChar(resourcePath, '/') || startsWithChar(resourcePath, '\\'))) { //noinspection HardCodedStringLiteral System.err.println("precondition failed: "+resourcePath); return null; } String protocol = resourceURL.getProtocol(); String resultPath = null; if (FILE.equals(protocol)) { String path = resourceURL.getFile(); final String testPath = path.replace('\\', '/'); final String testResourcePath = resourcePath.replace('\\', '/'); if (endsWithIgnoreCase(testPath, testResourcePath)) { resultPath = path.substring(0, path.length() - resourcePath.length()); } } else if ("jar".equals(protocol)) { String fullPath = resourceURL.getFile(); int delimiter = fullPath.indexOf(JAR_DELIMITER); if (delimiter >= 0) { String archivePath = fullPath.substring(0, delimiter); if (startsWithConcatenationOf(archivePath, FILE, PROTOCOL_DELIMITER)) { resultPath = archivePath.substring(FILE.length() + PROTOCOL_DELIMITER.length()); } } } if (resultPath == null) { //noinspection HardCodedStringLiteral System.err.println("cannot extract: "+resultPath + " from "+resourceURL); return null; } if (resourcePath.endsWith(File.separator)) { resultPath = resultPath.substring(0, resultPath.lastIndexOf(File.separator)); } resultPath = unescapePercentSequences(resultPath); return resultPath; } public static boolean startsWithConcatenationOf(String testee, String firstPrefix, String secondPrefix) { int l1 = firstPrefix.length(); int l2 = secondPrefix.length(); if (testee.length() < l1 + l2) return false; return testee.startsWith(firstPrefix) && testee.regionMatches(l1, secondPrefix, 0, l2); } public static boolean endsWithIgnoreCase(String str, String suffix) { final int stringLength = str.length(); final int suffixLength = suffix.length(); return stringLength >= suffixLength && str.regionMatches(true, stringLength - suffixLength, suffix, 0, suffixLength); } public static String unescapePercentSequences(String s) { if (s.indexOf('%') == -1) { return s; } StringBuilder decoded = new StringBuilder(); final int len = s.length(); int i = 0; while (i < len) { char c = s.charAt(i); if (c == '%') { List bytes = new ArrayList(); while (i + 2 < len && s.charAt(i) == '%') { final int d1 = decode(s.charAt(i + 1)); final int d2 = decode(s.charAt(i + 2)); if (d1 != -1 && d2 != -1) { bytes.add(new Integer(((d1 & 0xf) << 4 | d2 & 0xf))); i += 3; } else { break; } } if (!bytes.isEmpty()) { final byte[] bytesArray = new byte[bytes.size()]; for (int j = 0; j < bytes.size(); j++) { bytesArray[j] = (byte) ((Integer) bytes.get(j)).intValue(); } try { decoded.append(new String(bytesArray, "UTF-8")); continue; } catch (UnsupportedEncodingException ignored) { } } } decoded.append(c); i++; } return decoded.toString(); } private static int decode(char c) { if ((c >= '0') && (c <= '9')) return c - '0'; if ((c >= 'a') && (c <= 'f')) return c - 'a' + 10; if ((c >= 'A') && (c <= 'F')) return c - 'A' + 10; return -1; } }