Showing posts with label java. Show all posts
Showing posts with label java. Show all posts

Wednesday, April 21, 2010

IcedTea Java Console: How to debug Java Applets on Unix / Linux based systems

If you've ever used the IcedTea Java plugin, you may have noticed that it does not have a console like it's Windows based cousin.

How do you debug or see the Java output without a console? The answer is very simple: If you are using IcedTea it's because you are running a Unix / Linux based system. You have built-in consoles all around you!

THE QUICK SOLUTION: (for the impatient)

Before running your applet in a browser, open a terminal window and type:

$ watch -n 1 'cat $HOME/.icedteaplugin/java.stdout'

Now run your applet and see the output fill up the screen.

THE FULL EXPLANATION:

Open a terminal and go to your icedteaplugin personal settings folder. It should be named .icedteaplugin in your $HOME directory:

$ cd $HOME/.icedteaplugin

Do a directory listing and you will see a few files and a directory.

$ ls

cache
java.stdout
java.stderr


cache is the directory which contains java applets that have been accessed before. If you ever debug an applet you will know that sometimes it's useful to 'clear' the cache. You can individually remove the cached applet that you are debugging, to force IcedTea to download the latest version, by deleting the file.

java.stdout contains standard output from a running java applet, or if none is running it may contain data from the last running applet.

java.stderr contains standard error output.

Now that you know where all the data is, how can you see the output in real time?

Well, you can. At least you can see the output in near real time by using the useful Unix/Linux watch and cat commands.

If you are already in your $HOME/.icedteaplugin directory, type:

$ watch -n 1 'cat ./java.stdout'

If you open another terminal window, type:

$ watch -n 1 'cat $HOME/.icedteaplugin/java.stderr'

Use man watch and man cat for all the optional parameters, but note that the -n option for watch specifies the update rate in seconds.

Friday, January 15, 2010

WakeOnLan ported to C#

Paul Mutton wrote a great article on how to use Wake-On-Lan which includes a tutorial on how to create a Magic Packet sender in Java.  He even provides the source of his java implementation: http://www.jibble.org/wake-on-lan/

I took the liberty of converting it to C# with a few minor modifications.  It allows a user to specify a Port number manually.

WHY C#?  Well why not?  I'm using C# at work so it comes naturally.  Mono gives me the ability to run code on both Windows and Linux.  Yes, so does Java.  There are a variety of tools out there and I like to familiarize myself with a good number of them.  In this spirit, I am currently writing a small connection testing tool in Java using Swing.  Maybe I'll write another port of Wake-On-LAN in C++ for fun.

Here is the C# code below:


using System;
using System.Net;
using System.Net.Sockets;

namespace WakeOnLan
{
    class Program
    {       
        static void Main(string[] args)
        {
            string macAdd = "";
            string ip = "";
            string port = "9";
            int iPort = 0;

            if (args.Length < 2) {
                System.Console.WriteLine("Usage: wakeonlan <broadcast-ip> <mac-address> [<port>]");
                System.Console.WriteLine("Example: wakeonlan 192.168.0.255 00:0D:61:08:22:4A");
                System.Console.WriteLine("Example: wakeonlan 192.168.0.255 00-0D-61-08-22-4A");
                System.Environment.Exit(1);
            }

            ip = args[0];
            macAdd = args[1];
            if (args.Length > 2)           
                port = args[2];

            if (!IsNumeric(port))
            {
                System.Console.WriteLine("Port entered was not a number...");
                return; // quit
            }                     

            iPort = Int32.Parse(port);

            if (iPort > 65535 || iPort < 0)
            {
                System.Console.WriteLine("Port value is invalid");
                return;
            }

            byte[] mac = getMacBytes(macAdd);
            //byte[] mac = new byte[] { 0x00, 0x0F, 0x1F, 0x20, 0x2D, 0x35 };
            WakeUp(mac, iPort, ip);
        }

        ///
        /// Check whether string can be converted to a number value
        ///
        private static bool IsNumeric(string num)
        {
            try
            {
                double d = Double.Parse(num);
                return true;
            }
            catch
            {
                return false;
            }
        }

        ///
        /// Sends a Wake-On-Lan packet to the specified MAC address.
        ///
        private static void WakeUp(byte[] mac, Int32 iPort, string myIP)
        {
            //
            // WOL packet is sent over UDP 255.255.255.0:40000.
            //
            UdpClient client = new UdpClient();
            client.Connect(myIP, iPort);

            //
            // WOL packet contains a 6-bytes trailer and 16 times a 6-bytes sequence 
            // containing the MAC address.
            byte[] packet = new byte[17 * 6];

            //
            // Trailer of 6 times 0xFF.
            //
            for (int i = 0; i < 6; i++)
                packet[i] = 0xFF;

            //
            // Body of magic packet contains 16 times the MAC address.
            //
            for (int i = 1; i <= 16; i++)
                for (int j = 0; j < 6; j++)
                    packet[i * 6 + j] = mac[j];

            //
            // Submit WOL packet.
            //
            client.Send(packet, packet.Length);
            System.Console.WriteLine("Wake-on-LAN packet sent.");
        }
   
        private static byte[] getMacBytes(String macStr)
        {
            byte[] bytes = new byte[6];
            string[] hex = macStr.Split(new Char[] { ':', '-' });
            if (hex.Length != 6) {
                throw new ArgumentException("Invalid MAC address.");
            }
            try {
                for (int i = 0; i < 6; i++) {
                    Int32 intVal = Int32.Parse(hex[i], System.Globalization.NumberStyles.AllowHexSpecifier);
                    bytes[i] = (byte)intVal;
                }
            }
            catch (FormatException e) {
                throw new ArgumentException("Invalid hex digit in MAC address.");
            }
            return bytes;
        }
    }
}