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

Wednesday, May 11, 2011

Dev Diary

     Spent most of this last week switching between work on developing a Check() hierarchy for validating xml importation, and a minesweeper app for my android app programming class.  The former project I can't discuss too much, only to say that I need to learn how to work with registry design patterns, and am not quite clear where the hierarchy is going to go.  The latter I am finding much more difficult than it seemed at first.

     Apparently, most everyone is treating the actual setup of the boxes manually instead of programattically, putting their positioning information into the xml by hand.  The way I envision it is more automated (but in turn, more difficult to figure out how to do), with the number and size of the boxes adapting to user input.

Wednesday, May 4, 2011

Dev Diary May 4th, 2011

      So, I got a job working as an intern working for a company by the name of Data In Motion as of this last Monday.  Not much to say about it as of yet except that there's a ton to the job, and I am currently... whelmed at the tasks ahead.  That is to say, it's certainly daunting, but I think if I take it one piece at a time (like one of my favorite Johnny Cash songs) I'll get to understanding it, and be able to make myself useful to my employers.  For the time being, they are doing a lot more for me than I am for them, and it is currently just a hope to be a good return on that investment.

     All that having been said, I probably won't be sharing my code from work-related projects here on my blog, unless given explicit permission to do so.  I am also starting a class for developing android applications, and may share some of the toy programs from that class (albeit if it looks even marginally profitable I'd be keeping mum).  So that's the situation if you were wondering when my next interesting tidbit of code would appear.

     And now I'm off to spend the rest of the evening getting used to some new equipment.  And to read up on marker, visitor, and singleton design patterns.  On a complete sidenote, I should remind myself to strongly suggest to my professors here at Westminster to implement a class focused on design patterns.

Monday, November 15, 2010

An n^n algorithm (or a surefire way to freeze up your memory lickety-split)

     So one of my friends and I were talking about algorithm analysis and tried to think up a quick and dirty n^n algorithm (that is, one which grows on a more than factorial order) and this is what we came up with.  Be forewarned:  Calling this function with an argument of more than 30 is likely to eat all your memory (on the school computer we tried it on we got a BSOD.  Wheeeeee!)

void int sum(int n)
{
      //base case
      if(n == 0)
          return 1;

      int sum = 0;
      for(int i = 0; i < n; i++)
           sum += sum(i);
      return sum;
}

This is like the fibonacci series on crack (in terms of the call hierarchy), though it ends up falling into a pattern of simply doubling.  You get a slightly more interesting pattern by switching the initialization of sum from 0 to n, but the main point here is to maximize the number of operations in as little code as possible without generating an infinite loop.

Wednesday, June 16, 2010

Iterated Circles - Mod of Sierpenski Square program

/* CMPT 300X  Chaos  Working with Fractals: Iterated Circle
 *
 * rewrite of Sierpinski Square code to iterate a circular fractal
 Author: Daniel Tanner
 *Note you can mess around with the code here a bit to avoid printing circles inside each other to generate a different fractal pattern (which I kinda like better but... eh).
 */

import javax.swing.JFrame;     //imports for the frame
import java.awt.*;         //imports the colour
import java.awt.Graphics;    //imports the graphics
import java.util.Random;  // imports the random class for random colour

import javax.swing.JPanel;

public class IteratedCircle extends JPanel
{
  public Graphics g;
  public Color c =Color.WHITE; // set colour to white to create the blanks
  public Random r = new Random();
   
  public static void main (String[]args)
  {
     JFrame SS = new JFrame("Drawing with Recursion");
     SS.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
     SS.setVisible(true);   //Show the first drawing.
     IteratedCircle S = new IteratedCircle();  //call default constructor (not written);
     SS.setBackground(Color.BLACK);
     SS.add(S);
     SS.setSize(500, 500);  //(width ,height )   */

    //new SFrame();  // call to the frame, program
  }

  public void paint(Graphics g)
  {
    this.g = g;
    // start recursion with first call to draw square
    drawCircle( getWidth() / 2, getHeight() / 2, getWidth() / 4);    
   }
 
  private void drawCircle ( int x, int y ,int radius)
  {
      if (radius > 3) //control when to stop: when size is 2x2 pixels
      {      
      g.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      g.drawRoundRect(x - radius / 2, y - radius / 2, radius, radius, radius * radius, radius / 2);
      drawCircle((int)(x + radius * .75), y, radius / 2);  //draws and fill the square, bigger one
      drawCircle((int)(x - radius * .75), y, radius / 2);
      drawCircle(x, (int)(y + radius * .75), radius / 2);
      drawCircle(x, (int)(y - radius * .75), radius / 2);
      //repaint();
      }
  }
 
  private void drawUpCircle( int x, int y ,int radius)
  {
      if (radius > 1) //control when to stop: when size is 2x2 pixels
      {      
      g.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      g.drawRoundRect(x - radius / 2, y - radius / 2, radius, radius, radius * radius, radius / 2);
      drawUpCircle(x, (int)(y + radius * .75), radius / 2);
      drawRightCircle((int)(x + radius * .75), y, radius / 2);
      drawLeftCircle((int)(x - radius * .75), y, radius / 2);
      //repaint();
      }
  }
 
  private void drawDownCircle( int x, int y ,int radius)
  {
      if (radius > 1) //control when to stop: when size is 2x2 pixels
      {      
      g.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      g.drawRoundRect(x - radius / 2, y - radius / 2, radius, radius, radius * radius, radius / 2);
      drawDownCircle(x, (int)(y - radius * .75), radius / 2);
      drawRightCircle((int)(x + radius * .75), y, radius / 2);
      drawLeftCircle((int)(x - radius * .75), y, radius / 2);
      //repaint();
      }
  }
 
  private void drawLeftCircle( int x, int y ,int radius)
  {
      if (radius > 1) //control when to stop: when size is 2x2 pixels
      {      
          g.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      g.drawRoundRect(x - radius / 2, y - radius / 2, radius, radius, radius * radius, radius / 2);
      drawUpCircle(x, (int)(y + radius * .75), radius / 2);
      drawDownCircle(x, (int)(y - radius * .75), radius / 2);
      drawLeftCircle((int)(x - radius * .75), y, radius / 2);
      //repaint();
      }
  }
 
  private void drawRightCircle( int x, int y ,int radius)
  {
      if (radius > 1) //control when to stop: when size is 2x2 pixels
      {      
          g.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      g.drawRoundRect(x - radius / 2, y - radius / 2, radius, radius, radius * radius, radius / 2);
      drawUpCircle(x, (int)(y + radius * .75), radius / 2);
      drawRightCircle((int)(x + radius * .75), y, radius / 2);
      drawDownCircle(x, (int)(y - radius * .75), radius / 2);
      //repaint();
      }
  }
}//end of class

The Dragon Curve

/*
 * Author: Daniel Tanner
 * Dragon Curve Program
 *
 * This program runs a recursive program to keep replacing a given
 * string such as "f" with "f+h" and "h" with "f-h",
 *  and after a certain number of said recursions, translates that
 *  string into a physical display.  The result is known as the
 *  Dragon Curve.
 */

import java.awt.*;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JPanel;

public class DragonCurve extends JPanel {
 
 public Graphics g1;
 public Color c =Color.WHITE; // set colour to white to create the blanks
 public Random r = new Random();

 public static double degToRad(int deg) { //degree to radian conversion
  return deg * Math.PI / 180;
 }


 //paint method is automatically called for us by tree recursive (will be called 4 times! Once for each call to drawFractal
 public void paint(final Graphics g) {
  this.g1 = g;
  g1.setColor(c);
  int numRecursions = 14;
  double startAngle = degToRad(0);
  int distance = 3;
   //First call to do the drawing, this call draws the trunk: start(X,Y) at base, angle 0, len calculated)
  drawCurve(getWidth() / 2, getHeight() / 2, numRecursions, startAngle, distance);  //first call
     //System.out.println("in paint, number of calls to drawFractal is " + count +"\n");
   }

 //dragon curve method -- starts at the middle and applies rules to curve
 public void drawCurve(int x0, int y0, int numRecursions, double startAngle, int distance)
 {
    String dragonString = "f";
    for(int i = 0; i < numRecursions; i++)
    {
        String tempString = "";
        for(int j = 0; j < dragonString.length(); j++)
        {    //replace the f with f + h
            if(dragonString.charAt(j) == 'f')
                tempString += "f-h";
            else if(dragonString.charAt(j) == 'h')
                tempString += "f+h";
            else
                tempString += dragonString.charAt(j);
        }
        dragonString = tempString;
    }
    System.out.println(dragonString);
    //now draw the image
    for(int index = 0; index < dragonString.length(); index++)
    {
        if(dragonString.charAt(index) == 'f' || dragonString.charAt(index) == 'h')
        {
            g1.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
            int x1 = (int)(x0 + distance * Math.cos(startAngle));
            int y1 = (int)(y0 + distance * Math.sin(startAngle));
            g1.drawLine(x0, y0, x1, y1);
            x0 = x1; y0 = y1;
        }
        else if(dragonString.charAt(index) == 'g')
        {
            g1.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
            int x1 = (int)(x0 + distance * Math.cos(startAngle));
            int y1 = (int)(y0 + distance * Math.sin(startAngle));
            x0 = x1; y0 = y1;
        }
        else if(dragonString.charAt(index) == '+')
            startAngle = startAngle - Math.PI / 2.0;
        else if(dragonString.charAt(index) == '-')
            startAngle = startAngle + Math.PI / 2.0;
    }
 }

 //main method
 public static void main(String args[]) {
   // System.out.println("count begins with at " + count +"\n");
  JFrame FF = new JFrame("Drawing the Dragon Curve");
  FF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  FF.setVisible(true);   //Show the first drawing.
  DragonCurve F = new DragonCurve();  //call default constructor (not written); F is the Tree.
  FF.setBackground(Color.BLACK);
  FF.add(F);
  FF.setSize(1000, 1000);  //(width 1200,height 1000)   
 }
}

Chaos Program - Julia Orbits

/*Author: Daniel Tanner
 *Julia Orbits Display Program
 *This program displays all the orbit diagrams for a given julia set
 *(which the user can change by clicking on the viewing window)
 *
 *Basically displaying a line following the points when you take a
 *pair of starting values for a complex number 'c' (IE, x + yi), plug
 *it into the function (z^2 + c) where z is the starting point, and then
 *plug the result back into the function until the result is > 2
 */

import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import java.util.Random;

import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.JPanel;

public class JuliaOrbit extends JPanel implements MouseListener, WindowListener {
 
 public Graphics g1;
 public Color c =Color.WHITE; // set colour to white to create the blanks
 public Random r = new Random();
 private double cX = .360248, cY = .100376;

 public static double degToRad(int deg)
 { //degree to radian conversion
  return deg * Math.PI / 180;
 }


 //paint method is automatically called for us by tree recursive (will be called 4 times! Once for each call to drawFractal
 public void paint(Graphics g)
 {
  this.g1 = g;
  g1.setColor(c);
  double initX, initY;
   //First call to do the drawing, this call draws the trunk: start(X,Y) at base, angle 0, len calculated)
  for(initX = -2.0; initX <= 2.0; initX += 0.01)
  {
      for(initY = -2.0; initY <= 2.0; initY += 0.01)
      {
          drawJuliaOrbit(cX, cY, initX, initY);  //first call
          g1.setColor(new Color((int)(Math.random() * 255), (int)(Math.random() * 255), (int)(Math.random() * 255)));          //random colour (default is white)
      }
  }
 }

 //dragon curve method -- starts at the middle and applies rules to curve
 public void drawJuliaOrbit(double cX, double cY, double initX, double initY)
 {
    int m0 = (int)((initX + 1.0) * getWidth() / 2);
    int n0 = (int)((1.0 - initY) * getHeight() / 2);
   
    int iterations = 0;
    double q = Math.sqrt(initX * initX + initY * initY);
    while(q < 2 && iterations < 35)
    {
        iterations++;
        double y1 = 2.0 * (initX * initY);
        double x1 = (initX * initX) + -(initY * initY);
        initX = x1 + cX;
        initY = y1 + cY;
        int m1 = (int)((initX + 2.0) * getWidth() / 4);
        int n1 = (int)((2.0 - initY) * getHeight() / 4);
        g1.drawLine(m0, n0, m1, n1);
        q = Math.sqrt(initX * initX + initY * initY);
        m0 = m1; n0 = n1;
    }
 }

 //main method
 public static void main(String args[]) {
   // System.out.println("count begins with at " + count +"\n");
  JFrame FF = new JFrame("Drawing the Julia Orbit");
  FF.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
  FF.setVisible(true);   //Show the first drawing.
  JuliaOrbit F = new JuliaOrbit();  //call default constructor (not written); F is the Tree.
  FF.setBackground(Color.BLACK);
  FF.addMouseListener(F);
  FF.add(F);
  FF.setSize(200, 200);  //(width 1200,height 1000)   
 }

 public void mousePressed(MouseEvent e) { }

 public void mouseReleased(MouseEvent e)
 {
     if(e.getButton() == MouseEvent.BUTTON1)
     {
         cX = Double.parseDouble(JOptionPane.showInputDialog("Enter a new cX value:"));
         cY = Double.parseDouble(JOptionPane.showInputDialog("Enter a new cY value:"));
         this.repaint();
     }
 }

 public void mouseEntered(MouseEvent e) { }

 public void mouseExited(MouseEvent e) { }

 public void mouseClicked(MouseEvent e) {
 }


@Override
public void windowActivated(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowClosed(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowClosing(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowDeactivated(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowDeiconified(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowIconified(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}


@Override
public void windowOpened(WindowEvent arg0) {
    // TODO Auto-generated method stub
   
}
}

Tuesday, April 13, 2010

Chat Server (final version)

/** Chat Server
Authors: Daniel J. Tanner and Jon Fidler
March 29th, 2010
CMPT 352 - Networking

This program implements the Spring 2010 Networking class' Chat Protocol
**/

import java.io.*;
import java.net.*;
import java.util.*;


public class ChatServer
{
    //constants & globals
    public static final int PORT = 2222;
    private static ChatServerSubject buffer = null;
   
   
    public static void main(String[] args) throws java.io.IOException
    {
        //load everything up
        buffer = new ChatServerSubject();
       
        //Create socket
        ServerSocket sock = null;
        try
        {
            //establish socket
            sock = new ServerSocket(PORT);
           
            while(true)
            {
                Socket client = sock.accept();
                //debug testing
                InetAddress ipAddr = client.getInetAddress();
                System.out.print(ipAddr.getHostAddress() + " : ");
                System.out.println(client.getPort() + " connected.");
                Thread worker = new Thread(new Connection(client, buffer));
               
                worker.start();
            }
        }
        //catch any errors opening sockets
        catch(IOException ioe)
        {
            System.err.println(ioe);
            System.exit(0);
        }
       
        finally
        {
            //close streams
            if(sock != null)
                sock.close();
        }
    }
   
    //getUserList function - returns a pointer to the user List
    public static Vector<String> getUserList() {return buffer.getUserList();}
}

/** ChatServerSubject object
-- implementation of the Subject class, containing the user list, an observer list, and the message buffer
-- This class will notify each child thread of the server whenever a change is made on either of these 2 objects.
Authors:  Jon Fidler & Daniel Tanner
March 31st, 2010
CMPT 352 - Networking
*/
import java.util.*;
import java.net.*;
import java.awt.*;

public class ChatServerSubject extends Observable
{
    //members
    private Vector<String> userList;
    private Vector<MessageObject> messageBuffer;
    private String removedUser;
   
    //flags
    /* whatHappened flag = int representing the state of the object.
    0 = nothing's changed
    1 = user added
    2 = user removed
    3 = message added
    */
    private int whatHappened;
   
    //constructors
    public ChatServerSubject()
    {
        userList = new Vector<String>();
        messageBuffer = new Vector<MessageObject>();
        removedUser = "NOBODY";
        whatHappened = 0;
    }
   
    /** userList changing functions
    */
    //add a user
    public void addUser(String userName)
    {
        userList.add(userName);
       
        //set flags
        whatHappened = 1;
        setChanged();
        notifyObservers();
    }
   
    //remove a user from the list
    public void removeUser(String userName)
    {
        removedUser = userName;
        userList.remove(userName);
       
        //set flags
        whatHappened = 2;
        setChanged();
        notifyObservers();
    }
   
    //check if a user is on the list or not
    public boolean userExists(String userName)
    {
        return userList.contains(userName);
    }
   
    //get user list
    public Vector<String> getUserList(){return userList;}
   
    //get the name of the user who just disconnected
    public String getDCedUser() {return removedUser;}
   
    //returns the last user on the list (most recently added user
    public String getNewUser() {return userList.lastElement();}
   
    /**Message Buffer functions
    */
    //get message function
    public MessageObject getMessage() {return messageBuffer.firstElement();}
   
    //add message function
    public void addMessage(MessageObject message)
    {
        messageBuffer.add(message);
        whatHappened = 3;
        setChanged();
        notifyObservers();
    }
   
    //remove a message
    public void removeMessage(MessageObject message)
    {
        messageBuffer.remove(message);
    }
   
    /* Flag checking functions*/
    public boolean userAdded()
    {
        if(whatHappened == 1)
            return true;
        return false;
    }
   
    public boolean userRemoved()
    {
        if(whatHappened == 2)
            return true;
        return false;
    }
   
    public boolean messageAdded()
    {
        if(whatHappened == 3)
            return true;
        return false;
    }
}

/** Connection Class for threaded Chat Server
Daniel Tanner & John Fidler
CMPT 352 - Computer Networking
March 29th, 2010
 */

import java.net.*;
import java.io.*;
import java.text.*;
import java.util.*;

public class Connection implements Runnable
{
    //create variables
    private Socket    client;
    private ChatServerSubject buffer;
    private Handler handler = new Handler();

    public Connection(Socket client, ChatServerSubject buffer)
    {
        this.client = client;
        this.buffer = buffer;
    }

    //Separate thread
    public void run()
    {
        try
        {
            handler.process(client, buffer);
        }
       
        catch (java.io.IOException ioe)
        {
            System.err.println(ioe);
        }
    }
}

/**
Daniel Tanner & Jon Fidler
CMPT 352 - Computer Networking
March 29th, 2010
Handler class for threaded Chat Server
 */

import java.net.*;
import java.lang.Object.*;
import java.util.*;
import java.text.*;
import javax.activation.*;
import java.io.*;
import java.util.regex.Pattern;

public class Handler implements Observer
{       
    //Create variables
    private BufferedReader fromClient = null;
    private BufferedOutputStream toClient = null;
    private ChatServerSubject buffer = null;
    private String myUserName = null;
    private String command = null;
    private boolean connectedProperly = false;
    private static Pattern alphaNum = Pattern.compile("^[A-Za-z0-9\\*]+$");

    //This method invoked as a separate thread
    public void process(Socket client, ChatServerSubject buffer) throws IOException
    {   
        //set up the method
        this.buffer = buffer;
       
        //try block for opening streams and getting hostname
        try
        {
            //open Streams
            fromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
            toClient = new BufferedOutputStream(client.getOutputStream());       
       
            //initial connection state
            command = fromClient.readLine();
            command = command.toLowerCase();
            if(!command.equalsIgnoreCase("connect"))
            {
                error("Bad Request.  Please input a proper command.", 2);
                return;
            }
           
            //get username, check against userList
            myUserName = fromClient.readLine();
            myUserName = myUserName.toUpperCase();
            if(buffer.userExists(myUserName))
            {
                error("Duplicate Handle.  Please try another name.", 1);
                return;
            }
           
            //check that username is within bounds
            if(!(myUserName.length() <= 16 && alphaNum.matcher(myUserName).matches()))
            {
                error("Invalid handle.  Handle must be an alphanumeric string with size less than or euqal to 16.", 3);
                return;
            }
            connectedProperly = true;
           
            //add username to userList
            buffer.addUser(myUserName);
            buffer.addObserver(this);
           
            //print userList to client
            printUserList();
           
            //listen for commands
            do
            {
                command = fromClient.readLine();
                command = command.toUpperCase();
               
                //getHandles command
                if(command.equalsIgnoreCase("gethandles"))
                    printUserList();
               
                //Post command
                else if(command.equalsIgnoreCase("post"))
                    constructMessage();
               
                //invalid command
                else if(!command.equalsIgnoreCase("disconnect"))
                    error("Invalid request.  Please input a proper command.", 2);
            }
            while(!command.equalsIgnoreCase("disconnect"));
        }
       
        catch(IOException ioe)
        {
            System.err.println(ioe);
            return;
        }
       
        finally
                {
                    //disconnection state
                    if(connectedProperly)
                    {
                            buffer.deleteObserver(this);
                            buffer.removeUser(myUserName);
                    }
                    // close streams and socket
                    if (fromClient != null)
                        fromClient.close();
                    if (toClient != null)
                        toClient.close();
                    if (client != null)
                        client.close();
                }
    }
   
    //broadcast method - this method is the basic broadcasting method
    //it assumes that we're sending a public message
    private void broadcast(MessageObject message) throws IOException
    {
        toClient.write("posted\n".getBytes());
        toClient.write((message.getFromUser() + "\n").getBytes());
        toClient.write("public\n".getBytes());
        toClient.write((message.getMessage() + "\n").getBytes());
        toClient.flush();
    }
   
    //private message broadcast method
    private void privateMessage(MessageObject message) throws IOException
    {
        toClient.write("posted\n".getBytes());
        toClient.write((message.getFromUser() + "\n").getBytes());
        toClient.write("private\n".getBytes());
        toClient.write((message.getMessage() + "\n").getBytes());
        toClient.flush();
    }
   
    //connected/disconnected message
    private void userConnected(String userName, boolean connected) throws IOException
    {
        if(connected)
            toClient.write("connected\n".getBytes());
        else
            toClient.write("disconnected\n".getBytes());
        toClient.write((userName + "\n").getBytes());
        toClient.flush();
    }
   
    //Error message
    private void error(String errorMessage, int errorNum) throws IOException
    {
        toClient.write("error\n".getBytes());
        toClient.write((errorNum + "\n").getBytes());
        toClient.write((errorMessage + "\n").getBytes());
        toClient.flush();
    }
   
    //Print user list function
    private void printUserList() throws IOException
    {
        Vector<String> currentUserList = new Vector<String>(buffer.getUserList());
        toClient.write("handles\n".getBytes());
        toClient.write((currentUserList.size() + "\n").getBytes());
        for(int index = 0; index < currentUserList.size(); index++)
            toClient.write((currentUserList.get(index) + "\n").getBytes());
        toClient.flush();
    }
   
    //CreateMessage method - goes to this state after receiving the post command from the user
    private void constructMessage() throws IOException
    {
        MessageObject newMessage = new MessageObject();
        newMessage.setFromUser(myUserName);
        String temp;
       
        //read the toUser
        temp = fromClient.readLine();
        temp = temp.toUpperCase();
        if(!(alphaNum.matcher(temp).matches() && temp.length() <= 16))
        {
            error("Invalid username entered.  Try again!.", 3);
            return;
        }
        if(!buffer.userExists(temp) && !temp.equalsIgnoreCase("*"))
        {
            error("User not found.", 4);
            return;
        }
        newMessage.setToUser(temp);
           
           
        //read the message and check to make sure it's within bounds
        temp = fromClient.readLine();
        if(temp.length() > 1024)
        {
            error("Message too Long", 5);
            return;
        }
        newMessage.setMessage(temp);
        buffer.addMessage(newMessage);
    }
   
    //update function - this is the observer functionality implemented
    //it will check the flags when the subject has changed, and act appropriately
    public void update(Observable o, Object arg)
    {
        try
        {
            //check if a user was added or removed
            if(buffer.userAdded())
                userConnected(buffer.getNewUser(), buffer.userAdded());
            else if(buffer.userRemoved())
                userConnected(buffer.getDCedUser(), buffer.userAdded());
                       
            //here's the routine when we get a new message
            else if(buffer.messageAdded())
            {
                MessageObject newMessage = buffer.getMessage();
                //check if it's a private message
                if(newMessage.getToUser().equals(myUserName))
                    privateMessage(newMessage);
               
                //now check if it's a broadcast and not from me
                else if(newMessage.getToUser().equals("*"))
                    broadcast(newMessage);
               
                //now decrement and check if the counter is at 0, remove from the list if it is
                newMessage.viewed();
                if(newMessage.getCounter() == 0)
                    buffer.removeMessage(newMessage);
            }
        }
        catch(IOException ioe)
        {
            System.err.println(ioe);
            command = "disconnect";
            return;
        }
           
    }
}

/**
BufferKeyEntry class

Contain fields to put into the key of the message buffer
The value will be the unformatted message

Members of the BufferEntry are as follows:

-Who sent the message (so we don't echo it back)

-A non-static counter which will tell us when all the threads have sent the message
so we know when to remove the message from our buffer.

-Who the message is to (* for broadcasts)
*/

/**
Authors: Daniel Tanner & Jon Fidler
March 29th, 2010
CMPT 352 - Networking
*/

import java.net.*;
import java.io.*;
import java.text.*;
import java.util.*;

public class MessageObject
{
    //create variables
    private String toUser;
    private String fromUser;
    private int counter;
    private String message;
   
    //constructor
    MessageObject()
    {
        counter = ChatServer.getUserList().size();
        toUser = null;
        fromUser = null;
        message = null;
    }
   
    //copy constructor
    MessageObject(MessageObject copy)
    {
        this.toUser = copy.toUser;
        this.fromUser = copy.fromUser;
        this.counter = copy.counter;
        this.message = copy.message;
    }
       
    //Constructor with arguments
    MessageObject(String toUser, String fromUser, String message)
    {
        counter = ChatServer.getUserList().size();
        this.toUser = toUser;
        this.fromUser = fromUser;
        this.message = message;
    }
   
    //get functions
    int getCounter() {return counter;}
    String getToUser() {return toUser;}
    String getFromUser() {return fromUser;}
    String getMessage() {return message;}
   
    //set functions
    void setToUser(String toUser) {this.toUser = toUser;}
    void setFromUser(String fromUser) {this.fromUser = fromUser;}
    void setMessage(String message) {this.message = message;}
   
    //viewed function - This function will decrement the counter
    void viewed() {counter--;}
   
    //equals function
    boolean equals(MessageObject rhs)
    {
        if(toUser.equals(rhs.toUser) && fromUser.equals(rhs.fromUser) && counter == rhs.counter && message.equals(rhs.message))
            return true;
        else
            return false;
    }
}
      

Wednesday, March 31, 2010

Chat Server (Working for the most part)

/** ChatServerSubject object
-- implementation of the Subject class, containing the user list, an observer list, and the message buffer
-- This class will notify each child thread of the server whenever a change is made on either of these 2 objects.
Authors:  Jon Fidler & Daniel Tanner
March 31st, 2010
CMPT 352 - Networking
*/
import java.util.*;
import java.net.*;
import java.awt.*;

public class ChatServerSubject extends Observable
{
    //members
    private Vector<String> userList;
    private Vector<MessageObject> messageBuffer;
    private String removedUser;
   
    //flags
    /* whatHappened flag = int representing the state of the object.
    0 = nothing's changed
    1 = user added
    2 = user removed
    3 = message added
    */
    private int whatHappened;
   
    //constructors
    public ChatServerSubject()
    {
        userList = new Vector<String>();
        messageBuffer = new Vector<MessageObject>();
        removedUser = "NOBODY";
        whatHappened = 0;
    }
   
    /** userList changing functions
    */
    //add a user
    public void addUser(String userName)
    {
        userList.add(userName);
       
        //set flags
        whatHappened = 1;
        setChanged();
        notifyObservers();
    }
   
    //remove a user from the list
    public void removeUser(String userName)
    {
        removedUser = userName;
        userList.remove(userName);
       
        //set flags
        whatHappened = 2;
        setChanged();
        notifyObservers();
    }
   
    //check if a user is on the list or not
    public boolean userExists(String userName)
    {
        return userList.contains(userName);
    }
   
    //get user list
    public Vector<String> getUserList(){return userList;}
   
    //get the name of the user who just disconnected
    public String getDCedUser() {return removedUser;}
   
    //returns the last user on the list (most recently added user
    public String getNewUser() {return userList.lastElement();}
   
    /**Message Buffer functions
    */
    //get message function
    public MessageObject getMessage() {return messageBuffer.firstElement();}
   
    //add message function
    public void addMessage(MessageObject message)
    {
        messageBuffer.add(message);
        whatHappened = 3;
        setChanged();
        notifyObservers();
    }
   
    //remove a message
    public void removeMessage(MessageObject message)
    {
        messageBuffer.remove(message);
    }
   
    /* Flag checking functions*/
    public boolean userAdded()
    {
        if(whatHappened == 1)
            return true;
        return false;
    }
   
    public boolean userRemoved()
    {
        if(whatHappened == 2)
            return true;
        return false;
    }
   
    public boolean messageAdded()
    {
        if(whatHappened == 3)
            return true;
        return false;
    }
}

/**
Daniel Tanner & Jon Fidler
CMPT 352 - Computer Networking
March 29th, 2010
Handler class for threaded Chat Server
 */

import java.net.*;
import java.lang.Object.*;
import java.util.*;
import java.text.*;
import javax.activation.*;
import java.io.*;
import java.util.regex.Pattern;

public class Handler implements Observer
{       
    //Create variables
    private BufferedReader fromClient = null;
    private BufferedOutputStream toClient = null;
    private ChatServerSubject buffer = null;
    private String myUserName = null;
    private String command = null;
    private boolean connectedProperly = false;
    private static Pattern alphaNum = Pattern.compile("^[A-Za-z0-9\\*]+$");

    //This method invoked as a separate thread
    public void process(Socket client, ChatServerSubject buffer) throws IOException
    {   
        //set up the method
        this.buffer = buffer;
       
        //try block for opening streams and getting hostname
        try
        {
            //open Streams
            fromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
            toClient = new BufferedOutputStream(client.getOutputStream());       
       
            //initial connection state
            command = fromClient.readLine();
            command = command.toLowerCase();
            if(!command.equalsIgnoreCase("connect"))
            {
                error("Bad Request.  Please input a proper command.", 2);
                return;
            }
           
            //get username, check against userList
            myUserName = fromClient.readLine();
            myUserName = myUserName.toUpperCase();
            if(buffer.userExists(myUserName))
            {
                error("Duplicate Handle.  Please try another name.", 1);
                return;
            }
           
            //check that username is within bounds
            if(!(myUserName.length() <= 16 && alphaNum.matcher(myUserName).matches()))
            {
                error("Invalid handle.  Handle must be an alphanumeric string with size less than or euqal to 16.", 3);
                return;
            }
            connectedProperly = true;
           
            //add username to userList
            buffer.addUser(myUserName);
            buffer.addObserver(this);
           
            //print userList to client
            printUserList();
           
            //listen for commands
            do
            {
                command = fromClient.readLine();
                command = command.toUpperCase();
               
                //getHandles command
                if(command.equalsIgnoreCase("gethandles"))
                    printUserList();
               
                //Post command
                else if(command.equalsIgnoreCase("post"))
                    constructMessage();
               
                //invalid command
                else if(!command.equalsIgnoreCase("disconnect"))
                    error("Invalid request.  Please input a proper command.", 2);
            }
            while(!command.equalsIgnoreCase("disconnect"));
        }
       
        catch(IOException ioe)
        {
            System.err.println(ioe);
            return;
        }
       
        finally
                {
                    //disconnection state
                    if(connectedProperly)
                    {
                            buffer.deleteObserver(this);
                            buffer.removeUser(myUserName);
                    }
                    // close streams and socket
                    if (fromClient != null)
                        fromClient.close();
                    if (toClient != null)
                        toClient.close();
                    if (client != null)
                        client.close();
                }
    }
   
    //broadcast method - this method is the basic broadcasting method
    //it assumes that we're sending a public message
    private void broadcast(MessageObject message) throws IOException
    {
        System.out.println("You've reached the broadcast method!");
        toClient.write("posted\n".getBytes());
        toClient.write((message.getFromUser() + "\n").getBytes());
        toClient.write("public\n".getBytes());
        toClient.write((message.getMessage() + "\n").getBytes());
        toClient.flush();
    }
   
    //private message broadcast method
    private void privateMessage(MessageObject message) throws IOException
    {
        System.out.println("privateMessage method!");
        toClient.write("posted\n".getBytes());
        toClient.write((message.getFromUser() + "\n").getBytes());
        toClient.write("private\n".getBytes());
        toClient.write((message.getMessage() + "/n").getBytes());
        toClient.flush();
    }
   
    //connected/disconnected message
    private void userConnected(String userName, boolean connected) throws IOException
    {
        if(connected)
            toClient.write("connected\n".getBytes());
        else
            toClient.write("disconnected\n".getBytes());
        toClient.write((userName + "\n").getBytes());
        toClient.flush();
    }
   
    //Error message
    private void error(String errorMessage, int errorNum) throws IOException
    {
        toClient.write("error\n".getBytes());
        toClient.write((errorNum + "\n").getBytes());
        toClient.write((errorMessage + "\n").getBytes());
        toClient.flush();
    }
   
    //Print user list function
    private void printUserList() throws IOException
    {
        Vector<String> currentUserList = new Vector<String>(buffer.getUserList());
        toClient.write("handles\n".getBytes());
        toClient.write((currentUserList.size() + "\n").getBytes());
        for(int index = 0; index < currentUserList.size(); index++)
            toClient.write((currentUserList.get(index) + "\n").getBytes());
        toClient.flush();
    }
   
    //CreateMessage method - goes to this state after receiving the post command from the user
    private void constructMessage() throws IOException
    {
        MessageObject newMessage = new MessageObject();
        newMessage.setFromUser(myUserName);
        String temp;
       
        //read the toUser
        temp = fromClient.readLine();
        temp = temp.toUpperCase();
        if(!(alphaNum.matcher(temp).matches() && temp.length() <= 16))
        {
            error("Invalid username entered.  Try again!.", 3);
            return;
        }
        if(!buffer.userExists(temp) && !temp.equalsIgnoreCase("*"))
        {
            error("User not found.", 4);
            return;
        }
        newMessage.setToUser(temp);
           
           
        //read the message and check to make sure it's within bounds
        temp = fromClient.readLine();
        if(temp.length() > 1024)
        {
            error("Message too Long", 5);
            return;
        }
        newMessage.setMessage(temp);
        buffer.addMessage(newMessage);
    }
   
    //update function - this is the observer functionanility implemented
    //it will check the flags when the subject has changed, and act appropriately
    public void update(Observable o, Object arg)
    {
        System.out.println("your observers are being updated!");
        try
        {
            //check if a user was added or removed
            if(buffer.userAdded())
                userConnected(buffer.getNewUser(), buffer.userAdded());
            else if(buffer.userRemoved())
                userConnected(buffer.getDCedUser(), buffer.userAdded());
               
           
            //here's the routine when we get a new message
            else if(buffer.messageAdded())
            {
                MessageObject newMessage = buffer.getMessage();
                //check if it's a private message
                if(newMessage.getToUser().equals(myUserName))
                    privateMessage(newMessage);
               
                //now check if it's a broadcast and not from me
                else if(newMessage.getToUser().equals("*") && !newMessage.getFromUser().equals(myUserName))
                    broadcast(newMessage);
               
                //now decrement and check if the counter is at 0, remove from the list if it is
                newMessage.viewed();
                if(newMessage.getCounter() == 0)
                    buffer.removeMessage(newMessage);
            }
        }
        catch(IOException ioe)
        {
            System.err.println(ioe);
            command = "disconnect";
            return;
        }
           
    }
}

/** Connection Class for threaded Chat Server
Daniel Tanner & John Fidler
CMPT 352 - Computer Networking
March 29th, 2010
 */

import java.net.*;
import java.io.*;
import java.text.*;
import java.util.*;

public class Connection implements Runnable
{
    //create variables
    private Socket    client;
    private ChatServerSubject buffer;
    private Handler handler = new Handler();

    public Connection(Socket client, ChatServerSubject buffer)
    {
        this.client = client;
        this.buffer = buffer;
    }

    //Separate thread
    public void run()
    {
        try
        {
            handler.process(client, buffer);
        }
       
        catch (java.io.IOException ioe)
        {
            System.err.println(ioe);
        }
    }
}

/** Chat Server
Authors: Daniel J. Tanner and Jon Fidler
March 29th, 2010
CMPT 352 - Networking

This program implements the Spring 2010 Networking class' Chat Protocol
**/

import java.io.*;
import java.net.*;
import java.util.*;


public class ChatServer
{
    //constants & globals
    public static final int PORT = 2222;
    private static ChatServerSubject buffer = null;
   
   
    public static void main(String[] args) throws java.io.IOException
    {
        //load everything up
        buffer = new ChatServerSubject();
       
        //Create socket
        ServerSocket sock = null;
        try
        {
            //establish socket
            sock = new ServerSocket(PORT);
           
            while(true)
            {
                Socket client = sock.accept();
                //debug testing
                InetAddress ipAddr = client.getInetAddress();
                System.out.print(ipAddr.getHostAddress() + " : ");
                System.out.println(client.getPort() + " connected.");
                Thread worker = new Thread(new Connection(client, buffer));
               
                worker.start();
            }
        }
        //catch any errors opening sockets
        catch(IOException ioe)
        {
            System.err.println(ioe);
            System.exit(0);
        }
       
        finally
        {
            //close streams
            if(sock != null)
                sock.close();
        }
    }
   
    //getUserList function - returns a pointer to the user List
    public static Vector<String> getUserList() {return buffer.getUserList();}
}

/**
BufferKeyEntry class

Contain fields to put into the key of the message buffer
The value will be the unformatted message

Members of the BufferEntry are as follows:

-Who sent the message (so we don't echo it back)

-A non-static counter which will tell us when all the threads have sent the message
so we know when to remove the message from our buffer.

-Who the message is to (* for broadcasts)
*/

/**
Authors: Daniel Tanner & Jon Fidler
March 29th, 2010
CMPT 352 - Networking
*/

import java.net.*;
import java.io.*;
import java.text.*;
import java.util.*;

public class MessageObject
{
    //create variables
    private String toUser;
    private String fromUser;
    private int counter;
    private String message;
   
    //constructor
    MessageObject()
    {
        counter = ChatServer.getUserList().size();
        toUser = null;
        fromUser = null;
        message = null;
    }
   
    //copy constructor
    MessageObject(MessageObject copy)
    {
        this.toUser = copy.toUser;
        this.fromUser = copy.fromUser;
        this.counter = copy.counter;
        this.message = copy.message;
    }
       
    //Constructor with arguments
    MessageObject(String toUser, String fromUser, String message)
    {
        counter = ChatServer.getUserList().size();
        this.toUser = toUser;
        this.fromUser = fromUser;
        this.message = message;
    }
   
    //get functions
    int getCounter() {return counter;}
    String getToUser() {return toUser;}
    String getFromUser() {return fromUser;}
    String getMessage() {return message;}
   
    //set functions
    void setToUser(String toUser) {this.toUser = toUser;}
    void setFromUser(String fromUser) {this.fromUser = fromUser;}
    void setMessage(String message) {this.message = message;}
   
    //viewed function - This function will decrement the counter
    void viewed() {counter--;}
   
    //equals function
    boolean equals(MessageObject rhs)
    {
        if(toUser.equals(rhs.toUser) && fromUser.equals(rhs.fromUser) && counter == rhs.counter && message.equals(rhs.message))
            return true;
        else
            return false;
    }
}
       
/**
Daniel Tanner & Jon Fidler
CMPT 352 - Computer Networking
March 29th, 2010
Handler class for threaded Chat Server
 */

import java.net.*;
import java.lang.Object.*;
import java.util.*;
import java.text.*;
import javax.activation.*;
import java.io.*;
import java.util.regex.Pattern;

public class Handler implements Observer
{       
    //Create variables
    private BufferedReader fromClient = null;
    private BufferedOutputStream toClient = null;
    private ChatServerSubject buffer = null;
    private String myUserName = null;
    private String command = null;
    private boolean connectedProperly = false;
    private static Pattern alphaNum = Pattern.compile("^[A-Za-z0-9\\*]+$");

    //This method invoked as a separate thread
    public void process(Socket client, ChatServerSubject buffer) throws IOException
    {   
        //set up the method
        this.buffer = buffer;
       
        //try block for opening streams and getting hostname
        try
        {
            //open Streams
            fromClient = new BufferedReader(new InputStreamReader(client.getInputStream()));
            toClient = new BufferedOutputStream(client.getOutputStream());       
       
            //initial connection state
            command = fromClient.readLine();
            command = command.toLowerCase();
            if(!command.equalsIgnoreCase("connect"))
            {
                error("Bad Request.  Please input a proper command.", 2);
                return;
            }
           
            //get username, check against userList
            myUserName = fromClient.readLine();
            myUserName = myUserName.toUpperCase();
            if(buffer.userExists(myUserName))
            {
                error("Duplicate Handle.  Please try another name.", 1);
                return;
            }
           
            //check that username is within bounds
            if(!(myUserName.length() <= 16 && alphaNum.matcher(myUserName).matches()))
            {
                error("Invalid handle.  Handle must be an alphanumeric string with size less than or euqal to 16.", 3);
                return;
            }
            connectedProperly = true;
           
            //add username to userList
            buffer.addUser(myUserName);
            buffer.addObserver(this);
           
            //print userList to client
            printUserList();
           
            //listen for commands
            do
            {
                command = fromClient.readLine();
                command = command.toUpperCase();
               
                //getHandles command
                if(command.equalsIgnoreCase("gethandles"))
                    printUserList();
               
                //Post command
                else if(command.equalsIgnoreCase("post"))
                    constructMessage();
               
                //invalid command
                else if(!command.equalsIgnoreCase("disconnect"))
                    error("Invalid request.  Please input a proper command.", 2);
            }
            while(!command.equalsIgnoreCase("disconnect"));
        }
       
        catch(IOException ioe)
        {
            System.err.println(ioe);
            return;
        }
       
        finally
                {
                    //disconnection state
                    if(connectedProperly)
                    {
                            buffer.deleteObserver(this);
                            buffer.removeUser(myUserName);
                    }
                    // close streams and socket
                    if (fromClient != null)
                        fromClient.close();
                    if (toClient != null)
                        toClient.close();
                    if (client != null)
                        client.close();
                }
    }
   
    //broadcast method - this method is the basic broadcasting method
    //it assumes that we're sending a public message
    private void broadcast(MessageObject message) throws IOException
    {
        System.out.println("You've reached the broadcast method!");
        toClient.write("posted\n".getBytes());
        toClient.write((message.getFromUser() + "\n").getBytes());
        toClient.write("public\n".getBytes());
        toClient.write((message.getMessage() + "\n").getBytes());
        toClient.flush();
    }
   
    //private message broadcast method
    private void privateMessage(MessageObject message) throws IOException
    {
        System.out.println("privateMessage method!");
        toClient.write("posted\n".getBytes());
        toClient.write((message.getFromUser() + "\n").getBytes());
        toClient.write("private\n".getBytes());
        toClient.write((message.getMessage() + "/n").getBytes());
        toClient.flush();
    }
   
    //connected/disconnected message
    private void userConnected(String userName, boolean connected) throws IOException
    {
        if(connected)
            toClient.write("connected\n".getBytes());
        else
            toClient.write("disconnected\n".getBytes());
        toClient.write((userName + "\n").getBytes());
        toClient.flush();
    }
   
    //Error message
    private void error(String errorMessage, int errorNum) throws IOException
    {
        toClient.write("error\n".getBytes());
        toClient.write((errorNum + "\n").getBytes());
        toClient.write((errorMessage + "\n").getBytes());
        toClient.flush();
    }
   
    //Print user list function
    private void printUserList() throws IOException
    {
        Vector<String> currentUserList = new Vector<String>(buffer.getUserList());
        toClient.write("handles\n".getBytes());
        toClient.write((currentUserList.size() + "\n").getBytes());
        for(int index = 0; index < currentUserList.size(); index++)
            toClient.write((currentUserList.get(index) + "\n").getBytes());
        toClient.flush();
    }
   
    //CreateMessage method - goes to this state after receiving the post command from the user
    private void constructMessage() throws IOException
    {
        MessageObject newMessage = new MessageObject();
        newMessage.setFromUser(myUserName);
        String temp;
       
        //read the toUser
        temp = fromClient.readLine();
        temp = temp.toUpperCase();
        if(!(alphaNum.matcher(temp).matches() && temp.length() <= 16))
        {
            error("Invalid username entered.  Try again!.", 3);
            return;
        }
        if(!buffer.userExists(temp) && !temp.equalsIgnoreCase("*"))
        {
            error("User not found.", 4);
            return;
        }
        newMessage.setToUser(temp);
           
           
        //read the message and check to make sure it's within bounds
        temp = fromClient.readLine();
        if(temp.length() > 1024)
        {
            error("Message too Long", 5);
            return;
        }
        newMessage.setMessage(temp);
        buffer.addMessage(newMessage);
    }
   
    //update function - this is the observer functionanility implemented
    //it will check the flags when the subject has changed, and act appropriately
    public void update(Observable o, Object arg)
    {
        System.out.println("your observers are being updated!");
        try
        {
            //check if a user was added or removed
            if(buffer.userAdded())
                userConnected(buffer.getNewUser(), buffer.userAdded());
            else if(buffer.userRemoved())
                userConnected(buffer.getDCedUser(), buffer.userAdded());
               
           
            //here's the routine when we get a new message
            else if(buffer.messageAdded())
            {
                MessageObject newMessage = buffer.getMessage();
                //check if it's a private message
                if(newMessage.getToUser().equals(myUserName))
                    privateMessage(newMessage);
               
                //now check if it's a broadcast and not from me
                else if(newMessage.getToUser().equals("*") && !newMessage.getFromUser().equals(myUserName))
                    broadcast(newMessage);
               
                //now decrement and check if the counter is at 0, remove from the list if it is
                newMessage.viewed();
                if(newMessage.getCounter() == 0)
                    buffer.removeMessage(newMessage);
            }
        }
        catch(IOException ioe)
        {
            System.err.println(ioe);
            command = "disconnect";
            return;
        }
           
    }
}