How to copy folder from .jar file using shell script - java

I have jar file ex: sample.jar under this jar file there is a folder structure ex: "environment/xyz.properties" and "environment/abc.properties".
My Requirement: I need to copy entire "environment" folder with all property files and past in some other (ex: /tmp/environment)location using shell script.
Please help how to do copy folder from .jar using shell script.

struct
├── a
│   └── file_a.txt
├── b
│   └── file_b.txt
└── c
└── file_c.txt
Create jar
jar cf struct.jar ./struct
Extract dir
jar xf struct.jar struct/a
After file is extracted you can do whatever you like:
jar xf struct.jar struct/a
cp -r struct/a /tmp/environment

From what I understand you want to copy a directory in a shell,
so you type
cp -R /path/to/directory /path/to/other/location/

Related

"ClassNotFoundException" while trying to run .jar file

I have a .jar that I built following the Oracle docs, using jar cfm hangman.jar Manifest.txt src/classes/app/Main.class. The manifest.txt file contains Main-Class as classes.app.Main, telling where my Main class is. When executed, ClassNotFoundException is thrown, saying it couldn't find classes.app.Main. I need help trying to understand what's wrong here. Is it the main class or maybe a missing classpath?
Here's the project tree:
.
├── hangman.jar
├── Manifest.txt
├── README.md
└── src
├── app
│   ├── Main.java
│   ├── Player.java
│   ├── Players.java
│   ├── Play.java
│   ├── Themes.java
│   ├── Word.java
│   └── Words.java
└── classes
└── app
├── Main.class
├── Play.class
├── Player.class
├── Players.class
├── Themes.class
├── Word.class
└── Words.class
You don't show the code, but it is extremely likely that the package for your class is just app not classes.app, and classes is only a directory name to contain the class files, not actually part of the package hierarchy. The name of a class file entry in a jar, OR the name of a class file relative to a classpath directory, must be exactly a directory path equal to the package hierarchy (if any) plus the class name and the suffix .class, with nothing added or removed. This means your jar should be created by going to the classes directory and then adding the file(s) relative to that directory:
jar cfm hangman.jar Manifest.txt -C classes app/Main.class
and the Main-class entry in the manifest should be app.Main. If you only need main-class in the manifest and nothing else (except version, IIRC), you can have jar create it for you:
jar cfe hangman.jar app.Main -C classes app/Main.class
Also I note that there are other classes in your source tree. If these classes are called or referenced from the Main class, directly or indirectly (i.e. nested), they must also be in the jar. You probably want to use app/* instead, although it is possible you want or even need to be more selective.
Meta: I thought this was covered in the standard tutorial, but although most of the pieces are there they aren't really pulled together anyplace I could find and refer to.

Open a file from the src directory (Java)

I've written a short documentation for my Java program. When clicking on the menu Help -> Documentation the default PDF reader of the OS should open the documentation.pdf.
I'm trying to open the PDF which is located in the directory src/doc with Desktop.getDesktop().open(new File("doc/documentation.pdf")); in Controller.java.
However, Java does not find the file. When I open the icon for the program with primaryStage.getIcons().add(new Image("icon/icon_512x512.png")); it works perfectly in Main.java.
Here you can see layout of my IntelliJ project.
src
├── META-INF
├── de
│   └── myapp
│   ├── model
│ │ └── *.java
│   ├── view
│ │ └── *.java
│ ├── Main.java
│   └── Controller.java
├── doc
│ └── documentation.pdf
└── icon
└── icon_512x512.png
My stack
IntelliJ 2016.2
Java 1.8.0_77
It works with new Image("icon/icon_512x512.png") because internally it gets is from the context ClassLoader which is not the case of new File("doc/documentation.pdf") that gets it from the user working directory in case of a relative path, so you could simply apply the same logic.
ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
URL resource = contextClassLoader.getResource("doc/documentation.pdf");
Desktop.getDesktop().open(new File(resource.toURI()));
3-rd party applications can not access src dir in your application, in case, when your app assemble in jar archive. You should place your file separately from src.
Of course, java find icons, because it's java API.
You can access any resources in src folder through follow methods:
URL url = getClass().getResource("/path/in/src");
InputStream is = getClass().getResourceAsStream("/path/in/src");
If your app is NOT assemble in JAR - try provide full path to file like this:
URL url = getClass().getResource("/path/in/src");
File file = new File(url.toURI());
The files from Classpath can be loaded by using ClassLoader's getResourceAsStream Method.
So you can try with generating an Input stream object
InputStream is = Controller.class.getClassLoader().getResourceAsStream("doc/documentation.pdf");
And After generating Input Stream you can read it by Java Program.

Java jar can't access resources

I need to execute a jar file which uses some files located in some subfolders.
For example the directory tree can be like this:
jar_root/
├── executable.jar
├── folder1/
│ └── required_file1.txt
│
├── folder2/
│ └── required_file2.txt
│
├── other_folder/
│ └── ...
└── other_file.txt
In this example executable.jar needs to access required_file1 and required_file2.
I need to execute the jar from another directory, so I tried this command:
java -cp /path/to/jar_root/ -jar /path/to/jar_root/executable.jar <options>
But what I got is a FileNotFoundException on required_file1 (I guess the same Exception will be raised for required_file2)
How can I make the jar work?
Note that I cannot modify the jar, so I can't use getResourceAsStream, as suggested by this (and other) answer(s).
It depends on how the code in the jar tries to access the files. If by relative path, that can only work if you start the program from the appropriate working directory, for example:
cd /path/to/jar_root/
java -jar executable.jar <options>
An alternative is to reference the files by absolute path, or relative from classpath instead of filesystem path.

Java Ant: classpath hierachy

I have several class files like such hierarchy directories:
classes
└── com
├── www
│   ├── ant
│   │   └── TAPJUnitResultFormatter.class
│   ├── taglib
│   │   └── IncludeTag.class
│   ├── tomcat
│ ├── util
How could I include them in classpath? I tried to include them one by one, but didn't work.
Thanks.
You might find this helpful
Quoted:
When classes are stored in a directory (folder), like /java/MyClasses/utility/myapp, then the class path
entry points to the directory that contains the first element of the
package name. (in this case, /java/MyClasses, since the package name
is utility.myapp.)
But when classes are stored in an archive file (a .zip or .jar file)
the class path entry is the path to and including the .zip or .jar
file. For example, to use a class library that is in a .jar file, the
command would look something like this:
% java -classpath /java/MyClasses/myclasses.jar utility.myapp.Cool
So basically, point it to the root directory that all your classes exist under. Your "MyClasses" folder is probably named "bin".

How to compile multiple Java files when there are Java files in other packages?

I am compiling multiple files in a directory (javac *.java) but I have a problem when I try to do this.
I get compile errors saying that javac cannot find a symbol of an object.
I have multiple packages that contain Java files that are needed to run the main program. But it seems that trying to compile these one by one won't work. It runs fine in my IDE but I'm interested in learning how it's done via command prompt.
The main program is in the drivers folder. I have tried compiling the files in order of dependency but that didn't work out.
Javac documentation provides all the necessary information. However, it might be useful to use Ant or Maven for command line builds.
This page provides a good example of using first javac and then Ant for building a simple project.
Here is an example project and how can it be compiled with javac.
The tree structure of the project is this:
.
├── build
└── src
├── attacks
├── drivers
│   └── Driver.java
└── exceptions
└── MyException.java
There are two special directories -- build for containing compiled classes and src to contain source files (could be in different subdirectories -- packages).
The following command compiles the whole project and puts the result into the build directory.
javac -sourcepath src -d build src/**/*.java
The -sourcepath src specifies directory src as the place where all the source can be found by the compiler. The -d build options tells the compiler where to place the compiled files.
Option src/**/*.java tells the compiler what files to actually compile. In this specific case it tells javac to look two levels down and pick all *.java at that level.
If there are *.java files at different levels than a list of files needs to be specified. For this, one could create such listing as an external file and pass this files as in input option for javac.
Here is how this could be done under Linux/Unix:
find -name "*.java" > source.txt
The above command creates file source.txt that contains full paths for the found *.java files. For this example it contains:
./src/drivers/Driver.java
./src/exceptions/MyException.java
In order to compile the project with the list of source files flushed into source.txt, the following command can be used:
javac -d build #source.txt
Please note that #source.txt specified at the end that tells the compiler where to look for a list of source files. Please also note that the -sourcepath option can be omitted.
Here is how the directory structure changed after running the above command.
.
├── build
│   ├── drivers
│   │   └── Driver.class
│   └── exceptions
│   └── MyException.class
└── src
├── attacks
├── drivers
│   └── Driver.java
└── exceptions
└── MyException.java
As can be observed the build directory now contains the compiled class files in respective packages.
And, if you'd like to run it, assuming, for example, that Driver has method main, the following command executes the program.
java -cp .:build:**/*.class drivers.Driver
Please note that file separator : (colon) is used under Unix, for Windows change it to ; (semicolon).
I am compiling multiple files in a directory (javac *.java)
Wrong already. That will only work correctly if the Java classes aren't in packages. The correct way to do this is as follows, where src is the name of the directory at which all your package directories are rooted:
cd src
javac package1/package2/*.java
javac package3/package4/package5/*.java
etc for whatever your package/directory layout is. Each javac command line will compile all the files in the named directory and all the .java files in other packages/directories that it depends on that aren't already compiled or that are out of date.
See the Tool documentation for javac.
two options:
1) Use the command line to specify all files to compile
2) Create a file with all the filenames (output from find, perhaps), and run javac #argfile

Categories