How to get a Resource in Apache Brooklyn - java

I am trying to build my own entity, which is based on VanillaWindowsProcess. The idea is, after the installation of the windows Machine, to execute some powershell commands, which are in a file.
I tried something which I used a lot of times in another Java projects to get a resource:
private void runInstallationScript() {
List<String> lines;
try {
lines = FileUtils.readLines(
new File(TalendWindowsProcessWinRmDriver.class.getResource("/my/path/file.txt").getFile()),
"utf-8");
executePsScript(lines);
} catch (IOException e) {
LOG.error("Error reading the file: ", e);
}
}
But I'm always getting the following:
ava.io.FileNotFoundException: File 'file:/opt/workspace/incubator-brooklyn/usage/dist/target/brooklyn-dist/brooklyn/lib/dropins/myProject-0.0.1-SNAPSHOT.jar!/my/path/file.txt' does not exist
It is strange, because the file is in the jar in that path. I did a test (without Apache Brooklyn infrastructure) and it works, but the other way, it does not.
The project follows the Maven standard structure and the file itself is under, src/main/resources/my/path/file.txt
Is there something that is wrong? Or maybe there is another approach to get that file? Any help would be appreciated.

You cannot access a resource inside a jar as a File object. You need to use an InputStream (or an URL) to access it.
Since you are already using getResource, you should change the method FileUtils.readLines to accept an InputStream (or an URL) as input.
If you don't have access to the source code, you can write your own method or use Files.readAllLines for Java >= 7.

Related

Is there a way to get the file path of the .java file executed or compiled?

In Python the global variable __file__ is the full path of the current file.
System.getProperty("user.dir"); seems to return the path of the current working directory.
I want to get the path of the current .java, .class or package file.
Then use this to get the path to an image.
My project file structure in Netbeans looks like this:
(source: toile-libre.org)
Update to use code suggested from my chosen best answer:
// read image data from picture in package
try {
InputStream instream = TesseractTest.class
.getResourceAsStream("eurotext.tif");
bufferedImage = ImageIO.read(instream);
}
catch (IOException e) {
System.out.println(e.getMessage());
}
This code is used in the usage example from tess4j.
My full code of the usage example is here.
If you want to load an image file stored right next to your class file, use Class::getResourceAsStream(String name).
In your case, that would be:
try (InputStream instream = TesseractTest.class.getResourceAsStream("eurotext.tif")) {
// read stream here
}
This assumes that your build system copies the .tif file to your build folder, which is commonly done by IDEs, but requires extra setup in build tools like Ant and Gradle.
If you package your program to a .jar file, the code will still work, again assuming your build system package the .tif file next to the .class file.
Is there a way to get the file path of the .java file executed or compiled?
For completeness, the literal answer to your question is "not easily and not always".
There is a round-about way to find the source filename for a class on the callstack via StackFrameElement.getFileName(). However, the filename won't always be available1 and it won't necessarily be correct2.
Indeed, it is quite likely that the source tree won't be present on the system where you are executing the code. So if you needed an image file that was stashed in the source tree, you would be out of luck.
1 - It depends on the Java compiler and compilation options that you use. And potentially on other things.
2 - For example, the source tree can be moved or removed after compilation.
Andreas has described the correct way to solve your problem. Make sure that the image file is in your application's JAR file, and access it using getResource or getResourceAsStream. If your application is using an API that requires a filename / pathname in the file system, you may need to extract the resource from the JAR to a temporary file, or something like that.
public class Main {
public static void main(String[] args) throws Exception {
System.out.println(getPackageParent(Main.class, false));
}
public static String getPackageParent(Class<?> cls, boolean include_last_dot)
throws Exception {
StringBuilder sb = new StringBuilder(cls.getPackage().getName());
if (sb.lastIndexOf(".") > 0)
if (include_last_dot)
return sb.delete(sb.lastIndexOf(".") + 1, sb.length())
.toString();
else
return sb.delete(sb.lastIndexOf("."), sb.length()).toString();
return sb.toString();
}
}

Java 7 fails to create a file on Win7 with a 230-character path

I had some new code using the commons-io FileUtils.openOutputStream(File) method, for a file that doesn't exist at the point of the call. This was failing with a "FileNotFoundException". I first thought this was a bug in commons-io, but then I realized that it's just calling "new FileOutputStream(file, append)", which is also supposed to create the file if it doesn't exist.
I then added code right before my call to FileUtils.openOutputStream(File) like the following:
if (!file.exists()) {
logger.info("Parent file exists: " + file.getParentFile().exists());
try {
file.createNewFile();
}
catch (Exception ex) {
logger.error("Creating file failed", ex);
}
}
This prints "true" for the parent file, and then "java.io.IOException: The system cannot find the path specified". I googled for this situation, and some people were hitting this if they went past the supposed 260 character limit for a file path on Windows. I thought that might be relevant, but my file path is only 230 characters long.
I also tried an experiment of trying to "touch" the same file path in my Cygwin bash shell, and it had no trouble doing that.
Update:
So I took the partial advice of trying to use Paths & Files to do this instead of just "File". My incoming parameter is a "File", so I can't do anything about that. I added the following code:
try {
Path path = Paths.get(file.getAbsolutePath()).toAbsolutePath();
if (!Files.exists(path.getParent())) {
Files.createDirectories(path);
}
file = Files.createFile(path).toFile();
}
catch (Exception ex) {
logger.error("Failed to create file");
}
What's curious is that this doesn't give me a better error message. In fact, it doesn't give me any error message, because it doesn't fail. It appears that NIO is taking a very different path to creating the file than the regular File object.
Update:
What is now working fine is the following:
file = Paths.get(file.getAbsolutePath()).toAbsolutePath().toFile();
try {
Path path = file.toPath();
if (!Files.exists(path.getParent())) {
Files.createDirectories(path);
}
if (!file.exists()) {
file = Files.createFile(path).toFile();
}
}
catch (Exception ex) {
logger.error("Failed to create file");
}
What's curious is that I should be able to remove that first line, which is essentially converting a relative path to an absolute path. My test run creates 50 or so files in the process. I tried commenting out that line and then clearing out my output tree and running the test. It got the following exception attempting to create the first file:
java.nio.file.AccessDeniedException: build\gen1\org\opendaylight\yang\gen\v1\urn\opendaylight\params\xml\ns\yang\pcep\types\rev131005\vs\tlv\vs\tlv\VendorPayload.java
at sun.nio.fs.WindowsException.translateToIOException(WindowsException.java:83)
What the heck?
Also note that I never did remove the older code that uses "File.createNewFile()", I just put the "Files" code before that, and the old code checks for "!file.exists()", so theoretically the old code would only execute if the new code somehow didn't create the file. On this first file, since the NIO creation failed, the file still didn't exist, and it went through the old creation code, which SUCCEEDED.
And even stranger, I let the test case run to the next file, and that failed in the NEW code with:
java.nio.file.FileAlreadyExistsException: build\gen1\org\opendaylight\yang\gen\v1\urn\opendaylight\params\xml\ns\yang\pcep\types\rev131005\vs\tlv\VsTlv.java
Note that the only way that block could have gotten that exception is if it executed the "Files.createFile(path).toFile()" line, and the only way it could have gotten to that line is if "!file.exists()" was TRUE, which means that the file did not exist. my brain is starting to melt. Also note that while I'm sitting at this breakpoint, I examined the file system, and that file does not exist.
This is 2015 and you say that you use Java 7.
Don't use File. Use this instead:
final Path path = Paths.get("....").toAbsolutePath();
// use Files.exists(path.getParent()) to check for the existence;
// if it doesn't exist use Files.createDirectories() on it
Files.createFile(thePath);
If the operation fails, you will at least get a meaningful exception telling you why it fails.
This is 2015. Drop. File. Now.

How can I return the file path using the JNLP file chooser

Hi I am trying to get the returned file path by my JNLP file chooser. Here's my code.
I don't know how and where to get the file path. is it from fileContents? fileConents.getfilepath something like that?
try {
if (fileOpenService==null) {
fileOpenService = (FileOpenService)ServiceManager.
lookup("javax.jnlp.FileOpenService");
}
fileContents = fileOpenService.openFileDialog(path, xtns);
} catch(UnavailableServiceException use) {
use.printStackTrace();
} catch(IOException ioe) {
ioe.printStackTrace();
}
Thanks in advance!
According to http://docs.oracle.com/javase/tutorial/uiswing/components/filechooser.html
You can call other methods on the File object, such as
getPath, isDirectory, or exists to obtain information about the file.
You can also call other methods such as delete and rename to change
the file in some way. Of course, you might also want to open or save
the file by using one of the reader or writer classes provided by the
Java platform. See Basic I/O for information about using readers and
writers to read and write data to the file system.
It is for security reasons that a FileContents will not return a path. The JRE asked the user if our app. could access the content of that file, not it's path.
It is a bit like the brower/HTML based file upload field. Some browsers provide the entire path, while more typically it is just the content/name.

File not found exception with external files

Hi i have made a small program that reads a config file. This file is stored outside the actual jar file. On the same level as the jarfile actually.
When i start my program from a commandline in the actual directory (ie. D:\test\java -jar name.jar argument0 argument1) in runs perfectly.
But when i try to run the program from another location then the actual directory i get the filenotfound exception (ie. D:\java -jar D:\test\name.jar argument0 argument1).
The basic functionality does seem to work, what am i doing wrong?
As requested a part of the code:
public LoadConfig() {
Properties properties = new Properties();
try {
// load the properties file
properties.load(new FileInputStream("ibantools.config.properties"));
} catch (IOException ex) {
ex.printStackTrace();
} // end catch
// get the actual values, if the file can't be read it will use the default values.
this.environment = properties.getProperty("application.environment","tst");
this.cbc = properties.getProperty("check.bankcode","true");
this.bankcodefile = properties.getProperty("check.bankcodefile","bankcodes.txt");
} // end loadconfig
The folder looks like this:
This works:
This doesn't:
The jar doesn't contain the text file.
When reading a File using the String/path constructors of File, FileInpustream, etc.. a relative path is derived from the working directory - the directory where you started your program.
When reading a file from a Jar, the file being external to the jar, you have at least two options :
Provide an absolute path: D:/blah/foo/bar
Make the directory where your file is located part of the class path and use this.getClass().getClassLoader().getResourceAsStream("myfile")
The latter is probably more appropriate for reading configuration files stored in a path relative to the location of your application.
There could be one more possibility:
If one part of your code is writing the file and another one is reading, then it is good to consider that the reader is reading before the writer finishes writing the file.
You can cross check this case by putting your code on debug mode. If it works fine there and gives you FileNotFoundException, then surely this could be the potential reason of this exception.
Now, how to resolve:
You can use retry mechanism something similar to below code block
if(!file..exists()){
Thread.sleep(200);
}
in your code and change the sleep value according to your needs.
Hope that helps.!!

Java: get absolute path of project

I'm trying to run a exe file in path outside of the current package. My code.java file that runs it is in
%Workspace_path%\Project\src\main\java\com\util\code.java
However the directory of where the exe is
%Workspace_path%\Project\src\main\resources\program.exe
If possible, it seems like the best solution here would be to get the absolute path of the Project then append "src\main\resources\" to it. Is there a good way to do this or is there an alternative solution?
I'm using Eclipse, but it would great if it could be used in other IDEs too. Thanks for any help.
The de facto approach to solving this is to bundle the EXE as a classpath resource. It seems you have arranged for this already.
When working with classpath resources, a mature program should not assume that the resource is in the filesystem. The resources could be packaged in a JAR file, or even in a WAR file. The only thing you can trust at that point is the standard methods for accessing resources in Java, as hinted below.
The way to solve your problem, then, is to access the resource contents using the de facto standard of invoking Class.getResourceAsStream (or ClassLoader.getResourceAsStream), save the contents to a temporary file, and execute from that file. This will guarantee your program works correctly regardless of its packaging.
In other words:
Invoke getClass().getResourceAsStream("/program.exe"). From static methods, you can't call getClass, so use the name of your current class instead, as in MyClass.class.getResourceAsStream. This returns an InputStream.
Create a temporary file, preferably using File.createTempFile. This returns a File object identifying the newly created file.
Open an OutputStream to this temp file.
Use the two streams to copy the data from the resource into the temp file. You can use IOUtils.copy if you're into Apache Commons tools. Don't forget to close the two streams when done with this step.
Execute the program thus stored in the temporary file.
Clean up.
In other words (code snippet added later):
private void executeProgramFromClasspath() throws IOException {
// Open resource stream.
InputStream input = getClass().getResourceAsStream("/program.exe");
if (input == null) {
throw new IllegalStateException("Missing classpath resource.");
}
// Transfer.
OutputStream output = null;
try {
// Create temporary file. May throw IOException.
File temporaryFile = File.createTempFile(getClass().getName(), "");
output = new FileOutputStream(temporaryFile);
output = new BufferedOutputStream(output);
IOUtils.copy(input, output);
} finally {
// Close streams.
IOUtils.closeQuietly(input);
IOUtils.closeQuietly(output);
}
// Execute.
try {
String path = temporaryFile.getAbsolutePath();
ProcessBuilder processBuilder = new ProcessBuilder(path);
Process process = processBuilder.start();
process.waitFor();
} catch (InterruptedException e) {
// Optional catch. Keeps the method signature uncluttered.
throw new IOException(e);
} finally {
// Clean up
if (!temporaryFile.delete()) {
// Log this issue, or throw an error.
}
}
}
Well,in your context,the project root is happen to be the current path
.
,that is where the java.exe start to execute,so a easy way is:
String exePath="src\\main\\resources\\program.exe";
File exeFile=new File(".",exePath);
System.out.println(exeFile.getAbusolutePath());
...
I tested this code on Eclipse,It's ok. I think is should work on different ide.
Good Luck!

Categories