Does there exist a tool for combining java files - java

I am joining a competition that requires me to put all my java classes in one single .java file. Does there exist a tool that does this for me (including changing the visibility of classes to be able to do this)?
Addition: thanks for trying to help me to read the site of the competition but I quote:
It is possible to make more than one
class for your program, but you will
have to put the source for all classes
in a single .java file (the compiler
will produce multiple .class files
anyway). When you do this, you should
not declare your classes public, or
the compiler will complain about it.
So, only 1 .java file is allowed (no jar) and in that file I can have multiple non-public classes besides my public main class (and not only static inner classes as suggested).

If you have access to Unix-y shell (for Windows, you can install e.g. Git for a decent Bash implementation, and it gives you a great VC tool):
cat *.java | sed 's/public class/class/g' >AllTehCodez.java
Doesn't have to be more complicated than that (unless you have a lot of strings containing the substring "public class", of course).
Edit: Doesn't work for package and imports. But...
(
egrep -h ^package *.java | head -1
egrep -h ^import *.java | sort -u
egrep -hv '^(import|package)' *.java | sed 's/public class/class/g'
) >AllTehCodez.java
This does of course assume all the classes are in the same package.

If we exclude various "bijou scripting haquettes" along the lines suggested above, I seriously doubt that any serious tool exists for doing this.
Why? Because this kind of nonsense goes against all known Java style rules and conventions!
The people behind that website need to be taught about archive file formats; e.g. TAR, ZIP, JAR.
EDIT
I take that back. They DO understand JAR files. Quoting from one of their documents:
Using your own executable Java jar with Caia
You can also use your own Java jar in
Caia competitions. We have written the
jarwrapper for that. The source of
jarwrapper.c is put in the
caia_install_/jarwrapper/
folder. In the Windows distro this is
put into the src/ folder.
Suppose the name of your class file is
JavaPlayer.class. The only thing you
will have to do is to rename the
executable in the bin/ folder from
jarwrapper to JavaPlayer. The
executable now will perform the
command: java -jar JavaPlayer. The jar
file should contain a manifest which
points to the class with the main
method.
In manager.txt you can use the program
name JavaPlayer which refers to the
executable that starts your Java jar
player.

Related

How to compile and run java programs ignoring package info?

I have a pile of .java files. They all have the same class name public MyClass. They all have a main method. They all may or may not have a package declaration at top, and I do not know ahead of time.
I am trying to write a script to compile and run these java programs. This is easy for the files without the package declaration... I just do some cp operations to setup, javac MyClass.java and java MyClass, then rm to teardown. However, the files with the package declaration require special attention. I have a few options that occur to me, including deleting the package lines, or attempting to read the package lines so that I know what the resulting directory structure should be. Both of these require me to go parsing through the .java files, which makes me sad.
Is there a way to compile and run these files without having to parse the .java files? Something like:
javac --ignore_package_structure MyClass.java
would be ideal, but a quick look at the javac man pages suggests that such a thing doesn't exist.
If we can assume that each student submits a single source file named HelloWorld.java, then we can use the "Launch Single-File Source-Code Programs" feature added by JEP 330 in Java 11:
java HelloWorld.java
We don't run javac first, we don't get a .class file (no cleanup needed), and any package declaration is handled automatically.
Remember, the students are still allowed to use many classes, they just all have to be submitted to you in a single source file.
The name of the class doesn't even matter. The first class in the source file is executed.
There isn't any easy way to do this. You could use regex though, and replace all imports with this simple java regex:
"package \w+;"g
Simply stated, you create a Java program to replace all the package names.
How to replace files: Find and replace words/lines in a file

How to compile with a bash script a multipackaged java project that uses jar file

I am developing a project for my Computer Network course.
Actually I ended it, now I need to write a script to compile it, so the teacher will be able to run it
I developed with Netbeans and now I am struggling to compile it by command line.
I have 3 folders (packages)
client: classes of the client process
server: classes of the server process
sharedClasses: classes usefull to both client and server (like User.java)
Also I am using the Gson as a jar file which is needed in the sharedClasses package
for example in sharedClasses there is a class called Message that uses Gson to be transformed in a json string
I tried a lot to create a script that compile it all but every time I get "ClassNotFoundException" or stuff like that: the online guides to understand classpath and so on are pretty bad.
Can someone tell me how to do my script and explain why things are done the way they are? Thanks
Path variables are a concept in all Unix and Windows operating systems. They are not a Java invention, but Java bases its own classpath and module path concepts on them.
A path variable’s value is simply a string which contains a list of file locations, separated by a colon (:) in Unix or a semicolon (;) in Windows.
The most common path variable is simply PATH. (I believe that in Windows, the variable’s canonical name is Path, but environment variables are case-insensitive in Windows, so it can be referred to as PATH in most cases.)
When you try to execute a program on the command line, by specifying a command name with no directory components, the operating system checks each file location in PATH, in order, and for each location which is a directory, the system will look for a match there. The first match is the one the operating system uses.
Java borrows this concept for the classpath. In the very early days of Java, it was exactly the same: If your classpath were /home/giulio:/opt/libraries, and you were looking for a class named com.example.ConnectionFactory, Java would look for a compiled file named com/example/ConnectionFactory.class in /home/giulio and then in /opt/libraries.
It wasn’t long before the classpath was allowed to contain files which are compressed archives of classes, in addition to directories. Your classpath might contain /home/giulio:/opt/libraries/foolib.jar, in which case Java would first check for a requested class in /home/giulio, since that is a directory, and if that failed, it would look for a matching entry in the /opt/libraries/foolib.jar archive file. (Zip files are also acceptable, and in fact a .jar file is really just a zip file with a few special Java-specific entries.)
So, when you want to tell Java to look in certain places for libraries, specify them in the classpath.
For instance, when compiling your client code:
projectroot=`dirname "$0"`
javac -classpath "$projectroot"/sharedClasses/classes \
-d "$projectroot"/client/classes \
"$projectroot"/client/src/*.java
When you run your code:
java -classpath "$projectroot"/sharedClasses/classes:"$projectroot"/client/classes \
edu.acme.giulio.client.Main

Java makefile that creates a folder for the classes

I'm trying without any success to create a java makefile that compiles the java source codes to classes which go in a specific folder. So far, I managed to get the classes but I am really having trouble understanding how to create a folder and place the classes in there.
Here's my code so far:
JC = javac
JVM = java
.SUFFIXES: .java .class
.java.class:
$(JC) *.java
default: .java.class
clean:
$(RM) *.class
I followed a lot of tutorials and still can't figure it out. Basically I have my .java files in my folder. When I run make, I would like the classes to go in /bin folder and if it doesn't exist it gets created
You cannot do what you want to do with suffix rules. You'll have to use pattern rules if you want the output to be placed in a different directory than the source. Pattern rules are a feature of GNU make so hopefully you're using that (you don't say).
Plus, the way you're using suffix rules is not right: you don't declare the suffix rule itself as a prerequisite. You declare the actual files you want to build as prerequisites.
Also, make cannot do this by itself: you have to tell your compiler where to put the output. I'm not a Java person so I can't help you with that. Check your manual.
Your recipe builds all the .java files with a single invocation, which is not really how make works: make wants to translate a single source file (plus possibly other header files etc.) into a single output file.
Replace your suffix rule:
.SUFFIXES: .java .class
.java.class:
$(JC) *.java
with a pattern rule:
$(OUT)/%.class : %.java
mkdir -p $(#D)
$(JC) -o $# $<
(I have no idea if -o is right for javac: as I said you'll have to consult your Java manual). You don't need to declare .SUFFIXES when you use pattern rules.
Then, declare your default target to depend on the output files you want to be generated:
classfiles := $(wildcard *.class)
default: $(classfiles:%.class=$(OUT)/%.java)

Getting all imported classes for a jar

For a given jar, I want to find out all classes (as far as possible) that are used by this jar. Since I have a lot of jars, I want to automate this process. My best idea so far is to
Decompile the jar (I have no experience with that but there should be command line tools).
Look for imports and parse them.
But I hope that someone else has done something like this before and give me advice on this.
Using a specialised tool is probably the way to do this reliably.
However, one really janky way of doing this would be to grab a list of all the .class files in your JAR, put the JAR on the classpath and use javap to get references to other classes:
#!/usr/bin/env bash
javap -cp $1 -v \
`zipinfo -1 $1 '*.class' | sed 's:/:.:g' | sed 's:\.class$::'` | \
grep ' = Class' | sed 's:.*// ::' | sort | uniq
Running this on guava-19.0.jar gives this:
"[[B"
"[B"
"[[C"
"[C"
com/google/common/annotations/Beta
com/google/common/annotations/GwtCompatible
com/google/common/annotations/GwtIncompatible
com/google/common/annotations/VisibleForTesting
com/google/common/base/Absent
com/google/common/base/AbstractIterator
...............................................................
"[Lcom/google/common/util/concurrent/MoreExecutors$DirectExecutor;"
"[Lcom/google/common/util/concurrent/Service$State;"
"[Lcom/google/thirdparty/publicsuffix/PublicSuffixType;"
"[Ljava/io/File;"
"[[Ljava/lang/annotation/Annotation;"
"[Ljava/lang/annotation/Annotation;"
"[Ljava/lang/Class;"
"[Ljava/lang/Comparable;"
"[Ljava/lang/Enum;"
"[[Ljava/lang/Object;"
"[Ljava/lang/Object;"
"[Ljava/lang/reflect/Field;"
"[Ljava/lang/reflect/Method;"
"[Ljava/lang/reflect/Type;"
"[Ljava/lang/reflect/TypeVariable;"
"[Ljava/lang/StackTraceElement;"
"[Ljava/lang/String;"
"[Ljava/net/URL;"
"[Ljava/util/Iterator;"
"[Ljava/util/Map$Entry;"
"[[S"
"[S"
sun/misc/Unsafe
"[[Z"
"[Z"
You'll need more output formatting, and, as others have pointed out, it won't pick up any use of reflection.
How this works:
zipinfo -1 $1 '*.class' will print out the names of all .class files in $1, which is the argument to the script shown. The seds change /s to .s and remove the .class extension, so that you end up with a list of Java-style class names. You could do this more elegantly, but it should work.
The javap invocation puts the jar on the classpath with -cp, and passes all the classes. -v makes it output a lot of information, including some entries which represent references to names of classes. The grep ensures we're only looking at those, the sed removes some extra information we're not interested in. sort | uniq ensures we're not printing the name of any class more than once. It does need a bit more sedding to standardize an output format.
A simple way is to try to compile your code without adding that jar.
Try to compile and looking at the compiler errors is the fastest way to do that.
But remember that a class can be loaded also a runtime using reflection (for example via spring configuration files) and compiling the code without the jar will not inform you about potential errors at runtime.

Java not compiling .class files under $CLASSPATH

I'm trying to figure out how organize source and class files working with packages. I found a very useful tutorial. But I still have some questions.
As far as I understood it is a good practice to have an isomorphism between name of packages and name of the directories where elements of a package are stored. For example if I have a package named aaa.bbb.ccc which contains class ddd it is a good practice to have a class file called "ddd.class" and located in "$CLASSPATH/aaa/bbb/ccc/". Did I get it right?
If it is the case, will Java compiler put *.class files into the correct directory automatically?
I was not able to get this behavior. I set the $CLASSPATH variable to "/home/myname/java/classes". I executed javac KeyEventDemo.java which contains package events;. I expected that javac will create a subdirectory events under /home/myname/java/classes and put the KeyEventDemo.class in this subdirectory.
It did not happen. I tried to help to javac and created "events" subdirectory by myself. I used javac again but it does not want to put class files under "/home/myname/java/classes/events". What am I doing wrong?
You need to use the -d option to specify where you want the .class files to end up. Just specify the base directory; javac will create any directories necessary to correspond to the right package.
Example (based on your question):
javac -d ~/java/classes KeyEventDemo.java
For example if I have a package named
"aaa.bbb.ccc" which contains class
"ddd" it is a good practice to have a
class file called "ddd.class" and
located in "$CLASSPATH/aaa/bbb/ccc/".
Did I get it right?
That's not "good practice" - this is how the Sun JDK expects things to be. Otherwise, it will not work. Theoretically, other Java implementations could work differently, but I don't know any that do.
If it is the case, will Java compiler
put *.class file into a correct
directory automatically?
Yes
What am I doing wrong?
The source code must also already follow this structure, i.e. KeyEventDemo.java must reside in a subdirectory named "events". Then you do "javac events/KeyEventDemo.java", and it should work.
It is not only good practice but a must in most cases.
consider a Java class named:
com.example.Hello
If you store it on the filesystem, it has to got to
/path/to/my/classes/com/example/Hello.java
The compiler (or at least the vast majority) will create the class file at
/path/to/my/classes/com/example/Hello.class
Personally I would not use the CLASSPATH variable to set the path but the -cp option on java. A call to the above "application" could be done with:
java -cp /path/to/my/classes com.example.Hello

Categories

Resources