my problem is that I want to add some .class files from a normal directory into an .jar file. Do I have to extract it before or can I add the files "on the fly"?
Although I agree with Jordan and suggest using the system command, that was not an option for the team I work on.
If you have to use his second solution, it is extremely important to note that Zip::ZipOutputStream will override any existing jars; i.e., you won't be adding to an existing jar, you will be creating a new one. This code will add a file to an existing jar:
require 'zip/zip'
Zip::ZipFile::open 'path/to/jar' do |jar|
jar.add 'filename_in_jar', 'path/to/file/you/want/to/add'
end
If it was me I would almost certainly just call the jar command within Ruby to do this:
system 'jar uf jar_file.jar input_file(s).class'
# or
%x[ 'jar uf jar_file.jar input_file(s).class' ]
Reference here.
If you still want to do this without calling jar you should be able to do it with rubyzip, since JAR files are just ZIP files with a particular structure. Something like this:
require 'zip/zip'
filename = 'class_file.class'
Zip::ZipOutputStream::open "jar_file.jar" do |zip|
zip.put_next_entry 'dest/path/in/jar/' + filename # don't forget the path
File.open filename, 'rb' {|f| zip.write f.read }
end
There are also a few Ruby wrappers for libarchive that could do this. E.g.
Related
I'm making a file import system, and I can't move files into the compiled .jar file the application is in.
Here's what I'm trying to do:
Path FROM = Paths.get(filePath.getText());
Path TO = Paths.get("C:\\Users\\" + System.getProperty("user.name") +
"\\AppData\\Roaming\\.minecraft\\mods\\music_crafter-1.0\\src\\main\\resources\\assets\\music_crafter\\sounds\\block\\music_player");
//jar file
Files.move(FROM, TO.resolve(FROM.getFileName()), StandardCopyOption.REPLACE_EXISTING);
You need to handle the jar file internally. A Jar is not a directory, it is a compressed container file (pretty much a ZIP file with a different extension).
To do this, given that you are on Java 6, you have 2 options:
Unzip the contents to a temporary working directory (there are built
in APIs for this, or use a library such as Apache Commons Compress)
do your work (copying, deleting, etc) and then re-zip.
Make external command line calls to the Jar utilities that come with
Java
Of those, only (1) makes any real sense.
A third option would be available if you could up your Java to 7+ which would be:
3. Use a Zip File System Provider to to treat it as a file system in code
All that said, however:
As per comments on your question, you really might want to look at if this something you need to do at all? Why do you need to insert into existing jars? If this is 'external' data, it would be much better in a separate resource location/container, not the application jar.
I have a JAR file that I wanted to edit a string inside on of it's classes . So I extracted it using Winrar , done the changes I wanted and saved it . Now I have a folder with subfolders inside that contains class files (about 30 one) .My question here is how can I recreate the Jar file from those folders&files ? Like it's it's doing the reverse action of extracting the Jar file .. ?
You could create a .zip file, rename it (with WinRAR) to something.jar so it becomes a .jar archive and then copy the folders in there.
But what you are doing is not really recommended to be done
You shouldn't extract and re-archive it like that.
And DON'T I repeat DON'T edit .class files!
Jar file is basically a zip file - however the best way to edit jars is to use a file manager (like Total Commander). You can delete, copy, rename, ... whatever, transparently inside the archive.
http://en.wikipedia.org/wiki/JAR_%28file_format%29
May be only one tip for the Total Commander - to enter the archive just use Ctrl-Pagedown. And I don't think that is something wrong on jar editing (in some circumstances you have no other option). However class files editing... it is a different game ...
I am writing some code to my phd project and I am using VIM as my code editor.
As I am coding in Java, I chose Syntastic to check and compile my code. So far so good.
My issue comes when I try to create a directory with all my .classes. I want to do this, because then I intend to create a .jar using this directory using a simple make file. So, this is my scenario:
source code:
C:\Users\LABIMD05\workspace\backhoe-nomvn2\src (all .java)
class files:
C:\Users\LABIMD05\workspace\backhoe-nomvn2\bin\classes (where I want to put all the .classes)
In this way, let's say I am coding br.ufrn.Project. When I use :SyntasticCheck, I want the br.ufrn.Project .class file to be generate at:
C:\Users\LABIMD05\workspace\backhoe-nomvn2\bin\classes\br\ufrn\Project.class
and not at:
C:\Users\LABIMD05\workspace\backhoe-nomvn2\src\br\ufrn\Project.class (the same of the .java)
Here goes the options that I am using at my _vimrc file
let g:syntastic_java_javac_classpath = 'C:\Users\LABIMD05\workspace\szz_lib\*;C:\Users\LABIMD05\workspace\backhoe-nomvn2\bin\classes'
let g:syntastic_java_javac_delete_output = 0
let g:syntastic_always_populate_loc_list = 1
let g:syntastic_mode_map = { 'mode': 'passive',
\ 'passive_filetypes': ['java']}
THE PROBLEM:
Everytime I compile br.ufrn.Project file, the .class file goes to the same directory of the .java file
I thought it would be because Syntastic would create the .class file in the current working directory. Then I used:
cd C:\Users\LABIMD05\workspace\backhoe-nomvn2\bin\classes
To see if Syntastic would create the .class in the desired place. But I had no success.
Would you guys have some clue where can I configure it? I just want to separate the .class files from .java files and then use a make file to create a jar with the binaries only. Simple thing.
Thank you for any help you can provide.
You can't configure Syntastic to compile the java files to a different location. However, you can make a command that uses SyntasticCheck and compiles the java files to a different directory.
Using the javac -d dir File.java command you can tell the java compiler where to generate .class files.
Using this you can make a vim command, I called it Javac but you can choose what to call it. It will call Syntastic check and generate the .class files to the other file.
function! Javac()
execute "w"
execute "SyntasticCheck"
execute "!javac -d C:\Users\LABIMD05\workspace\backhoe-nomvn2\bin\classes %"
endfunction
command! Javac :call Javac()
If the SyntasticCheck part is not necessary you can remove that.
Just put this in your .vimrc and then you can use :Javac to execute it.
Alternatively you could also put it in ~/.vim/ftplugin/java.vim if you want it to only be active when editing the java filetype.
Suppose my project structure is:
/project
/src
/java
Util.java
/cpp
/bin
a.out
I'd like to execute a.out from within Util.java without hard-coding any absolute paths in my java file. What's the best way to go about doing this?
EDIT -- Here's what I ended up doing: I happen to be using autoconf as most of the code is c++. I defined a substitution variable like AC_SUBST([project_root], [$(pwd)]) in configure.ac and substituted it in a Config.java.in file.
Perhaps using a properties file to be loaded on deployment/running time depending on the nature of your app.
More about its use in this thread
How to use Java property files?
You're file path to a.out could be ../bin/a.out. And then execute the file using that path.
Below is some pseudo code that might help you.
// look for the executable in the current working directory
File executable = new File("a.out");
if( executable.exists()){
System.exec() .... etc
} else {
String location = YourMainClass.class.getProtectionDomain().getCodeSource().getLocation();
// write code to form a path name to the a.out based on the location of .jar file
}
I have a project that uses the normal Maven structure, e.g.
module
\ src
\ main
- java
- resources
\ test
- java
- resources
etc. Under test/resources, I'd like to keep a set of test input files for a parser I'm writing, then run all files in the directory through the test suite. As written now, the test code works from the command line, but fails when run through the Eclipse JUnit plugin:
File file = new File("src/test/resources");
file.list();
(I'm actually using a FilenameFilter, but I'm trying to simplify.)
The problem, after poking through the unit test with a debugger, turns out to be that the File I'm constructing points to /path/to/workspace/myproj/src/test/resources, whereas the actual files reside in /path/to/workspace/myproj/modulename/src/test/resources (it's a Maven multi-module project). Apparently, this isn't a problem when running mvn test from the command line.
I guess my question is two-fold: one, am I doing this wrong? I see a lot of people using the class loader to discover resources, as in this question, but I don't want all the resources of a particular type, just one directory under test/resources. Two, if this isn't a terrible idea in the first place, do I have a configuration error (e.g. it "should" work)? Is it Eclipse's fault, a Maven problem, or what?
One trick would be to place a file in resources with a known name, get the URI of this file through the classloader, then construct a File from this URI, then get the parent, and list() the contents of that directory. Kind of a hack, but it should work.
So here's what the code should look like, but place a file called MY_TEST_FILE (or whatever) in test/src/resources
URL myTestURL = ClassLoader.getSystemResource("MY_TEST_FILE");
File myFile = new File(myTestURL.toURI());
File myTestDir = myFile.getParentFile();
Then you have access to the directory you're looking for.
That said, I'd be surprised if there's not a more 'maven-y' way to do it..
Just for completeness, wanted to point out the way to get this without having to grab the current instance of the ClassLoader, using ClassLoader#getSystemResource. This example does the work without having to place a file at the top.
//Obtains the folder of /src/test/resources
URL url = ClassLoader.getSystemResource("");
File folder = new File(url.toURI());
//List contents...
Try this?
1)put test data files into the same package structure as you test classes. That is, if you have a test class named Apple in src/test/java/com/fruits, you test data file will be in src/resources/java/com/fruits.
2) When the files are compiled both the class and the data file should be in target/test-classes/com/fruits. If this is the case, in you code, you can obtain the file this way "this.getClass().getResourceAsStream("myFile")"
put desired resource into /src/test/resources/lipsum.pdf
find it's full path using
String fileName = ClassLoader.getSystemResource("lipsum.pdf").getFile();