Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File api nio #9

Open
wants to merge 18 commits into
base: new-file-api
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,9 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.IOException;
import java.nio.channels.SeekableByteChannel;

/**
* Can be used to close a file object.
Expand All @@ -55,10 +54,8 @@ public class Close extends AbstractNativeFunction {
@Override
public BValue[] execute(Context context) {
BStruct struct = (BStruct) getRefArgument(context, 0);
BufferedInputStream is = (BufferedInputStream) struct.getNativeData("inStream");
BufferedOutputStream os = (BufferedOutputStream) struct.getNativeData("outStream");
closeQuietly(is);
closeQuietly(os);
SeekableByteChannel channel = (SeekableByteChannel) struct.getNativeData("channel");
closeQuietly(channel);
return VOID_RETURN;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,16 @@
import org.ballerinalang.natives.annotations.BallerinaAnnotation;
import org.ballerinalang.natives.annotations.BallerinaFunction;
import org.ballerinalang.util.exceptions.BallerinaException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Closeable;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.file.CopyOption;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;

/**
* Copies a file from a given location to another.
Expand All @@ -58,80 +58,65 @@
value = "The location where the File should be pasted") })
public class Copy extends AbstractNativeFunction {

private static final Logger logger = LoggerFactory.getLogger(Copy.class);

@Override
public BValue[] execute(Context context) {

BStruct source = (BStruct) getRefArgument(context, 0);
BStruct destination = (BStruct) getRefArgument(context, 1);

File sourceFile = new File(source.getStringField(0));
File destinationFile = new File(destination.getStringField(0));
Path sourcePath = Paths.get(source.getStringField(0));
Path destinationPath = Paths.get(destination.getStringField(0));

if (!sourceFile.exists()) {
throw new BallerinaException("failed to copy file: file not found: " + sourceFile.getPath());
if (!Files.exists(sourcePath)) {
throw new BallerinaException("failed to copy file: file not found: " + sourcePath);
}
File parent = destinationFile.getParentFile();
if (parent != null && !parent.exists() && !parent.mkdirs()) {
throw new BallerinaException("failed to copy file: cannot create directory: " + parent.getPath());

Path parent = destinationPath.getParent();
if (parent != null && !Files.exists(parent)) {
try {
Files.createDirectories(parent);
} catch (IOException e) {
throw new BallerinaException("failed to copy file: cannot create directory: " + parent);
}
}
if (!copy(sourceFile, destinationFile)) {
throw new BallerinaException("failed to copy file: " + sourceFile.getPath());

try {
Files.walkFileTree(sourcePath, new CopyDirVisitor(sourcePath, destinationPath,
new CopyOption[] { StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.COPY_ATTRIBUTES }));
} catch (IOException e) {
throw new BallerinaException("failed to copy file: " + sourcePath);
}

return VOID_RETURN;
}

private boolean copy(File src, File dest) {
private static class CopyDirVisitor extends SimpleFileVisitor<Path> {
private final Path fromPath;
private final Path toPath;
private final CopyOption[] copyOptions;

InputStream in = null;
OutputStream out = null;
try {
if (src.isDirectory()) {
if (!dest.exists() && !dest.mkdir()) {
return false;
}
String files[] = src.list();
if (files == null) {
return false;
}
for (String file : files) {
File srcFile = new File(src, file);
File destFile = new File(dest, file);
//recursive copy
if (!copy(srcFile, destFile)) {
return false;
}
}
} else {
in = new FileInputStream(src);
out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;

while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
}
return true;
} catch (IOException e) {
throw new BallerinaException("failed to copy file: " + e.getMessage(), e);
} finally {
if (in != null) {
closeQuietly(in);
}
if (out != null) {
closeQuietly(out);
private CopyDirVisitor(Path fromPath, Path toPath, CopyOption[] copyOptions) {
this.fromPath = fromPath;
this.toPath = toPath;
this.copyOptions = copyOptions;
}

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
Path targetPath = toPath.resolve(fromPath.relativize(dir));
if (!Files.exists(targetPath)) {
Files.createDirectory(targetPath);
}

return FileVisitResult.CONTINUE;
}
}

private void closeQuietly(Closeable resource) {
try {
resource.close();
} catch (IOException e) {
logger.error("Exception during Resource.close()", e);
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.copy(file, toPath.resolve(fromPath.relativize(file)), copyOptions);
return FileVisitResult.CONTINUE;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,13 @@
import org.ballerinalang.natives.annotations.BallerinaFunction;
import org.ballerinalang.util.exceptions.BallerinaException;

import java.io.File;
import java.io.IOException;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;

/**
* Deletes a file from a given location.
Expand All @@ -46,34 +52,40 @@
value = "File that should be deleted") })
public class Delete extends AbstractNativeFunction {

@Override
@Override
public BValue[] execute(Context context) {

BStruct target = (BStruct) getRefArgument(context, 0);
File targetFile = new File(target.getStringField(0));
if (!targetFile.exists()) {
throw new BallerinaException("failed to delete file: file not found: " + targetFile.getPath());
Path targetPath = Paths.get(target.getStringField(0));
if (!Files.exists(targetPath)) {
throw new BallerinaException("error: ballerina.lang.errors:Error, message: failed to delete file:" +
" file not found: " + targetPath.toString());
}
if (!delete(targetFile)) {
throw new BallerinaException("failed to delete file: " + targetFile.getPath());
try {
delete(targetPath);
} catch (IOException e) {
throw new BallerinaException("failed to delete file: " + targetPath.toString());
}
return VOID_RETURN;
}

private boolean delete(File targetFile) {

String[] entries = targetFile.list();
if (entries != null && entries.length != 0) {
for (String s : entries) {
File currentFile = new File(targetFile.getPath(), s);
if (currentFile.isDirectory()) {
delete(currentFile);
} else if (!currentFile.delete()) {
return false;
}
}
private void delete(Path targetPath) throws IOException {
if (Files.isDirectory(targetPath)) {
Files.walkFileTree(targetPath, new DeleteDirVisitor());
} else {
Files.delete(targetPath);
}
return targetFile.delete();
}

private static class DeleteDirVisitor extends SimpleFileVisitor<Path> {

@Override public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
Files.delete(file);
return FileVisitResult.CONTINUE;
}

@Override public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
Files.delete(dir);
return FileVisitResult.CONTINUE;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,11 @@
import org.ballerinalang.natives.annotations.BallerinaFunction;
import org.ballerinalang.util.exceptions.BallerinaException;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;

/**
* Moves a file from a given location to another.
Expand All @@ -53,21 +57,27 @@ public class Move extends AbstractNativeFunction {

@Override
public BValue[] execute(Context context) {

BStruct source = (BStruct) getRefArgument(context, 0);
BStruct destination = (BStruct) getRefArgument(context, 1);

File sourceFile = new File(source.getStringField(0));
if (!sourceFile.exists()) {
throw new BallerinaException("failed to move file: file not found: " + sourceFile.getPath());
Path sourcePath = Paths.get(source.getStringField(0));
if (!Files.exists(sourcePath)) {
throw new BallerinaException("failed to move file: file not found: " + sourcePath);
}
File destinationFile = new File(destination.getStringField(0));
File parent = destinationFile.getParentFile();
if (parent != null && !parent.exists() && !parent.mkdirs()) {
throw new BallerinaException("failed to move file: cannot create directory: " + parent.getPath());
Path destinationPath = Paths.get(destination.getStringField(0));
Path parent = destinationPath.getParent();
if (parent != null && !Files.exists(parent)) {
try {
Files.createDirectories(parent);
} catch (IOException e) {
throw new BallerinaException("failed to move file: cannot create directory: " + parent);
}
}
if (!sourceFile.renameTo(destinationFile)) {
throw new BallerinaException("failed to move file: " + sourceFile.getPath());
try {
Files.move(sourcePath, destinationPath, StandardCopyOption.REPLACE_EXISTING,
StandardCopyOption.ATOMIC_MOVE);
} catch (IOException e) {
throw new BallerinaException("failed to move file: " + sourcePath);
}
return VOID_RETURN;
}
Expand Down
Loading