writing temporary files in Tomcat - java

I need to create temporary directory but I'm always getting access denied when I try to create a file into the temporary directory.
java.io.FileNotFoundException: C:\tmpDir7504230706415790917 (Access Denied)
here's my code:
public static File createTempDir() throws IOException {
File temp = File.createTempFile("tmpDir", "", new File("C:/"));
temp.delete();
temp.mkdir();
return temp;
}
public File createFile(InputStream inputStream, File tmpDir ) {
File file = null;
if (tmpDir.isDirectory()) {
try {
file = new File(tmpDir.getAbsolutePath());
// write the inputStream to a FileOutputStream
OutputStream out = new FileOutputStream(file);
int read = 0;
byte[] bytes = new byte[1024];
while ((read = inputStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
inputStream.close();
out.flush();
out.close();
System.out.println("New file created!");
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
return file;
}
I'm working on a web application and I'm using tomcat. Is there a way to create temporary file on tomcat server memory? I know that's bizarre, but I don't know ... maybe it's possible.

You could use Tomcat's temp folder.
If you use
<%=System.getProperty("java.io.tmpdir")%>
in a JSP you can get path to it.

This line in your code says create a file whose name starts with text "tmpDir" in the directory "C:\". That is not what you want.
File temp = File.createTempFile("tmpDir","",new File("C:/"));
The operating system is properly disallowing that because C:\ is a protected directory. Use the following instead:
File temp = File.createTempFile("tmp",null);
This will let Java determine the appropriate temporary directory. Your file will have the simple prefix "tmp" followed by some random text. You can change "tmp" to anything meaningful for your app, in case you need to manually clean out these temp files and you want to be able to quickly identify them.

You usually cannot write onto C:\ directly due to the default permission setting. I sometime have permission issue for doing so. However, you can write your temporary file in your user folder. Usually, this is C:\Documents and Settings\UserName\ on XP or C:\Users\UserName\ on vista and Windows 7. A tool called SystemUtils from Apache Lang can be very useful if you want to get the home directory depending on OS platform.
For example:
SystemUtils.getUserDir();
SystemUtils.getUserHome();
Update
Also, you create a temp file object but you call mkdir to make it into a directory and try to write your file to that directory object. You can only write a file into a directory but not on the directory itself. To solve this problem, either don't call temp.mkdir(); or change this file=new File(tmpDir.getAbsolutePath()); to file=new File(tmpDir, "sometempname");

On Linux with tomcat7 installation:
So if you are running web application this is the temp directory Tomcat uses for the creation of temporary files.
TOMCAT_HOME/temp
In my case TOMCAT_HOME => /usr/share/tomcat7
If you are running Java program without tomcat, by default it uses /tmp directory.
Not sure if it affects but i ran this command too.
chmod 777 on TOMCAT_HOME/temp

Related

Creating a file in linux server Java

i upload a csv file from client side and i want to create this file in server side.
Here is my function
public void uploadFile(FileUploadEvent e) throws IOException{
UploadedFile uploadedCsv=e.getFile();
String filePath="//ipAdress:/home/cg/Temp/input/ressource.csv";
byte[] bytes=null;
if(uploadedCsv != null){
bytes=uploadedCsv.getContents();
BufferedOutputStream stream = new BufferedOutputStream(new FileOutputStream(new File(filePath)));
String filename = FilenameUtils.getName(uploadedCsv.getFileName());
stream.write(bytes);
stream.close();
}
}
When I want to write the file I get this exception (No such file or directory)
SEVERE: java.io.FileNotFoundException: /ipAdress:/home/cg/Temp/input/ressource.csv (No such file or directory)
Knowing that the / home / cg / Temp / input path is created on the server.
Could you try:
String filePath="////ipAdress/home/cg/Temp/input/ressource.csv";
Instead of:
String filePath="//ipAdress:/home/cg/Temp/input/ressource.csv";
And this:
new File(new URI(filePath))
Instead of:
new File(filePath)
Or you can use jcif API How can I open a UNC path from Linux in Java?
I would use the <file>.mkdirs(); at one level above the file itself.
So do String filePath="//ipAdress:/home/cg/Temp/input
File directory = new File(filePath);
directory.mkdirs();
You can then make the file
File tempFile = new File(directory + "/ressource.csv);
Or a cleaner solution all around is just use Files.createTempFile(prefix, suffix) this will create a file in the temp directory of the system.
The reason that your code does not work is that you are trying to use a UNC pathname on Linux. Linux does not support UNC pathnames ... natively. They are a Windows-ism.
Here's your example
"//ipAdress:/home/cg/Temp/input/ressource.csv";
If you try to use that on Linux, the OS will look for a directory in the root directory of the file system. The directory it will look for will have the name ipaddress: ... noting that there is a colon in the directory name!
That will most likely fail ... because no directory with that name exists in the / directory.. And the exception message you are getting is consistent with this diagnosis.
If you are doing this because you are trying to push files out to other systems then you are going to do it some other way. For example:
Use NFS and mount the other system's file systems on the server.
Use a Java implementation of UNC names; e.g. How can I open a UNC path from Linux in Java?
(Which ever way you do it, there are security issues to consider!)
trying this new File(new URI(filePath)) instead of new File(filePath) i get this erreur. SEVERE: java.lang.IllegalArgumentException: URI is not absolute
It won't work. A UNC name is NOT a valid URL or URI.
I have found a solution for this problem, but it's not smart and still and it works
String fileName="ressource.csv";
File f = new File(System.getProperty("user.home") + "/Temp/input",fileName);
if (f.exists() && !f.canWrite())
throw new IOException("erreur " + f.getAbsolutePath());
if (!f.exists())
Files.createFile(f.toPath());
if (!f.isFile()) {
f.createNewFile(); // Exception here
} else {
f.setLastModified(System.currentTimeMillis());
}
Pending a more intelligent solution

Get file in the resources folder in Java

I want to read the file in my resource folder in my Java project. I used the following code for that
MyClass.class.getResource("/myFile.xsd").getPath();
And I wanted to check the path of the file. But it gives the following path
file:/home/malintha/.m2/repository/org/wso2/carbon/automation/org.wso2.carbon.automation.engine/4.2.0-SNAPSHOT/org.wso2.carbon.automation.engine-4.2.0-SNAPSHOT.jar!/myFile.xsd
I get the file path in the maven repository dependency and it is not getting the file. How can I do this?
You need to give the path of your res folder.
MyClass.class.getResource("/res/path/to/the/file/myFile.xsd").getPath();
Is your resource directory in the classpath?
You are not including resource directory in your path:
MyClass.class.getResource("/${YOUR_RES_DIR_HERE}/myFile.xsd").getPath();
A reliable way to construct a File instance from the resource folder is it to copy the resource as a stream into a temporary File (temp file will be deleted when the JVM exits):
public static File getResourceAsFile(String resourcePath) {
try {
InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream(resourcePath);
if (in == null) {
return null;
}
File tempFile = File.createTempFile(String.valueOf(in.hashCode()), ".tmp");
tempFile.deleteOnExit();
try (FileOutputStream out = new FileOutputStream(tempFile)) {
//copy stream
byte[] buffer = new byte[1024];
int bytesRead;
while ((bytesRead = in.read(buffer)) != -1) {
out.write(buffer, 0, bytesRead);
}
}
return tempFile;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
It is not possible to access resources of other maven modules. So you need to provide your resource myFile.xsd in your src/main/resources or src/test/resources folder.
The path is correct, though not on the file system, but inside the jar. That is, because the jar was running. A resource never is guaranteed to be a File.
However if you do not want to use resources, you can use a zip file system. However Files.copy would suffice to copy the file outside the jar. Modifying the file inside the jar is a bad idea. Better use the resource as "template" to make an initial copy in the user's home (sub-)directory (System.getProperty("user.home")).
In maven project, lets assume that, we have the file whose name is "config.cnf" and it's location is below.
/src
/main
/resources
/conf
config.cnf
In IDE (Eclipse), I access this file by using ClassLoader.getResource(..) method, but if I ran this application by using jar, I always across "File not found" exception. Finally, I wrote a method which accessing the file by looking at where app works.
public static File getResourceFile(String relativePath)
{
File file = null;
URL location = <Class>.class.getProtectionDomain().getCodeSource().getLocation();
String codeLoaction = location.toString();
try{
if (codeLocation.endsWith(".jar"){
//Call from jar
Path path = Paths.get(location.toURI()).resolve("../classes/" + relativePath).normalize();
file = path.toFile();
}else{
//Call from IDE
file = new File(<Class>.class.getClassLoader().getResource(relativePath).getPath());
}
}catch(URISyntaxException ex){
ex.printStackTrace();
}
return file;
}
If you call this method by sending "conf/config.conf" param, you access this file from both jar and IDE.

Do I need to delete tmp files created by my java application?

I output several temporary files in my application to tmp directories but was wondering if it is best practise that I delete them on close or should I expect the host OS to handle this for me?
I am pretty new to Java, I can handle the delete but want to keep the application as multi-OS and Linux friendly as possible. I have tried to minimise file deletion if I don't need to do it.
This is the method I am using to output the tmp file:
try {
java.io.InputStream iss = getClass().getResourceAsStream("/nullpdf.pdf");
byte[] data = IOUtils.toByteArray(iss);
iss.read(data);
iss.close();
String tempFile = "file";
File temp = File.createTempFile(tempFile, ".pdf");
FileOutputStream fos = new FileOutputStream(temp);
fos.write(data);
fos.flush();
fos.close();
nopathbrain = temp.getAbsolutePath();
System.out.println(tempFile);
System.out.println(nopathbrain);
} catch (IOException ex) {
ex.printStackTrace();
System.out.println("TEMP FILE NOT CREATED - ERROR ");
}
createTempFile() only creates a new file with a unique name, but does not mark it for deletion. Use deleteOnExit() on the created file to achieve that. Then, if the JVM shuts down properly, the temporary files should be deleted.
edit:
Sample for creating a 'true' temporary file in java:
File temp = File.createTempFile("temporary-", ".pdf");
temp.deleteOnExit();
This will create a file in the default temporary folder with a unique random name (temporary-{randomness}.pdf) and delete it when the JVM exits.
This should be sufficient for programs with a short to medium run time (e.g. scripts, simple GUI applications) that do sth. and then exit. If the program runs longer or indefinitely (server application, a monitoring client, ...) and the JVM won't exit, this method may clog the temporary folder with files. In such a situation the temporary files should be deleted by the application, as soon as they are not needed anymore (see delete() or Files helper class in JDK7).
As Java already abstracts away OS specific file system details, both approaches are as portable as Java. To ensure interoperability have a look at the new Path abstraction for file names in Java7.

Hosting an executable within Android application

I am working on an Android application that depends on an ELF binary:
our Java code interacts with this binary to get things done. This
runtime needs to be started and terminated on Application startup and
application exit / on demand.
Questions:
I am assuming that we will be able to execute this binary using the
Runtime.exec() API. Is there any constraints as to where I
need to be putting my library in the folder structure? How would the system runtime locate this executable? Is there some sort of class path setting?
Since the application has dependencies on this Runtime, I was
thinking of wrapping it around a service so that it can be started or
stopped as required. What is the best way to handle such executables
in Android project?
What are other alternatives, assuming that I do not have source code for this executable?
Please advice.
Thanks.
1) No, there should be no constrains, besides those that access system files and thus require root. The best place would be straight to /data/data/[your_package_name] to avoid polluting elsewhere.
2) A very thorough discussion about compiling against native libraries can be found here: http://www.aton.com/android-native-libraries-for-java-applications/ . Another option is a cross-compiler for arm (here is the one used to compile the kernel, it's free: http://www.codesourcery.com/sgpp/lite/arm ). If you plan to maintain a service that executes your cammand, be warned that services can be stopped and restarted by android at any moment.
3) Now, if you don't have the source code, I hope that your file is at least compiled as an arm executable. If not, I don't see how you could even run it.
You will execute the file by running the following commands in your java class:
String myExec = "/data/data/APPNAME/FILENAME";
Process process = Runtime.getRuntime().exec(myExec);
DataOutputStream os = new DataOutputStream(process.getOutputStream());
DataInputStream osRes = new DataInputStream(process.getInputStream());
I know nothing about your executable, so you may or may not need to actually get the inputStream and outputStream.
I am assuming that running adb to push the binary file is out of the question, so
I was looking for a neat way to package it. I found a great post about including an executable in your app. Check it out here:
http://gimite.net/en/index.php?Run%20native%20executable%20in%20Android%20App
The important part is this one (emphasis mine):
From Android Java app, using assets folder
Include the binary in the assets folder.
Use getAssets().open(FILENAME) to get an InputStream.
Write it to /data/data/APPNAME (e.g. /data/data/net.gimite.nativeexe), where your application has access to write files and make it executable.
Run /system/bin/chmod 744 /data/data/APPNAME/FILENAME using the code above.
Run your executable using the code above.
The post uses the assets folder, insted of the raw folder that android suggests for static files:
Tip: If you want to save a static file in your application at compile time, save the file in your project res/raw/ directory. You can open it with openRawResource(), passing the R.raw. resource ID. This method returns an InputStream that you can use to read the file (but you cannot write to the original file).
To access the data folder, you can follow the instructions here:
http://developer.android.com/guide/topics/data/data-storage.html#filesInternal
Also, there's the File#setExecutable(boolean); method that should works instead of the shell command.
So, putting everything together, I would try:
InputStream ins = context.getResources().openRawResource (R.raw.FILENAME)
byte[] buffer = new byte[ins.available()];
ins.read(buffer);
ins.close();
FileOutputStream fos = context.openFileOutput(FILENAME, Context.MODE_PRIVATE);
fos.write(buffer);
fos.close();
File file = context.getFileStreamPath (FILENAME);
file.setExecutable(true);
Of course, all this should be done only once after installation. You can have a quick check inside onCreate() or whatever that checks for the presence of the file and executes all this commands if the file is not there.
Let me know if it works. Good luck!
Here is a complete guide for how to package and run the executable. I based it on what I found here and other links, as well as my own trial and error.
1.) In your SDK project, put the executable file in your /assets folder
2.) Programmatically get the String of that files directory (/data/data/your_app_name/files) like this
String appFileDirectory = getFilesDir().getPath();
String executableFilePath = appFileDirectory + "/executable_file";
3.) In your app's project Java code: copy the executable file from /assets folder into your app's "files" subfolder (usually /data/data/your_app_name/files) with a function like this:
private void copyAssets(String filename) {
AssetManager assetManager = getAssets();
InputStream in = null;
OutputStream out = null;
Log.d(TAG, "Attempting to copy this file: " + filename); // + " to: " + assetCopyDestination);
try {
in = assetManager.open(filename);
Log.d(TAG, "outDir: " + appFileDirectory);
File outFile = new File(appFileDirectory, filename);
out = new FileOutputStream(outFile);
copyFile(in, out);
in.close();
in = null;
out.flush();
out.close();
out = null;
} catch(IOException e) {
Log.e(TAG, "Failed to copy asset file: " + filename, e);
}
Log.d(TAG, "Copy success: " + filename);
}
4.) Change the file permissions on executable_file to actually make it executable. Do it with Java calls:
File execFile = new File(executableFilePath);
execFile.setExecutable(true);
5.) Execute the file like this:
Process process = Runtime.getRuntime().exec(executableFilePath);
Note that any files referred to here (such as input and output files) must have their full path Strings constructed. This is because this is a separate spawned process and it has no concept of what the "pwd" is.
If you want to read the command's stdout you can do this, but so far it's only working for me for system commands (like "ls"), not the executable file:
BufferedReader reader = new BufferedReader(
new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[4096];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
reader.close();
process.waitFor();
Log.d(TAG, "output: " + output.toString());
For executing binary file starting from Android 10 it's only possible from read-only folder. It means that you should pack binary with your app. Android doc
Put android:extractNativeLibs="true" into AndroidManifest;
Put your binary to src/main/resources/lib/* directory, where * – stands for architecture of CPU, for instance armeabi-v7a;
Use code like this for executing:
private fun exec(command: String, params: String): String {
try {
val process = ProcessBuilder()
.directory(File(filesDir.parentFile!!, "lib"))
.command(command, params)
.redirectErrorStream(true)
.start()
val reader = BufferedReader(
InputStreamReader(process.inputStream)
)
val text = reader.readText()
reader.close()
process.waitFor()
return text
} catch (e: Exception) {
return e.message ?: "IOException"
}
}
Here is discussion with answer from android team on reddit.
I've done something like this using the NDK. My strategy was to recompile the program using the NDK and write some wrapper JNI code that called into the program's main function.
I'm not sure what the lifecycle of NDK code is like. Even services that are intended to be long-running can be started and stopped by the system when convenient. You would probably have to shutdown your NDK thread and restart it when necessary.

Copying a file from a temporary tomcat folder using java

Basically my problem is a that I need to copy an uploaded file (which is placed in a temporary folder on my server providers Tomcat ie. not a local Tomcat).
The code I'm using works when I deploy my project on my local machine but stops working when I deploy it live.
I've found out that it has something to with my permissions in java.policy.
What I need to find out is how do I get access to the folder in which Tomcat stores the temporary file using Java.
When reading catalina.out this is the clue that the log gives me.
/usr/local/tomcat/work/Catalina/project name here/context of project here/upload_490341a6_12b1d397355_76ce_00000001.tmp
I'm thinking somewhere along the lines (note: this is not an actual method :P )
ServletActionContext.getContext().getSuperHiddenTemporaryCatalog();
The code snippet at the bottom has one flaw.
sourceFile and targetFile points to the same directory at the moment.
I want the sourceFile path to be the temporary tomcat-folder.
Thanks in advance! :D
public String saveImage(File file, String uploadedFileName) {
String path = ServletActionContext.getServletContext().getRealPath("images");
System.out.println(path);
String fullFileName = path + "/" + uploadedFileName;
System.out.println(fullFileName);
boolean successful = false;
try {
File sourceFile = new File(fullFileName);
File targetFile = new File(path + "/" + uploadedFileName);
InputStream in = new FileInputStream(sourceFile);
OutputStream out = new FileOutputStream(targetFile);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
} catch (Exception e) {
successful = false;
e.printStackTrace();
}
if (successful) {
return "context of project/images/" + uploadedFileName;
} else {
return "";
}
}
File tempDir = (File) servletContext.getAttribute("javax.servlet.context.tempdir");
should give you access to your temporary directory in Tomcat. It would be strange if you could not at least read files from there.
The code I'm using works when I deploy my project on my local machine but stops working when I deploy it live. I've found out that it has something to with my permissions in java.policy.
Yes. This is an example of a Java security sandbox.
What I need to find out is how do I get access to the folder in which Tomcat stores the temporary file using Java.
You cannot circumvent the security sandbox (modulo some unpatched bug in your JVM). What you need to do is change the "java.policy" settings so that your webapp has permission copy the file to where it needs to be copied. You may need to discuss this with whoever has done the security design, etc for your production Tomcats.

Categories