are there any things that once can do ignorantly that can prevent a java web application from being cross platform? (windows/linux/mac)
Tools I am planning to use are java/spring framework/hibernate
Hard-coding file separators/paths.
Using native libraries.
Using Runtime.exec()
Using sun.* classes (this may cause portability issues with non-Sun JVMs).
not honoring case-sensitivity in filesystem
Using system default character encoding for input/output when inappropriate
In addition to what Dan Dyer said:
calling executables by a fixed path or of a fixed name
assuming a certain shell command syntax will work properly (eg 2>&1 or something)
deleting or renaming a file that some other process (or the same one!) might have open
Making assumptions about the working directory (eg using relative paths to load resouces from the file system)
Related
What's the best way of processing *ix file path strings when running on Windows?
If I just use Paths.get() it invokes Filesystem.getDefault() which ends up processing it like a Windows path. The parsing seems to work in my tests but they're pretty rudimentary, and of course toString uses the wrong path separator.
Can I manually load up the LinuxFileSystem somehow? Or should I use the commons-io parser instead?
Can I manually load up the LinuxFileSystem somehow?
I doubt it, because one JDK distribution is oriented either to Unix or either to Windows. The only chance I think of is that you look for an open source distribution of some UnixFileSystemProvider and import into your application's runtime.
But even in that case, I have my doubts it will work 100%, because a FileSystemProvider class deals with low-level details from the underlying OS - not just path separators, so there is a risk that it won't be compatible over a Windows filesystem.
Looks like #Little Santi's comment on the question is in fact the answer. If I run:
for (FileSystemProvider provider: FileSystemProvider.installedProviders()) {
System.out.println(provider.getClass().getName());
}
I get:
sun.nio.fs.WindowsFileSystemProvider
com.sun.nio.zipfs.ZipFileSystemProvider
If I interpret this correctly it means I can't use the LinuxFileSystem path methods under Windows but should use commons-io instead.
Is there any mechanism to get and set the file/directory permissions?
For example, I want to show the permisssions of a file in a shell way:
-rwxr-xr--
Is it possible to do this using Java?
I know that there are some methods in the File class to know if the file canExecute, canRead and canWrite, but AFAIK this info is for the current user only. I need to know the whole octal number, for example 755, so I need to get it from the user, from group and from others.
I know that Java7 brings Posix operations, but how could do this using a smaller JRE?
I would like not to use a command like ls, or chmod.
If you can use external libraries, there are several:
JPosix
Posix for java
jnr-posix
If an entire library seems a hassle, creating a JNI wrapper that calls the lstat C function and returns the access mode takes you about 10 minutes. Here's a tutorial that creates such a wrapper for the isatty and ttyname functions.
As you say, in Java7, the JVM supports it, so you have a guarantee that this can be done portably in all OSs (because the JVM implementation takes care of it). Under Java7, you'd have to use a native library per OS you want to support. This is potentially even dirtier than executing chmod
I am currently writing a program in JAVA that examines the behavior of external executable. One of the requirements is to observe the file operations of the external executable in real time (check if the executable creates/ deletes/modifies any file). I tried to find a suitable API in java to help me do this though it was not possible to find one. I have found the Class FileAlterationObserver which is not suitable for my program since you have to specify manually all the directories you want to monitor.
I was wondering if any of you knows a good API to use?
Thanks for your time in advance.
Without java, you could use the linux lsof command to list the open files in the system. Alternatively, and with Java, you can use libnotify, but you will need to specify the folders. I can't see any other way of doing this with pure java.
EDIT #Keppil linked you to the file change notification API that looks way more suitable than libjnotify. I wasn't aware it existed!
I am trying to create executable under windows platform for Java program using JNI ,C/C++ and invocation API, I have already created jar file for my program which includes all dependencies. I want to embed it in exe file, I was successful in running simple main class(present in file system) using JNI invocation API, I am planning to add jar file as resource in C/C++ program. But I don't know how do I run that jar file , One option is create temporary jar file on file system and run it using java, But I do not want to expose my jar file to everyone for security reasons, How can I run jar file on the fly using JNI ?
Compiling Java to an executable with GCJ does not work all the time, there are limitations as far as using reflection and other items such as UI classes, Look at this page.
If you convert you Java Code to a library or simply another module then you could link to it and simply run it without the need for a JVM.
My initial reaction was that I would be shocked if you could get this to work and have it be performant. But then I started thinking about it, and maybe you could pull this off using a custom class loader. If you embed the jar in the exe as a resource, it would be exactly the same as having the jar bytes be present at a particular offset in any file (whether an exe or not).
So, here's a potential strategy: implement a custom class loader that accepts the exe path and offset of the jar resource in that file. This would use a custom version of ZipFile that uses a fixed index offset for it's reads (unfortunately, it isn't going to be possible to use ZipFile itself - but if you grab the source of ZipFile it should be pretty obvious where you'll need to add the offset).
There is a bootstrapping issue here (how do you load the custom class loader?) - but I think it might be possible to do that from the JNI side. Basically you'd store the .class file for the loader as a separate resource in the exe, load it fully into memory then construct it using JNI calls. That will be a hassle, but it's just for one class, and then you can let the Java runtime take over the rest.
Sounds like an interesting project (Although, as others are pointing out, there isn't much security in what you are doing... I suppose that you could encrypt the embedded jar and add decryption code to the classloader, but you've kinda got to decide how far you want to take this thing).
Where should I store persistent files in a Tomcat web app ?
javax.servlet.context.tempdir is not feasible, it's erased when the app is redeployed/removed
Don't want to use an absolute path in e.g. servlet init parameters
Storing the files in a database is not an option
Our team does this a lot. A general rule we follow is outside the web app and outside Tomcat.
Our sysadmin set up a directory on our server that the tomcat user has rw permissions to (e.g. /var/tomcat/persist). We have a built a directory structure under this that tomcat uses to store files, read app-specific init files, etc.
If you don't want to use an absolute path in your init-params for your servlet, consider setting a system property when tomcat is started up. The good thing about that is every application running under tomcat will have access to it. The bad thing about that is every application running under tomcat will have access to it. You could set a property named base.persist.dir and build subdirectories for each application underneath it. We set system properties in the setenv.sh script in the bin/ directory under the CATALINA_OPTS environment variable.
Answering the title of the question, what about using a database, a DataSource and JDNI? Even in a web only context, writing to files using java.io is not really recommended because of concurrency, threading, security, clustering, portability issues. Some of these problems can be "workarounded" but still, this is not really a best practice. The standard approach is to use a database and I'd suggest to reconsider this option, throwing "file-based" lightweight database like HSQLBD or JavaDB into the mix.
(EDIT: For an unknown reason, database is not an option. Using JNDI or context parameters or init parameters to pass an absolute path - which are the less worse options IMHO - is excluded too. For a relative path, maybe look at user.home or user.dir then - or any other system property that you could pass on the command line. I don't like it, I wouldn't do it, and this doesn't solve the issues previously mentioned, but it's your choice after all.)
Storing the files in a webapp directory under the home directory of the user running Tomcat is a good and convenient option. It is outside of Tomcat, which means it will survive redeployment, and it is usually a writable directory (because it is created under the users' home dir).
But it is always a good idea to allow overriding the location of such directory via system property.
Generally, this would go to the database. But since the OP insists on not using a database, I'd try a different approach:
Filesystem path which is known: ${user.home}/.myapp. Applications sometimes use this for e.g. search indices which can be recalculated based on data in the database. Might be okay for your use case to use the user's home.
Store the configurable filesystem path in a configuration repository such as the database or perhaps Java Preferences (if you don't like to use servlet init params). Commercial applications such as Atlassian JIRA use a configurable (but absolute) filesystem path where they store issue attachments. If they don't know a better way, i don't know who does :)
I generally would suggest to use a database to store persistent data and expose it via a DataSource.
If you don't want to do that, I guess you could consider using the "user.home" system property (I have seen this used in a few circumstances). But... there are no guarantees that your servlet will be run with permission to write access unless you configure that yourself.