Gradle "exclude" from folder inside distribution zip - java

I am creating a distribution Zip and Tar file using gradle (java) distribution plugin.
My java project creates the file "abc.jar" inside the "lib" folder and puts all "implementation" libraries beside it. (<- I also tried to change this behaviour, couldn't figure it out though)
Now I want to either move "abc.jar" to the root of my distribution zip or exclude "abc.jar" from the subfolder "lib" exclusively.
I tried copying from my build directory directly, but I couldn't make it work to exclude the "abc.jar" that is copied to the "lib"-subdir.
distributions {
main {
distributionBaseName.set("abc")
contents {
into("/") // to remove subfolder and place everything inside root of the zip
// v1: exclude not working at all
exclude("lib/abc*")
// v2: exclude also excluding the follow up copy of my jar
exclude("abc*")
from(layout.buildDirectory.file("libs/abc.jar")) // copy abc-jars
}
}
}

Related

Files duplicated after manually renaming

Using Intellij, Springboot.
When I rename the files in a directory manually(Intellij->refactor->rename) and restart my web application, when I walk in that directory I can see the renamed files are duplicated (there now is both old name and new name in my app)
What am I missing?!
my directory is under /resources/my_dir
File myDirectory = new ClassPathResource(MY_DIR).getFile();
try (Stream<Path> paths = Files.walk(queryDirectory.toPath())) {
paths.filter(Files::isRegularFile).forEach(path -> setFile(path));
}
I'll assume here, that you are talking about files in the directory of compiled files. The reason is that only the source files are renamed when renaming something like an XML file in the resources folder, or whatever the case may be.
That, however is not in any way tied to the target directory. Build tools, like maven, or I assume the compiler intellij uses copies everything it can't compile to that target directory.
What you have to do is clean the project and build again, so that the target directory is "clean"

Can't Access resource path, only the target path

I want to access the resource's form of my project "\src\main\resources" but for any reason I can only access the target classes.
Here is my code:
System.out.println(Main.class.getResourceAsStream("/123.txt")); // java.io.BufferedInputStream#66cd51c3
System.out.println(Main.class.getResource("/123.txt")); // file:/C:/Users/Raul/workspace/Serial/target/classes/123.txt
System.out.println(Thread.currentThread().getContextClassLoader().getResource("123.txt").getPath()); // /C:/Users/Raul/workspace/Serial/target/classes/123.txt
and here my Project Dirs:
The thing is, even if I delete all the files in the target/classes and run the code, the compiler will copy the files from "src/main/ressources" into "target/classes" and read them from there.
I want to access the resource's form of my project "\src\main\resources" but for any reason i can only access the target classes.
I think the question is answered by user #VGR. Just to clarify it in another words:
You put your resources in the /src/main/resources folder, and these resouces will be copied as is into the /target/classes folder when you build your project.
Example
src/main/resouces/123.txt -> target/classes/123.txt
src/main/resources/myresources/145.txt -> target/classes/myresources/145.txt
...
Now if you run the program inside of your IDE you'll observe the following:
System.out.println(Main.class.getResource("/123.txt"));
output: file:/C:/Users/Raul/workspace/Serial/target/classes/123.txt
System.out.println(Main.class.getResource("/myresources/145.txt"));
output: file:/C:/Users/Raul/workspace/Serial/target/classes/myresources/145.txt
But if you open the generated jar file you'll not see the target folder because the file 123.txt will be on the root of the jar file and the file 145.txt will be under the folder myresources/145.txt.
The folder target is just an output directory for the build tool and will not be packaged within your jar file.
Now to the following question:
the problem is that i dont know how to export the target classes to my jar, or how can I get "src/main/ressources" as return value.
To answer this question you have to look into your pom.xml file on the root of your project. There should be a <packaging>jar</packaging> entry in it. If that is so you create the jar file as follows:
Option 1: from the command line
mvn clean install
the jar file will be created and copied into the folder target.
Option 2: from within Eclipse (for example)
right click on the pom.xml > Run AS > Maven install
the jar file should also be generated and copied into the folder target.
Note: on your screenshot there are two jar files: core-0.0.1-SNAPSHOT.jar and Serial-0.0.1-SNAPSHOT.jar; remove them (mvn clean or right click > Run AS > Maven clean) before generating the jar file. The reason is Maven can only generate one jar file per Maven module / project, afaik.
You are seeing the intended behavior. A Java program is compiled into an executable form—meaning, .class files and resources. When other users run your program, they will not have access to the source, so your code should not assume your source tree will be available.
Simply put, your code is correct as is. Do not attempt to read the source tree. If you want target/classes to contain up-to-date files, rebuild your project.
A word of caution: Never use the getPath() method of URL to convert a URL to a file name. There are many characters which are not permitted in URLs, and those characters will be “percent-escaped” in order to conform to the URL specification; as a result, the path portion of a URL is not a valid filename! The only correct way to convert a URL to a file is Paths.get(url.toURI()). However, you should not even try to convert a resource to a file at all, because once you move on to packaging your programs in .jar files, your resources will not exist as regular files at all, only as entries in .jar files (which are actually just zip files with some Java-specific entries added).

generate jar without dependencies

I am generating a jar inside a java program by using the jdk system-compiler.
I have some class files which I add into a jar:
JarOutputStream target = new JarOutputStream(jarStream, manifest);
addClassFilesToJar(new File(classDirectory), target);
I have some dependencies which I added into the manifest as:
lib/dependency1.jar
lib/dependency2.jar
...
Now the jar looks up in a sub-folder lib for the dependencies.
The jar itself should not be a runnable standalone jar. I want to include the jar in a project where all the dependencies are already present.
MyApp/ <-- Root folder of project
MyApp/MyJar <-- folder for the generated jar lies
MyApp/dependencies <-- folder for dependencies from MyApp and MyJar
So what do I have to do, to generate the jar in a manner that the classpath argument itself given to the jvm will handle the dependencies? (wanted solution)
Is it possible or do I have to create the manifest so that it points to the MyApp/dependencies folder? (not wanted solution)

why xml files in eclipse project's source directory is copied to target/classes directory?

I have xml files in eclipse project's source directory, like:
src/java/main/com/xx/zz.xml
1.When using eclise to build automatically, xml files are copied to target/classes.
2.When using 'mvn complie', xml files are not copied to target/classes.
For the second case, I found this:why xml files in eclipse project's source directory is not copied to target/classes directory?.
but for the first case, I cannot find any document.
Can someone explain it for me ?
Thanks!
Eclipse works quite a bit differently than standalone Maven. Maven uses javac from JDK. By default javac only processes .java files and generates .class files in the same directory as .java sources. Maven asks it to generate classes in a separate directory and javac only moves .class files there.
The reason for this is that javac gives you more freedom in organizing your source files than most developers use. For instance javac does not care if your class is located in a folder structure that mimics declared packages. You can put a module together by putting several .java files along with some other files like .properties or .xml in the same folder. Your .java files can have different package declarations. For instance you can have files A.java:
package aaa.bbb;
class A {}
and B.java:
package zzz.uuu;
class B {}
If you ask javac to put classes in a target directory, it will create necessary subfolders for .class files, that will resemble the package structure. However it cannot do so for properties and xml files, because they do not contain package declarations. Such 'resource' management is left for the build tool.
Maven expects that you put such resources in another source folder (resources). They will be copied to generated package structure, so you should match it in resource folder. This is why it does not copy non-java files in source folders.
Eclipse expects you to put even .java files in a target package structure and complains if your package declaration does not reflect relative path of the file. This is where you have less freedom compared to bare javac. Thanks to this rule it can copy resources along with .class files and does not need another 'resource' folder.
You can configure Eclipse to use source folder as output folder. Eclipse will not touch resources in this case.
If you right click on the project in eclipse and select 'properties', then Java Build Path you see an input at the bottom for the Default Build Path, which should be target/classes. The source folders are shown in the main dialogue. If you click on the source folders then you can modify each, to exclude the xml files (if that is what you want to do).
Maven will include your xml files automatically if you put them in src/main/resources.
If you don't want to have xml files in build directory, you need to configure eclipse excluded source file types -
right-click on the file in the Project Explorer, choose Resource Configurations > Exclude from Build and choose the configurations that you want.

How to convert AAR to JAR

Situation:
I intend to use a Java library and I only have an AAR file from a Maven repository but I need the JAR file.
Background story:
I tried to compile a library, but its Gradle structure was unstable. So I asked for a compiled jar file, and its developer handed me an aar file from some Maven repository (the developer couldn't compile his own project).
The Gradle configuration was a mess, it depended on multiple libraries and Gradle has thrown some exceptions.
I tried to use it in my IDEA IDE, but it couldn't see it. A library project should be able to be compiled into a jar file, right?
Question:
What should I do to convert that AAR file to a JAR file?
The AAR file consists of a JAR file and some resource files (it is basically a standard zip file with a custom file extension). Here are the steps to convert:
Extract the AAR file using standard zip extract (rename it to *.zip to make it easier)
Find the classes.jar file in the extracted files
Rename it as you like and use that jar file in your project
.aar is a standard zip archive, the same one used in .jar. Just change the extension and, assuming it's not corrupt or anything, it should be fine.
If you needed to, you could extract it to your filesystem and then repackage it as a jar.
1) Rename it to .jar
2) Extract: jar xf filename.jar
3) Repackage: jar cf output.jar input-file(s)
As many other people have pointed out, just extracting the .jar from the .aar file doesn't quite cut it as resources may be missing.
Here are the steps that worked for me (context of Android, your mileage may vary if you have other purposes):
Rename the .aar file to .zip and extract.
The extracted folder is an ADT project that you can import in Eclipse with some minor modifications (see below)!
In the extracted folder rename the contained file classes.jar to whatever you like (in this example myProjectLib.jar) and move it to the lib folder within the extracted folder.
Now in order for Eclipse to accept it you need to put two files into the extracted folder root:
.project
.classpath
To do that, create a new Android dummy project in Eclipse and copy over the files, or copy over from an existing Android project.
Open the .project file and look for the XML name tag and replace the contents of it with myProjectLib (or whatever you called your jar file above) and save.
Now in Eclipse you can File -> New -> Project -> Android Project from existing source.. and point to the extracted folder content.
After import right click on the newly created project, select Properties -> Android, and check Is Library.
In your main project that you want to use the library for, also go to Properties -> Android and add the newly added myProjectLib to the list of dependencies.
For those, who want to do it automatically, I have wrote a little two-lines bash script which does next two things:
Looks for all *.aar files and extracts classes.jar from them
Renames extracted classes.jar to be like the aar but with a new extension
find . -name '*.aar' -exec sh -c 'unzip -d `dirname {}` {} classes.jar' \;
find . -name '*.aar' -exec sh -c 'mv `dirname {}`/classes.jar `echo {} | sed s/aar/jar/g`' \;
That's it!
Android Studio (version: 1.3.2) allows you to seamlessly access the .jar inside a .aar.
Bonus: it automatically decompiles the classes!
Simply follow these steps:
File > New > New Module > Import .JAR/.AAR Package to import you .aar as a module
Add the newly created module as a dependency to your main project (not sure if needed)
Right click on "classes.jar" as shown in the capture below, and click "Show in explorer". Here is your .jar.
Resource based .aar-projects
Finding the classes.jar file inside the .aar file is pretty trivial. However, that approach does not work, if the .aar-project defined some resources (example: R.layout.xyz)
Therefore deaar from CommonsGuy helped me to get a valid
ADT-friendly project out of an .aar-file. In my case I converted
subsampling-scale-image-view. It took me about an hour to set up ruby on my PC.
Another approach is using android-maven-plugin for Eclipse/ADT as
CommonsGuy writes in his blog.
Yet another approach could be, just cloning the whole desired project
as source from git and import it as "Existing Android project"
The 'aar' bundle is the binary distribution of an Android Library Project. .aar file
consists a JAR file and some resource files. You can convert it
as .jar file using this steps
1) Copy the .aar file in a separate folder and Rename the .aar file to .zip file using
any winrar or zip Extractor software.
2) Now you will get a .zip file. Right click on the .zip file and select "Extract files".
Will get a folder which contains "classes.jar, resource, manifest, R.java,
proguard(optional), libs(optional), assets(optional)".
3) Rename the classes.jar file as yourjarfilename.jar and use this in your project.
Note: If you want to get only .jar file from your .aar file use the
above way.
Suppose If you want to include the manifest.xml and resources with your .jar file means
you can just right click on your .aar file and save it as .jar file directly instead of
saving it as a .zip. To view the .jar file which you have extracted, download JD-GUI(Java Decompiler). Then drag and drop your .jar file into this JD_GUI, you can see the .class file in readable formats like a .java file.
If you are using Gradle for your builds - there is a Gradle plugin which allows you to add aar dependency to your java|kotlin|scala|... modules.
https://github.com/stepango/aar2jar
plugins {
id 'java'
id 'com.stepango.aar2jar' version “0.6” // <- this one
}
dependencies {
compileOnlyAar "com.android.support:support-annotations:28.0.0" // <- Use any AAR dependencies
}

Categories