20 December, 2011

Remote Desktop Viewer - The cheap way [Part 1]

Microsoft RDP, RemoteFX, VNC.  That is the real stuff.  Solutions such as those will allow you to secure your connections, log you in to your desktop, compress the connection, etc.  But have you ever thought if it is possible to implement something rudimentary, totally in Java.  Actually it is possible.  But it's nothing much, and what I'll be doing here is a very, very basic implementation of an idea.  Obviously one can go on and enhance it, but it's almost totally impossible to produce a real solution, since Java does not have direct access to the OS, so for example you cannot remotely log-in, as you would for example using ssh.  Well it might be possible, but it would be an overkill.

As I said, I will simply implement an idea, so even though I know we won't be building the next Remote Desktop protocol, it is still interesting.

First we shall lay out some basic requirements.  Basically we will build a server and a client.  The server shall receive a request, it will then grab a screen shot, and send it back.  Meanwhile the client will wait for the server to reply with the image, and will then draw it.  This will go on until we disconnect.

So create three packages first, com.jf.rd, com.jf.rd.client and com.jf.rd.server.  Obviously you can name them whatever you want, but ideally you should have xxx.xxx.client and .server.

We'll start off with the server.  That way we can define what we expect from the client and what we intend to send back.

Now, in the server package create the JRDServer class.


package com.jf.rd.server;




public class JRDServer
{
public static int PORT;

public static String USER;
public static String PASS;

/**
* Parameters:
* Port, User, Password
* @param args
*/
public static void main(String[] args)
{
if (args.length < 3)
{
System.out.println("Usage: JRDServer Port User Password");
System.exit(0);
}

PORT = Integer.parseInt(args[0]);
USER = args[1];
PASS = args[2];

System.out.println("JRD Server sdtarted.  Will listen for connections on " +
"port " + PORT);

JRDServer server = new JRDServer();

server.start();
}

private ConnectionListen listen;

public JRDServer()
{
this.listen = new ConnectionListen(this);
}

public void start()
{
System.out.println("Service Thread starting...");
listen.startServer();
Thread srv = new Thread(listen);
srv.start();
}

public void stop()
{
System.out.println("Service Thread stopping...");
listen.stopServer();
listen.destroy();
}
}


This class is basically an entry point to the server.  I expect some basic Java knowledge so I will describe this only briefly.  We start the server by passing 3 arguments; the port to which we will bind, a username and a password.  The port is the real necessity, and as yet the user and password will not be really used, and will be there so that one day we can implement some sort of security.

There are also the start and stop methods.  start will initialise a listener class which will be running on a separate thread.  That way we can serve our clients in a parallel fashion and also prevent any user from blocking us to the rest of the application in a manner which will stop us from stopping the server.

stop simple stops the listener class and releases its resources.

Next up is the listening class.  This class will loop while the server is running and every time a connection is requested, an other, separate thread is created and the client is served.


package com.jf.rd.server;


import java.io.IOException;
import java.net.ServerSocket;


public class ConnectionListen implements Runnable
{
private boolean running;
private ServerSocket serv;

public ConnectionListen(JRDServer server)
{
try
{
serv = new ServerSocket(JRDServer.PORT);
}
catch (IOException e) 
{
System.err.println("The ServerSocket could not be initialised.");
System.err.println("Reason : " + e);
}
}

public void startServer()
{
running = true;
}

public void stopServer()
{
running = false;
}

@Override
public void run()
{
while (running)
{
try
{
Connection conn = new Connection(serv.accept());
Thread tr = new Thread(conn);
tr.start();
}
catch (IOException e) 
{
System.err.println("A connection could not be accepted.");
System.err.println("Reason : " + e);
}
}
}

public void destroy()
{
try
{
serv.close();
}
catch (IOException e) 
{
System.err.println("The ServerSocket was not closed.");
System.err.println("Reason : " + e);
}
}
}


This time, a server socket is passed as a variable to the constructor. This is the socket which will listen for and accept connections.  The run method, which is the implementation of the Runnable class is what will be running on a separate thread.  Therefore we can simply put a while loop and, kind of, forget about it, since it won't be blocking us (the main thread).  It shall keep on looping until the running flag is false.  So when we start the server we must set running to true and then start it.  To stop it - well - set it to false, and the looping will stop.

Of course, if we won't be listening for any more connections, we should close the server socket.

Finally, the Connection class is created.  Once this is done, the server is basically complete.  Now I should explain what will happen when this is actually run.  Any client that shall connect to this server will receive a byte stream resulting from a screenshot.  It is irrelevant if the client is a web browser, a mobile app or a simple socket.  Also, we won't be checking what the client is actually requesting, so as you can see, the username and password are irrelevant.   That means that you should either practice, and implement an authentication system (easily done) or simply avoid running this server if you fear someone might connect to it and, sort of, spy on you (aye, this is easier).

So, to the connection class.

package com.jf.rd.server;


import java.awt.AlphaComposite;
import java.awt.Dimension;
import java.awt.Graphics2D;
import java.awt.Rectangle;
import java.awt.RenderingHints;
import java.awt.Robot;
import java.awt.Toolkit;
import java.awt.image.BufferedImage;
import java.io.BufferedInputStream;
import java.io.InputStream;
import java.io.PrintStream;
import java.net.Socket;


import javax.imageio.ImageIO;


public class Connection implements Runnable
{
private static final int IMG_WIDTH  = 960;
private static final int IMG_HEIGHT = 600;

private Socket connSock;
private static final int BUF_SIZE = 2048;
static final byte[] EOL =
{ (byte) '\r', (byte) '\n' };
private byte[] buf;


public Connection(Socket connSock)
{
this.connSock = connSock;
buf = new byte[BUF_SIZE];
}


@Override
public void run()
{
try
{
InputStream is = new BufferedInputStream(connSock.getInputStream());
PrintStream ps = new PrintStream(connSock.getOutputStream());


for (int i = 0; i < BUF_SIZE; i++)
buf[i] = 0;


int nread = 0, r = 0;


outerloop: while (nread < BUF_SIZE)
{
r = is.read(buf, nread, BUF_SIZE - nread);
if (r == -1) return;
int i = nread;
nread += r;
for (; i < nread; i++)
{
if (buf[i] == (byte) '\n' || buf[i] == (byte) '\r')
break outerloop;
}
}


System.out.println("Done reading.");


Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
Rectangle screenRectangle = new Rectangle(screenSize);
Robot robot = new Robot();
BufferedImage image = robot.createScreenCapture(screenRectangle);
int type = image.getType() == 0? BufferedImage.TYPE_INT_ARGB : image.getType();
image = resizeImage(image, type);

ImageIO.write(image, "JPG", connSock.getOutputStream());


ps.flush();


connSock.close();
}
catch (Exception e)
{
System.err.println("Error, somewhere...");
e.printStackTrace();
}
}


private static BufferedImage resizeImage(BufferedImage originalImage,
int type)
{
BufferedImage resizedImage = new BufferedImage(IMG_WIDTH, IMG_HEIGHT, type);
Graphics2D g = resizedImage.createGraphics();
g.drawImage(originalImage, 0, 0, IMG_WIDTH, IMG_HEIGHT, null);
g.dispose();
g.setComposite(AlphaComposite.Src);
 
g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
RenderingHints.VALUE_INTERPOLATION_BILINEAR);
g.setRenderingHint(RenderingHints.KEY_RENDERING,
RenderingHints.VALUE_RENDER_QUALITY);
g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
 
return resizedImage;
}


}


There it is then.  The Main screen grabber and sender.  We're not doing much here;  just receiving a request and then write "Done reading" when the process finishes, and then a picture is sent.  The resizeImage method is used to reduce the size of the image so that we do not send an image the size of your screen resolution.  That would be slow and besides, you can also specify what "resolution" you intend to receive.  The socket is also closed here, that's important too.  The lines between printing "done reading" and ImageIO.write are grabbing the screen using the AWT (Advanced Window Toolkit), so what this means is that you must have an OS that supports GUI (i.e. not headless, as it is known) and you must be logged in basically, since it grabs the screen as seen by the current user.  Therefore apart from the fact that we cannot remotely login, we also can't turn off the video card.  You can turn off the screen, obviously (lol).

That was part one of this, erm, tutorial, or whatever it is.  I like doing these sort of mini programs when I am trying to solve other problems, that's why they are not at the bleeding edge of technology.  And then, when I'm done, I just write something about it, maybe someone out there learns something hehe.

The next thing we'll do, is build a client application.  I currently plan on supporting only viewing, but eventually, we might spice it up a bit by adding cursor support so that you may click on the client and it will then be forwarded to the server and eventually consumed by the OS that is hosting the server.

Also, the second part will probably come out either just before 2012, or probably in the first week of January, so until then, Merry Christmas and a Happy New Year! :D

16 December, 2011

Comparing two XML documents in Java

How many times have you, for example, modified some XML file but wanted to make sure that only certain parts were changed?  Well it did occurred to me, a number of times.  Actually the problem is this:  I had a small application which modifies XML files in a graphical way and I wanted to ensure that nothing got messed up when I saved the file.  By "messed up" I mean tags changing their values or positions.

So what I did was build a simple program which will take in two files (XML, naturally) and then map all the nodes and compare their paths and values.  Quite a simple task.


So first, we'll start off with the usual Utilities class.  Static methods such as those reading a file should be placed here, ideally.


package com.jf.xmlcomp.util;




import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.util.Scanner;


import javax.xml.parsers.DocumentBuilderFactory;


import org.w3c.dom.Document;


public class Utils
{
public static String readStringFromFile(File file)
{
StringBuilder ds_text = new StringBuilder();
String str_sep = System.getProperty("line.separator");
try
{
Scanner ds_scan = new Scanner(new FileInputStream(file), "UTF-8");
while (ds_scan.hasNextLine())
ds_text.append(ds_scan.nextLine() + str_sep);
ds_scan.close();
}
catch (Exception e) 
{
System.err.println(file.getPath() + " :: Not read");
}

return ds_text.toString();
}

public static Document stringToDocument(String str_doc)
{
Document ds_doc = null;
try
{
ds_doc = DocumentBuilderFactory
.newInstance()
.newDocumentBuilder()
.parse(new ByteArrayInputStream(str_doc.getBytes()));
}
catch (Exception e) 
{
System.err.println("String could not be converted to Document");
}

return ds_doc;
}
}


We only have two simple methods here; one which reads in the contents of a file and one which converts an XML String to a W3C Document object.  I won't be detailing much about reading a file or converting a String as it is not the scope of this post.

Next thing to do is create a very simple implementation of a Map, sort of.  Now those that actually know what a Map is will be frothing at their mouths, since what we will be doing is a simple ArrayList mapping and we won't even be using Generics, hashes or even collision tables.  The reason is that this is a simple post about creating a simple XML Comparator.

So, to the SimpleMap thing...


package com.jf.xmlcomp.util;


import java.util.ArrayList;
import java.util.Comparator;
import java.util.Set;
import java.util.TreeSet;


public class SimpleMap
{
private ArrayList<String> keys;
private ArrayList<String> values;


public SimpleMap()
{
keys = new ArrayList<String>();
values = new ArrayList<String>();
}


public void put(String s, String v)
{
keys.add(s);
values.add(v);
}


public ArrayList<String> get(String k)
{
ArrayList<String> result = new ArrayList<String>();
for (int c = 0; c < keys.size(); c++)
if (keys.get(c).equals(k)) result.add(values.get(c));


return result;
}


As you can see, we created the usual methods you'd find in a Map: the put and get.  The rest should be pretty easy; declaring the ArrayLists containing the keys and values and then initialising them in the constructor.

The put method will simply add the new key and value Strings in the respective ArrayList while get, gets a little over-done.  In the get method we first set up a results ArrayList and then loop through the keys list and store every matching key.  The key won't be stored though, as they are of no use really; if you ask for door which is opened by a particular key, you will want to find a door.  So we get the index at which the key was found and then store the value found at the same index in the values list in the results list.  Finally the results list is returned.  Probably you now know that we can have the same key appearing more than once in this map.


public ArrayList<String> keys()
{
return keys;
}

public ArrayList<String> getCompleteItemList()
{
ArrayList<String> res = new ArrayList<String>();
for (String key : uniqueKeys())
for (String val : get(key))
res.add(key + " :: " + val);
return res;
}

Following the mapping details are two other simple methods.  One simply returns the list of keys while the other will return all the items we have as a String of key :: value.  At first it might look like an over kill.  Getting only the unique keys only to loop over the values obtained by every key.  What happens if you use the normal key list and loop over it, is a repetitive amount of values.

Let's say there are two keys named "a" and "b".  If we loop over the key list we get "a", "a", "b".  Now let's include the part which gets the values obtained from each key.  We will get two values for each key named "a", so eventually we'll end up with the values of a key named "a", twice.

So to "fix" this, we will simple get each key once and then simply add the resulting values of each.  That way we can be totally sure that no key-value pair is repeated.

Naturally we'll be needing the uniqueKeys method, so here it comes.




public ArrayList<String> uniqueKeys()

{
Set<String> s = new TreeSet<String>(new Comparator<String>()
{
@Override
public int compare(String o1, String o2)
{
if (o1.equals(o2))
return 0;
return 1;
}
});
s.addAll(keys);

ArrayList<String> result = new ArrayList<String>();
result.addAll(s);

return result;
}


This method will create a Set (which will not accept duplicates) and give it a String Comparator.  The compare method is overridden so basically you will have to write it ("you", as in "the programmer").  As these are Strings we are comparing, the equals method is needed (Don't even think about using "==" when comparing Strings.  Really, don't.)  Next, the key list is added to the set and it will automatically store each value once, so no duplicates.  Finally a new ArrayList is declared and the new modified set of unique keys are added to the list, and then it's returned.

This is a rather quick and dirty way to get unique values from a List object.  This is basically our new Map, which should be used only in this project.  And nowhere else.


package com.jf.xmlcomp;


import java.io.File;
import java.util.ArrayList;


import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;


import com.jf.xmlcomp.util.SimpleMap;
import com.jf.xmlcomp.util.Utils;


public class XMLValueComp
{
private File xfile1;
private File xfile2;

private SimpleMap f1v;
private SimpleMap f2v;

public static void main(String[] args)
{
if (args.length < 2)
printHelp();

XMLValueComp xmlComp = new XMLValueComp(args[0], args[1]);

xmlComp.compare();
}

public static void printHelp()
{
System.out.println("Usage: xmlcomp file1 file2");
System.exit(0);
}

This is the main class for this project.  There are the two files which shall be compared along with the SimpleMaps for each of them.  The main class will accept two arguments; the two files.  If not enough arguments are passed, a help message is printed out, and the program exits.


public XMLValueComp(String file1, String file2)
{
f1v = new SimpleMap();
f2v = new SimpleMap();
File f1 = new File(file1);
File f2 = new File(file2);

if (!f1.exists() || !f2.exists())
{
System.out.println("One of the files does not exist!");
System.exit(0);
}
xfile1 = f1;
xfile2 = f2;
}


Now we have the class constructor.  Doesn't do much except for initialisation and ensuring we are not comparing nothingness.  If the files do exist, then we will initilise them.  If they don't, the application will exit.


public void compare()
{
Document doc1 = Utils.stringToDocument(
Utils.readStringFromFile(xfile1));

Document doc2 = Utils.stringToDocument(
Utils.readStringFromFile(xfile2));

if (doc1 == null || doc2 == null)
{
System.err.println("Could not build docs");
System.exit(0);
}

buildMap(f1v, doc1);
buildMap(f2v, doc2);


ArrayList<String> uniques = new ArrayList<String>();


uniques.addAll(f1v.getCompleteItemList());
uniques.removeAll(f2v.getCompleteItemList());


System.out.println("Unique to F1");
for (String v : uniques)
System.out.println(v);




uniques = new ArrayList<String>();


uniques.addAll(f2v.getCompleteItemList());
uniques.removeAll(f1v.getCompleteItemList());

System.out.println("\n\nUnique to F2");
for (String v : uniques)
System.out.println(v);
}

That the core of the application, where we shall be dealing with the real comparator part.  So first off, the documents are created from the String we got from the files.  After that, we shall perform the usual checking to make sure we don't have corrupted files, for example, in which case we'll report the problem and stop.  Then the Maps for each Document are built and a list of unique pairs is created.

The duplicates from each document are removed by filling the unique list with the values from one document and then removing the ones which are found in the other document.  It is a quick way to remove the common nodes and getting only the ones that don't appear in both documents.  The same process is repeated for both documents, so eventually a list of unique items in document one and document two are printed separately.  If you compare a file with itself you can easily deduce that all the common nodes will be removed and the list of unique values will always be empty.


private void buildMap(SimpleMap map, Document doc)
{
Element e = doc.getDocumentElement();


mapNodes(map, e, "/" + e.getNodeName());
}


private void mapNodes(SimpleMap map, Element elem, String parent)
{
for (int x = 0; x < elem.getChildNodes().getLength(); x++)
{
Node n = elem.getChildNodes().item(x);
String path = parent + "/" + n.getNodeName(); 

if (n.getChildNodes().getLength() == 1)
map.put(path, n.getTextContent());

if (n.getNodeType() == Node.ELEMENT_NODE)
mapNodes(map, (Element) n, path);
}
}


The buildMap method is simply preparing some stuff for the mapNodes method.  The document element is passed as the root element to the mapNodes so that it can use recursion to obtain all nodes.

The mapNodes will loop the current child nodes and store the value and path.  Every time an Element Node is encountered it will call itself and the children of that node are stored.  That will go on until all the nodes in the document have been traversed.

You can now try it out by running it and passing in two paths that point to XML documents.  You should try it with the same document to ensure that it actually does not detect any differences.  Then you can go on to see if a modified XML document has kept its integrity :)

As usual, the full code is available here.

14 December, 2011

Caching : The unsung hero of performance

It's not just abstract numbers after all :)
Many people tend to forget, or worse, ignore the fact that caching plays a vital role in many applications.  Why would they place a cache in the CPU for example?

This idea might come from the fact that in an age dominated by the web and fast internet access, some might think that cached pages are unnecessary.  True, at times you end up with a lot of space taken up by pages you visited only once.

But caching is more than just a copy of a page on your hard drive (or SD Card).  In this post I shall demonstrate how a terribly simple implementation of a cache in a Fibonacci algorithm will have a massive impact on performance.  Obviously one might not find many uses for Fibonacci numbers, but the idea can be used in many areas, such as crawlers, searching and environments where some value which is unknown but is somewhat constant is required frequently.

Many know what Fibonacci numbers are, so I won't be going into a lot of details about their algorithm, but don't worry though, it's very easy to implement it Java.  This time we'll be writing a single class, having only 3 methods.


import java.math.BigInteger;
import java.util.HashMap;


public class Fibonacci 
{
private static HashMap<Integer, BigInteger> cache = new HashMap<Integer, BigInteger>();

public static void main(String[] args) 
{
int v = 35;
if(args.length>0)
v = Integer.valueOf(args[0]).intValue();

System.out.println("Fibonacci efficiency tester for Fib("+v+").\n\n");

long n = System.currentTimeMillis();
System.out.println("Cached: "+fib(v, true));
long mst = (System.currentTimeMillis() - n);
System.out.println(getTimeFromMs(mst/1000));

n = System.currentTimeMillis();
System.out.println("Non-Cached: "+fib(v, false));
mst = (System.currentTimeMillis() - n);
System.out.println(getTimeFromMs(mst/1000));
}

Not much here.  Just declaring some variables and a main class.  The main class starts off by declaring the number of iterations we plan on doing.  In this case variable v takes care of that.  Don't set it too high, otherwise you might end up waiting 5 minutes until you get a result!  Next we check if we have any arguments;  if so, we assume that it is the number of iterations to perform, so we set v as that value.

Then we just start displaying the result messages.  As you can see we are measuring the time it takes for cached and non cached calculations.  I know I have created a benchmarking tool, but it's OK to use the normal system time here.

Now it's time to code the real Fibonacci method.


private static BigInteger fib(int f, boolean cached)
{
if(f<2) return new BigInteger(""+f);


if(cached)
{
if(!cache.containsKey(new Integer(f)))
{
BigInteger v  = (fib(f-2, cached)).add(fib(f-1, cached));


cache.put(new Integer(f), v);
}
else
{
return cache.get(new Integer(f));
}
}

BigInteger n1 = fib(f - 2, cached);
BigInteger n2 = fib(f - 1, cached);
return n1.add(n2);
}


What we are doing here is recursively calling the same method.  It is much cleaner than a loop, and anyway, a loop does not always suffice, such as in cases of crawling.  Before performing anything complicated, we check if the number is high enough to be calculated.  So if we have a 1 or 0, there's nothing much to do, so just return it.  Otherwise, we will perform the normal calculation.

We check if the caching is enabled, as this is all about caching after all, an then the calculation is performed.  So if we have caching enabled, we will first check if the cache contains the Fibonacci of the number we are currently analysing, and if it does, we are done, and return it.  Otherwise we will calculate it and cache it.  If caching is not enabled, the value is calculated every time.

We then write the usual method which cleanly shows the value in a more humane way :)


public static String getTimeFromMs(long ms)
{
if (ms < 1000)
return ms + "ms";
else if (ms >= 1000 && ms < 60000)
return (ms/1000) + "s " + getTimeFromMs(ms - ((ms/1000)*1000));
else if (ms >=60000 && ms < 3600000)
return (ms/60000) + "m " + getTimeFromMs(ms - ((ms/60000)*60000));
else return (ms/3600000) + "h " + getTimeFromMs(ms - ((ms/3600000)*3600000));
}


That is all basically.  You can now run this program and see for yourself the improvement which is gained through caching.  I have provided my results below;  naturally yours will have some variations, but there definitely will be a huge difference between the cached and non-cached runs.



Fibonacci efficiency tester for Fib(35).


Cached: 9227465
in 2ms
Non-Cached: 9227465
in 3s


Make no mistake. There is an 'm' in the cached, while there is not in the non-cached. That means we had a whole 3 second difference. Now, hopefully, you shall be writing more sensible code and freeing the CPU from eccessive and unnecessary work :)

The full code is available here.