001/* 002 * $Id: Utilities.java 4847 2011-05-05 19:46:13Z redlab_b $ 003 * 004 * This file is part of the iText (R) project. 005 * Copyright (c) 1998-2011 1T3XT BVBA 006 * Authors: Bruno Lowagie, Paulo Soares, et al. 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU Affero General Public License version 3 010 * as published by the Free Software Foundation with the addition of the 011 * following permission added to Section 15 as permitted in Section 7(a): 012 * FOR ANY PART OF THE COVERED WORK IN WHICH THE COPYRIGHT IS OWNED BY 1T3XT, 013 * 1T3XT DISCLAIMS THE WARRANTY OF NON INFRINGEMENT OF THIRD PARTY RIGHTS. 014 * 015 * This program is distributed in the hope that it will be useful, but 016 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 017 * or FITNESS FOR A PARTICULAR PURPOSE. 018 * See the GNU Affero General Public License for more details. 019 * You should have received a copy of the GNU Affero General Public License 020 * along with this program; if not, see http://www.gnu.org/licenses or write to 021 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 022 * Boston, MA, 02110-1301 USA, or download the license from the following URL: 023 * http://itextpdf.com/terms-of-use/ 024 * 025 * The interactive user interfaces in modified source and object code versions 026 * of this program must display Appropriate Legal Notices, as required under 027 * Section 5 of the GNU Affero General Public License. 028 * 029 * In accordance with Section 7(b) of the GNU Affero General Public License, 030 * a covered work must retain the producer line in every PDF that is created 031 * or manipulated using iText. 032 * 033 * You can be released from the requirements of the license by purchasing 034 * a commercial license. Buying such a license is mandatory as soon as you 035 * develop commercial activities involving the iText software without 036 * disclosing the source code of your own applications. 037 * These activities include: offering paid services to customers as an ASP, 038 * serving PDFs on the fly in a web application, shipping iText with a closed 039 * source product. 040 * 041 * For more information, please contact iText Software Corp. at this 042 * address: sales@itextpdf.com 043 */ 044package com.itextpdf.text; 045 046import java.io.File; 047import java.io.FileInputStream; 048import java.io.IOException; 049import java.io.InputStream; 050import java.net.MalformedURLException; 051import java.net.URL; 052import java.util.Collections; 053import java.util.Hashtable; 054import java.util.Properties; 055import java.util.Set; 056 057import com.itextpdf.text.pdf.PRTokeniser; 058 059/** 060 * A collection of convenience methods that were present in many different iText 061 * classes. 062 */ 063 064public class Utilities { 065 066 /** 067 * Gets the keys of a Hashtable. 068 * Marked as deprecated, not used anywhere anymore. 069 * @param <K> type for the key 070 * @param <V> type for the value 071 * @param table 072 * a Hashtable 073 * @return the keyset of a Hashtable (or an empty set if table is null) 074 */ 075 @Deprecated 076 public static <K, V> Set<K> getKeySet(final Hashtable<K, V> table) { 077 return table == null ? Collections.<K>emptySet() : table.keySet(); 078 } 079 080 /** 081 * Utility method to extend an array. 082 * 083 * @param original 084 * the original array or <CODE>null</CODE> 085 * @param item 086 * the item to be added to the array 087 * @return a new array with the item appended 088 */ 089 public static Object[][] addToArray(Object original[][], final Object item[]) { 090 if (original == null) { 091 original = new Object[1][]; 092 original[0] = item; 093 return original; 094 } else { 095 Object original2[][] = new Object[original.length + 1][]; 096 System.arraycopy(original, 0, original2, 0, original.length); 097 original2[original.length] = item; 098 return original2; 099 } 100 } 101 102 /** 103 * Checks for a true/false value of a key in a Properties object. 104 * @param attributes 105 * @param key 106 * @return a true/false value of a key in a Properties object 107 */ 108 public static boolean checkTrueOrFalse(final Properties attributes, final String key) { 109 return "true".equalsIgnoreCase(attributes.getProperty(key)); 110 } 111 112 /** 113 * Unescapes an URL. All the "%xx" are replaced by the 'xx' hex char value. 114 * @param src the url to unescape 115 * @return the unescaped value 116 */ 117 public static String unEscapeURL(final String src) { 118 StringBuffer bf = new StringBuffer(); 119 char[] s = src.toCharArray(); 120 for (int k = 0; k < s.length; ++k) { 121 char c = s[k]; 122 if (c == '%') { 123 if (k + 2 >= s.length) { 124 bf.append(c); 125 continue; 126 } 127 int a0 = PRTokeniser.getHex(s[k + 1]); 128 int a1 = PRTokeniser.getHex(s[k + 2]); 129 if (a0 < 0 || a1 < 0) { 130 bf.append(c); 131 continue; 132 } 133 bf.append((char)(a0 * 16 + a1)); 134 k += 2; 135 } 136 else 137 bf.append(c); 138 } 139 return bf.toString(); 140 } 141 142 /** 143 * This method makes a valid URL from a given filename. 144 * <P> 145 * This method makes the conversion of this library from the JAVA 2 platform 146 * to a JDK1.1.x-version easier. 147 * 148 * @param filename 149 * a given filename 150 * @return a valid URL 151 * @throws MalformedURLException 152 */ 153 public static URL toURL(final String filename) throws MalformedURLException { 154 try { 155 return new URL(filename); 156 } 157 catch (Exception e) { 158 return new File(filename).toURI().toURL(); 159 } 160 } 161 162 /** 163 * This method is an alternative for the <CODE>InputStream.skip()</CODE> 164 * -method that doesn't seem to work properly for big values of <CODE>size 165 * </CODE>. 166 * 167 * @param is 168 * the <CODE>InputStream</CODE> 169 * @param size 170 * the number of bytes to skip 171 * @throws IOException 172 */ 173 static public void skip(final InputStream is, int size) throws IOException { 174 long n; 175 while (size > 0) { 176 n = is.skip(size); 177 if (n <= 0) 178 break; 179 size -= n; 180 } 181 } 182 183 /** 184 * Measurement conversion from millimeters to points. 185 * @param value a value in millimeters 186 * @return a value in points 187 * @since 2.1.2 188 */ 189 public static final float millimetersToPoints(final float value) { 190 return inchesToPoints(millimetersToInches(value)); 191 } 192 193 /** 194 * Measurement conversion from millimeters to inches. 195 * @param value a value in millimeters 196 * @return a value in inches 197 * @since 2.1.2 198 */ 199 public static final float millimetersToInches(final float value) { 200 return value / 25.4f; 201 } 202 203 /** 204 * Measurement conversion from points to millimeters. 205 * @param value a value in points 206 * @return a value in millimeters 207 * @since 2.1.2 208 */ 209 public static final float pointsToMillimeters(final float value) { 210 return inchesToMillimeters(pointsToInches(value)); 211 } 212 213 /** 214 * Measurement conversion from points to inches. 215 * @param value a value in points 216 * @return a value in inches 217 * @since 2.1.2 218 */ 219 public static final float pointsToInches(final float value) { 220 return value / 72f; 221 } 222 223 /** 224 * Measurement conversion from inches to millimeters. 225 * @param value a value in inches 226 * @return a value in millimeters 227 * @since 2.1.2 228 */ 229 public static final float inchesToMillimeters(final float value) { 230 return value * 25.4f; 231 } 232 233 /** 234 * Measurement conversion from inches to points. 235 * @param value a value in inches 236 * @return a value in points 237 * @since 2.1.2 238 */ 239 public static final float inchesToPoints(final float value) { 240 return value * 72f; 241 } 242 243 /** 244 * Check if the value of a character belongs to a certain interval 245 * that indicates it's the higher part of a surrogate pair. 246 * @param c the character 247 * @return true if the character belongs to the interval 248 * @since 2.1.2 249 */ 250 public static boolean isSurrogateHigh(final char c) { 251 return c >= '\ud800' && c <= '\udbff'; 252 } 253 254 /** 255 * Check if the value of a character belongs to a certain interval 256 * that indicates it's the lower part of a surrogate pair. 257 * @param c the character 258 * @return true if the character belongs to the interval 259 * @since 2.1.2 260 */ 261 public static boolean isSurrogateLow(final char c) { 262 return c >= '\udc00' && c <= '\udfff'; 263 } 264 265 /** 266 * Checks if two subsequent characters in a String are 267 * are the higher and the lower character in a surrogate 268 * pair (and therefore eligible for conversion to a UTF 32 character). 269 * @param text the String with the high and low surrogate characters 270 * @param idx the index of the 'high' character in the pair 271 * @return true if the characters are surrogate pairs 272 * @since 2.1.2 273 */ 274 public static boolean isSurrogatePair(final String text, final int idx) { 275 if (idx < 0 || idx > text.length() - 2) 276 return false; 277 return isSurrogateHigh(text.charAt(idx)) && isSurrogateLow(text.charAt(idx + 1)); 278 } 279 280 /** 281 * Checks if two subsequent characters in a character array are 282 * are the higher and the lower character in a surrogate 283 * pair (and therefore eligible for conversion to a UTF 32 character). 284 * @param text the character array with the high and low surrogate characters 285 * @param idx the index of the 'high' character in the pair 286 * @return true if the characters are surrogate pairs 287 * @since 2.1.2 288 */ 289 public static boolean isSurrogatePair(final char[] text, final int idx) { 290 if (idx < 0 || idx > text.length - 2) 291 return false; 292 return isSurrogateHigh(text[idx]) && isSurrogateLow(text[idx + 1]); 293 } 294 295 /** 296 * Returns the code point of a UTF32 character corresponding with 297 * a high and a low surrogate value. 298 * @param highSurrogate the high surrogate value 299 * @param lowSurrogate the low surrogate value 300 * @return a code point value 301 * @since 2.1.2 302 */ 303 public static int convertToUtf32(final char highSurrogate, final char lowSurrogate) { 304 return (highSurrogate - 0xd800) * 0x400 + lowSurrogate - 0xdc00 + 0x10000; 305 } 306 307 /** 308 * Converts a unicode character in a character array to a UTF 32 code point value. 309 * @param text a character array that has the unicode character(s) 310 * @param idx the index of the 'high' character 311 * @return the code point value 312 * @since 2.1.2 313 */ 314 public static int convertToUtf32(final char[] text, final int idx) { 315 return (text[idx] - 0xd800) * 0x400 + text[idx + 1] - 0xdc00 + 0x10000; 316 } 317 318 /** 319 * Converts a unicode character in a String to a UTF32 code point value 320 * @param text a String that has the unicode character(s) 321 * @param idx the index of the 'high' character 322 * @return the codepoint value 323 * @since 2.1.2 324 */ 325 public static int convertToUtf32(final String text, final int idx) { 326 return (text.charAt(idx) - 0xd800) * 0x400 + text.charAt(idx + 1) - 0xdc00 + 0x10000; 327 } 328 329 /** 330 * Converts a UTF32 code point value to a String with the corresponding character(s). 331 * @param codePoint a Unicode value 332 * @return the corresponding characters in a String 333 * @since 2.1.2 334 */ 335 public static String convertFromUtf32(int codePoint) { 336 if (codePoint < 0x10000) 337 return Character.toString((char)codePoint); 338 codePoint -= 0x10000; 339 return new String(new char[]{(char)(codePoint / 0x400 + 0xd800), (char)(codePoint % 0x400 + 0xdc00)}); 340 } 341 342 /** 343 * Reads the contents of a file to a String. 344 * @param path the path to the file 345 * @return a String with the contents of the file 346 * @throws IOException 347 * @since iText 5.0.0 348 */ 349 public static String readFileToString(final String path) throws IOException { 350 return readFileToString(new File(path)); 351 } 352 353 /** 354 * Reads the contents of a file to a String. 355 * @param file a file 356 * @return a String with the contents of the file 357 * @throws IOException if file was not found or could not be read. 358 * @since iText 5.0.0 359 */ 360 public static String readFileToString(final File file) throws IOException { 361 byte[] jsBytes = new byte[(int) file.length()]; 362 FileInputStream f = new FileInputStream(file); 363 f.read(jsBytes); 364 return new String(jsBytes); 365 } 366}