Monday, December 19, 2011

Encrypting the password in the configuration files of MYBATIS

In the configuration file of ORM tools like hibernate , mybatis, jpa we have a common concern that the password of the database is exposed to each and every developer or whoever has the access to the code. It’s a great security concern for the enterprise which has the sensitive data in the database. So there comes the need to have an encrypted password in the configuration file and read it programmatically and make the decrypted password available to the application only at the run time. So that no one can read the password.
We can achieve this through any encryption codec algorithm providers like apache, sun and many more. I am demonstrating here using apache codec which is opensource library to encrypt and decrypt the password. I am demonstrating it for mybatis but the same can be achieved through similar process in hibernate or JPA.
We have a database properties file which contains all the database related properties like username, password, driver and url. The configuration file reads from this property file. We will be storing the password (in encrypted form in this property file) and while reading we will decrypt the password and give it to the builder for creating a sqlSession. To write to the database properties file we will use the command line argument to provide it with the properties file.
Lets have a look at the properties file:
driver=com.ibm.db2.jcc.DB2Driver
url=jdbc:db2://localhost:50000/CDR
username=db2admin
password=VXR!tre6g

Lets have a look at the configuration.xml file.

















]]>



Lets have a look at the PasswordService.java file which will write to the database.properties file and will have functions like encrypt and decrypt the password.
public final class PasswordService {
private static PasswordService instance;

public PasswordService() {
}

public synchronized String encrypt(String plaintext) throws Exception {
if(plaintext != null)
return new String(Base64.encodeBase64(plaintext.getBytes()));
return null;
}

public synchronized String decrypt(String plaintext) throws Exception {
if(plaintext != null)
return new String(Base64.decodeBase64(plaintext.getBytes()));
return null;
}
public static synchronized PasswordService getInstance()
{
if (instance == null) {
instance = new PasswordService();
}
return instance;
}
public static void main(String args[]){
try {
String encryped = getInstance().encrypt(args[0]);
Properties prop = new Properties();
InputStream in = ConnectionFactory.class.getResourceAsStream("prop.properties");
prop.load(in);
Properties databaseprop = PropsUtils.load(prop.getProperty("databasepropertiesfile"));
Enumeration e = databaseprop.keys();
while(e.hasMoreElements()){
String str = (String)e.nextElement();
if(str.equals("password")){
databaseprop.setProperty("password", encryped);
}
}
URL url = ClassLoader.getSystemResource(prop.getProperty("databasepropertiesfile"));
FileOutputStream fos =new FileOutputStream(url.getFile());
databaseprop.store(fos, null);
} catch (Exception e) {
e.printStackTrace();
}
}
}


Lets have a look at the ConnectionFactory.java file which will create the sqlSession.

public class ConnectionFactory {

private static SqlSessionFactory sqlMapper;
private static Reader reader;
static {
try {
Properties prop = new Properties();
InputStream in = ConnectionFactory.class.getResourceAsStream("prop.properties");
prop.load(in);
Properties databaseprop = PropsUtils.load(prop.getProperty("databasepropertiesfile"));
String encrypedPassword = databaseprop.getProperty("password");
String password = PasswordService.getInstance().decrypt(encrypedPassword);
databaseprop.setProperty("password", password);
String conf =prop.getProperty("configurationfile");
reader = Resources.getResourceAsReader(conf);
sqlMapper = new SqlSessionFactoryBuilder().build(reader,databaseprop);

} catch (Exception e) {
e.printStackTrace();
}
}

public static SqlSessionFactory getSession() {
return sqlMapper;
}
}

Lets have a look at the PropUtils.java file

public class PropsUtils {
private PropsUtils() { }
/**
* Load a properties file from the classpath
* @param propsName
* @return Properties
* @throws Exception
*/
public static Properties load(String propsName) throws Exception {
Properties props = new Properties();
URL url = ClassLoader.getSystemResource(propsName);
props.load(url.openStream());
return props;
}

/**
* Load a Properties File
* @param propsFile
* @return Properties
* @throws IOException
*/
public static Properties load(File propsFile) throws IOException {
Properties props = new Properties();
FileInputStream fis = new FileInputStream(propsFile);
props.load(fis);
fis.close();
return props;
}
}

Tuesday, December 6, 2011

Encapsulating the subclass creation in superclass

One of the common mistake that the programmers make it to instantiate the subclass directly rather than by the common interface. Lets explain it by a simple example. Say you have Animal , Tiger, Lion, Mouse and Bird as the classes. When you will design you will make Animal as the super class and Tiger, Lion, Mouse and Bird as its subclasses. Say Tiger has its own constructor. The client instantiate using
Tiger tig = new Tiger();
What is wrong with this? According to design principle one should always program to an interface. Something like this
Animal tig = new Tiger();
But why ? The basic reason for that is once developers write code that’s talks directly to the subclass type rather than through its common interface then its common tendency to change the subclass code in response to the needs of the client. And this will result into a number of special cases logic in the subclasses and will lead to maintenance problem.
How to restrict this ?
The answer to this is to encapsulate the creation of subclasses in the superclass. Something like this in the Animal abstract class add a method like
public abstract class Animal {
public Animal (){}
public static Animal createTiger(){return new Tiger()}
}
In Tiger subclass do something like this
public class Tiger{
protected Tiger(){}
}
What we have done is to modify the constructor of Tiger to provide it with protected access and have a creation method in the Animal. This will solve a lot of problem regarding the maintenance of code in the future.

Sunday, December 4, 2011

Dojo charting and capturing the event on mouse event on particular chart

Dojo as a javascript library is known for a long time. Its look and feel , features, ease to code make them a great library to construct a java script based UI.
To add to the features another thing has been added in dojo 1.2 and made very rich till the 1.6 is charting. Charting comes in the dojox.charting library and has a support for wide varieties of charting like pie, area, bar, line graph, grid and many more.
In this article I will look at line chart as well as pie chart. I will try to present a way to get the action invoked on different slices of a pie chart. The action can be rendering a different pie chart, line graph or a simple alert message.
Lets look at the require statements in the rendering of a pie chart.
dojo.require("dojox.charting.Chart2D");
dojo.require("dojox.charting.themes.MiamiNice");
dojo.require("dojox.charting.plot2d.Pie");
dojo.require("dojox.charting.action2d.Highlight");
dojo.require("dojox.charting.action2d.MoveSlice");
dojo.require("dojox.charting.action2d.Tooltip");
All the require statement are very easy to understand. The theme I have chosen is MiamiNice. You can choose a theme according to your choice. The dojox.charting.action2d.Tooltip is basically for the Tooltip that the pie chart would use. dojox.charting.action2d.MoveSlice is for the slice to move when we will get the mouse pointer at the particular slice.

Lets look at the function to render the pie chart.
var dc = dojox.charting;
var pieData = [5,6,4];
var chart1 = new dojox.charting.Chart2D("simplechart");
chart1.setTheme(dojox.charting.themes.MiamiNice);
chart1.addPlot("default", {
type: "Pie",
font: "normal normal 11pt Tahoma",
fontColor: "black",
labelOffset: -30,
radius: 80
});
chart1.addSeries("Series 1",pieData);
var anim_a = new dc.action2d.MoveSlice(chart1, "default");
var anim_b = new dc.action2d.Highlight(chart1, "default");
var anim_c = new dc.action2d.Tooltip(chart1, "default");

chart1.render();
var legendTwo = new dojox.charting.widget.Legend({chart: chart1},"legendTwo");

The piedata is a data in the form of an array.
var chart1 = new dojox.charting.Chart2D("simplechart");
chart1 is the name I have given to the pie chart that I would to generate. The argument in the dojox.charting.Chart2D is simplechart which is the id of the div on which I would to generate the chart. In the chart1.addPlot we give the type as pie, radius as 80 which is 80px. In the pie chart we add the series. Series is the data on which we want to generate the pie chart. We add the array of data in the argument of addSeries. We add three different actions like slice to move up when a mouse pointer comes on that slice, highlighting the slice and adding the tooltip. Then we say dojo to render the chart by calling chart1.render(). Then we add the legend which says what color denotes what. The argument legendTwo is again the name of the div on which the legend would render.
Now we will look at the way to associate an action to a particular pie slice. There is a function connectToPlot.
chart1.connectToPlot("default",function(evt) {
var shape = evt.shape;

if(evt.type == "onclick") {
if(evt.y == ‘4’){

secondPieChart();
}if(evt.y == ‘5’){
renderLineGraph();
}if(evt.y == ‘6’){
var rotateFx = new dojox.gfx.fx.animateTransform({
duration: 2000,
shape: shape,
transform: [{ name: 'rotategAt', start: [0,240,240], end: [360,240,240] }] }).play();
}

else{
alert("no chart has been defined");
}
}


});

};

The function connectToPlot is being associated with the chart1. Another argument to the function is the event. It captures any of the mouse events like onmouseover, onmouseout and onclick. It has made elements associated with it. Y gives the value of the slice of the pie chart on which the mouse is clicked. X gives the number of the series. For example in our piedata we have piedata = [5,6,4]. The chart will have evt.x = 0 and evt.y = 5, evt.x=1 and evt.y = 6 and evt.x = 3 and evt.y = 4. Now I have mapped it to the value of the slice. In the code above I say if(evt.y == ‘4’) which means if the slice has the value of 4 then it will call the secondPieChart() function which is another pie chart rendering function.
I hope I am clear with the dojo pie charting. I am adding a working example code with the blog which is slightly different from the example I explained above.


dojo.require("dojox.charting.Chart2D");
dojo.require("dojox.charting.themes.MiamiNice");
dojo.require("dojox.charting.plot2d.Pie");
dojo.require("dojox.charting.action2d.Highlight");
dojo.require("dojox.charting.action2d.MoveSlice");
dojo.require("dojox.charting.action2d.Tooltip");

dojo.require("dojox.charting.widget.Legend");

makeCharts = function(){
var dc = dojox.charting;
var pieData = [{
y: 4,
text: "High",
stroke: "black",
tooltip: "Need attention"
},
{
y: 2,
text: "Moderate",
stroke: "black",
tooltip: "Not so Necessary"
},
{
y: 1,
text: "Low",
stroke: "black",
tooltip: "Not so Necessary"
},
{
y: 1,
text: "Critical",
stroke: "black",
tooltip: "Need immediate attention"
}];



var chart1 = new dojox.charting.Chart2D("simplechart");
chart1.setTheme(dojox.charting.themes.MiamiNice);
chart1.addPlot("default", {
type: "Pie",
font: "normal normal 11pt Tahoma",
fontColor: "black",
labelOffset: -30,
radius: 80
});
chart1.addSeries("Series 1",pieData);
var anim_a = new dc.action2d.MoveSlice(chart1, "default");
var anim_b = new dc.action2d.Highlight(chart1, "default");
var anim_c = new dc.action2d.Tooltip(chart1, "default");

chart1.render();
var legendTwo = new dojox.charting.widget.Legend({chart: chart1},"legendTwo");

chart1.connectToPlot("default",function(evt) {
var shape = evt.shape;

if(evt.type == "onclick") {

alert("y value " + evt.y);
alert(pieData[0].y);
if(evt.y == pieData[0].y){

secondPieChart();
}if(evt.y == pieData[1].y){
renderLineGraph();
}if(evt.y == pieData[2].y){
var rotateFx = new dojox.gfx.fx.animateTransform({
duration: 2000,
shape: shape,
transform: [{ name: 'rotategAt', start: [0,240,240], end: [360,240,240] }] }).play();
}

else{
alert("no chart has been defined");
}
}


});

};
makeChart2 = function(){

var chart2 = new dojox.charting.Chart2D("simplechart1");
chart2.addPlot("default", {type: "Lines"});
chart2.addAxis("x");
chart2.addAxis("y", {vertical: true});
chart2.addSeries("Series 1", [1, 2, 2, 3, 4, 5, 5, 7]);
chart2.render();
}
makepiechart2 = function(){

var pieData1 = [5,4,2,8,1,1];



var chart2 = new dojox.charting.Chart2D("simplechart2");
chart2.setTheme(dojox.charting.themes.MiamiNice);
chart2.addPlot("default", {
type: "Pie",
font: "normal normal 11pt Tahoma",
fontColor: "black",
labelOffset: -30,
radius: 80
});
chart2.addSeries("Series 1",pieData1);
var anim_a = new dojox.charting.action2d.MoveSlice(chart2, "default");
var anim_b = new dojox.charting.action2d.Highlight(chart2, "default");
var anim_c = new dojox.charting.action2d.Tooltip(chart2, "default");

chart2.render();


}

dojo.addOnLoad(makeCharts);
dojo.addOnLoad(makepiechart2);
dojo.addOnLoad(makeChart2);
function secondPieChart(){
alert('in second pie chart rendering');
document.getElementById("simplechart").style.display = "none";
document.getElementById("simplechart1").style.display = "none";
document.getElementById("simplechart2").style.display = "inline";
}
function renderLineGraph(){
alert('in line graph rendering');
document.getElementById("simplechart").style.display = "none";
document.getElementById("simplechart1").style.display = "inline";
document.getElementById("simplechart2").style.display = "none";
}




/>