How to change a class inside jasper jar file - java

I'm facing some issues with jasper and I need to try to edit SmapUtil class inside jasper.jar file
However, I'm facing some problems to do so.
I've used jd-gui to decompile the jasper.jar file, took out the SmapUtil.java file, changed the
install method from
static void install(File classFile, byte[] smap) throws IOException {
File tmpFile = new File(classFile.getPath() + "tmp");
SDEInstaller installer = new SDEInstaller(classFile, smap);
installer.install(tmpFile);
if (!classFile.delete()) {
throw new IOException("classFile.delete() failed");
}
if (!tmpFile.renameTo(classFile)) {
throw new IOException("tmpFile.renameTo(classFile) failed");
}
}
to
static void install(File classFile, byte[] smap){
File tmpFile = new File(classFile.getPath() + "tmp");
SDEInstaller installer = new SDEInstaller(classFile, smap);
installer.install(tmpFile);
while (!classFile.delete());
while (!tmpFile.renameTo(classFile));
}
it's basically to keep trying to delete the file if it doens't work the first time.
Now it's where I'm facing my problem.
If I try to compile SmapUtil.java, I face a lot of missing sources.
I've tried using javac -classpath (original)jasper.jar SmapUtil.java, but I still have a lot of sources missings.
I've downloaded a jasper-sources.jar file from god knows where and used that as a -classpath, but the missing sources remains..
How should I do that? I don't think that it should that hard to change 2 lines of a file inside a jar..
Thankss

Compiling a large project such as Tomcat can be a fairly complicated endeavour. If you try decompiling/editing/recompiling without knowing this process you will probably run into a lot of issues.
It might easier (or at least predictable) to build the entire project from sources. Once you have managed to build it, you can try editing the sources.
You should be able to checkout the sources from the project's website.
If you need to patch this class because you feel it's not working correctly, it might be worth trying submitting a bugreport

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();
}
}

How to get a Resource in Apache Brooklyn

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.

Know what methods are in .jar files

I know that there is a plugin for ImageJ that handles NIfTI-1 files (http://rsb.info.nih.gov/ij/plugins/nifti.html).
But all its instructions on that page is to use ImageJ as a standalone program, however I am using its API. How can I know what methods are available in this jar file without its source?
I couldn't find the source code either.
For the supported archives in imageJ (such as DICOM) is quite easy :
public class ImageJTest {
public static void main(){
String path = "res/vaca.dcm";
FileInputStream fis;
ImageView image;
try {
fis = new FileInputStream(path);
DICOM d = new DICOM(fis);
d.run(path);
// Stretches the histogram because the pictures were being
// displayed too dark.
(new ij.plugin.ContrastEnhancer()).stretchHistogram(d, 0.1);
Image picture = SwingFXUtils.toFXImage(d.getBufferedImage(),
null);
// Makes the size standard for thumbnails
image = new ImageView(picture);
} catch (FileNotFoundException e) {
e.printStackTrace();
}
}
}
How can I load the NIfTI-1 files in imageJ ?
Once you have the class files, which are embedded in the jar file (as #Alvin Thompson pointed out, these are just zip files by a different name), you can use the reflection API to mine the class files to get their methods. A sample follows for one class, cribbed from here:
Method[] methods = thisClass.getClass().getMethods(); // thisClass is an instance of the class you're working with
for(Method method : methods){
System.out.println("method = " + method.getName());
}
JAR files are just fancy ZIP files. You can rename the file to foo.zip, then use any unzip utility to expand its contents. You should be able to at least see what the class files are, and the javadocs may be bundled with it (unlikely these days but possible).
However, if you just want to know what methods are available, probably the best way is to add the JAR to the class path of a project in NetBeans, Eclipse, or IntelliJ and use their code completion features to figure out the API methods and classes.
you can do even a decompile of the jar and see the code that is behind each class using a decompiler.
A good one i found: Java Decompiler
JD-GUI home page: http://java.decompiler.free.fr
It does really good it's job. At least in the tasks i had.

NoSuchMethodError for Class File Method toPath()

I'm attempting to copy the file StandardQuestions.csv to a new filename with the following code:
String standardQuestions = "StandardQuestions.csv";
if(new File(standardQuestions).exists()){
try{
Path source = new File(standardQuestions).toPath();
Path dest = new File(filename).toPath();
Files.copy(source,dest);
}
catch(java.io.IOException e){JOptionPane.showMessageDialog(this,"Error: Input/Output exception.");}
}
I get an error thrown on the line Path source = new File(standardQuestions).toPath(); My error message is NoSuchMethodError, method toPath not found in class File. How could the File class not have this method? The program runs correctly on 3-4 machines, but for one user, it always throws this error. Any idea what's causing this? Is there any additional information needed to answer this question?
Since Path and toPath() are relatively recent additions to the Java library (they've been added in Java 7), I'd make sure you are using the same version of Java across the machines.
The first thing that comes up is that one user is running a significantly different version of Java. It might be particularly old or non-standard (GNU Classpath).
Have your user upgrade their Java installation version.

Locating default root folder for an Eclipse project

I am reading a file as follows:
File imgLoc = new File("Player.gif");
BufferedImage image = null;
try {
image = ImageIO.read(imgLoc);
}
catch(Exception ex)
{
System.out.println("Image read error");
System.exit(1);
}
return image;
I do not know where to place my file to make the Eclipse IDE, and my project can detect it when I run my code.
Is there a better way of creating a BufferedImage from an image file stored in your project directory?
Take a look in the comments for Class.getResource and Class.getResourceAsStream. These are probably what you really want to use as they will work whether you are running from within the directory of an Eclipse project, or from a JAR file after you package everything up.
You use them along the lines of:
InputStream in = MyClass.class.getResourceAsStream("Player.gif");
In this case, Java would look for the file "Player.gif" next to the MyClass.class file. That is, if the full package/class name is "com.package.MyClass", then Java will look for a file in "[project]/bin/com/package/Player.gif". The comments for getResourceAsStream indicate that if you lead with a slash, i.e. "/Player.gif", then it'll look in the root (i.e. the "bin" directory).
Note that you can drop the file in the "src" directory and Eclipse will automatically copy it to the "bin" directory at build time.
In the run dialog you can choose the directory. The default is the project root.
From my experience it seems to be the containing projects directory by default, but there is a simple way to find out:
System.out.println(new File(".").getAbsolutePath());
Are you trying to write a plugin for Eclipse or is it a regular project?
In the latter case, wouldn't that depend on where the program is installed and executed in the end?
While trying it out and running it from Eclipse, I'd guess that it would find the file in the project workspace. You should be able to find that out by opening the properties dialog for the project, and looking under the Resource entry.
Also, you can add resources to a project by using the Import menu option.
The default root folder for any Eclipse project is also a relative path of that application.
Below are steps I used for my Eclipse 4.8.0 and Java 1.8 project.
I - Place your file you want to interact with along the BIN and SRS folders of your project and not in one of those folders.
II - Implement below code in your main() method.
public static void main(String [] args) throws IOException {
FileReader myFileReader;
BufferedReader myReaderHelper;
try {
String localDir = System.getProperty("user.dir");
myFileReader = new FileReader(localDir + "\\yourFile.fileExtension");
myReaderHelper = new BufferedReader(myFileReader);
if (myReaderHelper.readLine() != null) {
StringTokenizer myTokens =
new StringTokenizer((String)myReaderHelper.readLine(), "," );
System.out.println(myTokens.nextToken().toString()); // - reading first item
}
} catch (FileNotFoundException myFileException) {
myFileException.printStackTrace(); } } // End of main()
III - Implement a loop to iterate through elements of your file if your logic requires this.

Categories