FileTransfer "Saved file:" followed by FileNotFoundException - java

My app downloads a zip file from a remote webserver, then extracts it.
The javascript successfully calls FileTransfer, which logs:
FileTransfer Saved file: file:///data/data/com.yadda.yadda/update.zip
As part of the success function, javascript calls my custom update plugin which immediately tests for the file:
Context ctx = this.cordova.getActivity().getBaseContext();
File update = new File(ctx.getFilesDir(),"update.zip");
if(!update.exists()) Log.w("File not found",update.getAbsolutePath());
The log for that last line is:
File Not Found /data/data/com.yadda.yadda/update.zip
Later in a try/catch block I have an InputStream variable created and one of the catch blocks is a FileNotFoundException which is firing every time.
Begin edit - more info
The FileNotFoundException has an interesting bit. The file path is wrong - even though I'm sending the same "update" variable to create the FileInputStream
InputStream fileis = new FileInputStream(update);
And the interesting bit of the exception:
Caused by: java.io.FileNotFoundException: /data/data/com.yadda.yadda/files/update.zip
End edit
What is going wrong here? Cordova logs that the file transfer completed and the file was saved, but then the file doesn't exist when I test for it! When I create the FileInputStream, why is the path different, causing the exception?
What am I missing? Everything works fine in the IOS version of the app.
Edit 2: per request, I browsed the device filesystem and found that update.zip does indeed exist in /data/user/0/com.yadda.yadda

OK, somewhere there is a bug. I'm inclined to believe it's a bug in getAbsolutePath() because I'm seeing consistent operation elsewhere.
When I create the "File update" variable, then immediately test and log the update.getAbsolutePath() - it shows the correct path. But when I attempt to create the FileInputStream, the path is different (+ /files/)
So, a little searching and I found that in order to access the application data directory (without /files) I must send a different directory with the new File command. Here's what it looks like:
File update = new File(ctx.getApplicationInfo().dataDir,"update.zip");
Obtaining the dir with getFilesDir()
ctx.getFilesDir() = /data/data/com.yadda.yadda/files
Obtaining the correct dir
ctx.getApplicationInfo().dataDir = /data/data/com.yadda.yadda

Related

How to avoid resource leaks using FileSystemResource in Drools 7.73.0?

I'm currently working with Drools 7.73.0, and seem to be running into a file lock issue when adding a KieModule to KieServices repository, using just a file path to a kjar file that exists on a local file system. It appears that the file path resource needs to be closed after adding it to the repository, however there does not appear to be a close method available.
The code I am currently using to load the kieModule from the kjar file into the repository is as follows:
String pathKjar = "pathToKjarFile.kjar";
...
KieServices ks = KieServices.Factory.get();
Resource resource = ks.getResources().newFileSystemResource(pathKjar);
ks.getRepository().addKieModule(resource); //<-- pathKjar is locked at this line
KieContainer kc = ks.newKieContainer(releaseId);
...
File testFile = new File(pathKjar);
testFile.delete(); //<-- pathKjar is still locked, delete always returns false
As noted above, the line of code ks.getRepository().addKieModule(resource); puts a lock on the resource, while it is in use, however I have not been able to find a way to close the resource afterwards, leaving the resource open.
What is the proper way to close the Resource?
Note, I was able to use an inputstream to accomplish the same thing, and the resource does close successfully using that method, and all seems to work as expected. This question is solely on how to properly use newFileSystemResource with a String path to the file location, and ensure there are no resource leaks.
I've tried to reproduce the problem that you're reporting but in all honesty I couldn't. In particular I quickly modified this example by putting the jar file returned by the getFile() method into a variable before passing it to the newFileSystemResource() one. Then trying to delete that file at the end of the test works as expected for me and returns true.
In case this problem persists I suggest you to open a ticket in the Drools tracking system and attach a complete reproducer.

How to delete file in Java if locked by a process?

I decided to post a new question on this since none of the existing posts lead to me a solution. Mine is a Spring Boot application and here is the service:
public String fetchPrediction(MultipartFile file) throws IOException, InterruptedException {
File convFile = new File( System.getProperty("user.dir")+"/"+file.getOriginalFilename());
convFile.setWritable(true);
file.transferTo(convFile);
INDArray array = new CustomerLossPrediction().generateOutput(convFile);
Files.delete(Paths.get(convFile.getPath()));
return array.toString();
}
File deletion isn't happening and it gets stored at user home directory:
Found that the file is being used by the Java process. How can I delete this file once execution is completed? Is there a better approach here rather than writing to a file? Some of you would bring up writing to OutputStream here, but note that I need to work with MultipartFile in order to have file upload functionality.
I don't know if that's possible but I think you can rename the file to a randomly generated string then afterwards lock, read, unlock then delete the renamed file. In theory, another program could guess the filename and read the file just after it's unlocked but before it is deleted. But in practice, you'll probably be fine.

Upload retry mechanism using JSch library

I have a file to upload (say abc.pdf). Very first time I want to upload this file as a temp file (say abc.pdf.temp). Then , if the file is successfully transferred (fully transferred) then I need to rename it to its original name (abc.pdf). But if the file is not fully transferred then I need to delete the temp file that I uploaded initially since I don't want to keep a corrupted file in the server. Is this achievable to do using this JSch library. Below is the sample code. Does this code make sense to achieve this?
Sample Code:
originalFile = 'abc.pdf';
tempFile = 'abc.pdf.temp';
fileInputStream = createobject("java", "java.io.FileInputStream").init('C:\abc.pdf');
SftpChannel.put(fileInputStream,tempFile);
// Comparing remote file size with local file
if(SftpChannel.lstat(tempFile).getSize() NEQ localFileSize){
// Allow to Resume the file transfer since the file size is different
SftpChannel.put(fileInputStream,tempFile,SftpChannel.RESUME);
if(SftpChannel.lstat(tempFile).getSize() NEQ localFileSize){
// Check again if the file is not fully transferred (During RESUME) then
// deleting the file since dont want to keep a corrupted file in the server.
SftpChannel.rm(tempFile);
}
}else{//assuming file is fully transferred
SftpChannel.rename(tempFile ,originalFile);
}
It's very unlikely that after the put finishes without throwing, the file size won't match. It can hardly happen. Even if it happens, it makes little sense to call RESUME. If something catastrophic goes wrong that is not detected by put, RESUME is not likely to help.
And even if you want to try with RESUME, it does not make sense to try once. If you believe it makes sense to retry, you have to keep retrying until you succeed, not only once.
You should catch exception and resume/delete/whatever. That's the primary recovery mechanism. This is 100x more likely to happen than 1.

Directory & File Creation on Android File System

I'm trying to create a directory hierarchy and then copy a file from my assets into the newly created directory. I've used the code samples offered here on stackoverflow but I'm not getting anywhere. Essentially my code goes like this:
InputStream in = getAssets.open(mydb.sqlite);
File dir = new File("/data/data/my.package/databases/");
dir.mkdirs();
out = new FileOutputStream("/data/data/my.package/databases/mydb.sqlite");
while ((len = in.read(buffer)) > 0)
{
out.write(buffer, 0, len);
}
out.flush();
out.close();
in.close
This is all done within the main activity on first launch and of course should only be done once. Before the code runs, the only directory that exists is /data/. Yes, it is a database file but that shouldn't matter at this point since I'm just copying the file and haven't yet tried to access it with the database code.
The code doesn't throw any exceptions, and dir.mkdirs() returns true. Regardless, the directories are not created and the file is not copied. I have added the permissions line for WRITE_EXTERNAL_STORAGE to my manifest as has been suggested in several places, FWIW. I can step through the code and everything appears to be fine. But of course it's not.
What do I need to be looking for here? File permissions problems? Why does the code think everything is there (ie, when it gets to the copy code, it doesn't throw FileNotFoundException) but in reality there's nothing on the file system?
Edit: Here's what I've learned. getDir() creates the directory in /data/data/my.package/app_*. Not sure why it uses this prefix on the directory name. This won't work if you need to put something in a standard location such as databases/ or files/.
Use openFileOutput instead as /data/data is internal storage and you should only use the Android APIs to get a file handle there. See: http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
Edit:
/data/data/my.package is handled by openFileOutput/getDir so you would create your directory with getDir('databases',MODE_PRIVATE) and create your file there.
Edit2:
From getDir documentation:
You can use the returned File object to create and access files in this directory.

FileInputStream and FileNotFound Exception

I am trying to retrieve a jrxml file in a relative path using the following java code:
String jasperFileName = "/web/WEB-INF/reports/MemberOrderListReport.jrxml";
File report = new File(jasperFileName);
FileInputStream fis = new FileInputStream(report);
However, most probably I didn't succeed in defining the relative path and get an java.io.FileNotFoundException: error during the execution.
Since I am not so experienced in Java I/O operations, I didn't solve my problem. Any helps or ideas are welcomed.
You're trying to treat the jrxml file as an object on the file-system, but that's not applicable inside a web application.
You don't know how or where your application will be deployed, so you can't point a File at it.
Instead you want to use getResourceAsStream from the ServletContext. Something like:
String resourceName = "/WEB-INF/reports/MemberOrderListReport.jrxml"
InputStream is = getServletContext().getResourceAsStream(resourceName);
is what you're after.
You should place 'MemberOrderListReport.jrxml' in classpath, such as it being included in a jar placed in web-inf\lib or as a file in web-inf\classes.
The you can read the file using the following code:
InputStream is=YourClass.class.getClassLoader().getResourceAsStream("MemberOrderListReport.jrxml");
String jasperFileName = "/web/WEB-INF/reports/MemberOrderListReport.jrxml";
Simple. You don't have a /web/WEB-INF/reports/MemoberOrderListReport.jrxml file on your computer.
You are clearly executing in a web-app environment and expecting the system to automatically resolve that in the context of the web-app container. It doesn't. That's what getRealPath() and friends are for.
check that your relative base path is that one you think is:
File f = new File("test.txt");
System.out.println(f.getAbsoluteFile());
I've seen this kind of problem many times, and the answer is always the same...
The problem is the file path isn't what you think it is. To figure it out, simply add this line after creating the File:
System.out.println(report.getAbsolutePath());
Look at the output and you immediately see what the problem is.

Categories

Resources