javax.xml.xpath package provides support for executing XPath expressions against a given XML document. The XPath expressions can be compiled for performance reasons, if it is to be reused.
By the way, the XPath APIs in JAXP are designed to be stateless, which means every time you want to evaluate an XPath expression, you also need to pass in the XML document. Often, many XPath expressions are evaluated against a single XML document. In such a case, it would have been better if the XPath APIs in JAXP were made stateful by passing the XML document once. The underlying implementation would then have had a choice of storing the XML source in an optimized fashion (say, a DTM) for faster evaluation of XPath expressions.
Sample XML to evaluate the XPath expressions :
<?xml version="1.0"?>
<employees>
<employee>
<name>e1</name>
</employee>
<employee>
<name>e2</name>
</employee>
</employees>
Code to evaluate the xml:
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class XpathTest
{
public void parseXml()throws Exception{
//parse an XML to get a DOM to query
DocumentBuilderFactory dbfactory = DocumentBuilderFactory.newInstance();
dbfactory.setNamespaceAware(true);
dbfactory.setXIncludeAware(true);
DocumentBuilder parser = dbfactory.newDocumentBuilder();
Document doc = parser.parse(new File("data.xml"));
//get an XPath processor
XPathFactory xpfactory = XPathFactory.newInstance();
XPath xpathprocessor = xpfactory.newXPath();
//set the namespace context for resolving prefixes of the Qnames
//to NS URI, if the xpath expresion uses Qnames. XPath expression
//would use Qnames if the XML document uses namespaces.
//xpathprocessor.setNamespaceContext(NamespaceContext nsContext);
//create XPath expressions
String xpath1 = "/employees/employee";
XPathExpression employeesXPath = xpathprocessor.compile(xpath1);
String xpath2 = "/employees/employee[1]";
XPathExpression employeeXPath = xpathprocessor.compile(xpath2);
String xpath3 = "/employees/employee[1]/name";
XPathExpression empnameXPath = xpathprocessor.compile(xpath3);
//execute the XPath expressions
System.out.println("XPath1="+xpath1);
NodeList employees = (NodeList)employeesXPath.evaluate(doc, XPathConstants.NODESET);
for (int i=0; i<employees.getLength(); i++) {
System.out.println(employees.item(i).getTextContent());
}
System.out.println("XPath2="+xpath2);
Node employee = (Node)employeeXPath.evaluate(doc, XPathConstants.NODE);
System.out.println(employee.getTextContent());
System..out..println("XPath3="+xpath3);
String empname = empnameXPath.evaluate(doc);
System.out.println(empname);
}
}
Thursday, August 30, 2007
Evaluating XML's XPath Expressions
Posted by Hari at 3:05 AM 2 comments
Caching static and semi-static data in JSP
A JSP is a combination of different sections. For example, the basic sections that a JSP contains are header, footer, navigation and body sections. These sections are generally independent of each other and most of these sections are either static or semi-static. For example, product categories in navigation bar do not change frequently. When you call a JSP, it process all data (static, semi-static and dynamic content) on every request but what we actually require to process is just the dynamic content.
So how can we avoid unnecessary static or semi-static data processing in JSP on every user request?
The recipe for this problem is to identify and cache static and semi-static sections in JSP. Cache should be refreshed at certain times depending up on data refreshing policy. If the data is fully static, you don't have to refresh it but it is a good practice to refresh after every day or week to make sure that any changes are reflected in JSP. A typical example of fully static data section is footer section in your JSP. If the data is semi-static, you should refresh the cache often depending upon its state change policy. An example for semi-static data sections in JSP is header or navigation sections. And some of the body sections also may be semi-static. You can identify and cache them accordingly to improve performance.
we have used free and well-implemented caching code oscache from opensymphony.com in this sample. You can see information on this at www.opensymphony.com/oscache. The below code shows the usage of caching in JSP subsections using oscache.
Code:
<%@ page import="com.cookbook.servlet.helper.*" %>
<%@ taglib uri="oscache" prefix="cache" %>
<cache:cache>
<%! public String getItems(){
ItemsHelper helper = new ItemsHelper();
List list = helper.getAllItems();
StringBuffer body = new StringBuffer();
if(list != null && list.size()>0){
ListIterator iter = list.listIterator();
body.append("<TABLE border=\"1\"><TBODY>");
while (iter.hasNext()) {
Item item = (Item) iter.next();
body.append("<TR>");
body.append("<TD>");
body.append(item.getName());
body.append("</TD>");
body.append("<TD>");
body.append(item.getDesc());
body.append("</TD>");
body.append("</TR>");
}
body.append("</TBODY></TABLE>");
}
return body.toString();
}
%>
Discussion:
You can cache any section of your JSP as shown in the above code. You can also give the location of cache store as application or session scope parameter in the oscache tag. The default is application scope. You should be careful when you use session scope in a clustered environment where the session data could be stored as persistent sessions depending upon configuration. There will be overhead involved in persistent sessions if the session data is huge.
In order to utilize oscache, all you need to do is just download the zip file from opensymphony.com/oscache, unzip it and place oscache.jar in /web-inf/lib directory, place oscache.properties and taglib.tld files in web-inf directory and configure web.xml file for this tag library as follows.
<taglib>
<taglib-uri>oscache</taglib-uri>
<taglib-location>/WEB-INF/oscache.tld</taglib-location>
</taglib>
You can also configure other caching properties in oscache such as cache capacity and type of algorithm in oscache.properties file.
Posted by Hari at 12:48 AM 0 comments Labels: jsp
Wednesday, August 29, 2007
String replace in a File
This is the code to replace the existing String with the given String in a given file present in the given directory.
Code:
public void replaceStringInFile(File dir, String fileName, String match, String replacingString){
try {
File file = new File(fileName);
if(file.isDirectory()||!file.exists()){
//the fileName specified is not a file hence returning.
return;
}
file = new File(dir, fileName);
RandomAccessFile randomAccessFile = new RandomAccessFile(file, "rw");
long fpointer = randomAccessFile.getFilePointer();
String lineData = "";
while((lineData =randomAccessFile.readLine()) != null){
fpointer = randomAccessFile.getFilePointer() - lineData.length()-2;
if(lineData.indexOf(match) > 0){
System.out.println("Changing string in file "+file.getName());
randomAccessFile.seek(fpointer);
randomAccessFile.writeBytes(replacingString);
// if the replacingString has less number of characters than the matching string line then enter blank spaces.
if(replacingString.length() < style="color: rgb(153, 0, 0);">int difference = (lineData.length() - replacingString.length())+1;
for(int i=0; i < style="color: rgb(51, 51, 255);">" ");
}
}
}
}
} catch (FileNotFoundException ex) {
ex.printStackTrace();
} catch (IOException ex) {
ex.printStackTrace();
} catch (Exception ex){
ex.printStackTrace();
}
}
Posted by Hari at 4:11 AM 2 comments Labels: Files
Friday, August 24, 2007
Time Scheduling in Java
Some Applications need to execute certain jobs and tasks at an exactly a perticular time or at regular time intervals. Let us see how to schedule the tasks to achieve that functionality, for this purpose java provides a standerd API Timer in java.util package, Now we will see how Java developers can implement such a requirement using the standard Java Timer API.
A Sample Code To use Timer:
import java.util.Timer;
import java.util.TimerTask;
public class Remainder {
Timer timer;
public Remainder ( int seconds ) {
timer = new Timer ( ) ;
timer.schedule ( new TimerTask(){
public void run ( ) {
System.out.println ( "Your scheduled Task Starts...." ) ;
timer.cancel ( ) ; //Terminate the Timer after task completion
}
} , seconds*1000 ) ;
}
public static void main (String args[]){
System.out.println ( "Before schedule task." ) ;
new Remainder ( 5 ) ;
System.out.println ( "Task scheduled." ) ;
}
}
Posted by Hari at 12:19 AM 0 comments Labels: scheduling
Wednesday, August 22, 2007
Working with Online xml
Some times we required to access the xml files which are present at online or working with another site it is required to access the data through the xml.This artical deals how to work with online xml file.The below sample code parse the xml file throuth the given URL String and returns the DOM Document.Then we can access the xml file using that document.
Code:
import java.io.InputStream;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class DOMProvider{
public Document getDocument(String strUrl)throws Exception{
URL url=new URL(strUrl);
InputStream in=url.openStream();
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder builder=factory.newDocumentBuilder();
Document document=builder.parse(in);
return document;
}
}
After getiing the document from getDocument() if you want to get retrive entire node list that can be done by
NodeList nodeList=document.getElementsByTagName("NameofTheNode");
By these all the node will come in that Node List.If you want to retrive the attributes with in that Node,that can be done by
Node node= nodeList.item(indx);
NamedNodeMap attrs=node.getAttributes();
String value=nnm.getNamedItem("AttributeNamewithinthatNode").getNodeValue();
Sample Work:
http://www.w3schools.com/xml/note.xml is in the form of
to work with the above xml as:
Code:
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
public class Test{
public static void main(String[] args)throws Exception{
DOMProvider test=new DOMProvider();
Document doc=test.getDocument("http://www.w3schools.com/xml/note.xml");
Node node=doc.getDocumentElement();
System.out.println("Root Node: "+node.getNodeName());
NodeList list=node.getChildNodes();
int childsLen=list.getLength();
for(int index=0;index
Node tag=list.item(index);
if(tag.getNodeType()==Node.ELEMENT_NODE){
NodeList val=tag.getChildNodes();
int vallen=val.getLength();
System.out.println("Tag Name: "+tag.getNodeName());
for(int i=0;i
if(val.item(i)!=null)
System.out.println("Tag Value: "+val.item(i).getNodeValue());
}
System.out.println();
}
}
}
}
OutPut:
Root Node: note
Tag Name: to
Tag Value: Tove
Tag Name: from
Tag Value: Jani
Tag Name: heading
Tag Value: Reminder
Tag Name: body
Tag Value: Don't forget me this weekend!
Posted by Hari at 3:44 AM 0 comments Labels: xml
ZIP Files in Java
The ZIP file format has become extremely popular for the distribution and storage of files. ZIP files allow for compression, making transporting a set of files from one location to another faster.Depending on the source file types being compressed, ZIP files can provide significant space savings. ZIP archives can also maintain the directory structure of files that are compressed, making the ZIP format a formidable file transport mechanism.
The java.util.zip package allows for the programmatic reading and writing of the ZIP and GZIP formats.Learning how to use the offerings of the java.util.zip package might best be facilitated via example.
The below example FileZip class has only one method makeZip(), takes two parameters,
String Array- Pass the files paths as strings which you want to Zip.
String - The target zip file name to save as.
Code:
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipFiles {
public String makeZip(String[] filesToZip,String zipFileName){
byte[] buffer = new byte[18024];
if(!zipFileName.endsWith(".zip")){
zipFileName+=".zip";
}
try {
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFileName)));
// Set the compression ratio
out.setLevel(Deflater.DEFAULT_COMPRESSION);
// iterate through the array of files, adding each to the zip file
int filesSiz=filesToZip.length;
for (int i = 0; i < style="color: rgb(0, 153, 0);">// Associate a file input stream for the current file
File file2Zip=new File(filesToZip[i].toString());
InputStream in = new BufferedInputStream(new FileInputStream(file2Zip));
// Add ZIP entry to output stream.
String fileExctNm=filesToZip[i].substring(filesToZip[i].lastIndexOf("/")+1);
out.putNextEntry(new ZipEntry(fileExctNm));
// Transfer bytes from the current file to the ZIP file
int len;
while ((len = in.read(buffer)) > 0)
{
out.write(buffer, 0, len);
}
// Close the current entry
out.closeEntry();
// Close the current file input stream
in.close();
}
// Close the ZipOutPutStream
out.close();
}
catch (IllegalArgumentException iae) {
iae.printStackTrace();
}
catch (FileNotFoundException fnfe) {
fnfe.printStackTrace();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
return new File(zipFileName).toString();
}
}
Posted by Hari at 2:22 AM 2 comments Labels: zip
Tuesday, August 21, 2007
Receive Application Errors via Yahoo Messenger
Logging application events is a central part of many applications. Most of our applications do some sort of logging, using a variety of mechanisms. When things go wrong, the first course of action is usually to get hold of the application log file and go through its contents.
Someone supporting live, deployed applications would probably appreciate the importance of getting notified of application errors as early as possible. It is much better to be proactive dealing with errors, rather than waiting to hear from the customer that something seems to have gone wrong.
How about getting notified immediately, by utilizing an instant messenger client like Yahoo Messenger? (Read More..)
Posted by Hari at 2:49 AM 0 comments Labels: log4j
Monday, August 20, 2007
RSS feed of your application logs.
Heres a sample and simple Log4J RSS appender.
1. to log4j.appender.rss=org.lorecraft.rssappender.RSSAppender
2. log4j.appender.rss.port=1234
3. log4j.appender.rss.maxSize=10
4. log4j.appender.rss.layout=org.apache.log4j.PatternLayout
5. log4j.appender.rss.layout.ConversionPattern=%d {ABSOLUTE} %5p %c {1}: %L - %m%n
6. log4j.rootLogger=info, rss
Posted by Hari at 11:31 PM 1 comments Labels: log4j
Screen Capture
The java.awt.Robot class provides several opportunities for fun. One opportunity involves building a screen-capture utility. This Java code uses Robot to capture the contents of the primary screen device.
To capture the screen with the Robot class, Capture must first create a Robot object. ScreenCapture class's printScreen()method attempts to create this object by invoking Robot's public Robot() constructor. If successful, a reference to a Robot configured to the primary screen device's coordinate system returns. If the platform does not support low-level control , a java.awt.AWTException is thrown. A java.lang.SecurityException is thrown if the platform doesn't grant permission to create a Robot. Hopefully, you will not encounter either exception.
Assuming a Robot object is created, createScreenCapture() invokes the Capture class's constructor .Capture obtains the dimensions of the primary screen device by invoking Toolkit.getDefaultToolkit ().getScreenSize ();. Because Robot's public BufferedImage createScreenCapture(Rectangle screenRect) method, which is used to perform a screen capture, requires a java.awt.Rectangle argument, the constructor converts the java.awt.Dimension object to a Rectangle object via rectScreenSize = new Rectangle(dimScreenSize);. The screen capture is done with java.awt.Robot.
Then call createScreenCapture() by passing required parameters through the reference of ScreenCapture Class where your application needs to capture the screen, or from public static void main(String[] a).
Code:
import java.awt.AWTException;
import java.awt.Rectangle;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import javax.imageio.ImageIO;
import javax.swing.JFrame;
class ScreenCapture {
public void printScreen() throws AWTException, IOException {
// capture the whole screen
BufferedImage screencapture = new Robot().createScreenCapture(new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()) );
// Save as JPEG
File file = new File("screencapture.jpg");
ImageIO.write(screencapture, "jpg", file);
// Save as PNG
File file = new File("screencapture.png");
ImageIO.write(screencapture, "png", file);
}
//To capture a specific area
public void printScreen(int x, int y, int width, int height) throws AWTException, IOException {
// capture the whole screen
BufferedImage screencapture = new Robot().createScreenCapture( new Rectangle( x, y, width, height));
// Save as JPEG
File file = new File("screencapture.jpg");
ImageIO.write(screencapture, "jpg", file);
// Save as PNG
File file = new File("screencapture.png");
ImageIO.write(screencapture, "png", file);
}
//To capture a specific visual object
public void printScreen(JFrame myframe) throws AWTException, IOException {
// capture the whole screen
BufferedImage screencapture = new Robot().createScreenCapture(new Rectangle( myframe.getX(), myframe.getY(), myframe.getWidth(), myframe.getHeight() ) );
// Save as JPEG
File file = new File("screencapture.jpg");
ImageIO.write(screencapture, "jpg", file);
// Save as PNG
File file = new File("screencapture.png");
ImageIO.write(screencapture, "png", file);
}
}
Posted by Hari at 10:41 PM 0 comments Labels: images
Sunday, August 19, 2007
Parsing & Binding XML
XML has arrived. Configuration files, application file formats, even database access layers make use of XML-based documents.Here is an accessible introduction to the two most widely used APIs
Application XML:
XML Processing:
Three traditional techniques for processing XML files are:
* Using a programming language and the SAX API.
* Using a programming language and the DOM API.
* Using a transformation engine and a filter
Xerses:
The Xerces Java Parser 1.4.4 supports the XML 1.0 recommendation and contains advanced parser functionality, such as support for the W3C's XML Schema recommendation version 1.0, DOM Level 2 version 1.0, and SAX Version 2, in addition to supporting the industry-standard DOM Level 1 and SAX version 1 APIs and supports Xml-dtd validation. For more Info http://xerces.apache.org/xerces-j/
DOM Vs SAX Parsing:
Dom create the dom tree by parsing the given xml where as SAX Creates the Event Structure as shown below
DOM Example:
// Create a Xerces DOM Parser
DOMParser parser = new DOMParser();
// Parse the Document and traverse the DOM
parser.parse(xmlFile);
Document document = parser.getDocument();
traverse (document);
// Traverse DOM Tree and print elements names
private void traverse (Node node) {
int type = node.getNodeType();
if (type == Node.ELEMENT_NODE)
System.out.println (node.getNodeName());
NodeList children = node.getChildNodes();
if (children != null) {
for (int i=0; i< color="#005e00">getLength(); i++)
traverse (children.item(i));
}
}
SAX Example:
public class BasicSAX extends org.xml.sax.helpers.DefaultHandler {
public BasicSAX (String xmlFile) {
//Create a Xerces SAX Parser
SAXParser parser = new SAXParser();
//Set Content Handler
parser.setContentHandler (this);
//Parse the Document
parser.parse(xmlFile)
}
// Start Element Event Handler
public void startElement (String uri, String local, String qName, Attributes atts) {
System.out.println (local);
}
JAXP:
The Java API for XML Processing (JAXP) supports processing of XML documents using DOM, SAX, and XSLT. JAXP enables applications to parse and transform XML documents independent of a particular XML processing implementation.
SAX with JAXP:
import java.xml.parsers.*
import javax.xml.parsers.SAXParserFactory
import org.xml.sax.*
...
SAXParserFactory factory =SAXParserFactory.newInstance();
factory.setValidating(true);
SAXParser parser = factory.newSAXParser();
parser.parse("sample.xml", handler);
// can also parse InputStreams, Files, and
// SAX input sources.
DOM With JAXP:
import java.xml.parsers.*
import javax.xml.parsers.DocumentBuilderFactory;
import org.w3c.dom.*
...
DocumentBuilderFactory factory =DocumentBuilderFactory.newInstance();
factory.setValidating(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse("sample.xml");
// can also parse InputStreams, Files, and
// SAX input sources.
XSLT with JAXP
import java.xml.transform.*;
import javax.xml.transform.TransformerFactory;
...
Transformer transformer;
TransformerFactory factory =TransformerFactory.newInstance();
// Create a transformer for a particular stylesheet.transformer = factory.newTransformer(new StreamSource(stylesheet));
// Transform the source xml to System.out.
transformer.transform(new StreamSource(sourceId),new StreamResult(System.out));
Posted by Hari at 11:10 PM 0 comments Labels: xml
Friday, August 17, 2007
XML Validation with DTD in Java
One thing you may have heard about XML is that it lets the system developer define custom tags. With a nonvalidating parser, you certainly have that ability. You can make up any tag you want and, as long as you balance your open and close tags and don't overlap them in absurd ways, the nonvalidating SAX parser will parse the document without any problems. For example, a nonvalidating SAX parser would correctly parse and fire events for the document in below.
A Well formed meaningless Document
Why DTD?
Two people generally can't talk to one another unless they speak a mutually understood language. Likewise, two programs can't communicate via XML unless the programs agree on the XML language they use. A DTD defines a set of rules for the allowable tags and attributes in an XML document, and the order and cardinality of the tags. Programs using the DTD must still agree on what the tags mean (semantics again), but a DTD defines the words (or, the tags) and the grammatical rules for a particular XML dialect.
In this section, you will learn to va
Program Description:
Validating a XML file against a DTD needs a xml file and its DTD document. First of all construct a well-formed xml file along with a DTD file . This DTD file defines all elements to keep in the xml file. After creating these, we parse the xml file using the parse() method and generates a Document object tree. The setErrorHandler() method invokes an object of DoucmentBuilder. Enable the setValidating() method of the factory to "true". If we pass 'true' the parser will validate xml documents otherwise not. To validate xml file , pass the DTD file as setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "fileinfo.dtd") in the transformer object.
DTD For above xml:
import java.io.FileInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
public class ValidateXML {
public static void main(String args[]) {
try{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(true);
DocumentBuilder builder = factory.newDocumentBuilder();
builder.setErrorHandler(new org.xml.sax.ErrorHandler() {
//To handle Fatal Errors
public void fatalError(SAXParseException exception)throws SAXException {
System.out.println("Line: " +exception.getLineNumber() + "\nFatal Error: "+exception.getMessage());
}
//To handle Errors
System.out.println("Line: " +e.getLineNumber() + "\nError: "+e.getMessage());
}
//To Handle warnings
System.out.println("Line: " +err.getLineNumber() + "\nWarning: "+err.getMessage());
}
});
Document xmlDocument = builder.parse(new FileInputStream("fileinfo.xml"));
DOMSource source = new DOMSource(xmlDocument);
StreamResult result = new StreamResult(System.out);
TransformerFactory tf = TransformerFactory.newInstance();
Transformer transformer = tf.newTransformer();
transformer.setOutputProperty(OutputKeys.DOCTYPE_SYSTEM, "fileinfo.dtd");
transformer.transform(source, result);
}
catch (Exception e) {
System.out.println(e.getMessage());
}
}
}
Posted by Hari at 4:05 AM 4 comments Labels: xml
Tuesday, August 14, 2007
Generating SAX Parsing Events by Traversing an XML Document
If you have developed a set of handlers for SAX events, it is possible to use these handlers on a source other than a file. This example demonstrates how to use the handlers on a DOM document.
By DOM Parser:
DocumentBuilder builder=DocumentBuilderFactory.newInstance().newDocumentBuilder()
Document doc = builder.parse(new File("inputFile.xml"));
//Prepare the DOM source
Source source = new DOMSource(doc);
//Set the systemId of the source. This call is not strictly necessary
URI uri = new File("inputFile.xml").toURI();
source.setSystemId(uri.toString());
// Create a handler to handle the SAX events
DefaultHandler handler = new MyHandler();
try {
// Prepare the result
SAXResult result = new SAXResult(handler);
// Create a transformer
Transformer xformer = TransformerFactory.newInstance().newTransformer();
// Traverse the DOM tree
xformer.transform(source, result);
} catch (TransformerConfigurationException e) {
} catch (TransformerException e) {
}
// DefaultHandler contain no-op implementations for all SAX events.
// This class should override methods to capture the events of interest.
class MyHandler extends DefaultHandler {
}
By SAX Parser:
SAXParser parser=SAXParserFactory.newInstance().newSAXParser();
//Prepare InputSource
InputSource inputSource=new InputSource(new FileInputStream("inputFile.xml"))
// Create a handler to handle the SAX events
DefaultHandler handler = new MyHandler();
try{
parser.parse(inputSource, handler);
} catch (TransformerConfigurationException e) {
} catch (TransformerException e) {
}
// DefaultHandler contain no-op implementations for all SAX events.
// This class should override methods to capture the events of interest.
class MyHandler extends DefaultHandler {
}
Posted by Hari at 6:00 AM 0 comments Labels: xml
Hack any Java class using Reflection
Ever wondered what evil power can be unleashed when using reflection? Do you think private methods are really only accessible from within the declaring class? Do you think that a private field can only be modified from within the declaring class? No? That's what I thought!! In this blog, I will try to demonstrate that it is always important to correctly set the security properties of your applications. For instance, let's look at the following example where we successfully retrieve a private password from another class:
Code:
class A {
private static String getPassword() {
return "someHighlyPreciousPassword";
}
}
public class Test {
public static void main(String[] args) throws Exception {
Class cl = Class.forName("A");
java.lang.reflect.Method[] m = cl.getDeclaredMethods();
m[0].setAccessible(true);
String password = (String) m[0].invoke(null, null);
System.out.println("I got it:" + password);
}
}
Output:
I got it: someHighlyPreciousPasswordOk, the example is not really sexy. Let's mess up a class that implements the Singleton pattern. In the normal case, a singleton object is supposed to be the only instance of a given class. To achieve this, we usually declare the class constructor private, so that no one can invoke it. Well, as demonstrated below, with reflection we can bypass this restriction and create a second "singleton object".
Code:
class A {
public static final A singleton = new A("I'm the only instance of class A");
private String name;
private A(String name) {
this.name = name;
}
public String toString() {
return this.name;
}
}
public class Test {
public static void main(String[] args) throws Exception {
Class cl = Class.forName("A");
java.lang.reflect.Constructor[] c = cl.getDeclaredConstructors();
c[0].setAccessible(true);
A anotherA = (A) c[0].newInstance(new Object[]{"Not anymore!!"});
System.out.println(A.singleton);
System.out.println(anotherA);
}
}
Output:
I'm the only instance of class A
Not anymore!!Using this technique, you can create an instance of any non-abstract class, even if all its constructors are declared private. For instance, below we create an instance of the Math class even though it is useless since the Math class has no instance method. Still, it is possible to do it.
Code:
public class Test {
public static void main(String[] args) throws Exception {
Class cl = Class.forName("java.lang.Math");
java.lang.reflect.Constructor[] c = cl.getDeclaredConstructors();
c[0].setAccessible(true);
Math mathInstance = (Math) c[0].newInstance(null);
System.out.println(mathInstance);
}
}
Output:
java.lang.Math@1cde100
Finally, let's mess with the Runtime
class which has one private static field for storing the current Runtime
instance. This is another example of a badly implemented singleton class. Let's look at the code below. We first retrieve the current runtime object and display it (3-4). Then, we set the Runtime.currentRuntime
static field to null, which means that all successive calls to Runtime.getRuntime()
will yield null (6-9) since currentRuntime
is initialized at class loading time. We then get the currentRuntime
field again and display its value (11-12). And finally, we try to use the current runtime to execute a command for displaying the content of the current directory (14). The output talks for itself.
Code:
public class Test {
public static void main(String[] args) throws Exception {
Runtime r = Runtime.getRuntime();
System.out.println("Before: Runtime.getRuntime() yields " + r);
Class cl = Class.forName("java.lang.Runtime");
java.lang.reflect.Field f = cl.getDeclaredField("currentRuntime");
f.setAccessible(true);
f.set(null, null);
r = Runtime.getRuntime();
System.out.println("After: Runtime.getRuntime() yields " + r);
r.exec("dir"); //raises NullPointerException!!
}
}
All this could have been avoided if the currentRuntime
field had been declared final. Nothing prevents setAccessible(true)
to be called on the field (8) but when the set(null, null)
method is called, IllegalAccessException
is thrown with the message "Field is final".
I'm pretty sure that there is a huge amount of code out there that could be broken this way. Watch out!!
Bottom line: singleton fields should always be declared private static final!!! Moreover, make sure you never grant ReflectPermission and RuntimePermission.accessDeclaredMembers in the java.policy
file of your production code.
Posted by Hari at 3:18 AM 0 comments Labels: Hacks
Monday, August 13, 2007
Creating thumbnails with Java
This programm loads an image via java.awt.Toolkit, scales it down to a user-defined resolution and saves it as a Developer required format.
This code is a works as a modeule to crate thumbnail for the given image with the given width and height.So you
can call this method by passwing the original image, file name to save as, width and height.
To use this program do the following:
* Insert the code in any Class
* Create the object for the class
* Call the method by passing the required parameters mentiond above
The file image.jpg must exist already, thumbnail.jpg will be created (and any existing file of that name overwritten).
Now let's see how this program works.
First the input image is loaded via Toolkit and MediaTracker.
The third and fourth program argument contain the maximum size of the thumbnail to be created. The actual size of the thumbnail will be computed from that maximum size and the actual size of the image (all sizes are given as pixels). The code that does this is not really very readable, and also not essential to loading and saving image files. But it is necessary to create a thumbnail that is scaled correctly.
As an example, if the two arguments for the maximum thumbnail size are both 100 and the image that was loaded is 400 times 200 pixels large, we want the thumbnail to be 100 times 50 pixels large, not 100 times 100, because the original image is twice as wide as it is high. A 100 times 100 pixel thumbnail would contain a very skewed version of the original image.
Now that we have determined the size of the thumbnail we create a BufferedImage of that size, named thumbImage. We ask for a Graphics2D object for that new thumbnail image and call its drawImage method to draw the original image on that new image. The call to drawImage does the actual scaling. The rendering hints for bilinear interpolation can be left out (remove the line with graphics2D.setRenderingHint) if high quality is not required and speed more important. Note that embedded color profiles can make scaling with bilinear interpolation very slow with certain versions of the JDK; this supposedly gets better with JDK 6. If you can't rule out that you are dealing with such JPEGs, make sure to not use the interpolation hint or thumbnail creation will take forever (well, two minutes on a modern system on a 6M image). For nicer results (at least in some cases) try RenderingHints.VALUE_INTERPOLATION_BICUBIC instead of RenderingHints.VALUE_INTERPOLATION_BILINEAR. Same warning as above.
In order to save the scaled-down image to a JPEG file, we create a buffered FileOutputStream with the second argument as name and initialize the necessary objects from the com.sun.image.codec.jpeg package.
Code:
import java.awt.Container;
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.MediaTracker;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import com.sun.image.codec.jpeg.JPEGCodec;
import com.sun.image.codec.jpeg.JPEGEncodeParam;
import com.sun.image.codec.jpeg.JPEGImageEncoder;
public class ThumbNail2 {
public static void main(String[] args) throws Exception {
new ThumbNail2().createThumbnail("C:/personal/a.jpg", "C:/personal/thumb.jpg", 50, 30);
}
public void createThumbnail(String imgFilePath,String thumbPath,int thumbWidth,int thumbHeight)throws Exception{
Image image = Toolkit.getDefaultToolkit().getImage(imgFilePath);
MediaTracker mediaTracker = new MediaTracker(new Container());
mediaTracker.addImage(image, 0);
mediaTracker.waitForID(0);
double thumbRatio = (double)thumbWidth / (double)thumbHeight;
int imageWidth = image.getWidth(null);
int imageHeight = image.getHeight(null);
double imageRatio = (double)imageWidth / (double)imageHeight;
if (thumbRatio < imageRatio) {
thumbHeight = (int)(thumbWidth / imageRatio);
} else {
thumbWidth = (int)(thumbHeight * imageRatio);
}
BufferedImage thumbImage = new BufferedImage(thumbWidth,
thumbHeight, BufferedImage.TYPE_INT_RGB);
Graphics2D graphics2D = thumbImage.createGraphics();
graphics2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
graphics2D.drawImage(image, 0, 0, thumbWidth, thumbHeight, null);
BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(thumbPath));
JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
JPEGEncodeParam param = encoder.
getDefaultJPEGEncodeParam(thumbImage);
int quality = 100;
param.setQuality((float)quality / 100.0f, false);
encoder.setJPEGEncodeParam(param);
encoder.encode(thumbImage);
out.close();
}
}
To Run the Above code from the console application as Below
public class ThumbNailEx {
public static void main(String[] args) throws Exception {
new ThumbNail2().createThumbnail("C:/img_path/a.jpg", "C:/image_path/thumb.jpg", 50, 30);
System.out.println("Thumbnail Created Successfully");
}
}
Posted by Hari at 9:48 PM 11 comments Labels: images
Thursday, August 9, 2007
Maintain Config files
Why and where we have to maintain Config Files?
Every application either accicentaly or by design have some configuaration parameters in configuaration ( .ini or .xml or .config or .properties) files.
-The config files are important in cases where certain information cannot be kept in database e.g. database connection details.
- It is good habit of maintaining config files.If the outside parameters for the application which may change in future maintain those in config files, Then it is easy to modify those parameters with out affecting the application.
- There are chances of making a mistake while editing it.
- There are some environment properties (outside our applications) which the runtime reads from the config files.
- Its usually easy to edit config files using any text editor.
- Its easier for development as it doesnot require any infrastructural code to read these parameters from the database.
- In the case of clustered application, the same parameters need to be synchronised to all nodes in the cluster.
- In case there are multiple environments, maintaining different files with most common, but some different values is cumbersome.
Posted by Hari at 12:43 AM 0 comments Labels: Tips
Wednesday, August 8, 2007
Password Encryption
Have you ever felt the need to encrypt those plain text passwords you store in the database for your application authentication?
Would you like to encrypt the plain text in such a way that it can only be interpreted by your application and does not make sense for a naked eye?
Where has your password been?
Most of the web sites today have some sort of a registration module where a user is asked to choose a username/password combination. This data gets stored in the database. You might wonder if the password you provide will be kept well-protected (read encrypted). In case you are the person designing such backend registration component, why not give your users peace of mind by encrypting their passwords?
There are several message-digest algorithms used widely today.
Algorithm | Strength |
---|---|
MD5 | 128 bit |
SHA-1 | 160 bit |
Typical registration scenario
Here is a typical flow of how our message digest algorithm can be used to provide one-way password hashing:
1) User registers with some site by submitting the following data:
username | password |
---|---|
jsmith | mypass |
2) before storing the data, a one-way hash of the password is created: "mypass" is transformed into "5yfRRkrhJDbomacm2lsvEdg4GyY="
The data stored in the database ends up looking like this:
username | password |
---|---|
jsmith | 5yfRRkrhJDbomacm2lsvEdg4GyY= |
3) When jsmith comes back to this site later and decides to login using his credentials (jsmith/mypass), the password hash is created in memory (session) and is compared to the one stored in the database. Both values are equal to "5yfRRkrhJDbomacm2lsvEdg4GyY=" since the same password value "mypass" was used both times when submitting his credentials. Therefore, his login will be successful.
Note, any other plaintext password value will produce a different sequence of characters. Even using a similar password value ("mypast") with only one-letter difference, results in an entirely different hash: "hXdvNSKB5Ifd6fauhUAQZ4jA7o8="
plaintext password | encrypted password |
---|---|
mypass | 5yfRRkrhJDbomacm2lsvEdg4GyY= |
mypast | hXdvNSKB5Ifd6fauhUAQZ4jA7o8= |
As mentioned above, given that strong encryption algorithm such as SHA is used, it is impossible to reverse-engineer the encrypted value from "5yfRRkrhJDbomacm2lsvEdg4GyY=" to "mypass". Therefore, even if a malicious hacker gets a hold of your password digest, he/she won't be able determine what your password is.
Sample Code To Achieve:
import java.io.UnsupportedEncodingException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.myorg.SystemUnavailableException;
import sun.misc.BASE64Encoder;
import sun.misc.CharacterEncoder;
public final class PasswordService
{
private static PasswordService instance;
private PasswordService()
{
}
public synchronized String encrypt(String plaintext) throws SystemUnavailableException{
MessageDigest md = null;
try{
md = MessageDigest.getInstance("SHA"); //step 2
}
catch(NoSuchAlgorithmException e){
throw new SystemUnavailableException(e.getMessage());
}
try{
md.update(plaintext.getBytes("UTF-8")); //step 3
}
catch(UnsupportedEncodingException e){
throw new SystemUnavailableException(e.getMessage());
}
byte raw[] = md.digest(); //step 4
String hash = (new BASE64Encoder()).encode(raw); //step 5
return hash; //step 6
}
public static synchronized PasswordService getInstance(){ //step 1
if(instance == null){
instance = new PasswordService();
}
return instance;
}
}
Posted by Hari at 2:35 AM 0 comments Labels: Security