/* * $Id$ * * Copyright (C) 2003-2015 JNode.org * * This library is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library 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 library; If not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ package org.jnode.fs.util; import java.io.IOException; import java.text.DateFormat; import java.text.SimpleDateFormat; import java.util.Date; import org.apache.log4j.Logger; import org.jnode.fs.FSDirectory; import org.jnode.fs.FSEntry; import org.jnode.fs.FSFile; /** * * @author Fabien DUMINY */ public class FSUtils { private static final Logger log = Logger.getLogger(FSUtils.class); protected static DateFormat dateFormat = new SimpleDateFormat(); /** * @param path * @param separator * @return the file name of a filename + path */ public static String getName(String path, char separator) { int idx = path.lastIndexOf(separator); if (idx >= 0) { path = path.substring(idx + 1); } return path; } /** * @param path a pathname * @param separator the pathname separator used in the pathname * @return the parent part of a pathname */ public static String getParentName(String path, char separator) { int idx = path.lastIndexOf(separator); if (idx < 0) { path = ""; } else { path = path.substring(0, idx); } return path; } /** * @param entry an FSEntry to be rendered * @param deep if {@code true}, include details of the FS object that the entry refers to. * @return a human readable rendering of the FSEntry */ public static String toString(FSEntry entry, boolean deep) { if (entry == null) return "<FSEntry>NULL</FSEntry>"; StringBuilder sb = new StringBuilder(2048); sb.append("<FSEntry>"); sb.append(" name=" + entry.getName()); try { sb.append(toStringDate(" lastModified=", entry.getLastModified())); } catch (IOException e) { sb.append(" lastModified=###" + e.getMessage() + "###"); log.error("error in lastModified", e); } try { sb.append(" isDirty=" + entry.isDirty()); } catch (IOException e1) { sb.append(" isDirty=###" + e1.getMessage() + "###"); log.error("error in isDirty", e1); } sb.append(" isValid=" + entry.isValid()); sb.append(" isFile=" + entry.isFile()); if (deep && entry.isFile()) { try { sb.append(toString(entry.getFile())); } catch (IOException e2) { sb.append(" getFile=###" + e2.getMessage() + "###"); log.error("error in getFile", e2); } } sb.append(" isDir=" + entry.isDirectory()); if (deep && entry.isDirectory()) try { sb.append(toString(entry.getDirectory())); } catch (IOException e3) { sb.append(" getDirectory=###" + e3.getMessage() + "###"); log.error("error in getDirectory", e3); } sb.append("</FSEntry>"); return sb.toString(); } /** * @param dir an FSDirectory * @return a human readable rendering of the FSDirectory * @throws IOException */ public static String toString(FSDirectory dir) throws IOException { return toString(dir, false); } /** * @param dir an FSDirectory * @param deep if {@code true} also render the directory's entries * @return a human readable rendering of the FSDirectory * @throws IOException */ public static String toString(FSDirectory dir, boolean deep) throws IOException { if (dir == null) return "<FSDirectory>NULL</FSDirectory>"; String str = "<FSDirectory>isValid=" + dir.isValid() + "</FSDirectory>"; if (deep) str += "\n" + dir.toString(); // also print entry table return str; } /** * @param file an FSFile * @return a human readable rendering of the FSFile */ public static String toString(FSFile file) { if (file == null) return "<FSEntry>NULL</FSEntry>"; StringBuilder sb = new StringBuilder(32); sb.append("<FSFile>"); sb.append(" isValid" + file.isValid()); sb.append(" length" + file.getLength()); sb.append("</FSFile>"); return sb.toString(); } /** * @param str a description * @param date a date/time expressed as milliseconds since the UNIX epoch * @return the concatenation of the description and the system default * rendering of the date. */ public static String toStringDate(String str, long date) { return toString(str, new Date(date)); } /** * @param str a description * @param date a date/time value * @return the concatenation of the description and the system default * rendering of the date. */ public static String toString(String str, Date date) { return str + dateFormat.format(date); } /** * @param data bytes to be rendered * @return a rendering of the bytes */ public static String toString(byte[] data) { return toString(data, 0, data.length); } /** * @param data an array of bytes * @param offset the start position of the first byte to be rendered * @param length the number of bytes to be rendered * @return a rendering of the bytes */ public static String toString(byte[] data, int offset, int length) { StringBuilder builder = new StringBuilder(); for (int i = offset; i < length; i += 16) { int bytes = Math.min(16, length - i); builder.append(String.format("0x%08x - ", i)); for (int j = 0; j < 16; j++) { if (j < bytes) { int value = data[i + j] & 0xFF; if (value < 16) { builder.append('0'); } builder.append(Integer.toHexString(value)).append(' '); } else { builder.append(" "); } } builder.append(" "); for (int j = 0; j < bytes; j++) { int value = data[i + j] & 0xFF; if (value >= 32 && value <= 126) { builder.append((char)value); } else { builder.append('.'); } } builder.append('\n'); } return builder.toString(); } /** * @param str the string to be padded * @param size pad to this size * @return the supplied string padded to the left with spaces. */ public static String lpad(String str, int size) { if (str.length() >= size) return str; String pad = ""; int nbBlanks = size - str.length(); for (int i = 0; i < nbBlanks; i++) pad += " "; return pad + str; } /** * Render bytes as a String by 'converting' each byte into a character * in the range 0 to 255. * @param data an array of bytes * @param offset the start position of the first byte to be rendered * @param length the number of bytes to be rendered * @return a rendering of the bytes */ public static String toStringAsChars(byte[] data, int offset, int length) { int l = Math.min(offset + length, data.length); StringBuilder sb = new StringBuilder(l); for (int i = offset; i < l; i++) { sb.append((char) data[i]); } return sb.toString(); } /** * Rounds a value up to the next boundary. * * @param boundary the boundary to round up to. * @param value the value to adjust. * @return the adjusted value. */ public static long roundUpToBoundary(int boundary, long value) { long rounding = value % boundary == 0 ? 0 : boundary - value % boundary; return rounding + value; } /** * Rounds a value up to the next boundary. * * @param boundary the boundary to round up to. * @param value the value to adjust. * @return the adjusted value. */ public static int roundUpToBoundary(int boundary, int value) { int rounding = value % boundary == 0 ? 0 : boundary - value % boundary; return rounding + value; } /** * Returns the value as an integer where it is safe to convert. * * @param value the value to convert. * @return the value as an integer. * @throws java.lang.IllegalArgumentException if the value is too large to convert to an integer. */ public static int checkedCast(long value) { int result = (int) value; if (result != value) { throw new IllegalArgumentException("Overflow converting to int: " + value); } return result; } }