/**
* Copyright 2008 - 2015 The Loon Game Engine Authors
*
* Licensed 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.
*
* @project loon
* @author cping
* @email:javachenpeng@yahoo.com
* @version 0.5
*/
package loon.html5.gwt.preloader;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.DataInputStream;
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.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import loon.html5.gwt.GWTResources.FileType;
public class ResourcesWrapper {
protected File file;
protected FileType type;
protected ResourcesWrapper() {
}
public ResourcesWrapper(String fileName) {
this.file = new File(fileName);
this.type = FileType.Absolute;
}
public ResourcesWrapper(File file) {
this.file = file;
this.type = FileType.Absolute;
}
protected ResourcesWrapper(String fileName, FileType type) {
this.type = type;
file = new File(fileName);
}
protected ResourcesWrapper(File file, FileType type) {
this.file = file;
this.type = type;
}
public String path() {
return file.getPath();
}
public String name() {
return file.getName();
}
public String extension() {
String name = file.getName();
int dotIndex = name.lastIndexOf('.');
if (dotIndex == -1)
return "";
return name.substring(dotIndex + 1);
}
public String nameWithoutExtension() {
String name = file.getName();
int dotIndex = name.lastIndexOf('.');
if (dotIndex == -1)
return name;
return name.substring(0, dotIndex);
}
public FileType type() {
return type;
}
public File file() {
if (type == FileType.External) {
return new File((String) null, file.getPath());
}
return file;
}
public InputStream read() {
if (type == FileType.Classpath
|| (type == FileType.Internal && !file.exists())
|| (type == FileType.Local && !file.exists())) {
InputStream input = ResourcesWrapper.class.getResourceAsStream("/"
+ file.getPath().replace('\\', '/'));
if (input == null)
throw new RuntimeException("File not found: " + file + " ("
+ type + ")");
return input;
}
try {
return new FileInputStream(file());
} catch (Exception ex) {
if (file().isDirectory())
throw new RuntimeException(
"Cannot open a stream to a directory: " + file + " ("
+ type + ")", ex);
throw new RuntimeException("Error reading file: " + file + " ("
+ type + ")", ex);
}
}
public BufferedInputStream read(int bufferSize) {
return new BufferedInputStream(read(), bufferSize);
}
public Reader reader() {
return new InputStreamReader(read());
}
public Reader reader(String charset) {
try {
return new InputStreamReader(read(), charset);
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException("Error reading file: " + this, ex);
}
}
public BufferedReader reader(int bufferSize) {
return new BufferedReader(new InputStreamReader(read()), bufferSize);
}
public BufferedReader reader(int bufferSize, String charset) {
try {
return new BufferedReader(new InputStreamReader(read(), charset),
bufferSize);
} catch (UnsupportedEncodingException ex) {
throw new RuntimeException("Error reading file: " + this, ex);
}
}
public String readString() {
return readString(null);
}
public String readString(String charset) {
int fileLength = (int) length();
if (fileLength == 0)
fileLength = 512;
StringBuilder output = new StringBuilder(fileLength);
InputStreamReader reader = null;
try {
if (charset == null)
reader = new InputStreamReader(read());
else
reader = new InputStreamReader(read(), charset);
char[] buffer = new char[256];
while (true) {
int length = reader.read(buffer);
if (length == -1)
break;
output.append(buffer, 0, length);
}
} catch (IOException ex) {
throw new RuntimeException("Error reading layout file: " + this, ex);
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return output.toString();
}
public byte[] readBytes() throws IOException {
InputStream is = new DataInputStream(new BufferedInputStream(
new FileInputStream(file)));
try {
long length = file.length();
byte[] bytes = new byte[(int) length];
int offset = 0;
int numRead = 0;
while (offset < bytes.length
&& (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0) {
offset += numRead;
}
if (offset < bytes.length) {
throw new IOException("Could not completely read file "
+ file.getName());
}
return bytes;
} finally {
is.close();
}
}
public int readBytes(byte[] bytes, int offset, int size) {
InputStream input = read();
int position = 0;
try {
while (true) {
int count = input.read(bytes, offset + position, size
- position);
if (count <= 0)
break;
position += count;
}
} catch (IOException ex) {
throw new RuntimeException("Error reading file: " + this, ex);
} finally {
try {
if (input != null)
input.close();
} catch (IOException ignored) {
}
}
return position - offset;
}
public OutputStream write(boolean append) {
if (type == FileType.Classpath)
throw new RuntimeException("Cannot write to a classpath file: "
+ file);
if (type == FileType.Internal)
throw new RuntimeException("Cannot write to an internal file: "
+ file);
parent().mkdirs();
try {
return new FileOutputStream(file(), append);
} catch (Exception ex) {
if (file().isDirectory())
throw new RuntimeException(
"Cannot open a stream to a directory: " + file + " ("
+ type + ")", ex);
throw new RuntimeException("Error writing file: " + file + " ("
+ type + ")", ex);
}
}
public void write(InputStream input, boolean append) {
OutputStream output = null;
try {
output = write(append);
byte[] buffer = new byte[4096];
while (true) {
int length = input.read(buffer);
if (length == -1)
break;
output.write(buffer, 0, length);
}
} catch (Exception ex) {
throw new RuntimeException("Error stream writing to file: " + file
+ " (" + type + ")", ex);
} finally {
try {
if (input != null)
input.close();
} catch (Exception ignored) {
}
try {
if (output != null)
output.close();
} catch (Exception ignored) {
}
}
}
public Writer writer(boolean append) {
return writer(append, null);
}
public Writer writer(boolean append, String charset) {
if (type == FileType.Classpath)
throw new RuntimeException("Cannot write to a classpath file: "
+ file);
if (type == FileType.Internal)
throw new RuntimeException("Cannot write to an internal file: "
+ file);
parent().mkdirs();
try {
FileOutputStream output = new FileOutputStream(file(), append);
if (charset == null)
return new OutputStreamWriter(output);
else
return new OutputStreamWriter(output, charset);
} catch (IOException ex) {
if (file().isDirectory())
throw new RuntimeException(
"Cannot open a stream to a directory: " + file + " ("
+ type + ")", ex);
throw new RuntimeException("Error writing file: " + file + " ("
+ type + ")", ex);
}
}
public void writeString(String string, boolean append) {
writeString(string, append, null);
}
public void writeString(String string, boolean append, String charset) {
Writer writer = null;
try {
writer = writer(append, charset);
writer.write(string);
} catch (Exception ex) {
throw new RuntimeException("Error writing file: " + file + " ("
+ type + ")", ex);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
public void writeBytes(byte[] bytes, boolean append) {
OutputStream output = write(append);
try {
output.write(bytes);
} catch (IOException ex) {
throw new RuntimeException("Error writing file: " + file + " ("
+ type + ")", ex);
} finally {
try {
output.close();
} catch (IOException ignored) {
}
}
}
public void writeBytes(byte[] bytes, int offset, int length, boolean append) {
OutputStream output = write(append);
try {
output.write(bytes, offset, length);
} catch (IOException ex) {
throw new RuntimeException("Error writing file: " + file + " ("
+ type + ")", ex);
} finally {
try {
output.close();
} catch (IOException ignored) {
}
}
}
public ResourcesWrapper[] list() {
if (type == FileType.Classpath)
throw new RuntimeException("Cannot list a classpath directory: "
+ file);
String[] relativePaths = file().list();
if (relativePaths == null)
return new ResourcesWrapper[0];
ResourcesWrapper[] handles = new ResourcesWrapper[relativePaths.length];
for (int i = 0, n = relativePaths.length; i < n; i++)
handles[i] = child(relativePaths[i]);
return handles;
}
public ResourcesWrapper[] list(String suffix) {
if (type == FileType.Classpath)
throw new RuntimeException("Cannot list a classpath directory: "
+ file);
String[] relativePaths = file().list();
if (relativePaths == null)
return new ResourcesWrapper[0];
ResourcesWrapper[] handles = new ResourcesWrapper[relativePaths.length];
int count = 0;
for (int i = 0, n = relativePaths.length; i < n; i++) {
String path = relativePaths[i];
if (!path.endsWith(suffix))
continue;
handles[count] = child(path);
count++;
}
if (count < relativePaths.length) {
ResourcesWrapper[] newHandles = new ResourcesWrapper[count];
System.arraycopy(handles, 0, newHandles, 0, count);
handles = newHandles;
}
return handles;
}
public boolean isDirectory() {
if (type == FileType.Classpath) {
return false;
}
return file().isDirectory();
}
public ResourcesWrapper child(String name) {
if (file.getPath().length() == 0) {
return new ResourcesWrapper(new File(name), type);
}
return new ResourcesWrapper(new File(file, name), type);
}
public ResourcesWrapper parent() {
File parent = file.getParentFile();
if (parent == null) {
if (type == FileType.Absolute) {
parent = new File("/");
} else {
parent = new File("");
}
}
return new ResourcesWrapper(parent, type);
}
public boolean mkdirs() {
if (type == FileType.Classpath) {
throw new RuntimeException("Cannot mkdirs with a classpath file: "
+ file);
}
if (type == FileType.Internal) {
throw new RuntimeException("Cannot mkdirs with an internal file: "
+ file);
}
return file().mkdirs();
}
public boolean exists() {
switch (type) {
case Internal:
if (file.exists()) {
return true;
}
case Classpath:
return ResourcesWrapper.class.getResource("/"
+ file.getPath().replace('\\', '/')) != null;
default:
break;
}
return file().exists();
}
public boolean delete() {
if (type == FileType.Classpath)
throw new RuntimeException("Cannot delete a classpath file: "
+ file);
if (type == FileType.Internal)
throw new RuntimeException("Cannot delete an internal file: "
+ file);
return file().delete();
}
public boolean deleteDirectory() {
if (type == FileType.Classpath)
throw new RuntimeException("Cannot delete a classpath file: "
+ file);
if (type == FileType.Internal)
throw new RuntimeException("Cannot delete an internal file: "
+ file);
return deleteDirectory(file());
}
public void copyTo(ResourcesWrapper dest) {
boolean sourceDir = isDirectory();
if (!sourceDir) {
if (dest.isDirectory())
dest = dest.child(name());
copyFile(this, dest);
return;
}
if (dest.exists()) {
if (!dest.isDirectory())
throw new RuntimeException(
"Destination exists but is not a directory: " + dest);
} else {
dest.mkdirs();
if (!dest.isDirectory())
throw new RuntimeException(
"Destination directory cannot be created: " + dest);
}
if (!sourceDir)
dest = dest.child(name());
copyDirectory(this, dest);
}
public void moveTo(ResourcesWrapper dest) {
if (type == FileType.Classpath)
throw new RuntimeException("Cannot move a classpath file: " + file);
if (type == FileType.Internal)
throw new RuntimeException("Cannot move an internal file: " + file);
copyTo(dest);
delete();
}
public long length() {
return file().length();
}
public long lastModified() {
return file().lastModified();
}
public String toString() {
return file.getPath();
}
static public ResourcesWrapper tempFile(String prefix) {
try {
return new ResourcesWrapper(File.createTempFile(prefix, null));
} catch (IOException ex) {
throw new RuntimeException("Unable to create temp file.", ex);
}
}
static public ResourcesWrapper tempDirectory(String prefix) {
try {
File file = File.createTempFile(prefix, null);
if (!file.delete())
throw new IOException("Unable to delete temp file: " + file);
if (!file.mkdir())
throw new IOException("Unable to create temp directory: "
+ file);
return new ResourcesWrapper(file);
} catch (IOException ex) {
throw new RuntimeException("Unable to create temp file.", ex);
}
}
static private boolean deleteDirectory(File file) {
if (file.exists()) {
File[] files = file.listFiles();
if (files != null) {
for (int i = 0, n = files.length; i < n; i++) {
if (files[i].isDirectory())
deleteDirectory(files[i]);
else
files[i].delete();
}
}
}
return file.delete();
}
static private void copyFile(ResourcesWrapper source, ResourcesWrapper dest) {
try {
dest.write(source.read(), false);
} catch (Exception ex) {
throw new RuntimeException("Error copying source file: "
+ source.file + " (" + source.type + ")\n" //
+ "To destination: " + dest.file + " (" + dest.type + ")",
ex);
}
}
static private void copyDirectory(ResourcesWrapper sourceDir,
ResourcesWrapper destDir) {
destDir.mkdirs();
ResourcesWrapper[] files = sourceDir.list();
for (int i = 0, n = files.length; i < n; i++) {
ResourcesWrapper srcFile = files[i];
ResourcesWrapper destFile = destDir.child(srcFile.name());
if (srcFile.isDirectory()) {
copyDirectory(srcFile, destFile);
} else {
copyFile(srcFile, destFile);
}
}
}
}