Java tutorial
package com.meterware.httpunit; /******************************************************************************************************************** * $Id: HttpUnitUtils.java 951 2008-05-02 10:11:40Z wolfgang_fahl $ * * Copyright (c) 2000-2008, Russell Gold * * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated * documentation files (the "Software"), to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and * to permit persons to whom the Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all copies or substantial portions * of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO * THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER * DEALINGS IN THE SOFTWARE. * *******************************************************************************************************************/ import java.util.StringTokenizer; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import org.w3c.dom.Document; import org.xml.sax.SAXException; import org.xml.sax.InputSource; import org.xml.sax.EntityResolver; /** * Utility code shared by httpunit and servletunit. **/ public class HttpUnitUtils { public static final int DEFAULT_TEXT_BUFFER_SIZE = 2048; public static final String DEFAULT_CHARACTER_SET = "iso-8859-1"; /** * set to true to debug Exception handling */ private static boolean EXCEPTION_DEBUG = true; /** * handle Exceptions and thowables * @param th */ public static void handleException(Throwable th) { if (EXCEPTION_DEBUG) { th.printStackTrace(); } } /** * are we running in the Eclipse IDE? * @return whether we are running in the Eclipse environment */ public static boolean isEclipse() { StackTraceElement[] ste = new Throwable().getStackTrace(); return (ste[ste.length - 1].getClassName().startsWith("org.eclipse.jdt")); } /** * Returns the content type and encoding as a pair of strings. * If no character set is specified, the second entry will be null. * @param header the header to parse * @return a string array with the content type and the content charset **/ public static String[] parseContentTypeHeader(String header) { String[] result = new String[] { "text/plain", null }; StringTokenizer st = new StringTokenizer(header, ";="); result[0] = st.nextToken(); while (st.hasMoreTokens()) { String parameter = st.nextToken(); if (st.hasMoreTokens()) { String value = stripQuotes(st.nextToken()); if (parameter.trim().equalsIgnoreCase("charset")) { result[1] = value; } } } return result; } /** * strip the quotes from a value * @param value * @return the stripped value */ public static String stripQuotes(String value) { if (value.startsWith("'") || value.startsWith("\"")) value = value.substring(1); if (value.endsWith("'") || value.endsWith("\"")) value = value.substring(0, value.length() - 1); return value; } /** * Returns an interpretation of the specified URL-encoded string, using the iso-8859-1 character set. * * @since 1.6 **/ public static String decode(String byteString) { return decode(byteString, "iso-8859-1"); } /** * Returns a string representation of a number, trimming off any trailing decimal zeros. */ static String trimmedValue(Number number) { String rawNumber = number.toString(); if (rawNumber.indexOf('.') == -1) return rawNumber; int index = rawNumber.length(); while (rawNumber.charAt(index - 1) == '0') index--; if (rawNumber.charAt(index - 1) == '.') index--; return rawNumber.substring(0, index); } /** * Decodes a URL safe string into its original form using the * specified character set. Escaped characters are converted back * to their original representation. * * This method is copied from the <b>Jakarta Commons Codec</b>; * <code>org.apache.commons.codec.net.URLCodec</code> class. * * @param string URL safe string to convert into its original form * @return original string * @throws IllegalArgumentException thrown if URL decoding is unsuccessful, */ public static String decode(String string, String charset) { try { if (string == null) return null; return new String(decodeUrl(string.getBytes("US-ASCII")), charset); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e.toString()); } } /** * Decodes an array of URL safe 7-bit characters into an array of * original bytes. Escaped characters are converted back to their * original representation. * * This method is copied from the <b>Jakarta Commons Codec</b>; * <code>org.apache.commons.codec.net.URLCodec</code> class. * * @param pArray array of URL safe characters * @return array of original bytes */ private static final byte[] decodeUrl(byte[] pArray) throws IllegalArgumentException { ByteArrayOutputStream buffer = new ByteArrayOutputStream(); for (int i = 0; i < pArray.length; i++) { int b = pArray[i]; if (b == '+') { buffer.write(' '); } else if (b != '%') { buffer.write(b); } else { try { int u = Character.digit((char) pArray[++i], 16); int l = Character.digit((char) pArray[++i], 16); if (u == -1 || l == -1) throw new IllegalArgumentException("Invalid URL encoding"); buffer.write((char) ((u << 4) + l)); } catch (ArrayIndexOutOfBoundsException e) { throw new IllegalArgumentException("Invalid URL encoding"); } } } return buffer.toByteArray(); } /** * parse an InputStream to a string (for debugging) * @param is * @return the string gotten from the inputString */ public static String parseISToString(java.io.InputStream is) { java.io.DataInputStream din = new java.io.DataInputStream(is); StringBuffer sb = new StringBuffer(); try { String line = null; while ((line = din.readLine()) != null) { sb.append(line + "\n"); } } catch (Exception ex) { // TODO handle exception properly here ex.getMessage(); } finally { try { is.close(); } catch (Exception ex) { } } return sb.toString(); } /** * parse the given inputSource with a new Parser * @param inputSource * @return the document parsed from the input Source */ public static Document parse(InputSource inputSource) throws SAXException, IOException { DocumentBuilder db = newParser(); try { Document doc = db.parse(inputSource); return doc; } catch (java.net.MalformedURLException mue) { if (EXCEPTION_DEBUG) { String msg = mue.getMessage(); if (msg != null) { System.err.println(msg); } InputStream is = inputSource.getByteStream(); is.reset(); String content = parseISToString(is); System.err.println(content); } throw mue; } } /** * parse the given inputStream with a new Parser * @param inputStream * @return the document parsed from the input Stream */ public static Document parse(InputStream inputStream) throws SAXException, IOException { DocumentBuilder db = newParser(); try { Document doc = db.parse(inputStream); return doc; } catch (java.net.MalformedURLException mue) { if (EXCEPTION_DEBUG) { String msg = mue.getMessage(); if (msg != null) { System.err.println(msg); } InputStream is = inputStream; is.reset(); String content = parseISToString(is); System.err.println(content); } throw mue; } } /** * creates a parser using JAXP API. */ public static DocumentBuilder newParser() throws SAXException { try { DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(new HttpUnitUtils.ClasspathEntityResolver()); return builder; } catch (ParserConfigurationException ex) { // redirect the new exception for code compatibility throw new SAXException(ex); } } /** * Returns a string array created by appending a string to an existing array. The existing array may be null. **/ static String[] withNewValue(String[] oldValue, String newValue) { String[] result; if (oldValue == null) { result = new String[] { newValue }; } else { result = new String[oldValue.length + 1]; System.arraycopy(oldValue, 0, result, 0, oldValue.length); result[oldValue.length] = newValue; } return result; } /** * Returns a string array created by appending an object to an existing array. The existing array may be null. **/ static Object[] withNewValue(Object[] oldValue, Object newValue) { Object[] result; if (oldValue == null) { result = new Object[] { newValue }; } else { result = new Object[oldValue.length + 1]; System.arraycopy(oldValue, 0, result, 0, oldValue.length); result[oldValue.length] = newValue; } return result; } /** * Return true if the first string contains the second. * Case sensitivity is according to the setting of HttpUnitOptions.matchesIgnoreCase */ static boolean contains(String string, String substring) { if (HttpUnitOptions.getMatchesIgnoreCase()) { return string.toUpperCase().indexOf(substring.toUpperCase()) >= 0; } else { return string.indexOf(substring) >= 0; } } /** * Return true if the first string starts with the second. * Case sensitivity is according to the setting of HttpUnitOptions.matchesIgnoreCase */ static boolean hasPrefix(String string, String prefix) { if (HttpUnitOptions.getMatchesIgnoreCase()) { return string.toUpperCase().startsWith(prefix.toUpperCase()); } else { return string.startsWith(prefix); } } /** * Return true if the first string equals the second. * Case sensitivity is according to the setting of HttpUnitOptions.matchesIgnoreCase */ static boolean matches(String string1, String string2) { if (HttpUnitOptions.getMatchesIgnoreCase()) { return string1.equalsIgnoreCase(string2); } else { return string1.equals(string2); } } /** * check whether the URL is a java script url * @param urlString - the string to analyze * @return - true if this is a javascript url */ static boolean isJavaScriptURL(String urlString) { boolean result = urlString.toLowerCase().startsWith("javascript:"); return result; } /** * Trims whitespace from the ends, and encodes from the middle. * Spaces within quotes are respected. */ static String encodeSpaces(String s) { s = s.trim(); // if no spaces we are fine if (s.indexOf(' ') < 0) return s; boolean inQuotes = false; StringBuffer sb = new StringBuffer(); char[] chars = s.toCharArray(); // loop over oper the chars of the URL for (int i = 0; i < chars.length; i++) { // get the current character char aChar = chars[i]; // toggle quotation and add quote if (aChar == '"' || aChar == '\'') { inQuotes = !inQuotes; sb.append(aChar); // append everything in quotes and printable chars above space } else if (inQuotes) { sb.append(aChar); } else if (aChar > ' ') { sb.append(aChar); } else if (aChar == ' ') { // encode spaces // TODO check what to do about breaking testLinkUrlAcrossLineBreaks then ... // sb.append("%20"); } } return sb.toString(); } static String replaceEntities(String string) { int i = 0; int ampIndex; while ((ampIndex = string.indexOf('&', i)) >= 0) { int semiColonIndex = string.indexOf(';', ampIndex + 1); if (semiColonIndex < 0) break; i = ampIndex + 1; String entityName = string.substring(ampIndex + 1, semiColonIndex); if (entityName.equalsIgnoreCase("amp")) { string = string.substring(0, ampIndex) + '&' + string.substring(semiColonIndex + 1); } } return string; } /** * Strips the fragment identifier (if any) from the Url. */ static String trimFragment(String rawUrl) { if (isJavaScriptURL(rawUrl)) return rawUrl; final int hashIndex = rawUrl.indexOf('#'); return hashIndex < 0 ? rawUrl : rawUrl.substring(0, hashIndex); } static class ClasspathEntityResolver implements EntityResolver { public InputSource resolveEntity(String publicID, String systemID) { if (systemID == null) return null; String localName = systemID; if (localName.indexOf("/") > 0) { localName = localName.substring(localName.lastIndexOf("/") + 1, localName.length()); } try { return new InputSource(getClass().getClassLoader().getResourceAsStream(localName)); } catch (Exception e) { // proposed patch for bug report // [ 1264706 ] [patch] replace ClasspathEntityResolver // by fabrizio giustina // even to return this in all cases! // return new InputSource( new ByteArrayInputStream( new byte[0] ) ); return null; } } } /** * @return the eXCEPTION_DEBUG */ protected static boolean isEXCEPTION_DEBUG() { return EXCEPTION_DEBUG; } /** * @param exception_debug the eXCEPTION_DEBUG to set */ public static boolean setEXCEPTION_DEBUG(boolean exception_debug) { boolean oldExceptionDebug = exception_debug; EXCEPTION_DEBUG = exception_debug; return oldExceptionDebug; } }