001 /** 002 * Copyright 2010-2013 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 package org.kuali.common.util; 017 018 import java.io.BufferedReader; 019 import java.io.BufferedWriter; 020 import java.io.File; 021 import java.io.FileWriter; 022 import java.io.IOException; 023 import java.io.InputStream; 024 import java.io.InputStreamReader; 025 import java.io.OutputStream; 026 import java.io.OutputStreamWriter; 027 import java.io.PrintStream; 028 import java.io.Reader; 029 import java.io.StringReader; 030 import java.io.Writer; 031 import java.net.MalformedURLException; 032 import java.net.URI; 033 import java.net.URISyntaxException; 034 import java.net.URL; 035 import java.security.MessageDigest; 036 import java.security.NoSuchAlgorithmException; 037 import java.util.ArrayList; 038 import java.util.Arrays; 039 import java.util.Collections; 040 import java.util.List; 041 import java.util.Properties; 042 043 import org.apache.commons.io.FileUtils; 044 import org.apache.commons.io.IOUtils; 045 import org.apache.commons.lang3.StringUtils; 046 import org.slf4j.Logger; 047 import org.slf4j.LoggerFactory; 048 import org.springframework.core.io.DefaultResourceLoader; 049 import org.springframework.core.io.Resource; 050 import org.springframework.core.io.ResourceLoader; 051 import org.springframework.util.Assert; 052 053 public class LocationUtils { 054 055 private static final Logger logger = LoggerFactory.getLogger(LocationUtils.class); 056 057 private static final String FILE_PREFIX = "file:"; 058 private static final String BACK_SLASH = "\\"; 059 private static final String FORWARD_SLASH = "/"; 060 private static final String SLASH_DOT_SLASH = "/./"; 061 private static final String DOT_DOT_SLASH = "../"; 062 private static final String SLASH_DOT_DOT = "/.."; 063 private static final String CLASSPATH = "classpath:"; 064 private static final String MD5 = "MD5"; 065 066 /** 067 * Get the MD5 checksum of the location 068 */ 069 public static String getMD5Checksum(String location) { 070 return getChecksum(location, MD5); 071 } 072 073 /** 074 * Get the MD5 checksum of the file 075 */ 076 public static String getMD5Checksum(File file) { 077 return getChecksum(getCanonicalPath(file), MD5); 078 } 079 080 /** 081 * Open a <code>PrintStream</code> to the indicated file. Parent directories are created if necessary. 082 */ 083 public static final PrintStream openPrintStream(File file) throws IOException { 084 return new PrintStream(FileUtils.openOutputStream(file)); 085 } 086 087 /** 088 * Open a <code>Writer</code> to the indicated file. Parent directories are created if necessary. 089 */ 090 public static final Writer openWriter(File file) throws IOException { 091 touch(file); 092 return new FileWriter(file); 093 } 094 095 /** 096 * Open a <code>Writer</code> to the <code>location</code> (It must be a writable file on the local file system). Parent directories are created if necessary. 097 */ 098 public static final Writer openWriter(String location) throws IOException { 099 return openWriter(new File(location)); 100 } 101 102 public static Properties getLocationProperties(LocationPropertiesContext context) { 103 104 Assert.notNull(context, "context is null"); 105 106 Properties properties = context.getProperties(); 107 String keySuffix = context.getKeySuffix(); 108 String locationPropertiesSuffix = context.getLocationPropertiesSuffix(); 109 String encoding = context.getEncoding(); 110 111 Assert.notNull(properties, "properties is null"); 112 Assert.notNull(keySuffix, "keySuffix is null"); 113 Assert.notNull(locationPropertiesSuffix, "locationPropertiesSuffix is null"); 114 115 List<String> keys = PropertyUtils.getEndsWithKeys(properties, keySuffix); 116 117 Properties locationProperties = new Properties(); 118 for (String key : keys) { 119 String location = properties.getProperty(key); 120 if (!exists(location)) { 121 continue; 122 } 123 String propertiesLocation = location + locationPropertiesSuffix; 124 if (!exists(propertiesLocation)) { 125 continue; 126 } 127 Properties p = PropertyUtils.load(propertiesLocation, encoding); 128 locationProperties.putAll(p); 129 } 130 logger.info("Located {} properties for {} location listings", locationProperties.size(), keys.size()); 131 return locationProperties; 132 } 133 134 public static TextMetaData getTextMetaData(File file) { 135 return getTextMetaData(getCanonicalPath(file)); 136 } 137 138 public static TextMetaData getTextMetaData(String location) { 139 long lines = 0; 140 long size = 0; 141 BufferedReader in = null; 142 try { 143 in = getBufferedReader(location); 144 String s = in.readLine(); 145 while (s != null) { 146 lines++; 147 size += s.length(); 148 s = in.readLine(); 149 } 150 return new TextMetaData(lines, size); 151 } catch (IOException e) { 152 throw new IllegalStateException(e); 153 } finally { 154 IOUtils.closeQuietly(in); 155 } 156 } 157 158 /** 159 * Count the lines of text in the file. 160 * 161 * @param file 162 * The file to read lines of text from 163 * @return A count representing the number of lines of text 164 * @throws IllegalStateException 165 * If there is an i/o exception reading the file 166 * @see BufferedReader 167 */ 168 public static long getLineCount(File file) { 169 return getLineCount(file, null); 170 } 171 172 public static long getLineCount(File file, String encoding) { 173 return getLineCount(getCanonicalPath(file)); 174 } 175 176 /** 177 * Count the lines of text in the location. 178 * 179 * @param location 180 * The location to read lines of text from 181 * @return A count representing the number of lines of text 182 * @throws IllegalStateException 183 * If there is an i/o exception reading the file 184 * @see BufferedReader 185 * @deprecated Use getLineCount(location,encoding) instead 186 */ 187 @Deprecated 188 public static long getLineCount(String location) { 189 return getLineCount(location, null); 190 } 191 192 /** 193 * Count the lines of text in the location. 194 * 195 * @param location 196 * The location to read lines of text from 197 * @return A count representing the number of lines of text 198 * @throws IllegalStateException 199 * If there is an i/o exception reading the file 200 * @see BufferedReader 201 */ 202 public static long getLineCount(String location, String encoding) { 203 long count = 0; 204 BufferedReader in = null; 205 try { 206 in = getBufferedReader(location, encoding); 207 while (in.readLine() != null) { 208 count++; 209 } 210 return count; 211 } catch (IOException e) { 212 throw new IllegalStateException("Unexpected IO error", e); 213 } finally { 214 IOUtils.closeQuietly(in); 215 } 216 } 217 218 public static final void copyLocationsToFiles(List<String> locations, List<File> files) { 219 Assert.isTrue(locations.size() == files.size()); 220 for (int i = 0; i < locations.size(); i++) { 221 String location = locations.get(i); 222 File destination = files.get(i); 223 copyLocationToFile(location, destination); 224 } 225 } 226 227 /** 228 * Return the text that appears after <code>classpath:</code>. Throws <code>IllegalArgumentException</code> if location does not start with <code>classpath:</code> 229 */ 230 public static final String getClasspathFilename(String location) { 231 return getClasspathFilenames(Arrays.asList(location)).get(0); 232 } 233 234 /** 235 * Return the text that appears after <code>classpath:</code>. Throws <code>IllegalArgumentException</code> if any locations do not start with <code>classpath:</code> 236 */ 237 public static final List<String> getClasspathFilenames(List<String> locations) { 238 List<String> classpathFilenames = new ArrayList<String>(); 239 for (String location : locations) { 240 if (!isClasspathLocation(location)) { 241 throw new IllegalArgumentException(location + " must start with " + CLASSPATH); 242 } else { 243 classpathFilenames.add(StringUtils.substring(location, CLASSPATH.length())); 244 } 245 } 246 return classpathFilenames; 247 } 248 249 /** 250 * Return <code>true</code> if location starts with <code>classpath:</code> 251 */ 252 public static final boolean isClasspathLocation(String location) { 253 return StringUtils.startsWith(location, CLASSPATH); 254 } 255 256 public static final List<String> getNormalizedPathFragments(String absolutePath, boolean directory) { 257 String normalized = getNormalizedAbsolutePath(absolutePath); 258 String[] tokens = StringUtils.split(normalized, FORWARD_SLASH); 259 List<String> fragments = new ArrayList<String>(); 260 StringBuilder sb = new StringBuilder(); 261 sb.append(FORWARD_SLASH); 262 int length = directory ? tokens.length : tokens.length - 1; 263 for (int i = 0; i < length; i++) { 264 if (i != 0) { 265 sb.append(FORWARD_SLASH); 266 } 267 sb.append(tokens[i]); 268 fragments.add(sb.toString()); 269 } 270 return fragments; 271 } 272 273 public static final List<String> getCanonicalPaths(List<File> files) { 274 List<String> paths = new ArrayList<String>(); 275 for (File file : files) { 276 String path = getCanonicalPath(file); 277 paths.add(path); 278 } 279 return paths; 280 } 281 282 public static final List<String> getLocations(String location, LocationType type, String encoding) { 283 switch (type) { 284 case LOCATION: 285 return Collections.singletonList(location); 286 case LOCATIONLIST: 287 return getLocations(location, encoding); 288 default: 289 throw new IllegalArgumentException("Location type '" + type + "' is unknown"); 290 } 291 } 292 293 public static final List<String> getLocations(String location, LocationType type) { 294 return getLocations(location, type, null); 295 } 296 297 public static final List<String> getLocations(String locationListing) { 298 return getLocations(Collections.singletonList(locationListing), null); 299 } 300 301 public static final List<String> getLocations(String locationListing, String encoding) { 302 return getLocations(Collections.singletonList(locationListing), encoding); 303 } 304 305 public static final List<String> getLocations(List<String> locationListings) { 306 return getLocations(locationListings, null); 307 } 308 309 public static final void copyLocationToFile(String location, File destination) { 310 Assert.notNull(location); 311 Assert.notNull(destination); 312 logger.debug("Copying [{}]->[{}]", location, destination); 313 InputStream in = null; 314 try { 315 in = getInputStream(location); 316 FileUtils.copyInputStreamToFile(in, destination); 317 } catch (IOException e) { 318 throw new IllegalStateException(e); 319 } finally { 320 IOUtils.closeQuietly(in); 321 } 322 } 323 324 public static final List<File> getFiles(File dir, List<String> filenames) { 325 List<File> files = new ArrayList<File>(); 326 for (String filename : filenames) { 327 File file = new File(dir, filename); 328 files.add(file); 329 } 330 return files; 331 } 332 333 public static final List<String> getFilenames(List<String> locations) { 334 Assert.notNull(locations); 335 List<String> filenames = new ArrayList<String>(); 336 for (String location : locations) { 337 filenames.add(getFilename(location)); 338 } 339 return filenames; 340 } 341 342 /** 343 * Throw IllegalArgumentException if the locationListing does not exist, or if any of the locations inside the locationListing do not exist 344 */ 345 public static final void validateLocationListing(String locationListing) { 346 validateLocationListings(Collections.singletonList(locationListing)); 347 } 348 349 /** 350 * Throw IllegalArgumentException if any of the locationListings do not exist, or if any of the locations inside any of the locationListings do not exist 351 */ 352 public static final void validateLocationListings(List<String> locationListings) { 353 for (String locationListing : locationListings) { 354 validateLocation(locationListing); 355 List<String> locations = getLocations(locationListing); 356 validateLocations(locations); 357 } 358 } 359 360 public static final void validateLocations(List<String> locations) { 361 for (String location : locations) { 362 validateLocation(location); 363 } 364 } 365 366 /** 367 * Throw IllegalArgumentException if the location does not exist 368 */ 369 public static final void validateLocation(String location) { 370 validateLocation(location, "[" + location + "] does not exist"); 371 } 372 373 /** 374 * Throw IllegalArgumentException if the location does not exist 375 */ 376 public static final void validateLocation(String location, String message) { 377 Assert.isTrue(exists(location), message); 378 } 379 380 public static final List<String> getLocations(List<String> locationListings, String encoding) { 381 List<String> locations = new ArrayList<String>(); 382 for (String locationListing : locationListings) { 383 List<String> lines = readLines(locationListing, encoding); 384 locations.addAll(lines); 385 } 386 return locations; 387 } 388 389 public static final String getCanonicalURLString(File file) { 390 if (file == null) { 391 return null; 392 } 393 String path = getCanonicalPath(file); 394 File canonical = new File(path); 395 return getURLString(canonical); 396 } 397 398 public static final void validateNormalizedPath(String originalPath, String normalizedPath) { 399 if (CollectionUtils.containsAny(normalizedPath, Arrays.asList(SLASH_DOT_DOT, SLASH_DOT_SLASH, DOT_DOT_SLASH))) { 400 throw new IllegalArgumentException("[" + originalPath + "] could not be normalized. Normalized path [" + normalizedPath + "]"); 401 } 402 } 403 404 /** 405 * Resolve and remove <code>..</code> and <code>.</code> from <code>absolutePath</code> after converting any back slashes to forward slashes 406 */ 407 public static final String getNormalizedAbsolutePath(String absolutePath) { 408 if (absolutePath == null) { 409 return null; 410 } 411 String replaced = StringUtils.replace(absolutePath, BACK_SLASH, FORWARD_SLASH); 412 boolean absolute = StringUtils.startsWith(replaced, FORWARD_SLASH); 413 if (!absolute) { 414 throw new IllegalArgumentException("[" + absolutePath + "] is not an absolute path."); 415 } 416 String prefixed = FILE_PREFIX + replaced; 417 try { 418 URI rawURI = new URI(prefixed); 419 URI normalizedURI = rawURI.normalize(); 420 URL normalizedURL = normalizedURI.toURL(); 421 String externalForm = normalizedURL.toExternalForm(); 422 String trimmed = StringUtils.substring(externalForm, FILE_PREFIX.length()); 423 validateNormalizedPath(absolutePath, trimmed); 424 return trimmed; 425 } catch (MalformedURLException e) { 426 throw new IllegalArgumentException(e); 427 } catch (URISyntaxException e) { 428 throw new IllegalArgumentException(e); 429 } 430 } 431 432 public static final String getURLString(File file) { 433 if (file == null) { 434 return null; 435 } 436 try { 437 URI uri = file.toURI(); 438 URL url = uri.toURL(); 439 return url.toExternalForm(); 440 } catch (MalformedURLException e) { 441 throw new IllegalArgumentException(e); 442 } 443 } 444 445 public static final void forceMkdir(File file) { 446 try { 447 FileUtils.forceMkdir(file); 448 } catch (IOException e) { 449 throw new IllegalArgumentException("Unexpected IO error", e); 450 } 451 } 452 453 public static final void touch(File file) { 454 try { 455 FileUtils.touch(file); 456 } catch (IOException e) { 457 throw new IllegalArgumentException("Unexpected IO error", e); 458 } 459 } 460 461 public static final String getCanonicalPath(File file) { 462 try { 463 return file.getCanonicalPath(); 464 } catch (IOException e) { 465 throw new IllegalArgumentException("Unexpected IO error", e); 466 } 467 } 468 469 /** 470 * Null safe method to unconditionally attempt to delete <code>filename</code> without throwing an exception. If <code>filename</code> is a directory, delete it and all 471 * sub-directories. 472 */ 473 public static final boolean deleteFileQuietly(String filename) { 474 File file = getFileQuietly(filename); 475 return FileUtils.deleteQuietly(file); 476 } 477 478 /** 479 * Null safe method for getting a <code>File</code> handle from <code>filename</code>. If <code>filename</code> is null, null is returned. 480 */ 481 public static final File getFileQuietly(String filename) { 482 if (filename == null) { 483 return null; 484 } else { 485 return new File(filename); 486 } 487 } 488 489 /** 490 * Get the contents of <code>file</code> as a <code>String</code> using the platform's default character encoding. 491 */ 492 public static final String toString(File file) { 493 return toString(file, null); 494 } 495 496 /** 497 * Get the contents of <code>file</code> as a <code>String</code> using the specified character encoding. 498 */ 499 public static final String toString(File file, String encoding) { 500 return toString(getCanonicalPath(file), encoding); 501 } 502 503 /** 504 * Get the contents of <code>location</code> as a <code>String</code> using the platform's default character encoding. 505 */ 506 public static final String toString(String location) { 507 return toString(location, null); 508 } 509 510 /** 511 * Get the contents of <code>location</code> as a <code>String</code> using the specified character encoding. 512 */ 513 public static final String toString(String location, String encoding) { 514 InputStream in = null; 515 try { 516 in = getInputStream(location); 517 if (encoding == null) { 518 return IOUtils.toString(in); 519 } else { 520 return IOUtils.toString(in, encoding); 521 } 522 } catch (IOException e) { 523 throw new IllegalStateException("Unexpected IO error", e); 524 } finally { 525 IOUtils.closeQuietly(in); 526 } 527 } 528 529 /** 530 * Get the contents of <code>s</code> as a list of <code>String's</code> one entry per line 531 */ 532 public static final List<String> readLinesFromString(String s) { 533 Reader reader = getBufferedReaderFromString(s); 534 return readLinesAndClose(reader); 535 } 536 537 public static final List<String> readLinesAndClose(InputStream in) { 538 return readLinesAndClose(in, null); 539 } 540 541 public static final List<String> readLinesAndClose(InputStream in, String encoding) { 542 Reader reader = null; 543 try { 544 reader = getBufferedReader(in, encoding); 545 return readLinesAndClose(reader); 546 } catch (IOException e) { 547 throw new IllegalStateException("Unexpected IO error", e); 548 } finally { 549 IOUtils.closeQuietly(reader); 550 } 551 } 552 553 public static final List<String> readLinesAndClose(Reader reader) { 554 try { 555 return IOUtils.readLines(reader); 556 } catch (IOException e) { 557 throw new IllegalStateException("Unexpected IO error", e); 558 } finally { 559 IOUtils.closeQuietly(reader); 560 } 561 } 562 563 /** 564 * Get the contents of <code>file</code> as a list of <code>String's</code> one entry per line using the platform default encoding 565 */ 566 public static final List<String> readLines(File file) { 567 return readLines(getCanonicalPath(file)); 568 } 569 570 /** 571 * Get the contents of <code>location</code> as a list of <code>String's</code> one entry per line using the platform default encoding 572 */ 573 public static final List<String> readLines(String location) { 574 return readLines(location, null); 575 } 576 577 /** 578 * Get the contents of <code>location</code> as a list of <code>String's</code> one entry per line using the encoding indicated. 579 */ 580 public static final List<String> readLines(String location, String encoding) { 581 Reader reader = null; 582 try { 583 reader = getBufferedReader(location, encoding); 584 return readLinesAndClose(reader); 585 } catch (IOException e) { 586 throw new IllegalStateException("Unexpected IO error", e); 587 } finally { 588 IOUtils.closeQuietly(reader); 589 } 590 } 591 592 /** 593 * Return a <code>BufferedReader</code> for the location indicated using the platform default encoding. 594 */ 595 public static final BufferedReader getBufferedReader(String location) throws IOException { 596 return getBufferedReader(location, null); 597 } 598 599 /** 600 * Return a <code>BufferedReader</code> for the location indicated using the encoding indicated. 601 */ 602 public static final BufferedReader getBufferedReader(String location, String encoding) throws IOException { 603 try { 604 InputStream in = getInputStream(location); 605 return getBufferedReader(in, encoding); 606 } catch (IOException e) { 607 throw new IOException("Unexpected IO error", e); 608 } 609 } 610 611 /** 612 * Return a <code>BufferedReader</code> that reads from <code>s</code> 613 */ 614 public static final BufferedReader getBufferedReaderFromString(String s) { 615 return new BufferedReader(new StringReader(s)); 616 } 617 618 /** 619 * Return a <code>Writer</code> that writes to <code>out</code> using the indicated encoding. <code>null</code> means use the platform's default encoding. 620 */ 621 public static final Writer getWriter(OutputStream out, String encoding) throws IOException { 622 if (encoding == null) { 623 return new BufferedWriter(new OutputStreamWriter(out)); 624 } else { 625 return new BufferedWriter(new OutputStreamWriter(out, encoding)); 626 } 627 } 628 629 /** 630 * Return a <code>BufferedReader</code> that reads from <code>file</code> using the indicated encoding. <code>null</code> means use the platform's default encoding. 631 */ 632 public static final BufferedReader getBufferedReader(File file, String encoding) throws IOException { 633 return getBufferedReader(FileUtils.openInputStream(file), encoding); 634 } 635 636 /** 637 * Return a <code>BufferedReader</code> that reads from <code>in</code> using the indicated encoding. <code>null</code> means use the platform's default encoding. 638 */ 639 public static final BufferedReader getBufferedReader(InputStream in, String encoding) throws IOException { 640 if (encoding == null) { 641 return new BufferedReader(new InputStreamReader(in)); 642 } else { 643 return new BufferedReader(new InputStreamReader(in, encoding)); 644 } 645 } 646 647 /** 648 * Null safe method for determining if <code>location</code> is an existing file. 649 */ 650 public static final boolean isExistingFile(String location) { 651 if (location == null) { 652 return false; 653 } 654 File file = new File(location); 655 return file.exists(); 656 } 657 658 /** 659 * Null safe method for determining if <code>location</code> exists. 660 */ 661 public static final boolean exists(File file) { 662 if (file == null) { 663 return false; 664 } 665 String location = getCanonicalPath(file); 666 if (isExistingFile(location)) { 667 return true; 668 } else { 669 Resource resource = getResource(location); 670 return resource.exists(); 671 } 672 } 673 674 public static void validateExists(List<String> locations) { 675 StringBuilder sb = new StringBuilder(); 676 for (String location : locations) { 677 if (!LocationUtils.exists(location)) { 678 sb.append("Location [" + location + "] does not exist\n"); 679 } 680 } 681 if (sb.length() > 0) { 682 throw new IllegalArgumentException(sb.toString()); 683 } 684 } 685 686 /** 687 * Null safe method for determining if <code>location</code> exists. 688 */ 689 public static final boolean exists(String location) { 690 if (location == null) { 691 return false; 692 } 693 if (isExistingFile(location)) { 694 return true; 695 } else { 696 Resource resource = getResource(location); 697 return resource.exists(); 698 } 699 } 700 701 /** 702 * Open an <code>InputStream</code> to <code>location</code>. If <code>location</code> is the path to an existing <code>File</code> on the local file system, a 703 * <code>FileInputStream</code> is returned. Otherwise Spring's resource loading framework is used to open an <code>InputStream</code> to <code>location</code>. 704 */ 705 public static final InputStream getInputStream(String location) throws IOException { 706 if (isExistingFile(location)) { 707 return FileUtils.openInputStream(new File(location)); 708 } 709 Resource resource = getResource(location); 710 return resource.getInputStream(); 711 } 712 713 public static final Resource getResource(String location) { 714 if (location == null) { 715 return null; 716 } 717 ResourceLoader loader = new DefaultResourceLoader(); 718 return loader.getResource(location); 719 } 720 721 public static final String getFilename(String location) { 722 if (location == null) { 723 return null; 724 } 725 if (isExistingFile(location)) { 726 return getFileQuietly(location).getName(); 727 } else { 728 Resource resource = getResource(location); 729 return resource.getFilename(); 730 } 731 } 732 733 public static final List<String> getAbsolutePaths(List<File> files) { 734 List<String> results = new ArrayList<String>(files.size()); 735 736 for (File f : files) { 737 results.add(f.getAbsolutePath()); 738 } 739 740 return results; 741 } 742 743 public static final ComparisonResults getLocationListComparison(List<String> newLocations, List<String> originalLocations) { 744 ComparisonResults result = new ComparisonResults(); 745 746 result.setAdded(new ArrayList<String>()); 747 result.setSame(new ArrayList<String>()); 748 result.setDeleted(new ArrayList<String>()); 749 750 for (String newLocation : newLocations) { 751 if (originalLocations.contains(newLocation)) { 752 // if a location is in both lists, add it to the "same" list 753 result.getSame().add(newLocation); 754 } else { 755 // if a location is only in the new list, add it to the "added" list 756 result.getAdded().add(newLocation); 757 } 758 } 759 760 // the "deleted" list will contain all locations from the original list that are NOT in the new list 761 result.getDeleted().addAll(originalLocations); 762 result.getDeleted().removeAll(newLocations); 763 764 return result; 765 } 766 767 public static String getChecksum(String location, String algorithm) { 768 byte[] bytes = createChecksum(location, algorithm); 769 return getChecksum(bytes, algorithm); 770 } 771 772 public static String getChecksum(byte[] bytes, String algorithm) { 773 StringBuilder sb = new StringBuilder(); 774 for (int i = 0; i < bytes.length; i++) { 775 sb.append(Integer.toString((bytes[i] & 0xff) + 0x100, 16).substring(1)); 776 } 777 return sb.toString(); 778 } 779 780 public static byte[] createChecksum(String location, String algorithm) { 781 InputStream in = null; 782 try { 783 in = LocationUtils.getInputStream(location); 784 return createChecksum(in, algorithm); 785 } catch (IOException e) { 786 throw new IllegalStateException("Unexpected IO error", e); 787 } finally { 788 IOUtils.closeQuietly(in); 789 } 790 } 791 792 public static byte[] createChecksum(InputStream in, String algorithm) throws IOException { 793 try { 794 byte[] buffer = new byte[1024]; 795 MessageDigest complete = MessageDigest.getInstance(algorithm); 796 int numRead; 797 do { 798 numRead = in.read(buffer); 799 if (numRead > 0) { 800 complete.update(buffer, 0, numRead); 801 } 802 } while (numRead != -1); 803 IOUtils.closeQuietly(in); 804 return complete.digest(); 805 } catch (NoSuchAlgorithmException e) { 806 throw new IllegalStateException("Unexpected message digest error", e); 807 } catch (IOException e) { 808 throw e; 809 } 810 } 811 }