Package org.hibernate.search.util.impl

Source Code of org.hibernate.search.util.impl.FileHelper

/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2010, Red Hat, Inc. and/or its affiliates or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors.  All third-party contributions are
* distributed under license by Red Hat, Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA  02110-1301  USA
*/
package org.hibernate.search.util.impl;

import java.io.BufferedReader;
import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;

import org.hibernate.search.util.logging.impl.Log;
import org.hibernate.search.util.logging.impl.LoggerFactory;

/**
* Utility class for file and directory operations, like synchronisation and reading from class path.
*
* @author Emmanuel Bernard
* @author Sanne Grinovero
* @author Hardy Ferentschik
*/
public abstract class FileHelper {

  private static final Log log = LoggerFactory.make();
  private static final int FAT_PRECISION = 2000;
  public static final long DEFAULT_COPY_BUFFER_SIZE = 16 * 1024 * 1024; // 16 MB


  public static boolean areInSync(File source, File destination) throws IOException {
    if ( source.isDirectory() ) {
      if ( !destination.exists() ) {
        return false;
      }
      else if ( !destination.isDirectory() ) {
        throw new IOException(
            "Source and Destination not of the same type:"
                + source.getCanonicalPath() + " , " + destination.getCanonicalPath()
        );
      }
      String[] sources = source.list();
      Set<String> srcNames = new HashSet<String>( Arrays.asList( sources ) );
      String[] dests = destination.list();

      // check for files in destination and not in source
      for ( String fileName : dests ) {
        if ( !srcNames.contains( fileName ) ) {
          return false;
        }
      }

      boolean inSync = true;
      for ( String fileName : sources ) {
        File srcFile = new File( source, fileName );
        File destFile = new File( destination, fileName );
        if ( !areInSync( srcFile, destFile ) ) {
          inSync = false;
          break;
        }
      }
      return inSync;
    }
    else {
      if ( destination.exists() && destination.isFile() ) {
        long sts = source.lastModified() / FAT_PRECISION;
        long dts = destination.lastModified() / FAT_PRECISION;
        return sts == dts;
      }
      else {
        return false;
      }
    }
  }

  public static void synchronize(File source, File destination, boolean smart) throws IOException {
    synchronize( source, destination, smart, DEFAULT_COPY_BUFFER_SIZE );
  }

  public static void synchronize(File source, File destination, boolean smart, long chunkSize) throws IOException {
    if ( chunkSize <= 0 ) {
      log.checkSizeMustBePositive();
      chunkSize = DEFAULT_COPY_BUFFER_SIZE;
    }
    if ( source.isDirectory() ) {
      if ( !destination.exists() ) {
        if ( !destination.mkdirs() ) {
          throw new IOException( "Could not create path " + destination );
        }
      }
      else if ( !destination.isDirectory() ) {
        throw new IOException(
            "Source and Destination not of the same type:"
                + source.getCanonicalPath() + " , " + destination.getCanonicalPath()
        );
      }
      String[] sources = source.list();
      Set<String> srcNames = new HashSet<String>( Arrays.asList( sources ) );
      String[] dests = destination.list();

      //delete files not present in source
      for ( String fileName : dests ) {
        if ( !srcNames.contains( fileName ) ) {
          delete( new File( destination, fileName ) );
        }
      }
      //copy each file from source
      for ( String fileName : sources ) {
        File srcFile = new File( source, fileName );
        File destFile = new File( destination, fileName );
        synchronize( srcFile, destFile, smart, chunkSize );
      }
    }
    else {
      if ( destination.exists() && destination.isDirectory() ) {
        delete( destination );
      }
      if ( destination.exists() ) {
        long sts = source.lastModified() / FAT_PRECISION;
        long dts = destination.lastModified() / FAT_PRECISION;
        //do not copy if smart and same timestamp and same length
        if ( !smart || sts == 0 || sts != dts || source.length() != destination.length() ) {
          copyFile( source, destination, chunkSize );
        }
      }
      else {
        copyFile( source, destination, chunkSize );
      }
    }
  }

  private static void copyFile(File srcFile, File destFile, long chunkSize) throws IOException {
    FileInputStream is = null;
    FileOutputStream os = null;
    try {
      is = new FileInputStream( srcFile );
      FileChannel iChannel = is.getChannel();
      os = new FileOutputStream( destFile, false );
      FileChannel oChannel = os.getChannel();
      long doneBytes = 0L;
      long todoBytes = srcFile.length();
      while ( todoBytes != 0L ) {
        long iterationBytes = Math.min( todoBytes, chunkSize );
        long transferredLength = oChannel.transferFrom( iChannel, doneBytes, iterationBytes );
        if ( iterationBytes != transferredLength ) {
          throw new IOException(
              "Error during file transfer: expected "
                  + iterationBytes + " bytes, only " + transferredLength + " bytes copied."
          );
        }
        doneBytes += transferredLength;
        todoBytes -= transferredLength;
      }
    }
    finally {
      if ( is != null ) {
        is.close();
      }
      if ( os != null ) {
        os.close();
      }
    }
    boolean successTimestampOp = destFile.setLastModified( srcFile.lastModified() );
    if ( !successTimestampOp ) {
      log.notChangeTimestamp( destFile );
    }
  }

  /**
   * Attempts to delete a file. If the file is a directory delete recursive all content.
   *
   * @param file the file or Directory to be deleted
   * @return false if it wasn't possible to delete it or all of the contents. A common problem on Windows systems.
   */
  public static boolean delete(File file) {
    boolean allok = true;
    if ( file.isDirectory() ) {
      for ( File subFile : file.listFiles() ) {
        boolean deleted = delete( subFile );
        allok = allok && deleted;
      }
    }
    if ( allok && file.exists() ) {
      if ( !file.delete() ) {
        log.notDeleted( file );
        return false;
      }
    }
    return allok;
  }

  /**
   * Reads the provided input stream into a string
   *
   * @param inputStream the input stream to read from
   * @return the content of the input stream as string
   * @throws java.io.IOException in case an error occurs reading from the input stream
   */
  public static String readInputStream(InputStream inputStream) throws IOException {
    Writer writer = new StringWriter();
    try {
      char[] buffer = new char[1000];
      Reader reader = new BufferedReader( new InputStreamReader( inputStream, "UTF-8" ) );
      int r = reader.read( buffer );
      while ( r != -1 ) {
        writer.write( buffer, 0, r );
        r = reader.read( buffer );
      }
      return writer.toString();
    }
    finally {
      closeResource( writer );
    }
  }

  /**
   * Load a resource from a specific classLoader
   *
   * @param resourceName the name of the resource
   * @param classLoader the classloader to use, or null to try the ContextClassloader first or the loading one second.
   * @return the resource contents as a String
   */
  public static String readResourceAsString(String resourceName, ClassLoader classLoader) {
    InputStream in;
    if ( classLoader != null ) {
      in = classLoader.getResourceAsStream( resourceName );
    }
    else {
      in = openResource( resourceName );
    }
    if ( in == null ) {
      throw log.unableToLoadResource( resourceName );
    }
    String s;
    try {
      s = FileHelper.readInputStream( in );
    }
    catch (IOException e) {
      throw log.unableToReadFile( resourceName, e );
    }
    finally {
      closeResource( in );
    }
    return s;
  }

  public static InputStream openResource(String resourceName) {
    //try loading from application context first:
    ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
    InputStream resource = classLoader.getResourceAsStream( resourceName );
    if ( resource != null ) {
      return resource;
    }
    else {
      classLoader = FileHelper.class.getClassLoader();
      return classLoader.getResourceAsStream( resourceName );
    }
  }

  /**
   * Closes a resource without throwing IOExceptions
   *
   * @param resource the resource to close
   */
  public static void closeResource(Closeable resource) {
    if ( resource != null ) {
      try {
        resource.close();
      }
      catch (IOException e) {
        //we don't really care if we can't close
        log.couldNotCloseResource( e );
      }
    }
  }
}
TOP

Related Classes of org.hibernate.search.util.impl.FileHelper

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.