mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -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