/** * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * 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.apache.metamodel.util; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.Flushable; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PushbackInputStream; import java.io.Reader; import java.io.Writer; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Various helper methods for handling files */ public final class FileHelper { private final static Logger logger = LoggerFactory.getLogger(FileHelper.class); public static final String UTF_8_ENCODING = "UTF-8"; public static final String UTF_16_ENCODING = "UTF-16"; public static final String US_ASCII_ENCODING = "US-ASCII"; public static final String ISO_8859_1_ENCODING = "ISO_8859_1"; public static final String DEFAULT_ENCODING = UTF_8_ENCODING; private FileHelper() { // prevent instantiation } public static File createTempFile(String prefix, String suffix) { try { return File.createTempFile(prefix, suffix); } catch (IOException e) { logger.error("Could not create tempFile", e); File tempDir = getTempDir(); return new File(tempDir, prefix + '.' + suffix); } } public static File getTempDir() { File result = null; String tmpDirPath = System.getProperty("java.io.tmpdir"); if (tmpDirPath != null && !"".equals(tmpDirPath)) { result = new File(tmpDirPath); } else { logger.debug("Could not determine tmpdir by using environment variable."); try { File file = File.createTempFile("foo", "bar"); result = file.getParentFile(); if (!file.delete()) { logger.warn("Could not delete temp file '{}'", file.getAbsolutePath()); } } catch (IOException e) { logger.error("Could not create tempFile in order to find temporary dir", e); result = new File("metamodel.tmp.dir"); if (!result.mkdir()) { throw new IllegalStateException("Could not create directory for temporary files: " + result.getName()); } result.deleteOnExit(); } } if (logger.isInfoEnabled()) { logger.info("Using '{}' as tmpdir.", result.getAbsolutePath()); } return result; } public static Writer getWriter(File file, String encoding, boolean append) throws IllegalStateException { boolean insertBom = !append; return getWriter(file, encoding, append, insertBom); } public static Writer getWriter(OutputStream outputStream, String encoding) throws IllegalStateException { return getWriter(outputStream, encoding, false); } public static Writer getWriter(OutputStream outputStream, String encoding, boolean insertBom) throws IllegalStateException { if (!(outputStream instanceof BufferedOutputStream)) { outputStream = new BufferedOutputStream(outputStream); } try { if (insertBom) { Writer writer = new UnicodeWriter(outputStream, encoding); return writer; } else { Writer writer = new OutputStreamWriter(outputStream, encoding); return writer; } } catch (Exception e) { throw new IllegalStateException(e); } } public static Writer getWriter(File file, String encoding, boolean append, boolean insertBom) throws IllegalStateException { if (append && insertBom) { throw new IllegalArgumentException("Can not insert BOM into appending writer"); } final OutputStream outputStream = getOutputStream(file, append); return getWriter(outputStream, encoding, insertBom); } public static Writer getWriter(File file, String encoding) throws IllegalStateException { return getWriter(file, encoding, false); } public static Reader getReader(InputStream inputStream, String encoding) throws IllegalStateException { try { if (encoding == null || encoding.toLowerCase().indexOf("utf") != -1) { final byte bom[] = new byte[4]; int unread; // auto-detect byte-order-mark @SuppressWarnings("resource") final PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream, bom.length); final int n = pushbackInputStream.read(bom, 0, bom.length); // Read ahead four bytes and check for BOM marks. if ((bom[0] == (byte) 0xEF) && (bom[1] == (byte) 0xBB) && (bom[2] == (byte) 0xBF)) { encoding = "UTF-8"; unread = n - 3; } else if ((bom[0] == (byte) 0xFE) && (bom[1] == (byte) 0xFF)) { encoding = "UTF-16BE"; unread = n - 2; } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE)) { encoding = "UTF-16LE"; unread = n - 2; } else if ((bom[0] == (byte) 0x00) && (bom[1] == (byte) 0x00) && (bom[2] == (byte) 0xFE) && (bom[3] == (byte) 0xFF)) { encoding = "UTF-32BE"; unread = n - 4; } else if ((bom[0] == (byte) 0xFF) && (bom[1] == (byte) 0xFE) && (bom[2] == (byte) 0x00) && (bom[3] == (byte) 0x00)) { encoding = "UTF-32LE"; unread = n - 4; } else { unread = n; } if (unread > 0) { pushbackInputStream.unread(bom, (n - unread), unread); } else if (unread < -1) { pushbackInputStream.unread(bom, 0, 0); } inputStream = pushbackInputStream; } final InputStreamReader inputStreamReader; if (encoding == null) { inputStreamReader = new InputStreamReader(inputStream); } else { inputStreamReader = new InputStreamReader(inputStream, encoding); } return inputStreamReader; } catch (IOException e) { throw new IllegalStateException(e); } } public static Reader getReader(File file, String encoding) throws IllegalStateException { final InputStream inputStream; try { inputStream = new BufferedInputStream(new FileInputStream(file)); } catch (IOException e) { throw new IllegalStateException(e); } return getReader(inputStream, encoding); } public static String readInputStreamAsString(InputStream inputStream, String encoding) throws IllegalStateException { Reader reader = getReader(inputStream, encoding); return readAsString(reader); } public static String readFileAsString(File file, String encoding) throws IllegalStateException { Reader br = getReader(file, encoding); return readAsString(br); } public static String readAsString(Reader reader) throws IllegalStateException { final BufferedReader br = getBufferedReader(reader); try { StringBuilder sb = new StringBuilder(); boolean firstLine = true; for (String line = br.readLine(); line != null; line = br.readLine()) { if (firstLine) { firstLine = false; } else { sb.append('\n'); } sb.append(line); } return sb.toString(); } catch (Exception e) { throw new IllegalStateException(e); } finally { safeClose(br, reader); } } public static void safeClose(Object... objects) { boolean debugEnabled = logger.isDebugEnabled(); if (objects == null || objects.length == 0) { logger.info("safeClose(...) was invoked with null or empty array: {}", objects); return; } for (Object obj : objects) { if (obj != null) { if (debugEnabled) { logger.debug("Trying to safely close {}", obj); } if (obj instanceof Flushable) { try { ((Flushable) obj).flush(); } catch (Exception e) { if (debugEnabled) { logger.debug("Flushing Flushable failed", e); } } } if (obj instanceof AutoCloseable) { try { ((AutoCloseable) obj).close(); } catch (Exception e) { if (debugEnabled) { logger.debug("Closing AutoCloseable failed", e); } } } else { logger.info("obj was not AutoCloseable, trying to find close() method via reflection."); try { Method method = obj.getClass().getMethod("close", new Class[0]); if (method == null) { logger.info("obj did not have a close() method, ignoring"); } else { method.setAccessible(true); method.invoke(obj); } } catch (InvocationTargetException e) { logger.warn("Invoking close() by reflection threw exception", e); } catch (Exception e) { logger.warn("Could not invoke close() by reflection", e); } } } } } public static BufferedWriter getBufferedWriter(File file, String encoding) throws IllegalStateException { Writer writer = getWriter(file, encoding); return new BufferedWriter(writer); } public static BufferedReader getBufferedReader(File file, String encoding) throws IllegalStateException { Reader reader = getReader(file, encoding); return new BufferedReader(reader); } public static BufferedReader getBufferedReader(InputStream inputStream, String encoding) throws IllegalStateException { Reader reader = getReader(inputStream, encoding); return new BufferedReader(reader); } public static Reader getReader(File file) throws IllegalStateException { return getReader(file, DEFAULT_ENCODING); } public static String readFileAsString(File file) throws IllegalStateException { return readFileAsString(file, DEFAULT_ENCODING); } public static BufferedWriter getBufferedWriter(File file) throws IllegalStateException { return getBufferedWriter(file, DEFAULT_ENCODING); } public static Writer getWriter(File file) throws IllegalStateException { return getWriter(file, DEFAULT_ENCODING); } public static void writeString(OutputStream outputStream, String string) throws IllegalStateException { writeString(outputStream, string, DEFAULT_ENCODING); } public static void writeString(OutputStream outputStream, String string, String encoding) throws IllegalStateException { final Writer writer = getWriter(outputStream, encoding); writeString(writer, string, encoding); } public static void writeString(Writer writer, String string) throws IllegalStateException { writeString(writer, string, DEFAULT_ENCODING); } public static void writeString(Writer writer, String string, String encoding) throws IllegalStateException { try { writer.write(string); } catch (Exception e) { throw new IllegalStateException(e); } finally { safeClose(writer); } } public static void writeStringAsFile(File file, String string) throws IllegalStateException { writeStringAsFile(file, string, DEFAULT_ENCODING); } public static void writeStringAsFile(File file, String string, String encoding) throws IllegalStateException { final BufferedWriter bw = getBufferedWriter(file, encoding); writeString(bw, string, encoding); } public static BufferedReader getBufferedReader(File file) throws IllegalStateException { return getBufferedReader(file, DEFAULT_ENCODING); } public static void copy(Reader reader, Writer writer) throws IllegalStateException { final BufferedReader bufferedReader = getBufferedReader(reader); try { boolean firstLine = true; for (String line = bufferedReader.readLine(); line != null; line = bufferedReader.readLine()) { if (firstLine) { firstLine = false; } else { writer.write('\n'); } writer.write(line); } } catch (IOException e) { throw new IllegalStateException(e); } } public static BufferedReader getBufferedReader(Reader reader) { if (reader instanceof BufferedReader) { return (BufferedReader) reader; } return new BufferedReader(reader); } public static void copy(InputStream fromStream, OutputStream toStream) throws IllegalStateException { try { byte[] buffer = new byte[1024 * 32]; for (int read = fromStream.read(buffer); read != -1; read = fromStream.read(buffer)) { toStream.write(buffer, 0, read); } } catch (IOException e) { throw new IllegalStateException(e); } } public static void copy(Resource from, Resource to) throws IllegalStateException { assert from.isExists(); final InputStream in = from.read(); try { final OutputStream out = to.write(); try { copy(in, out); } finally { safeClose(out); } } finally { safeClose(in); } } public static void copy(File from, File to) throws IllegalStateException { assert from.exists(); final InputStream in = getInputStream(from); try { final OutputStream out = getOutputStream(to); try { copy(in, out); } finally { safeClose(out); } } finally { safeClose(in); } } public static OutputStream getOutputStream(File file) throws IllegalStateException { return getOutputStream(file, false); } public static OutputStream getOutputStream(File file, boolean append) { try { return new BufferedOutputStream(new FileOutputStream(file, append)); } catch (FileNotFoundException e) { throw new IllegalStateException(e); } } public static InputStream getInputStream(File file) throws IllegalStateException { try { return new BufferedInputStream(new FileInputStream(file)); } catch (FileNotFoundException e) { throw new IllegalStateException(e); } } public static byte[] readAsBytes(InputStream inputStream) { final ByteArrayOutputStream baos = new ByteArrayOutputStream(); try { copy(inputStream, baos); } finally { safeClose(inputStream); } return baos.toByteArray(); } }