/* * Copyright 2015 Red Hat, Inc. and/or its affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * * 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 org.drools.core.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; 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.OutputStream; import java.net.DatagramSocket; import java.net.ServerSocket; import java.nio.channels.FileChannel; import java.nio.charset.Charset; import java.util.ArrayList; import java.util.List; import java.util.UUID; import java.util.function.Predicate; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; public class IoUtils { public static final Charset UTF8_CHARSET = Charset.forName("UTF-8"); public static int findPort() { for( int i = 1024; i < 65535; i++) { if ( validPort( i ) ) { return i; } } throw new RuntimeException( "No valid port could be found" ); } public static boolean validPort(int port) { ServerSocket ss = null; DatagramSocket ds = null; try { ss = new ServerSocket(port); ss.setReuseAddress(true); ds = new DatagramSocket(port); ds.setReuseAddress(true); return true; } catch (IOException e) { } finally { if (ds != null) { ds.close(); } if (ss != null) { try { ss.close(); } catch (IOException e) { /* should not be thrown */ } } } return false; } public static String readFileAsString(File file) { StringBuffer sb = new StringBuffer(); BufferedReader reader = null; try { reader = new BufferedReader(new InputStreamReader(new FileInputStream(file), UTF8_CHARSET)); for (String line = reader.readLine(); line != null; line = reader.readLine()) { sb.append(line).append("\n"); } } catch (IOException e) { throw new RuntimeException(e); } finally { if (reader != null) { try { reader.close(); } catch (IOException e) { } } } return sb.toString(); } public static void copyFile(File sourceFile, File destFile) { destFile.getParentFile().mkdirs(); if(!destFile.exists()) { try { destFile.createNewFile(); } catch (IOException ioe) { throw new RuntimeException("Unable to create file " + destFile.getAbsolutePath(), ioe); } } FileChannel source = null; FileChannel destination = null; try { source = new FileInputStream(sourceFile).getChannel(); destination = new FileOutputStream(destFile).getChannel(); destination.transferFrom(source, 0, source.size()); } catch (IOException ioe) { throw new RuntimeException("Unable to copy " + sourceFile.getAbsolutePath() + " to " + destFile.getAbsolutePath(), ioe); } finally { if(source != null) { try { source.close(); } catch (IOException e) { } } if(destination != null) { try { destination.close(); } catch (IOException e) { } } } } public static long copy( InputStream input, OutputStream output ) throws IOException { byte[] buffer = createBytesBuffer( input ); long count = 0; int n = 0; while ((n = input.read(buffer)) != -1) { output.write(buffer, 0, n); count += n; } return count; } public static File copyInTempFile( InputStream input, String fileExtension ) throws IOException { File tempFile = File.createTempFile( UUID.randomUUID().toString(), "." + fileExtension ); tempFile.deleteOnExit(); copy(input, new FileOutputStream(tempFile)); return tempFile; } public static List<String> recursiveListFile(File folder) { return recursiveListFile( folder, "", f -> true ); } public static List<String> recursiveListFile(File folder, String prefix, Predicate<File> filter) { List<String> files = new ArrayList<String>(); for (File child : safeListFiles(folder)) { filesInFolder(files, child, prefix, filter); } return files; } private static void filesInFolder(List<String> files, File file, String relativePath, Predicate<File> filter) { if (file.isDirectory()) { relativePath += file.getName() + "/"; for (File child : safeListFiles(file)) { filesInFolder(files, child, relativePath, filter); } } else { if (filter.test(file)) { files.add(relativePath + file.getName()); } } } /** * Returns {@link File#listFiles()} on a given file, avoids returning null when an IO error occurs. * * @param file directory whose files will be returned * @return {@link File#listFiles()} * @throws IllegalArgumentException when the file is a directory or cannot be accessed */ private static File[] safeListFiles(final File file) { final File[] children = file.listFiles(); if (children != null) { return children; } else { throw new IllegalArgumentException(String.format("Unable to retrieve contents of directory '%s'.", file.getAbsolutePath())); } } public static byte[] readBytesFromInputStream(InputStream input) throws IOException { return readBytesFromInputStream( input, true ); } public static byte[] readBytesFromInputStream(InputStream input, boolean closeInput) throws IOException { try { byte[] buffer = createBytesBuffer( input ); ByteArrayOutputStream output = new ByteArrayOutputStream( buffer.length ); int n = 0; while ( -1 != ( n = input.read( buffer ) ) ) { output.write( buffer, 0, n ); } return output.toByteArray(); } finally { try { if ( closeInput ) { input.close(); } } catch (Exception e) { // ignore } } } private static byte[] createBytesBuffer( InputStream input ) throws IOException { return new byte[Math.max(input.available(), 8192)]; } public static byte[] readBytesFromZipEntry(File file, ZipEntry entry) throws IOException { if ( entry == null ) { return null; } ZipFile zipFile = null; byte[] bytes = null; try { zipFile = new ZipFile( file ); bytes = IoUtils.readBytesFromInputStream( zipFile.getInputStream( entry ), true ); } finally { if ( zipFile != null ) { zipFile.close(); } } return bytes; } public static byte[] readBytes(File f) throws IOException { byte[] buf = new byte[1024]; BufferedInputStream bais = null; ByteArrayOutputStream baos = null; try { bais = new BufferedInputStream( new FileInputStream( f ) ); baos = new ByteArrayOutputStream(); int len; while ( (len = bais.read( buf )) > 0 ) { baos.write( buf, 0, len ); } } finally { if ( baos != null ) { baos.close(); } if ( bais != null ) { bais.close(); } } return baos.toByteArray(); } public static void write(File f, byte[] data) throws IOException { if ( f.exists() ) { // we want to make sure there is a time difference for lastModified and lastRead checks as Linux and http often round to seconds // http://saloon.javaranch.com/cgi-bin/ubb/ultimatebb.cgi?ubb=get_topic&f=1&t=019789 try { Thread.sleep( 1000 ); } catch ( Exception e ) { throw new RuntimeException( "Unable to sleep" ); } } // Attempt to write the file writeBytes(f, data ); // Now check the file was written and re-attempt if it was not // Need to do this for testing, to ensure the texts are read the same way, otherwise sometimes you get tail \n sometimes you don't int count = 0; while ( !areByteArraysEqual(data, readBytes( f ) ) && count < 5 ) { // The file failed to write, try 5 times, calling GC and sleep between each iteration // Sometimes windows takes a while to release a lock on a file System.gc(); try { Thread.sleep( 250 ); } catch ( InterruptedException e ) { throw new RuntimeException( "This should never happen" ); } writeBytes(f, data ); count++; } //areByteArraysEqual if ( count == 5 ) { throw new IOException( "Unable to write to file:" + f.getCanonicalPath() ); } } public static void writeBytes(File f, byte[] data) throws IOException { byte[] buf = new byte[1024]; BufferedOutputStream bos = null; ByteArrayInputStream bais = null; try { bos = new BufferedOutputStream( new FileOutputStream(f) ); bais = new ByteArrayInputStream( data ); int len; while ( (len = bais.read( buf )) > 0 ) { bos.write( buf, 0, len ); } } finally { if ( bos != null ) { bos.close(); } if ( bais != null ) { bais.close(); } } } public static boolean areByteArraysEqual(byte[] b1, byte[] b2) { if ( b1.length != b2.length ) { return false; } for ( int i = 0, length = b1.length; i < length; i++ ) { if ( b1[i] != b2[i] ) { return false; } } return true; } public static String asSystemSpecificPath(String urlPath, int colonIndex) { String ic = urlPath.substring( Math.max( 0, colonIndex - 2 ), colonIndex + 1 ); if ( ic.matches( "\\/[A-Z]:" ) ) { return urlPath.substring( colonIndex - 2 ); } else if ( ic.matches( "[A-Z]:" ) ) { return urlPath.substring( colonIndex - 1 ); } else { return urlPath.substring( colonIndex + 1 ); } } }