Showing posts with label Java. Show all posts
Showing posts with label Java. Show all posts

Tuesday, July 7, 2009

Find Bugs

Find Bugs is an eclipse plugin which shows the common errors in Java. I use the eclipse plugin, and as a Best Practice for java developers this should be used while development. :)

e.g.
For a piece of code the following error was received

When piece of code in given below:-
1. Long id = request.getId();
2.
3. if(request == null || id == null) {
4. throw new RuntimeException("id cannot be null");
5. }
Find the error if you can... :)

The check for request == null is fruitless, since if request is null the line 1 will fail. Below is provided the corrected code and thus removes the bug.
1. if(request == null || request.getId() == null) {
2. throw new RuntimeException("id cannot be null");
3. }

Long id = request.getId();


A note of caution, the code inspection tools need to be used intelligently, it may sometimes flag code as bug that may have been done for some valid reason. Ignore them in this case.

Tuesday, June 23, 2009

Keystore Setup for OWSM

Purpose
Set up the keystore to be used by Oracle Web Services Manager (OWSM) to perform digitial signature validation.

Prerequisites
The client's public key (.cer file) should be provided.

Steps
Step 1: Creating server store.
Use the java keytool command to create a keystore.

keytool -v -genkey -keyalg RSA -keysize 1024 -keystore [keystore-name.jks] -storepass [serverpass]-alias server1 -keypass [server]

Example server output:-
keytool -v -genkey -keyalg RSA -keysize 1024 -keystore server-store-1jks -storepass serverpass -alias server1 -keypass server
What is your first and last name?
[Unknown]: SashCo
What is the name of your organizational unit?
[Unknown]: DPP
What is the name of your organization?
[Unknown]: SashWorld
What is the name of your City or Locality?
[Unknown]: Dubai
What is the name of your State or Province?
[Unknown]: Dubai
What is the two-letter country code for this unit?
[Unknown]: AE
Is CN= SashCo, OU=DPP, O= SashWorld, L=Dubai, ST=Dubai, C=AE correct?
[no]: Y
Generating 1,024 bit RSA key pair and self-signed certificate (MD5WithRSA)
for: CN= SashCo, OU=DPP, O= SashWorld, L=Dubai, ST=Dubai, C=AE
[Storing server-store-1jks]

Step 2
Add the provided public key to the java keystore.

keytool -import -noprompt -trustcacerts -keystore [keystore-file.jks] -storepass [serverpass] -alias [alias] -file [certificate-file.cer]

Example server output:-
keytool -import -noprompt -trustcacerts -keystore server-store-1.jks -storepass serverpass -alias sashwat -file sashwat.cer

Certificate was added to keystore

Step 3:
Use the following command to list the certificates in the .jks file
keytool -list -keystore -storepass

keytool -list -keystore [keystore-file.jks] -storepass [serverpass]

Acronym / Abbreviation
OWSM - Oracle Web Services Manager
keystore-name.jks - Name of the new java keystore
serverpass - password of the keystore
keypass - password of the private key
clientalias - alias for the client
certificate-file.cer - the certificate file provided by client

Helpful Links:-
Java keytool reference :-

Monday, August 4, 2008

Sash IP Messenger

Forces compelling to learn RCP:-
For quite some time I have been involved in creating helper projects, small projects that help in coding, generate code etc. This seemed to be a very nice and effective way of producing a very nice UI for them.
It’s eclipse; I like the IDE and is my IDE of choice for Java. Using RCP would mean I could integrate the tools written with eclipse.
I have done some Swing coding, it’s not a very easy to write a nice UI. RCP provided a dream of producing feature rich applications written in java fast and clean.
Since the release of eclipse 3 the documentation there have been major modifications in the way eclipse works (or so I have read) and made RCP integration easier. I started with reading a book Eclipse Rich Client Platform: Designing, Coding, and Packaging Java Applications - By Jeff McAffer, Jean-Michel Lemieux. Very nice book, made the journey simpler.
When I had just started coding one of my leads had told me, the best way to learn was to implement a small project. Execute it like a real project, and you would learn what are the where a tool can be best utilized, what is the effort required for implementation and any issues with the tool. Quite a few books are written in similar fashion where they build one application from start to the end. So does the book Eclipse Rich Client Platform. This book creates a chat application using the XMPP protocol and smack library.
I decided to create a UI for IP Messenger, since this is the messaging tool I usually use and it does not have any nice UI. This is a free messenger available and does not need a server.
I have just downloaded Ganymede so I created a new Eclipse plug-in project in Ganymede. I realized later that the version I should have used is Eclipse Europa since Ganymede is still to be used widely. I was able to convert the project into an eclipse 3.3 compatible plugin, the only drawback was that I could not use an image with menu manager. I had to replace

MenuManager helpMenu = new MenuManager("&Help", AbstractUIPlugin.imageDescriptorFromPlugin(Application.PLUGIN_ID, IImageKeys.HELP) ,"help");

I had to remove the image from the menu manager to use it with Eclipse Europa. Now it is compatible with both Eclipse Europa and Eclipse Ganymede.
The prerequisites for learning RCP are basic knowledge of Java, SWT and Eclipse. I am still learning new things about RCP everyday but creating a feature rich UI using RCP was fun and fast. The working RCP application can be found at: http://code.google.com/p/sashipmessenger/downloads/list
Features:-
Customized splash screen, the project uses a very simple splash screen. I have just replaced the splash.bmp file in the project. I decided not to use a progress bar, which can easily be added. More customizations are possible. While googling I also found a nice article that used the splash screen for login.



Saving the workbench state. Include the code in the class that extends WorkbenchAdvisor.

public void initialize(IWorkbenchConfigurer configurer) { super.initialize(configurer); configurer.setSaveAndRestore(true); }
This ensures that the windows appear in the same location as when you closed the views.

Use perspective to decide the initial layout of the application
Minimize to system tray. RCP provides a good level of integration with the system tray.



Also to provide a notification when a message has arrived and application is not visible or inactive, the icon changes to a message and a system beep is sound.


In the menu preferences have been added, the preferences configuration is as shown below. This integrates nicely with the eclipse editor if this is used as an eclipse plugin.



The configurations shown are the display name for the user, group name and the log folder. The messenger shows the chat history with a user. The broadcast address is used to specify address not in the same subnet.
The application has two different views and an editor. The contacts view shows all the users on IP Messenger. The console view at the bottom provides information about different events. The different events like message read event, user removed message added etc. can be seen. The editor is open whenever a message is sent or received from a user.


The messenger saves the chat log. When the editor is opened again the log is greyed out.


The views can be closed and moved around.


The view can be opened from the menu.



Users can be found from the find item on the top of contacts view.


The RCP application can be integrated with the existing eclipse. Just drop the plugin jar into the plugin folder of eclipse dump.

Wednesday, September 26, 2007

Java Annotations

I was preparing a talk on annotations in java and ended up learning a few cool stuff.

I believe the utility of annotations would be the freedom from implementing interfaces like the JUnit test case and the EJB 3.0.

New and innovative uses for annotations are also likely to come up.

Annotations is cool if used intelligently. Now if a developer wants to use a annotations to save configuration values I ask can you blame annotations.

The problem lies sometimes in the fuzziness of what is configuration values. Say in hibernate in by bean I hard code my table name, is my table name configuration. I believe not, but in some cases it could be true. I haven't seen table names being different in production environment and development but using annotations makes it less flexible.

Sun could have made the creation of annotations more 'Java like' @interface to define an annotation and the definition of the default values....

The annotation processing tool is also very interesting. The tool ties us with the Sun jdk and probably would evolve as a part of standard SDK distribution.

Presentation is available at : http://sashwat.gupta.googlepages.com/Annotations.pdf
Example code is available at : http://sashwat.gupta.googlepages.com/annotation.zip

Wednesday, July 4, 2007

ClassCastException

When do we get a ClassCastException?

The java documentation of ClassCastException states:-

Thrown to indicate that the code has attempted to cast an object to a subclass of which it is not an instance.
For example, the following code generates a ClassCastException:

Object x = new Integer(0);
System.out.println((String)x);


The statement seems to be a very simple, but not when different class loaders are involved. Another scenario when this exception occurs is when the class accesses an object of the same class loaded by another class loader hierarchy.

I was determined to write a simple code to simulate the exception.

So I wrote two classes to be loaded by different classloaders.

package classldr;

public class Tree {

private String name = "sash";

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}
}

//------ different file ----------//
package classldr;

public class Person{

public void doIT(Object t)
{
//try to create the typecast exception here!!
System.out.println("Tree planted : " + ((Tree)t).getName());
}
}



I would try to load these classes using different classloaders and simulate the error.

So I created instances of URLClassLoader and did the same. I had to make sure that the class creating the class loaders could not access these classes, as it was the parent of the URLClassLoader and would have actually loaded the class due to delegation model followed by the classloaders.

package classldr;

import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

public class TestClassLoader {

public static void main(String[] args) throws Exception {

/*
* Class loader 1 to create instance of Tree class. I have put the
* Person and Tree classes in C:\classldr\ directory.
*/
ClassLoader cl1 = new URLClassLoader(new URL[] { new URL(
"file:C:\\") });
Class c = cl1.loadClass("classldr.Tree");
Object treeNewInstance = c.newInstance();

/*
* Class loader 2 to create instance of Person and Tree class.
*/
ClassLoader cl2 = new URLClassLoader(new URL[] { new URL(
"file:C:\\") });
Class treeClass = cl2.loadClass("classldr.Tree");
Class personTreeClass = cl2.loadClass("classldr.Person");
Object personTreeObj = personTreeClass.newInstance();
Object treeClassObj = treeClass.newInstance();
Method method = personTreeClass.getMethod("doIT",new Class[]{Object.class} );


//pass the object of tree loaded by cl 1 to
//person object loaded by cl 1
method.invoke(personTreeObj,new Object[]{ treeClassObj});

//pass the object of tree loaded by cl 1 to
//person object loaded by cl 2
//should throw a ClassCastException
method.invoke(personTreeObj,new Object[]{ treeNewInstance});
}
}



After I spent a lot of time on this I realized it could be demonstrated in a much simpler way. I decided that my URLClassLoader could be a child of the Bootstrap class loader, not necessarily the system class loader.

package classldr;

import java.net.URL;
import java.net.URLClassLoader;

public class TestClassLoader2 {

public static void main(String[] args) throws Exception {

//get current class location
URL resource = TestClassLoader2.class.getClassLoader().getResource(".");

//create a new classloader to load this class,
//have the parent of the classloader as null
ClassLoader cl1 = new URLClassLoader(new URL[] { resource }, null);
Class c = cl1.loadClass("classldr.TestClassLoader");

//this throws ClassCastException
TestClassLoader2 treeNewInstance = (TestClassLoader2) c.newInstance();
}
}


This code was good enough to simulate the exception.

Finally I successfully generated the exception and was feeling very stupid about my first method. :(

Friday, June 8, 2007

Finding Class Version

Facing class mismatch error, I decided to find the JRE version and the compiler version used to compile the class file.

Its easy to get the details of the JRE version using System.getProperties(). A more difficult task was to find out the version of the class file. I could not find any API which did it :(. But I did find out that these details were available in the class file, so I wrote a small code to determine if the class will run on the current version of JRE.
import java.io.DataInputStream;
import java.io.FileInputStream;

public class ClassRuntimeVersion {
public static void main(String[] args) throws Exception {

FileInputStream fis = null;
DataInputStream dis = null;

try {
if (args.length != 1) {
throw new Exception("specify the class file");
}

fis = new FileInputStream(args[0]);
dis = new DataInputStream(fis);

if (dis.readInt() != 0xCAFEBABE) {
throw new Exception("not a class file");
}

short minorVersion = dis.readShort();
short majorVersion = dis.readShort();

System.out.println("Java Class version info");
System.out.println("1.6 50");
System.out.println("1.5 49");
System.out.println("1.4 48");
System.out.println("1.3 47");
System.out.println("-------------------------");

float classVersion = Float.parseFloat(majorVersion + "."
+ minorVersion);
System.out.println("Class file compiled version : " + classVersion);

float jreJavaVersion = Float.parseFloat(System
.getProperty("java.class.version"));

System.out.println("JRE version : " + jreJavaVersion);
if (jreJavaVersion < classVersion) {
System.err.println("You r dead dude, versions did not match");
}
} finally {
if (fis != null) {
fis.close();
}
if (dis != null) {
dis.close();
}
}
}
}

Tuesday, May 29, 2007

Sampling Java SE 6

A lot of new features and API enhancements have been introduced in Java 6 (Mustang). Some of them are discussed briefly.

Compiler API

The new Java Compiler API allows invoking a compiler, gives access to diagnostics, and control over how files are read through a file manager. The file manager allows applications such as IDEs and JSP servers to keep all files in memory, which significantly speeds up compilation. Sun's open source Java EE implementation, GlassFish claims to have already benefited from this API.

//get the java compiler reference
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();

//compile the Java class
int compilationResult = compiler.run(
null,null,null, "C:\\Person.java");

The code snippet shows how to compile a Java file using the Compiler API.

Web Service

The new web services stack provides support for writing XML web service applications. The java classes can be exposed as a .NET interoperable web service with a simple annotation. Java SE 6 adds new parsing and XML to Java object-mapping APIs, previously only available in Java EE platform implementations or the Java Web Services Pack.

To create a web service on Mustang create a java class, annotate it as shown below.

@WebService
@SOAPBinding(style = SOAPBinding.Style.RPC)
public class Hello {
public String echo() {
return "Hello THBS";
}
}


To deploy the web service we just need to write the main method.

public static void main (String [] args) throws Exception {
Hello server = new Hello();
Endpoint.publish("http://localhost:9090/Hello", server);
}


The deployment can be verified by displaying the wsdl file on the browser
http://localhost:9090/Hello?wsdl. This feature is intended to be used for testing only.

Scripting for the Java Platform

Java SE 6 provides support for scripting, which enables the developers to integrate Java technology and scripting languages by defining a standard framework and interface to do the following:
• Access and control Java based objects from a scripting environment
• Create web content with scripting languages
• Embed scripting environments within Java technology-based applications

The Java Platform, Standard Edition (Java SE), does not mandate any particular script engine, but it does include the Mozilla Rhino engine for the JavaScript programming language.

ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
jsEngine.eval("function helloWorld(){"
+ " println('Hello, world!'); "
+ " return 's';" + "}");

Invocable invocableEngine = (Invocable) jsEngine;
invocableEngine.invokeFunction("helloWorld", (Object[]) null);

The example shows how to invoke a JavaScript function using java.

See: Carpe diem: Mustang released

Database

The Java SE 6 development kit co-bundles the all-Java JDBC database, Java DB based on Apache Derby. Out of the box developers have a database that can be used that implements the latest version of JDBC and is embeddable within desktop Java applications. Java DB has a small memory footprint and is fully transactional.

Also provided is JDBC 4.0, a well-used API with many important improvements, such as special support for XML as an SQL datatype and better integration of Binary Large OBjects (BLOBs) and Character Large OBjects (CLOBs) into the APIs.

Desktop Development

Desktop application development just became simpler with Java 6. It provides better platform look-and-feel in Swing technology, LCD text rendering, and snappier GUI performance overall. Java applications can integrate better with the native platform with things like new access to the platform's System Tray and Start menu. At long last, Java SE 6 unifies the Java Plug-in technology and Java WebStart engines, just makes sense. Installation of the Java WebStart application got a much needed makeover.

A new class added to the Java platform is java.awt.Desktop. It allows Java applications to launch associated applications registered on the native desktop to handle a java.net.URI or a file.


Desktop d = Desktop.getDesktop();
//opens the application associated with the txt file in your OS
d.browse(new URI("c:/text_file.txt"));


Similar enhancements have been made to make the development of a java desktop application simpler.

Class file structure update:

The class file structure in Java SE 6 has been modified to provide a much faster and simpler class verification process. The idea is to split the old verification process into two phases: type inferencing (compile time) and type checking (runtime). The new verifier (called the type-checking verifier) no longer needs to infer types because it uses type information embedded in the Java class file to check byte code type consistency. Removing the type inferencing process from the verifier significantly reduces the complexity of verifier code and improves verification performance. This provides performance improvements in byte code verification and thus class loading and start up time.

Monday, May 21, 2007

Mustang :- The Desktop bonus

One of the problems with java over the years is the lack on Desktop support. Sun has taken a major step with the release of Java 6.These changes have brought in a whole new flavour to the java desktop applications.

Java 6 now has system tray support.Now icons in the system tray can be added with menus and event handlers.Some applications that run in the background (eg mail client) can be seen in the system tray. Notifiers can also be provided to sent notification messages. The code demonstrates the use of the new functionality.
package com.sash.java6;

import java.awt.*;
import java.awt.TrayIcon.MessageType;
import java.awt.event.*;
import java.io.File;
import java.net.URI;

public class SystemTrayTest {

public SystemTrayTest() throws Exception {

if (SystemTray.isSupported()) {

SystemTray tray = SystemTray.getSystemTray();
//image for tray icon
Image image = Toolkit
.getDefaultToolkit().getImage("any_image.gif");

ActionListener exitListener = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.exit(0);
}};

//pop menu for the tray
PopupMenu popup = new PopupMenu();
MenuItem alertItem = new MenuItem("Message");
popup.add(alertItem);

MenuItem defaultItem = new MenuItem("Exit");
defaultItem.addActionListener(exitListener);
popup.add(defaultItem);

final TrayIcon trayIcon = new TrayIcon(image, "Tray Demo", popup);

alertItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
trayIcon.displayMessage(
"Finally",
"Desktop support for Java",
MessageType.INFO);
}
});

trayIcon.setImageAutoSize(true);
trayIcon.setToolTip("Tooltip test");
tray.add(trayIcon);
} else {
System.err.println(
"System tray is currently not supported.");
}
}

public static void main(String[] args) throws Exception {

//the system tray icon test
new SystemTrayTest();
}
}


Other enhancements include, the introduction of the Desktop API. Using this API now its very easy to open the default email client etc. It also provides an API to open any given file with the default application associated in the OS.

Desktop d = Desktop.getDesktop();
//guess what?
//opens the application associated in your OS with the jpg file
d.browse(new URI("c:/text_file.txt"));

This code opens the default program associated with the text files, on my windows system it opens the file in notepad.

API enhancements have been made to the getTotalSpace, getUsableSpace and getFreeSpace methods have been added. These are very useful enhancements made.

Very nicely done by the sun guys, finally adding some much needed support for the desktop applications.
:)

Friday, April 20, 2007

Source code generator

Recently I had to write some code in Delphi .NET . Instead of using 'getters' and 'setters' like in java using properties is preferred. But writing the properties by hand is very painful.. Imagine having to write all the getters and setters in java by hand and your IDE ( I preferably use Eclipse ) not generate it. So I decided to write a code generator.

The first decision I had to make was which language to use. I can code in Java, C# and Delphi. I did not find any feature present in any of the languages that would make them preferable for the job, so I used Java since I am much more comfortable using this language.

The I had to decide what would be the input and output.

Input would be like :-
 // Make these properties!!!!!
id : integer; // the id

//blah blah comment
id2 : integer;
// so whats up

line_code : string;
rate : integer;



Output would be like:-

   //Variables :::::::

_id : integer;
_id2 : integer;
_line_code : string;
_rate : integer;


//Properties :::::::
Property id : integer
read _id
write _id ;
Property id2 : integer
read _id2
write _id2 ;
Property line_code : string
read _line_code
write _line_code ;
Property rate : integer
read _rate
write _rate ;




I also decided the coolest way to get the input and write the output was the clipboard. So I had to just copy the text into the clipboard and execute the java program. This would write the output into the clipboard.

Now the implementation specific details begin.
The first thing I needed to do was to remove the comments. Also what was needed was to get two lists, one containing the variable names and the other containing the variable types.

And then output it in any way wanted... My complete code is given below..

import java.awt.Toolkit;
import java.awt.datatransfer.Clipboard;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.StringSelection;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.UnsupportedFlavorException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SashClipboard
{

public static final String NEWLINE = "\n";

public static String TAB = " ";

public static void main(String[] args) throws UnsupportedFlavorException,
IOException
{

//gets data from clipboard
String data = copyFromClipboard();

// System.out.println(data);

//get the diff lies
String[] lines = data.split(NEWLINE);

// System.out.println(Arrays.asList(lines));
//remove comments '//' and if two stmts exist on same line
ArrayList linesList = removeSingleLineCommentAndMultiStmt(lines);

// System.out.println(linesList);

ArrayList varNameList = new ArrayList();
ArrayList varTypeList = new ArrayList();

getVarAndType(linesList, varNameList, varTypeList);

String output = createOutput(varNameList, varTypeList);

System.out.println(output);

//copy data to clipboard
copyToClipboard(output);
}

private static void copyToClipboard(String output)
{
StringSelection ss = new StringSelection(output);
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
cb.setContents(ss, null);
}

public static String copyFromClipboard() throws UnsupportedFlavorException,
IOException
{
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
Transferable contents = cb.getContents(null);
Object transferData = contents.getTransferData(DataFlavor.stringFlavor);
String data = transferData.toString();
return data;
}

private static String createOutput(ArrayList varNameList,
ArrayList varTypeList)
{
StringBuilder output = new StringBuilder();

output.append("//Variables :::::::\n\n");
for (int i = 0; i < varNameList.size(); i++)
{
output.append(TAB + "_" + varNameList.get(i) + " : "
+ varTypeList.get(i) + ";" + NEWLINE);
}

output.append("\n\n//Properties :::::::\n");

for (int i = 0; i < varNameList.size(); i++)
{
output.append(TAB + "Property " + varNameList.get(i) + ":"
+ varTypeList.get(i) + NEWLINE + TAB + TAB + " read " + "_"
+ varNameList.get(i) + NEWLINE + TAB + TAB + " write "
+ "_" + varNameList.get(i) + ";" + NEWLINE);
}
return output.toString();
}

private static void getVarAndType(ArrayList linesList,
ArrayList varNameList, ArrayList varTypeList)
{
for (int i = 0; i < linesList.size(); i++)
{
String line = linesList.get(i);
String[] colonSeperated = line.split(":");
if (colonSeperated.length != 2)
{
System.out.println("Something wrong " + line);
continue;
}

String[] commaSeperated = colonSeperated[0].split(",");

for (String var : commaSeperated)
{
varNameList.add(var);
varTypeList.add(colonSeperated[1]);
}
}
}

/**
* Remove comments '//' and if two stmts exist on same line
* e.g a: integer; b:string;
*
* if input on a line is
* a:integer; b:integer; //to do something
*
* it will give two lines i.e
* a:integer;
* b:integer
*
* @param lines multi lines
* @return a list containg different lines
* and without single line comments
*/
private static ArrayList removeSingleLineCommentAndMultiStmt(
String[] lines)
{
ArrayList linesList = new ArrayList();
for (int i = 0; i < lines.length; i++)
{
String[] comment = lines[i].split("//");

String[] multiStmt = comment[0].split(";");
for (String str : multiStmt)
{
if (!str.trim().equals(""))
{
linesList.add(str.trim());
}
}
}
return linesList;
}
}


It was not just the fact that I code generate the properties and save time, I also loved writing this code..

I think the code is self explanatory. If any doubts please do post your doubts.

Tuesday, March 27, 2007

Java accesibility hack

Invoking a private method/variable using reflection in java is very simple. In the example I invoke the private methodA of the class.

public class A
{
private void methodA()
{
System.out.println("methodA");
}
}
This is pretty simple. But can we achieve this by setting setAccessible(true) for the Method.

public class B
{
public static void main(String[] args) throws Exception
{
A a = new A();
Method method = A.class.getDeclaredMethod("methodA");
method.setAccessible(true);
method.invoke(a,new Object[]{});
}
}


And the result is that methodA is printed on the console.

Now can we achieve this without the use of reflection? Yes we can and thats the java hack. I'll
explain how...

First write the class A, but mark the methodA as public. Then create a class B as

public class B
{
public static void main(String[] args) throws Exception
{
A a = new A();
a.methodA();
}
}

Compile class A and class B.
javac A
javac B

Run class B.
java B

The output is methodA as expected.

But where is the hack?
Now it comes..

Change the class A and change methodA as private again. Compile class A again only.
javac A

Do not try to compile class B, it will result in an comilation error. Now run B
java B

The output is not an Runtime error, but is methodA.

You can decompile using any java decompiler and see that methodA is still private but still B can invoke it. The probable reason for this is that accessiblity is a compile time check not a runtime one. At runtime it cannot be determined whether it is invoked using this hack or reflection. I cannot think of any other reason this is not done.

Friday, March 2, 2007

Running a class not in the classpath

This piece of code displays the invocation of a class not in the classpath of the application. This can be used to write utilities.

Say I have a jar file present on my system in say a directory "c:/MyUtils" (I have used windows locations, no reason why this should not work on any other OS) named SystemUtils.jar which has a main class in a class com.sash.DoIt. This jar is not in my classpath and I need to execute it. The following piece of code executes the main method.
 File file = new File("c:\\MyUtils\\SystemUtils.jar");
ClassLoader cl = new URLClassLoader(new URL[] { file.toURI().toURL()});
Class cls = cl.loadClass("com.sash.DoIt");
Method mainMethod = cls.getDeclaredMethod("main", new Class[]{String[].class});
mainMethod.invoke(null, new Object[]{null});

Very interesting stuff. Never used it but waiting for the first oppertunity to use this in one of my projects :).

Tuesday, February 27, 2007

Mustang released

The announcement made here is pretty old. It’s been in beta phase for some time and the final release has also been made some time back. Here I visit some of the new features in Mustang. I have been using Eclipse as a preferred java editor for a long time, though I've tried NetBeans, JDeveloper etc. Eclipse 3.2 has support for Mustang.
The feature I would talk about is the Scripting feature. This feature can be used to execute scripts in various languages. Mustang ships with the Rhino scripting engine for JavaScript. Its pretty interesting. I tried out various features of the Rhino Engine.

The major questions which I wanted an answer to were:
1. How to share data between Java and JavaScript?
2. Where is the utility of such scripting?
3. Can I add different Scripting engines?


The answer to the first question you can find in the example below. The sending of data from Java to Javascript was very simple and it even JavaScript recognized objects from user created classes (Java Car class has an object on which getName method could be invoked by the JavaScript). The return value also works. The List created in Java and modified in JS reflected in Java again. Awesome! Totally awesome!
Now the reasons given to use scripting language was what I am not convinced with.(Scripting for the Java Platform --> Reasons to Use a Scripting Language). I think the reasons to use scripting would be more specific, like using existing test scripts in some scripting language.
We can add different scripting engines according to specs.

Sample code explaining most of the concepts:-
import java.lang.reflect.Method;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import javax.script.Invocable;
import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public class TheScript
{
private final static String METHOD_HELLO = "function helloWorld(){"
+ " println('Hello, world!'); " + " return 's';" + "}";

private final static String METHOD_HELLO_NAME = "function helloName(){"
+ " println('Hello,'+ name.getName() +' !'); " + " return 's';"
+ "}";

private final static String METHOD_HELLO_LIST = "function helloList(){"
+ "var x;" + "var names = namesListKey.toArray(); "
+ " for(x in names)" + " {" + " println('Hello,'+ names[x] +' !');"
+ " }" + " namesListKey.add(\"king\");" + "}";

private final static String THE_JAVA_SCRIPT = METHOD_HELLO
+ METHOD_HELLO_NAME + METHOD_HELLO_LIST;

public static void main(String[] args) throws ScriptException,
NoSuchMethodException
{
ScriptEngineManager mgr = new ScriptEngineManager();
ScriptEngine jsEngine = mgr.getEngineByName("JavaScript");
jsEngine.eval(TheScript.THE_JAVA_SCRIPT);

// simple java method

// invoke method METHOD_HELLO
Invocable invocableEngine = (Invocable) jsEngine;
invocableEngine.invokeFunction("helloWorld", (Object[]) null);

System.out.println("---------------------------------");
// simple java method where java objects are used by javascript

// The parameter type is user defined object
// which is converted into a javascript object
// i.e I can use getName method of Car class
Car car = new Car();
car.setName("Sash");

// invoke method METHOD_NAME
jsEngine.put("name", car);
Object invokeFunction = invocableEngine.invokeFunction("helloName",
(Object[]) null);

// the return type should have been mapped by script provider
// Mozilla Rhino provides the mapping for number and string types
System.out.println(" --------------------------------- "
+ invokeFunction + " ----");

List namesList = new ArrayList(Arrays.asList(new String[] { "sash",
"siva", "baldie" }));
jsEngine.put("namesListKey", namesList);
invocableEngine.invokeFunction("helloList", (Object[]) null);

System.out.println(namesList);
System.out.println("---------------------------------");

}

public static class Car
{
private String name;

public String getName()
{
return name;
}

public void setName(String name)
{
this.name = name;
}

}
}

References:

http://www.mozilla.org/rhino/ScriptingJava.html
http://java.sun.com/developer/technicalArticles/J2SE/Desktop/scripting/

Thursday, January 11, 2007

Invoker class

For a long time I've been thinking how to write code to get the name of the calling class, some days back I was reading an article which arose my curiosity again. I was successful doing it in two ways.

1. Stacktrace method

One of the hints which I got was our exception class, whenever an exception is thrown we get the whole stack strace, which includes the invoking classes.
Throwable t = new Throwable(); 
StackTraceElement callerClass = t.getStackTrace()[1];
System.out.println(callerClass.getClassName());


Gets the class name :)

2. Security Manager method

class SM extends SecurityManager {
@Override
public Class[] getClassContext() {
return super.getClassContext();
}
}



SM sm = new SM();
Class[] classContext = sm.getClassContext();
System.out.println(classContext[2].getName());

Bingo, got the class name. getClassContext() is a protected method, to use it we need to extend security manager or use it as I've done above.