/*
* Copyright (C) 2011 Peransin Nicolas.
* Use is subject to license terms.
*/
package org.mypsycho.util;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
/**
* XXX Doc
* <p>Detail ... </p>
* @author Peransin Nicolas
*/
public class Files {
// Suppresses default constructor, ensuring non-instantiability.
private Files() {
}
private static final String JAR_PROTOCOL="jar";
private static final String FILE_FULL_PROTOCOL="file:";
public static File getLocation(Class<?> c) { // In Unix style
String extension = ".class";
char pathSeparator = '/';
String fileName = c.getName();
// Si pas de package => (-1)+1 = 0 : OK
URL url = c.getResource(fileName.substring(fileName.lastIndexOf('.')+1) + extension);
String path = url.getPath();
boolean hasFileProtocol = false;
int end = path.length() - fileName.length() - extension.length() - 1;
if (url.getProtocol().equals(JAR_PROTOCOL)) {
hasFileProtocol = path.startsWith(FILE_FULL_PROTOCOL);
end = path.lastIndexOf(pathSeparator, end-1);
}
if (!hasFileProtocol) {
path = FILE_FULL_PROTOCOL + path.substring(0, end);
} else {
path = path.substring(0, end);
}
URI uri = URI.create(path);
// System.out.println("uri " + uri.getAuthority());
return new File(uri);
}
public static File getLocationPath(Class<?> c) { // In Unix style
return getLocation(c).getAbsoluteFile();
}
public static File getLocationArchive(Class<?> c) { // In Unix style
String extension = ".class";
String fileName = c.getName();
// Si pas de package => (-1)+1 = 0 : OK
URL url = c.getResource(fileName.substring(fileName.lastIndexOf('.')+1) + extension);
if (!url.getProtocol().equals(JAR_PROTOCOL)) {
return null;
}
String path = url.getPath();
// suppressing '!/' tag
int end = path.length() - fileName.length() - extension.length() - 2;
boolean withFileProtocol = path.startsWith(FILE_FULL_PROTOCOL);
path = ((!withFileProtocol) ? FILE_FULL_PROTOCOL : "") + path.substring(0, end);
return new File(URI.create(path));
}
public static final String PATH_PARENT = "..";
public static final String PATH_IDENTITY = ".";
public static final String PATH_SEPARATOR = System.getProperty("path.separator");
public static final String LINE_SEPARATOR = System.getProperty("line.separator");
/* FILE_SEPARATOR \:Windows, /:Unix */
public static final String FILE_SEPARATOR = System.getProperty("file.separator");
/**
* Copy file and directory recursively
*/
public static boolean copy(File pIn, File pOut) {
if (!pIn.exists()) return false;
boolean success = true;
if (pIn.isDirectory()) {
if (!pOut.exists()) { // Creation du repertoire
if (!pOut.mkdirs())
return false;
} else if (!pOut.isDirectory()) {
if (!delete(pOut))
return false;
else if (!pOut.mkdirs())
return false;
}
File[] files = pIn.listFiles();
for (int indFile=0; indFile<files.length; indFile++)
success = copy(files[indFile],
new File(pOut, files[indFile].getName())) && success;
return success;
} else { // copy files
byte[] buffer = new byte[1024];
FileInputStream is = null;
FileOutputStream os = null;
try {
is = new FileInputStream(pIn);
os = new FileOutputStream(pOut);
for (int length = is.read(buffer); length>-1; length = is.read(buffer))
os.write(buffer, 0, length);
} catch (IOException ioe) {
success = false;
} finally {
if (os != null) try {
os.close();
} catch (IOException ignore) {}
if (is != null) try {
is.close();
} catch (IOException ignore) {}
}
return success;
}
}
/**
* Delete file and directory recursively
*/
public static boolean delete(File pFile) {
if (!pFile.exists())
return true;
if (pFile.isDirectory()) {
boolean success = true;
File[] files = pFile.listFiles();
for (int indFile=0; indFile<files.length; indFile++)
success = delete(files[indFile]) && success;
return success && pFile.delete();
} else
return pFile.delete();
}
/**
* Create a directory recursively
* or change a file into a directory
*/
public static boolean mkdir(File pDirectory) {
if (!pDirectory.exists())
return pDirectory.mkdirs();
else if (!pDirectory.isDirectory()) {
if (pDirectory.delete())
return false;
return pDirectory.mkdirs();
} else // pDirectory exist and is directory
return true;
}
/**
* Provide an relative path,
* can be done only with real files
*/
public static String relativize(String pFile, String pFrom) {
return relativize(new File(pFile), new File(pFrom));
}
public static String relativize(File pFile, File pFrom) {
try {
String filePath = pFile.getCanonicalPath();
String fromPath;
if (pFrom.isDirectory() || (!pFrom.exists()))
fromPath = pFrom.getCanonicalPath();
else if (pFrom.getParent() == null)
fromPath = new File(PATH_IDENTITY).getCanonicalPath(); // Portable ??
else
fromPath = pFrom.getParentFile().getCanonicalPath();
int index = 0;
for (boolean same=true; same; ) {
if (index >= filePath.length())
same = false;
else if (index >= fromPath.length())
same = false;
else
same = (filePath.charAt(index) == fromPath.charAt(index));
if (same)
index++;
}
if (index <= 0) // No common part, not even on same drive
return filePath;
else if (index >= fromPath.length()) { // the end of fromPath
if (index >= filePath.length()) // (pFile is a directory) and
// ( (is pFrom and pFrom is a directory)
// or (contains pFrom and pFrom is a directory) )
return PATH_IDENTITY;
else if (filePath.indexOf(FILE_SEPARATOR, index) == index) { // filePath is a part of fromPath
return filePath.substring(index + FILE_SEPARATOR.length());
} else { // only last dir is different
// begin or end of FILE_SEPARATOR ?? BEGIN
index = filePath.lastIndexOf(FILE_SEPARATOR, index) + FILE_SEPARATOR.length();
return PATH_PARENT + FILE_SEPARATOR + filePath.substring(index);
}
} else { // not the end of fromPath
if (index >= filePath.length() &&
(fromPath.indexOf(FILE_SEPARATOR, index) == index)) { // filePath is a part of fromPath
index = index+FILE_SEPARATOR.length();
String backward = PATH_PARENT;
for (index=fromPath.indexOf(FILE_SEPARATOR, index); index != -1;
index=fromPath.indexOf(FILE_SEPARATOR, index)) {
backward = backward + FILE_SEPARATOR + PATH_PARENT;
index = index + FILE_SEPARATOR.length();
}
return backward;
} else {
// begin or end of FILE_SEPARATOR ?? BEGIN
index = fromPath.lastIndexOf(FILE_SEPARATOR, index) + FILE_SEPARATOR.length();
filePath = filePath.substring(index);
fromPath = fromPath.substring(index);
String backward = PATH_PARENT;
for (index=fromPath.indexOf(FILE_SEPARATOR, 0); index != -1;
index=fromPath.indexOf(FILE_SEPARATOR, index)) {
backward = backward + FILE_SEPARATOR + PATH_PARENT;
index = index + FILE_SEPARATOR.length();
}
return backward + FILE_SEPARATOR + filePath;
}
}
} catch (IOException ioe) {
return null;
}
}
// --- Local test method ---------------------------------------------
public static void main(String[] pArgs) {
String[] files = new String[] {
// FILE from DIR
"w\\lib\\p1", "w\\lib\\p1",
"w\\lib\\p1", ".",
"w\\lib\\p1\\src\\code\\Test.java", "w\\lib\\p1\\jar\\code\\Test.class",
"w\\lib\\p1\\src\\code", "w\\lib\\p1\\jar\\code\\Test.class",
"w\\lib\\p1", "w",
"w\\lib\\p1\\", "w",
"w\\lib\\p1", "w\\",
"w2\\lib\\p1", "w",
"w\\lib\\p1\\src\\c", "w\\p3\\classes",
"w\\lib\\p1", "z\\lib", // ???
"w", "w\\lib",
"w", "w\\lib\\p1\\src\\c",
"w\\lib\\p1", "w\\z\\lib",
"..\\test", "w\\z\\lib",
"..\\c", "w\\z\\lib"
};
int size = 0;
for (int ind = 0; ind<files.length; ind++)
size = Math.max(size, files[ind].length());
for (int ind = 0; ind<files.length; ind =ind+2) try {
for (int c=0; c<size-files[ind].length(); c++) System.out.print(" "); // SPACE
System.out.print(files[ind]+" from "+files[ind+1]);
for (int c=0; c<size-files[ind+1].length(); c++) System.out.print(" "); // SPACE
// String res = new File(files[ind+1]).toURI().relativize(new File(files[ind]).toURI()).toString();
String res = Files.relativize(files[ind], files[ind+1]);
System.out.print(" => " + res );
// System.out.println();
if (new File(files[ind]).getCanonicalFile().equals(
new File(files[ind+1]+FILE_SEPARATOR+res).getCanonicalFile()))
System.out.println(" ---");
else {
System.out.println(" !!!");
System.out.println(">>> " + new File(files[ind]).getCanonicalPath());
System.out.println(">>> " + files[ind+1]+FILE_SEPARATOR+res);
System.out.println(">>> " + new File(files[ind+1]+FILE_SEPARATOR+res).getCanonicalPath());
}
} catch (Exception ex) {
ex.printStackTrace(System.out);
}
}
} // endclass Files