mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Add preliminary support of file I/O
This commit is contained in:
parent
86d151d953
commit
76590d759c
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.teavm.classlib.fs;
|
||||
|
||||
public abstract class AbstractInMemoryVirtualFile implements VirtualFile {
|
||||
String name;
|
||||
InMemoryVirtualDirectory parent;
|
||||
long lastModified = System.currentTimeMillis();
|
||||
|
||||
AbstractInMemoryVirtualFile(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void delete() {
|
||||
parent.children.remove(name);
|
||||
parent.modify();
|
||||
parent = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canRead() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean canWrite() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long lastModified() {
|
||||
return lastModified;
|
||||
}
|
||||
|
||||
void modify() {
|
||||
lastModified = System.currentTimeMillis();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.teavm.classlib.fs;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
public class InMemoryVirtualDirectory extends AbstractInMemoryVirtualFile {
|
||||
final Map<String, VirtualFile> children = new LinkedHashMap<>();
|
||||
|
||||
InMemoryVirtualDirectory(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFile() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile[] listFiles() {
|
||||
return children.values().toArray(new VirtualFile[0]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile getChildFile(String fileName) {
|
||||
return children.get(fileName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream read() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream write(boolean append) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile createFile(String fileName) {
|
||||
InMemoryVirtualFile file = new InMemoryVirtualFile(fileName);
|
||||
adoptFile(file);
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile createDirectory(String fileName) {
|
||||
InMemoryVirtualDirectory file = new InMemoryVirtualDirectory(fileName);
|
||||
adoptFile(file);
|
||||
return file;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
private void adoptFile(AbstractInMemoryVirtualFile file) {
|
||||
if (children.containsKey(file.name)) {
|
||||
throw new IllegalArgumentException("File " + file.getName() + " already exists");
|
||||
}
|
||||
file.parent = this;
|
||||
children.put(file.name, file);
|
||||
modify();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.teavm.classlib.fs;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Arrays;
|
||||
|
||||
public class InMemoryVirtualFile extends AbstractInMemoryVirtualFile {
|
||||
byte[] data = new byte[0];
|
||||
int size;
|
||||
|
||||
InMemoryVirtualFile(String name) {
|
||||
super(name);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDirectory() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isFile() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile[] listFiles() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile getChildFile(String fileName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream read() {
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
return new ByteArrayInputStream(data, 0, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public OutputStream write(boolean append) {
|
||||
if (parent == null) {
|
||||
return null;
|
||||
}
|
||||
if (!append) {
|
||||
data = new byte[0];
|
||||
size = 0;
|
||||
}
|
||||
return new OutputStreamImpl(data, size);
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile createFile(String fileName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public VirtualFile createDirectory(String fileName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int length() {
|
||||
return size;
|
||||
}
|
||||
|
||||
class OutputStreamImpl extends OutputStream {
|
||||
byte[] data;
|
||||
int pos;
|
||||
|
||||
OutputStreamImpl(byte[] data, int pos) {
|
||||
this.data = data;
|
||||
this.pos = pos;
|
||||
}
|
||||
|
||||
private void ensureIO() throws IOException {
|
||||
if (data == null) {
|
||||
throw new IOException("Stream was closed");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
ensureIO();
|
||||
expandData(pos + 1);
|
||||
data[pos++] = (byte) b;
|
||||
sync();
|
||||
}
|
||||
|
||||
private void expandData(int newSize) {
|
||||
if (newSize > data.length) {
|
||||
int newCapacity = Math.max(newSize, data.length) * 3 / 2;
|
||||
boolean actual = data == InMemoryVirtualFile.this.data;
|
||||
data = Arrays.copyOf(data, newCapacity);
|
||||
if (actual) {
|
||||
InMemoryVirtualFile.this.data = data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void sync() {
|
||||
if (data == InMemoryVirtualFile.this.data) {
|
||||
size = pos;
|
||||
modify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
ensureIO();
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (off < 0 || len < 0 || off + len >= b.length) {
|
||||
throw new IndexOutOfBoundsException();
|
||||
}
|
||||
|
||||
expandData(pos + len);
|
||||
while (len-- > 0) {
|
||||
data[pos++] = b[off++];
|
||||
}
|
||||
|
||||
sync();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
data = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.teavm.classlib.fs;
|
||||
|
||||
public class InMemoryVirtualFileSystem implements VirtualFileSystem {
|
||||
private InMemoryVirtualDirectory root = new InMemoryVirtualDirectory("");
|
||||
private String userDir = "/";
|
||||
|
||||
@Override
|
||||
public VirtualFile getRootFile() {
|
||||
return root;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUserDir() {
|
||||
return userDir;
|
||||
}
|
||||
|
||||
public void setUserDir(String userDir) {
|
||||
this.userDir = userDir;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.teavm.classlib.fs;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
public interface VirtualFile {
|
||||
String getName();
|
||||
|
||||
boolean isDirectory();
|
||||
|
||||
boolean isFile();
|
||||
|
||||
VirtualFile[] listFiles();
|
||||
|
||||
VirtualFile getChildFile(String fileName);
|
||||
|
||||
InputStream read();
|
||||
|
||||
OutputStream write(boolean append);
|
||||
|
||||
VirtualFile createFile(String fileName);
|
||||
|
||||
VirtualFile createDirectory(String fileName);
|
||||
|
||||
void delete();
|
||||
|
||||
boolean canRead();
|
||||
|
||||
boolean canWrite();
|
||||
|
||||
long lastModified();
|
||||
|
||||
int length();
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.teavm.classlib.fs;
|
||||
|
||||
public interface VirtualFileSystem {
|
||||
VirtualFile getRootFile();
|
||||
|
||||
String getUserDir();
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.teavm.classlib.fs;
|
||||
|
||||
public final class VirtualFileSystemProvider {
|
||||
private static VirtualFileSystem instance = new InMemoryVirtualFileSystem();
|
||||
|
||||
private VirtualFileSystemProvider() {
|
||||
}
|
||||
|
||||
public static VirtualFileSystem getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
public static void setInstance(VirtualFileSystem instance) {
|
||||
VirtualFileSystemProvider.instance = instance;
|
||||
}
|
||||
}
|
445
classlib/src/main/java/org/teavm/classlib/java/io/TFile.java
Normal file
445
classlib/src/main/java/org/teavm/classlib/java/io/TFile.java
Normal file
|
@ -0,0 +1,445 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.teavm.classlib.java.io;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.Objects;
|
||||
import org.teavm.classlib.fs.VirtualFile;
|
||||
import org.teavm.classlib.fs.VirtualFileSystem;
|
||||
import org.teavm.classlib.fs.VirtualFileSystemProvider;
|
||||
|
||||
public class TFile implements Serializable, Comparable<TFile> {
|
||||
private String path;
|
||||
|
||||
public static final char separatorChar = '/';
|
||||
public static final String separator = "/";
|
||||
public static final char pathSeparatorChar = ':';
|
||||
public static final String pathSeparator = ":";
|
||||
|
||||
public TFile(TFile dir, String name) {
|
||||
Objects.requireNonNull(name);
|
||||
path = dir == null ? fixSlashes(name) : calculatePath(dir.getPath(), name);
|
||||
}
|
||||
|
||||
public TFile(String path) {
|
||||
Objects.requireNonNull(path);
|
||||
this.path = fixSlashes(path);
|
||||
}
|
||||
|
||||
public TFile(String dir, String name) {
|
||||
Objects.requireNonNull(name);
|
||||
path = dir == null ? fixSlashes(name) : calculatePath(dir, name);
|
||||
}
|
||||
|
||||
public boolean canRead() {
|
||||
VirtualFile virtualFile = findVirtualFile();
|
||||
return virtualFile != null && virtualFile.canRead();
|
||||
}
|
||||
|
||||
public boolean canWrite() {
|
||||
VirtualFile virtualFile = findVirtualFile();
|
||||
return virtualFile != null && virtualFile.canWrite();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(TFile o) {
|
||||
return path.compareTo(o.path);
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
int separatorIndex = path.lastIndexOf(separator);
|
||||
return separatorIndex < 0 ? path : path.substring(separatorIndex + 1, path.length());
|
||||
}
|
||||
|
||||
private static VirtualFileSystem fs() {
|
||||
return VirtualFileSystemProvider.getInstance();
|
||||
}
|
||||
|
||||
public String getAbsolutePath() {
|
||||
if (isAbsolute()) {
|
||||
return path;
|
||||
}
|
||||
|
||||
String userdir = fs().getUserDir();
|
||||
|
||||
if (path.isEmpty()) {
|
||||
return userdir;
|
||||
}
|
||||
int length = userdir.length();
|
||||
|
||||
StringBuilder result = new StringBuilder(userdir);
|
||||
if (userdir.charAt(length - 1) != separatorChar) {
|
||||
if (path.charAt(0) != separatorChar) {
|
||||
result.append(separator);
|
||||
}
|
||||
} else if (path.charAt(0) == separatorChar) {
|
||||
result.append(result.substring(0, length - 2));
|
||||
|
||||
}
|
||||
result.append(path);
|
||||
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
public TFile getAbsoluteFile() {
|
||||
return new TFile(getAbsolutePath());
|
||||
}
|
||||
|
||||
public boolean isAbsolute() {
|
||||
return !path.isEmpty() && path.charAt(0) == separatorChar;
|
||||
}
|
||||
|
||||
public boolean isDirectory() {
|
||||
VirtualFile virtualFile = findVirtualFile();
|
||||
return virtualFile != null && virtualFile.isDirectory();
|
||||
}
|
||||
|
||||
public boolean isHidden() {
|
||||
return getName().startsWith(".");
|
||||
}
|
||||
|
||||
public boolean isFile() {
|
||||
VirtualFile virtualFile = findVirtualFile();
|
||||
return virtualFile != null && virtualFile.isFile();
|
||||
}
|
||||
|
||||
public String getCanonicalPath() throws IOException {
|
||||
return getCanonicalPathImpl();
|
||||
}
|
||||
|
||||
private String getCanonicalPathImpl() {
|
||||
String result = getAbsolutePath();
|
||||
|
||||
int numSeparators = 1;
|
||||
for (int i = 0; i < result.length(); i++) {
|
||||
if (result.charAt(i) == separatorChar) {
|
||||
numSeparators++;
|
||||
}
|
||||
}
|
||||
int[] sepLocations = new int[numSeparators];
|
||||
int rootLoc = 0;
|
||||
char[] newResult = new char[result.length() + 1];
|
||||
int newLength = 0;
|
||||
int lastSlash = 0;
|
||||
int foundDots = 0;
|
||||
sepLocations[lastSlash] = rootLoc;
|
||||
for (int i = 0; i <= result.length(); i++) {
|
||||
if (i < rootLoc) {
|
||||
newResult[newLength++] = result.charAt(i);
|
||||
} else {
|
||||
if (i == result.length() || result.charAt(i) == separatorChar) {
|
||||
if (i == result.length() && foundDots == 0) {
|
||||
break;
|
||||
}
|
||||
if (foundDots == 1) {
|
||||
/* Don't write anything, just reset and continue */
|
||||
foundDots = 0;
|
||||
continue;
|
||||
}
|
||||
if (foundDots > 1) {
|
||||
/* Go back N levels */
|
||||
lastSlash = lastSlash > (foundDots - 1) ? lastSlash - (foundDots - 1) : 0;
|
||||
newLength = sepLocations[lastSlash] + 1;
|
||||
foundDots = 0;
|
||||
continue;
|
||||
}
|
||||
sepLocations[++lastSlash] = newLength;
|
||||
newResult[newLength++] = (byte) separatorChar;
|
||||
continue;
|
||||
}
|
||||
if (result.charAt(i) == '.') {
|
||||
foundDots++;
|
||||
continue;
|
||||
}
|
||||
/* Found some dots within text, write them out */
|
||||
if (foundDots > 0) {
|
||||
for (int j = 0; j < foundDots; j++) {
|
||||
newResult[newLength++] = (byte) '.';
|
||||
}
|
||||
}
|
||||
newResult[newLength++] = result.charAt(i);
|
||||
foundDots = 0;
|
||||
}
|
||||
}
|
||||
// remove trailing slash
|
||||
if (newLength > (rootLoc + 1) && newResult[newLength - 1] == separatorChar) {
|
||||
newLength--;
|
||||
}
|
||||
return new String(newResult, 0, newLength);
|
||||
}
|
||||
|
||||
public TFile getCanonicalFile() throws IOException {
|
||||
return new TFile(getCanonicalPath());
|
||||
}
|
||||
|
||||
public String getParent() {
|
||||
int length = path.length();
|
||||
int firstInPath = 0;
|
||||
int index = path.lastIndexOf(separatorChar);
|
||||
if (index == -1 || path.charAt(length - 1) == separatorChar) {
|
||||
return null;
|
||||
}
|
||||
if (path.indexOf(separatorChar) == index && path.charAt(firstInPath) == separatorChar) {
|
||||
return path.substring(0, index + 1);
|
||||
}
|
||||
return path.substring(0, index);
|
||||
}
|
||||
|
||||
public TFile getParentFile() {
|
||||
String path = getParent();
|
||||
return path != null ? new TFile(getParent()) : null;
|
||||
}
|
||||
|
||||
public static TFile[] listRoots() {
|
||||
return new TFile[] { new TFile("/") };
|
||||
}
|
||||
|
||||
public String[] list() {
|
||||
VirtualFile virtualFile = findVirtualFile();
|
||||
if (virtualFile == null || !virtualFile.isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
VirtualFile[] entries = virtualFile.listFiles();
|
||||
String[] names = new String[entries.length];
|
||||
for (int i = 0; i < entries.length; ++i) {
|
||||
names[i] = entries[i].getName();
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
public TFile[] listFiles() {
|
||||
VirtualFile virtualFile = findVirtualFile();
|
||||
if (virtualFile == null || !virtualFile.isDirectory()) {
|
||||
return null;
|
||||
}
|
||||
VirtualFile[] entries = virtualFile.listFiles();
|
||||
TFile[] files = new TFile[entries.length];
|
||||
for (int i = 0; i < entries.length; ++i) {
|
||||
files[i] = new TFile(this, entries[i].getName());
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
public boolean exists() {
|
||||
return findVirtualFile() != null;
|
||||
}
|
||||
|
||||
public long lastModified() {
|
||||
VirtualFile virtualFile = findVirtualFile();
|
||||
return virtualFile != null ? virtualFile.lastModified() : 0;
|
||||
}
|
||||
|
||||
public long length() {
|
||||
VirtualFile virtualFile = findVirtualFile();
|
||||
return virtualFile != null && virtualFile.isFile() ? virtualFile.length() : 0;
|
||||
}
|
||||
|
||||
public boolean createNewFile() throws IOException {
|
||||
VirtualFile parentVirtualFile = getParentFile().findVirtualFile();
|
||||
if (parentVirtualFile == null) {
|
||||
throw new IOException("Can't create file " + getPath() + " since parent directory does not exist");
|
||||
}
|
||||
if (!parentVirtualFile.isDirectory()) {
|
||||
throw new IOException("Can't create file " + getPath() + " since parent path denotes regular file");
|
||||
}
|
||||
|
||||
if (parentVirtualFile.getChildFile(getName()) != null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return parentVirtualFile.createFile(getName()) != null;
|
||||
}
|
||||
|
||||
public boolean mkdir() {
|
||||
VirtualFile virtualFile = getParentFile().findVirtualFile();
|
||||
if (virtualFile == null || !virtualFile.isDirectory()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return virtualFile.createDirectory(getName()) != null;
|
||||
}
|
||||
|
||||
public boolean mkdirs() {
|
||||
String path = getCanonicalPathImpl();
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
|
||||
VirtualFile virtualFile = fs().getRootFile();
|
||||
int i = 0;
|
||||
while (i < path.length()) {
|
||||
int next = path.indexOf('/', i);
|
||||
if (next < 0) {
|
||||
next = path.length();
|
||||
}
|
||||
|
||||
String name = path.substring(i, next);
|
||||
VirtualFile child = virtualFile.getChildFile(name);
|
||||
if (child == null) {
|
||||
virtualFile = virtualFile.createDirectory(name);
|
||||
} else if (child.isFile()) {
|
||||
return false;
|
||||
} else {
|
||||
virtualFile = child;
|
||||
}
|
||||
|
||||
i = next + 1;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean delete() {
|
||||
VirtualFile virtualFile = findVirtualFile();
|
||||
if (virtualFile == null || (virtualFile.isDirectory() && virtualFile.listFiles().length == 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
virtualFile.delete();
|
||||
return true;
|
||||
}
|
||||
|
||||
public URI toURI() {
|
||||
String name = getAbsoluteName();
|
||||
try {
|
||||
if (!name.startsWith("/")) {
|
||||
// start with sep.
|
||||
return new URI("file", null, "/" + name, null, null);
|
||||
} else if (name.startsWith("//")) {
|
||||
return new URI("file", "", name, null);
|
||||
}
|
||||
return new URI("file", null, name, null, null);
|
||||
} catch (URISyntaxException e) {
|
||||
// this should never happen
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getAbsoluteName() {
|
||||
TFile f = getAbsoluteFile();
|
||||
String name = f.getPath();
|
||||
|
||||
if (f.isDirectory() && name.charAt(name.length() - 1) != separatorChar) {
|
||||
// Directories must end with a slash
|
||||
name = new StringBuilder(name.length() + 1).append(name).append('/').toString();
|
||||
}
|
||||
if (separatorChar != '/') { // Must convert slashes.
|
||||
name = name.replace(separatorChar, '/');
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof TFile)) {
|
||||
return false;
|
||||
}
|
||||
return path.equals(((File) obj).getPath());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return path.hashCode();
|
||||
}
|
||||
|
||||
private static String fixSlashes(String origPath) {
|
||||
int uncIndex = 0;
|
||||
int length = origPath.length();
|
||||
int newLength = 0;
|
||||
|
||||
boolean foundSlash = false;
|
||||
char[] newPath = origPath.toCharArray();
|
||||
for (int i = 0; i < length; i++) {
|
||||
char pathChar = newPath[i];
|
||||
if (pathChar == '/') {
|
||||
if (!foundSlash || i == uncIndex) {
|
||||
newPath[newLength++] = separatorChar;
|
||||
foundSlash = true;
|
||||
}
|
||||
} else {
|
||||
newPath[newLength++] = pathChar;
|
||||
foundSlash = false;
|
||||
}
|
||||
}
|
||||
if (foundSlash && (newLength > uncIndex + 1 || newLength == 2 && newPath[0] != separatorChar)) {
|
||||
newLength--;
|
||||
}
|
||||
|
||||
return new String(newPath, 0, newLength);
|
||||
}
|
||||
|
||||
private static String calculatePath(String dirPath, String name) {
|
||||
dirPath = fixSlashes(dirPath);
|
||||
if (!name.isEmpty() || dirPath.isEmpty()) {
|
||||
name = fixSlashes(name);
|
||||
|
||||
int separatorIndex = 0;
|
||||
while (separatorIndex < name.length() && name.charAt(separatorIndex) == separatorChar) {
|
||||
separatorIndex++;
|
||||
}
|
||||
if (separatorIndex > 0) {
|
||||
name = name.substring(separatorIndex, name.length());
|
||||
}
|
||||
|
||||
if (!dirPath.isEmpty() && dirPath.charAt(dirPath.length() - 1) == separatorChar) {
|
||||
return dirPath + name;
|
||||
}
|
||||
return dirPath + separatorChar + name;
|
||||
}
|
||||
|
||||
return dirPath;
|
||||
}
|
||||
|
||||
VirtualFile findVirtualFile() {
|
||||
String path = getCanonicalPathImpl();
|
||||
if (path.startsWith("/")) {
|
||||
path = path.substring(1);
|
||||
}
|
||||
|
||||
VirtualFile virtualFile = fs().getRootFile();
|
||||
int i = 0;
|
||||
while (i < path.length()) {
|
||||
int next = path.indexOf('/', i);
|
||||
if (next < 0) {
|
||||
next = path.length();
|
||||
}
|
||||
|
||||
virtualFile = virtualFile.getChildFile(path.substring(i, next));
|
||||
if (virtualFile == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
i = next + 1;
|
||||
}
|
||||
|
||||
return virtualFile;
|
||||
}
|
||||
|
||||
VirtualFile findParentFile() {
|
||||
return new TFile(getCanonicalPathImpl()).getParentFile().findVirtualFile();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
package org.teavm.classlib.java.io;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import org.teavm.classlib.fs.VirtualFile;
|
||||
|
||||
public class TFileInputStream extends InputStream {
|
||||
private InputStream underlyingStream;
|
||||
|
||||
public TFileInputStream(TFile file) throws FileNotFoundException {
|
||||
VirtualFile virtualFile = file.findVirtualFile();
|
||||
if (virtualFile == null || virtualFile.isDirectory()) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
underlyingStream = virtualFile.read();
|
||||
if (underlyingStream == null) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b) throws IOException {
|
||||
return underlyingStream.read(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read(byte[] b, int off, int len) throws IOException {
|
||||
return underlyingStream.read(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long skip(long n) throws IOException {
|
||||
return underlyingStream.skip(n);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int available() throws IOException {
|
||||
return underlyingStream.available();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
underlyingStream.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int read() throws IOException {
|
||||
return underlyingStream.read();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.teavm.classlib.java.io;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class TFileNotFoundException extends IOException {
|
||||
public TFileNotFoundException() {
|
||||
}
|
||||
|
||||
public TFileNotFoundException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Copyright 2017 Alexey Andreev.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
package org.teavm.classlib.java.io;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import org.teavm.classlib.fs.VirtualFile;
|
||||
|
||||
public class TFileOutputStream extends OutputStream {
|
||||
private OutputStream underlyingStream;
|
||||
|
||||
public TFileOutputStream(TFile file) throws FileNotFoundException {
|
||||
this(file, false);
|
||||
}
|
||||
|
||||
public TFileOutputStream(TFile file, boolean append) throws FileNotFoundException {
|
||||
VirtualFile virtualFile = file.findVirtualFile();
|
||||
if (virtualFile == null) {
|
||||
VirtualFile parentVirtualFile = file.findParentFile();
|
||||
if (parentVirtualFile != null && parentVirtualFile.isDirectory()) {
|
||||
virtualFile = parentVirtualFile.createFile(file.getName());
|
||||
}
|
||||
}
|
||||
if (virtualFile == null || virtualFile.isDirectory()) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
underlyingStream = virtualFile.write(append);
|
||||
if (underlyingStream == null) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b) throws IOException {
|
||||
underlyingStream.write(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int len) throws IOException {
|
||||
underlyingStream.write(b, off, len);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void flush() throws IOException {
|
||||
underlyingStream.flush();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
underlyingStream.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(int b) throws IOException {
|
||||
underlyingStream.write(b);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user