*** empty log message ***
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/summerofcode/mel/RoutingSMS/client/BTworker.java Wed Aug 31 21:01:10 2005 -0400
@@ -0,0 +1,255 @@
+Copyright (c) <2005>, <Mel Dooki> +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +* Neither the name of the <ORGANIZATION> nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import javax.bluetooth.*; +import javax.bluetooth.LocalDevice; + public static Vector devices = new Vector(); //to hold the remote devices discovered + public static Vector deviceClasses = new Vector(); + public static Vector services = new Vector(); //to hold services discovered + public static int selectedDevice = -1; //the index of the remote device, selected by the user,in the vector + //since device discovery and service discovery methods I used are non blocking + // these 2 variables will be needed for synchronization + public static boolean deviceWaiting = true; + public static boolean serviceWaiting = true; + public static BTworker instance; + public UUID[] serviceUUIDs = null; // list of UUID to match during service discovery + private LocalDevice device; //PC + private DiscoveryAgent agent; + serviceUUIDs = new UUID[1]; + serviceUUIDs[0] = new UUID(PCapplication.UUIDString, false); + * Function to write message on the console. + public static void Jout(String s) + *initialize the JABWT stack + public void initializeJABWTStack () + // obtain reference to singleton + device = LocalDevice.getLocalDevice(); + //in order to allow bluetooth devices to find your device + //GIAC to allow all other bt devices discover me. + device.setDiscoverable(DiscoveryAgent.GIAC); + // obtain reference to singleton + agent = device.getDiscoveryAgent(); + catch (BluetoothStateException e) + Jout ("Exception in initaializing stack"); + * Get the first discovered service from selected remote device, + * since the UUID that matches the start inquiry was placed at the begining + * of the array. This will return the first service that matches my + * UUIDs in startInquiry(). + * connects to the RemoteDevice where this ServiceRecord originated + * return ServiceRecord null if no service discovered + public ServiceRecord getOneDiscoveredService() + if ( services.size() > 0 ) + return (ServiceRecord) services.elementAt(0); + * Return user selected remote device that is used for service discovery. + * return RemoteDevice null if user didn't select anything + public RemoteDevice getSelectedDevice() + if ( selectedDevice != -1 ) + return (RemoteDevice) devices.elementAt(selectedDevice); + * Start device discovery. My application calls this method to do device discovery + public void startDeviceInquiry() + devices.removeAllElements(); //clears previous values first + deviceClasses.removeAllElements(); //clears previous values first + initializeJABWTStack (); + boolean result = agent.startInquiry( DiscoveryAgent.GIAC, new Listener() ); + Jout ("please wait " + "\n"); + catch ( BluetoothStateException e ) + ** Start service discovery. My application calls this method to do service discovery + public void startServiceInquiry () + services.removeAllElements(); //clears previous values first + //Searches for services on a remote Bluetooth device that have all the UUIDs specified in uuidSet + agent.searchServices(null,serviceUUIDs,this.getSelectedDevice(),new Listener() ); + catch (BluetoothStateException ex) + * Method that checks whether the server is still available and the client is connected to or not. + * it returns true if the connection is still present and false if the connection was lost + * The aim of this method is to ensure that the application terminates norally without raising + public boolean checkCellularPhoneConnectivity() + startServiceInquiry (); + while (serviceWaiting == true) + if (services.size ()== 0 ) + * Bluetooth listener object. + * Register this listener object to DiscoveryAgent in device inqury and service discovery. + class Listener implements DiscoveryListener + * called each time a device is discovered + public void deviceDiscovered(RemoteDevice remoteDevice, DeviceClass deviceClass) + Jout("A remote Bluetooth device is discovered:"); + devices.addElement( remoteDevice ); + deviceClasses.addElement( deviceClass ); + * called when device discovery is finished + public void inquiryCompleted(int complete) + if ( devices.size() == 0 ) + Jout ("No Bluetooth device found"); + System.out.println("finished searching"); + * called each time a service is discovered + public void servicesDiscovered(int transId, ServiceRecord[] records) + for ( int i=0; i< records.length; i ++ ) + ServiceRecord record = records[i]; + services.addElement( record ); + * called when service discovery is finished + public void serviceSearchCompleted(int transId, int complete) + Jout(""+services.size()+" services are discovered"); + serviceWaiting = false; --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/summerofcode/mel/RoutingSMS/client/Client.java Wed Aug 31 21:01:10 2005 -0400
@@ -0,0 +1,255 @@
+Copyright (c) <2005>, <Mel Dooki> +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +* Neither the name of the <ORGANIZATION> nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import javax.bluetooth.*; +import javax.microedition.io.*; //for StreamConnection class +import java.lang.Object; + //application variables + public static String number = ""; //to get the number entered by the user + public static boolean importedPhonebook; //set to true after the client imports the phone book + public static boolean importingPhonebook; //set to true if the operation of importing the phonebook was successful otherwise set to false + public static Vector contactNumbers; //holds the contacts number in phonebook + public static Vector contactNames; //holds the contacts names in phonebook + public static Vector unsuccessfulNumbers; // holds the numbers that were not successfuly sent + public static boolean serverSendingResponse; //set to true when the server sends a message indicating the success of sending the sms + private StreamConnection streamConnection = null; + /*private*/ DataOutputStream out = null; + /*private*/ DataInputStream in = null; + private String connectionURL; + boolean connectionOpen; + * Constructor initializes attributes. + contactNumbers = new Vector(); + contactNames = new Vector(); + unsuccessfulNumbers = new Vector (); //unsuccessfully sent numbers + importedPhonebook = false; + *now it is capable of receiving address book, + *when it is set to false it indicates that an error occured + *while retrieving the phone book and so the client doesnt keep waiting for the server. + importingPhonebook = true; + serverSendingResponse = false; + connectionOpen = false; + public void run_client (ServiceRecord r) + String url = r.getConnectionURL(ServiceRecord.AUTHENTICATE_NOENCRYPT, false ); + if (connectionOpen == true) + //reading phonebook from the phone + importedPhonebook = false; //still doesnt have the phone book + importingPhonebook = false; //unable to import the phonebook + * Connects to the server and retrieves the address book + public void retrieveContacts () + number_name = in.readUTF(); + while(!number_name.equals("EOF") ) //EOF indicates that the end of list was reached + if (number_name.equals ("EXCEPTION")) + {//this exception is raised from the phone side (for exmaple if the user refused to give permission to the application to access PIM library) + importedPhonebook = false; + importingPhonebook = false; + number = number_name.substring(0,number_name.indexOf(" ")); + name = number_name.substring(number_name.indexOf(" ")+1,number_name.length()); + contactNumbers.addElement(number); + contactNames.addElement(name); + Jout("read in data "+number_name+""); + number_name = in.readUTF(); + importedPhonebook = true; //succeeded importing the phone book + * connects to the server and sends the sms entered by the user + * to the cell phone via bluetooth + public void SMSroute (String message, int countRecipients, String[] desiredNumbers) + unsuccessfulNumbers.removeAllElements(); //clears the vector bec of batch sending + serverSendingResponse = false; + out.writeUTF (message); + out.write (countRecipients); //the number of the recipients entered by the user + for (int i=0; i<countRecipients; i++) + out.writeUTF (desiredNumbers[i]); //desired numbers entered by the user + success (); //waits for server reply indicating its success or failure of sending the sms + * This method receives from the server a message indicates whether ir was successful + * in sending the sms to the desired phone numbers + * if it failed to send the sms to any of the desired numbers, + * it notifies the client with those numbers to report to the user. + String theUnsuccessful = null; + serverSendingResponse = true; + for (int i = 0 ; i < intSize; i++) + theUnsuccessful = in.readUTF (); + unsuccessfulNumbers.addElement(theUnsuccessful); //vector of unsuccessful numbers + serverSendingResponse = true; + * Initializes connection and streams between PC and Cellular phone. + public boolean openConnection() + streamConnection = (StreamConnection) Connector.open(connectionURL); + out = streamConnection.openDataOutputStream(); + in = streamConnection.openDataInputStream(); + connectionOpen = false; + * Called when user disconnects connection or exception + * occurs during connection. Connection and streams between devices are closed. + public void closeConnection() + streamConnection.close(); + connectionOpen = false; + catch (IOException ioe) + public void Jout (String s) --- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/htdocs/summerofcode/mel/RoutingSMS/client/PCapplication.java Wed Aug 31 21:01:10 2005 -0400
@@ -0,0 +1,1226 @@
+Copyright (c) <2005>, <Mel Dooki> +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: +* Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. +* Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +* Neither the name of the <ORGANIZATION> nor the names of its contributors +may be used to endorse or promote products derived from this software without +specific prior written permission. +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +import javax.bluetooth.*; +import java.awt.image.*; +import java.awt.event.*; +import java.awt.image.ImageObserver; +import java.awt.image.BufferedImage; +public class PCapplication extends JFrame implements ImageObserver + int countRecipients; //the number of recipients entered by user to send message to + String desiredNumbers []; //the desired contacts to send message to + String msg; //the message entered by user + int messageCharacters; //the number of characters entered by the user in the message area + int messageNumber; //the number of messages that will be sent according to the number of characters + int searchDevicesThreadCounter = 0; //controls the SearchForDevices Button + int addToIndex = 0; //controls the action of displaying contacts beginning with a certain character. + public static final String UUIDString = "11223344556677889900aabbccddeeff"; //Both Client and Server retrives this UUID string from this MIDlet class. + BufferedImage bi; //background image + JPanel p1, //p1 provides interface for searching for nearby bluetooth devices and getting the selected device of the user + p2, //p2 provides the interface for importing the phonebook from the default database of the cellular phone and getting the mesage and the desired numbers from the user + p3; //p3 provides a report about the successfulness of routing the message to the phne and sendin it + private javax.swing.JFrame SMSFrame; //frame containing p2 + private javax.swing.JFrame ReportFrame; //frame containing p3 + //Home page Frame components: (those in p1) + private javax.swing.JButton SearchForDevicesButton; + private javax.swing.JButton QuitButton; + private javax.swing.JTextPane DisplayText1; //text for displaying messages to the user + private javax.swing.JButton SelectDevice; + private javax.swing.JList DevicesList; + Vector theDevices; //vector which holds the BT devices discovered + //SMS Frame components (those in p2) + private javax.swing.JButton BackButton2; //allows the use to return back to the home page + private javax.swing.JTextField RecipientNo; //text for the user to enter desired number (s), separated by commas + private javax.swing.JLabel RecipientNumLabel; + private javax.swing.JTextPane DisplayText2; //text to display messages to the user + private javax.swing.JButton ClearMsgButton; //clears the message entered by the user + private javax.swing.JButton SendButton; //routs the message to cell phone to be sent + private javax.swing.JTextArea Message; //area for message entered by the user + private javax.swing.JLabel MessageLabel; + private javax.swing.JLabel MessageInfoLabel; + private javax.swing.JList PhoneBook; //list which holds the contacts imported from the phone + private javax.swing.JButton RetrieveContacts; //triggers the action of displaying the address book + private javax.swing.JButton SelectContactNumber; + private javax.swing.JTextField StartsWith; //displays all te contacts that starts with the entered string + private javax.swing.JButton SendNewMessageButton; //returns to SMS frame to allow user to send new message hence allowing batch sending + private javax.swing.JButton QuitButton3; //returns to home page + private javax.swing.JTextPane DisplayText3; //displays messages to the user + public static PCapplication instance; // used singleton object + private Client client; //client instance + private BTworker blue ; //BTworker instance which does device and service discovery actions + initComponents(); //initializes components + private void initComponents() + //this file is for the background & should be placed with the directory containing class files + java.net.URL u = PCapplication.class.getResource ("babyblue.jpg"); + bi = javax.imageio.ImageIO.read (u); + p1.setOpaque (false); //so that the component does not paint some or all of its pixels, allowing the underlying pixels to show through + p3 = new Background (); + RecipientNumLabel = new javax.swing.JLabel(); + RecipientNumLabel.setText("Recipient(s):"); + p2.add(RecipientNumLabel); + RecipientNumLabel.setBounds( 10 ,65 , 80, 15); + RecipientNo = new javax.swing.JTextField(); + RecipientNo.setBounds(10 , 85 ,270 , 20); + RecipientNo.setText(""); + StartsWith = new javax.swing.JTextField(); + StartsWith.setBounds(335 ,415 ,155 , 20); + StartsWith.setText(""); + //this file is for start with icon & should be placed with the directory containing class files + java.net.URL url = PCapplication.class.getResource ("contacts.gif"); + ImageIcon icon = new ImageIcon(url); + JLabel SearchIcon = new JLabel(icon); + SearchIcon.setBounds (270 ,415 ,100 , 40); + SearchIcon.setOpaque (false); + SearchIcon.setVisible (true); + catch (Exception e){Jout ("exception here");} + MessageLabel = new javax.swing.JLabel(); + MessageLabel.setText("Message:"); + MessageLabel.setBounds( 10, 135 ,80 , 15); + MessageInfoLabel = new javax.swing.JLabel (); + MessageInfoLabel.setText(""); + p2.add(MessageInfoLabel); + MessageInfoLabel.setBounds( 90, 135 ,60 , 15); + Message = new javax.swing.JTextArea(10,10); + Message.setBounds( 10, 155 ,270 , 130); + Message.setLineWrap (true); + Message.setWrapStyleWord (true); + //scroll pane for the message area display + javax.swing.JScrollPane MessageScrollPane = new javax.swing.JScrollPane(Message); + p2.add(MessageScrollPane); + MessageScrollPane.setBounds( 10, 155 ,270 , 130); + ClearMsgButton = new javax.swing.JButton(); + ClearMsgButton.setText("Clear"); + p2.add(ClearMsgButton); + ClearMsgButton.setBounds(60 , 295 , 65, 25); + ClearMsgButton.setBackground(Color.LIGHT_GRAY); + SendButton = new javax.swing.JButton(); + SendButton.setText("Send"); + SendButton.setBounds( 170, 295 , 65, 25); + SendButton.setBackground(Color.LIGHT_GRAY); + BackButton2 = new javax.swing.JButton(); + BackButton2.setText("Back"); + BackButton2.setBounds(115, 350 ,65 , 25); + BackButton2.setBackground(Color.LIGHT_GRAY); + QuitButton3 = new javax.swing.JButton(); + QuitButton3.setText("Home Page"); + QuitButton3.setBounds(250, 260, 140, 25); + QuitButton3.setBackground(Color.LIGHT_GRAY); + // SendNewMessageButton + SendNewMessageButton = new javax.swing.JButton(); + SendNewMessageButton.setText("Send new message"); + p3.add(SendNewMessageButton); + SendNewMessageButton.setBounds(95, 260, 150, 25); + SendNewMessageButton.setBackground(Color.LIGHT_GRAY); + // SearchForDevicesButton + SearchForDevicesButton = new javax.swing.JButton(); + SearchForDevicesButton.setText("Search for Devices"); + SearchForDevicesButton.setVisible(true); + p1.add(SearchForDevicesButton); + SearchForDevicesButton.setBounds(183, 135, 142, 25); + SearchForDevicesButton.setBackground(Color.LIGHT_GRAY); + QuitButton = new javax.swing.JButton(); + QuitButton.setText("Exit"); + QuitButton.setBounds(370, 390, 65, 25); + QuitButton.setBackground(Color.LIGHT_GRAY); + PhoneBook = new javax.swing.JList(); + PhoneBook.setBounds( 335 , 85 ,155 ,320); + // scroll pane for the phonebook list + javax.swing.JScrollPane scrollPane = new javax.swing.JScrollPane(PhoneBook); + scrollPane.setBounds( 335 , 85 ,155 ,320); + RetrieveContacts = new javax.swing.JButton(); + RetrieveContacts.setText("Retrieve Contacts"); + p2.add(RetrieveContacts); + RetrieveContacts.setBounds( 335, 50 , 155 , 25); + RetrieveContacts.setBackground(Color.LIGHT_GRAY); + SelectContactNumber = new javax.swing.JButton(); + SelectContactNumber.setText("<<"); + SelectContactNumber.setEnabled(false); + p2.add(SelectContactNumber); + SelectContactNumber.setBounds( 283, 85, 50 ,20 ); + SelectContactNumber.setBackground(Color.LIGHT_GRAY); + SelectDevice = new javax.swing.JButton(); + SelectDevice.setText("Select Device"); + SelectDevice.setBounds(185, 360, 140, 25); + SelectDevice.setBackground(Color.LIGHT_GRAY); + DevicesList = new javax.swing.JList(); + DevicesList.setBorder(new javax.swing.border.MatteBorder(null)); + DevicesList.setBounds(165, 170, 180, 180); + DisplayText1 = new javax.swing.JTextPane (); + DisplayText1.setOpaque( false ); + DisplayText1.setFont(new java.awt.Font("MS Reference Sans Serif", 1, 18)); + DisplayText1.setForeground(java.awt.Color.BLUE); + DisplayText1.setBounds(90, 40, 170, 70); + DisplayText2 = new javax.swing.JTextPane (); + DisplayText2.setOpaque( false ); + DisplayText2.setFont(new java.awt.Font("MS Reference Sans Serif", 1, 18)); + DisplayText2.setForeground(java.awt.Color.BLUE); + DisplayText2.setBounds(10 ,8 ,490 , 40); + DisplayText3 = new javax.swing.JTextPane (); + DisplayText3.setOpaque( false ); + DisplayText3.setEnabled (false); + DisplayText3.setFont(new java.awt.Font("MS Reference Sans Serif", 1, 18)); + DisplayText3.setForeground(java.awt.Color.BLUE); + DisplayText3.setBounds(30, 30 , 440, 220); + addWindowListener(new java.awt.event.WindowAdapter() + public void windowClosing(java.awt.event.WindowEvent evt) + public void windowClosed(java.awt.event.WindowEvent evt) + SMSFrame = new javax.swing.JFrame(); + SMSFrame.addWindowListener(new java.awt.event.WindowAdapter() + public void windowClosing(java.awt.event.WindowEvent evt) + public void windowClosed(java.awt.event.WindowEvent evt) + ReportFrame = new javax.swing.JFrame(); + ReportFrame.addWindowListener(new java.awt.event.WindowAdapter() + public void windowClosing(java.awt.event.WindowEvent evt) + public void windowClosed(java.awt.event.WindowEvent evt) + SelectDevice.addActionListener(new java.awt.event.ActionListener() + public void actionPerformed(java.awt.event.ActionEvent evt) + SelectDeviceActionPerformed(evt); + BackButton2.addActionListener(new java.awt.event.ActionListener() + public void actionPerformed(java.awt.event.ActionEvent evt) + BackButton2ActionPerformed(evt); + QuitButton3.addActionListener(new java.awt.event.ActionListener() + public void actionPerformed(java.awt.event.ActionEvent evt) + QuitButton3ActionPerformed(evt); + SendNewMessageButton.addActionListener(new java.awt.event.ActionListener() + public void actionPerformed(java.awt.event.ActionEvent evt) + SendNewMessageButtonActionPerformed(evt); + SearchForDevicesButton.addActionListener(new java.awt.event.ActionListener() + public void actionPerformed(java.awt.event.ActionEvent evt) + searchDevicesThreadCounter++; + //this variable is set to zero searching for devices is completed + if (searchDevicesThreadCounter == 1) //to ignore multiple clicks of the user + SearchForDevicesButtonActionPerformed(evt); + ClearMsgButton.addActionListener(new java.awt.event.ActionListener() + public void actionPerformed(java.awt.event.ActionEvent evt) + * implements the key listener so that whenever the user releases a key + * all the contact names starting with that key are shown in the list of imported contacts + StartsWith.addKeyListener(new java.awt.event.KeyListener () + public void keyTyped (java.awt.event.KeyEvent kv) + public void keyReleased (java.awt.event.KeyEvent kv) + public void keyPressed (java.awt.event.KeyEvent kv) + * implements the key listener so that as the user releases a key + * a number beside the message label will indicate to him the number + * of characters displayed as well as how many SMS will be sent for this message + * One SMS contains a maximum of 160 characters + Message.addKeyListener(new java.awt.event.KeyListener () + public void keyTyped (java.awt.event.KeyEvent kv) + public void keyReleased (java.awt.event.KeyEvent kv) + public void keyPressed (java.awt.event.KeyEvent kv) + SendButton.addActionListener(new java.awt.event.ActionListener() + public void actionPerformed(java.awt.event.ActionEvent evt) + SendButtonActionPerformed(evt); + RetrieveContacts.addActionListener(new java.awt.event.ActionListener() + public void actionPerformed(java.awt.event.ActionEvent evt) + RetrieveContactsActionPerformed(evt); + SelectContactNumber.addActionListener(new java.awt.event.ActionListener() + public void actionPerformed(java.awt.event.ActionEvent evt) + SelectContactNumberActionPerformed(evt); + QuitButton.addActionListener(new java.awt.event.ActionListener() + public void actionPerformed(java.awt.event.ActionEvent evt) + QuitButtonActionPerformed(evt); + //setting the positions of the frames + java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize(); + setBounds((screenSize.width-450)/2, (screenSize.height-450)/2, 300, 300); + SMSFrame.setBounds((screenSize.width-450)/2, (screenSize.height-450)/2, 300, 300); + ReportFrame.setBounds((screenSize.width-450)/2, (screenSize.height-450)/2, 300, 300); + * Gets the selected bluetooth device by the user and call the service discovery method over it + private void SelectDeviceActionPerformed(java.awt.event.ActionEvent evt) + int selectedDevice = DevicesList.getSelectedIndex(); + if (selectedDevice != -1) + blue.selectedDevice = selectedDevice; //the blue instance discover services on that device + * a new thread to do service discovery + * so as not to freeze the current thread + Thread t = new Thread () + *Starts searching for nearby bluetooth devices as the user clicks on Search for devices button + private void SearchForDevicesButtonActionPerformed(java.awt.event.ActionEvent evt) + DevicesList.setListData(new Vector()); + /* a new thread to do device discovery + * so as not to freeze the current thread + Thread t =new Thread () + * Returns to the frame which allows the user to enter the SMS to be routed to the phone + private void SendNewMessageButtonActionPerformed(java.awt.event.ActionEvent evt) + RecipientNo.setText(""); + StartsWith.setText(""); + DisplayText2.setVisible (false); + SMSFrame.setVisible(true); + ReportFrame.setVisible(false); + messageCharacters = 160; + * when the user chooses to quit the application + * It avoids any abnormal termination of the client and + * notifies the server of the user action so that the server doesnt keep waiting for the same client. + * so this function sends a message to the server via bluetooth + * informing it that the client will exit + private void QuitButton3ActionPerformed(java.awt.event.ActionEvent evt) + //ensures that the server is still connected before sending a message to it + if (blue.checkCellularPhoneConnectivity()) + client.out.writeUTF("CLIENT_EXIT"); + client.closeConnection(); + client.contactNames.removeAllElements (); + this.setVisible (true); + ReportFrame.setVisible (false); + *Displays the contacts retrieved from the phone in a list + private void RetrieveContactsActionPerformed(java.awt.event.ActionEvent evt) + //thread prompts the user to wait till the contacts are retrieved from the phone + Thread t = new Thread () + if (client.connectionOpen == true) + DisplayText2.setVisible (true); + DisplayText2.setText ("Retrieving contacts.."); + while (client.importedPhonebook==false) //the client instance hasnt imported the phone book yet + DisplayText2.setText(DisplayText2.getText() + "." ); + if (DisplayText2.getText().equals ("Retrieving contacts....")) + DisplayText2.setText("Retrieving contacts"); + if (client.importingPhonebook == false) //the client instance finished importing phone book with error + DisplayText2.setVisible (false); + showMessageBox ("Unable to retrieve contacts from the cell phone.", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.ERROR_MESSAGE, "HomePage"); + if (client.importedPhonebook==false) + showMessageBox ("Unable to retrieve contacts from the cell phone. Please try again.", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.ERROR_MESSAGE, ""); + PhoneBook.setListData(client.contactNames); + SelectContactNumber.setEnabled(true); + showMessageBox ("Unable to connect to the phone. Please try again.", "Error",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.ERROR_MESSAGE, "HomePage"); + DisplayText2.setVisible (false); + * It copies the number from the contact list to the the recipient number + private void SelectContactNumberActionPerformed(java.awt.event.ActionEvent evt) + if (StartsWith.getText().equals ("")) + int selectedIndexName = PhoneBook.getSelectedIndex(); + if (selectedIndexName == -1) + if(RecipientNo.getText().equalsIgnoreCase("")) + RecipientNo.setText((String)client.contactNumbers.elementAt(selectedIndexName + addToIndex)); + alreadyEntered = RecipientNo.getText(); //append to the numbers already entered + RecipientNo.setText(alreadyEntered+","+(String)client.contactNumbers.elementAt(selectedIndexName + addToIndex)); + * Ensures that the client has entered at least one number and a message + * it also ensures that the server is still connected to the client before sending + private void SendButtonActionPerformed(java.awt.event.ActionEvent evt) + int maxRecipientNo = 10; + //int countRecipients = 0; + //String desiredNumbers []; + //String msg = Message.getText(); + msg = Message.getText(); + String allEntered = RecipientNo.getText()+','; + if (msg.equals("") && allEntered.equals (",")) + showMessageBox ("Please enter a message and desired number(s).", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.INFORMATION_MESSAGE, ""); + else if (msg.equals("")) + showMessageBox ("Please enter a message.", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.INFORMATION_MESSAGE, ""); + else if (allEntered.equals(",")) + showMessageBox ("Please enter the desired number(s).", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.INFORMATION_MESSAGE, ""); + //if the client is still trying to retrieve the contacts from the server. + //the user should wait until the import finishes + while (client.importedPhonebook ==false) + if (client.importingPhonebook == false) //finished to retrieve contacts but with error + if (client.connectionOpen == false) + showMessageBox ("Unable to connect to the cell phone", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.INFORMATION_MESSAGE, "Home Page"); + if (!blue.checkCellularPhoneConnectivity()) + showMessageBox ("Unable to connect to the cell phone. Please try again.", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.ERROR_MESSAGE, "HomePage"); + client.closeConnection(); + SMSFrame.setVisible (false); + desiredNumbers = new String [maxRecipientNo]; + for(int i = 0; i < allEntered.length(); i++) + if(allEntered.charAt(i) == ',') + number = allEntered.substring(begin,i); + if(countRecipients < maxRecipientNo) + desiredNumbers[countRecipients] = number; + showMessageBox ("You can only send a maximum of ten numbers at a time.", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.INFORMATION_MESSAGE, ""); + if (client.connectionOpen == false) + showMessageBox ("Unable to connect to the cell phone. Please try again.", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.ERROR_MESSAGE, "HomePage"); + //Two threads in order not to freeze the current thread + //Thread for routing the SMS to the cellular phone + Thread t = new Thread () + client.SMSroute(msg,countRecipients,desiredNumbers); + showMessageBox ("Unable to route the message to the phone.", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.INFORMATION_MESSAGE, "HomePage"); + // Thread to wait for the server response indicating the success of sending the message and display "Sending.." message to the user + Thread t2 = new Thread () + doWaitForSendingResponse (); + * The user desires to quit before a connection with the server established + private void QuitButtonActionPerformed(java.awt.event.ActionEvent evt) + private void StartsWithKeyTyped () + /* initializes the variable addToIndex to zero each time the user releases a key + * There are two vectors one containing the numbers and another containing the names + * the list of contacts displayed to the user contains only the names + * this variable is used because the list of devices contains only the contacts that starts with a certain string entered by the user + * hence, the index of the contact in the list will change causing wrong numbers to be retrieved from the vector + * so I used that variable to make track of the index of the selected device + if ((client.importingPhonebook==false) || (client.importedPhonebook==false)) + boolean visited = false; + while (client.importedPhonebook==false) + Vector startsWith = new Vector (); //containing the contacts starting with a certain string entered by the user + for (int i = 0 ; i < client.contactNames.size(); i++) + if (client.contactNames.elementAt(i).toString().toLowerCase().startsWith(StartsWith.getText().toLowerCase())) + startsWith.addElement(client.contactNames.elementAt(i)); + addToIndex = i; //this index will be added to the index of the selected contact name to retrieve the right number from the numbers' vector + PhoneBook.setListData(startsWith); + SelectContactNumber.setEnabled(true); + * messageNumber: variable that contains the number of SMS that will be sent from the phone + * carrying the message entered by the user + * messageCharacters: variable that contains the number of characters left in this message to be + * to be sent within the same SMS + private void MessageKeyTyped () + messageNumber = (Message.getText ().length () / 160) + 1; + messageCharacters = (messageNumber * 160) - Message.getText ().length (); + if (messageCharacters == 1) + messageCharacters = 160; + MessageInfoLabel.setText (messageCharacters + "["+messageNumber+"]"); + * Returns back to the home page + * the method notifies the server that the client will quit to release the erver from the task of waiting for serving this specific client + private void BackButton2ActionPerformed(java.awt.event.ActionEvent evt) + if (blue.checkCellularPhoneConnectivity()) + client.out.writeUTF("CLIENT_EXIT"); + client.closeConnection(); + SMSFrame.setVisible (false); + * The client closes the application from the window + private void exitForm1(java.awt.event.WindowEvent evt) + *There is already a connection with the server so the client sends a message to the server when it comes to quit + private void exitForm2(java.awt.event.WindowEvent evt) + //ensures that the server is still connected before sending a message to it + if (blue.checkCellularPhoneConnectivity()) + client.out.writeUTF("CLIENT_EXIT"); + client.closeConnection(); + * startApp Shows home page + protected void startApp() + blue = new BTworker (); + *Displays the home page components + public void showFirstPage() + //any interface added here + DisplayText1.setVisible(false); + SelectDevice.setVisible(true); + SelectDevice.setEnabled (false); + DevicesList.setListData(new Vector()); + DevicesList.setVisible (true); + PhoneBook.setListData (new Vector ()); + this.getContentPane ().add (p1); + QuitButton.setVisible(true); + SearchForDevicesButton.setVisible(true); + *Displays the sms frame components + public void showSecondPage () + messageCharacters = 160; + MessageInfoLabel.setText (messageCharacters + "["+messageNumber+"]"); + SMSFrame.setSize(510,510); + SMSFrame.getContentPane().add(p2); + SMSFrame.setVisible(true); + DisplayText2.setVisible(false); + ReportFrame.setVisible(false); + this.setVisible(false); + SelectContactNumber.setEnabled(false); + *diplays error messages and informative messages to the use + *parameters: message to be contained + * optiontype: OK, Cancel,etc.. + * messageType: error message, info message, etc.. + public void showMessageBox (String message, String title, int optionType, int messageType, String display) + javax.swing.JOptionPane msgBox = new javax.swing.JOptionPane (); + msgBox.showConfirmDialog(this,message,title, optionType , messageType); + if (display.equals ("HomePage")) + public void Jout (String s) + System.out.println (s); + *Displays the bluetooth devies discovered + public void showBTDevices () + DevicesList.setListData(theDevices); + SelectDevice.setEnabled(true); + * the blue instance starts the search for the devices + public void doDeviceSearch () + DisplayText1.setText ("Searching."); + theDevices = new Vector(); + DevicesList.removeAll(); + blue.startDeviceInquiry(); + //waits until the blue instance complete its search for devices + while (BTworker.deviceWaiting == true) + DisplayText1.setVisible(true); + DisplayText1.setText(DisplayText1.getText() + "." ); + if (DisplayText1.getText().equals ("Searching....")) + DisplayText1.setText("Searching"); + catch(java.lang.InterruptedException e) + if (BTworker.devices.size() > 0) + //some devices where discovered and placed in the vector for devices + DisplayText1.setVisible(false); + Jout ("[Found "+BTworker.devices.size()+" devices, selected one of the following:"); + for (int i = 0; i < BTworker.devices.size(); i++) + RemoteDevice device = (RemoteDevice) BTworker.devices.elementAt(i); + String name = device.getFriendlyName(false); + theDevices.addElement("["+i+"] "+name); + //no devices were discovered + DisplayText1.setVisible(true); + showMessageBox ("No devices found. Try again later.", "SMS Routing",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.INFORMATION_MESSAGE, "HomePage"); + Jout ("no devices found." +"\n"); + searchDevicesThreadCounter = 0; + * the blue instance does service discovery on the selected device by the user + public void doServiceSearch () + ReportFrame.setSize(510,510); + ReportFrame.getContentPane().add(p3); + blue.startServiceInquiry(); + DisplayText1.setText ("Connecting."); + //waits tll the blue instance finishes discovering the services + while (blue.serviceWaiting==true) + DisplayText1.setVisible(true); + DisplayText1.setText(DisplayText1.getText() + "." ); + if (DisplayText1.getText().equals ("Please wait....")) + DisplayText1.setText("Please wait"); + /*the blue instance finished service discovery on the device + *if the blue instance succeeded in finding services (the vector of services is not empty), + *the application start running the client that will perform the routing over bluetooth + if (blue.services.size() > 0) + Thread t = new Thread () + DisplayText1.setVisible(false); + showMessageBox ("Unable to connect to the selected device. Please try again.", "Error",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.ERROR_MESSAGE, "HomePage"); + * Method responsible for waiting for server response after sending the SMS to it via bluetooth + * and display the result in a frame to the user + public void doWaitForSendingResponse () + DisplayText2.setText ("Sending SMS.."); + DisplayText2.setVisible(true); + //waiting for the server response whether it succeeded in sending the message or not + while (client.serverSendingResponse == false) + if (client.connectionOpen == false) + DisplayText2.setText(DisplayText2.getText() + "." ); + if (DisplayText2.getText().equals ("Sending SMS....")) + DisplayText2.setText("Sending SMS"); + Thread t = new Thread () + ReportFrame.setVisible(true); + SMSFrame.setVisible(false); + SendNewMessageButton.setVisible(true); + QuitButton3.setVisible(true); + DisplayText3.setVisible (true); + if ((client.connectionOpen==false) && (client.serverSendingResponse == false)) + showMessageBox ("Connection to the phone was lost. Please try again.", "Error",javax.swing.JOptionPane.DEFAULT_OPTION,javax.swing.JOptionPane.ERROR_MESSAGE, "HomePage"); + if (client.unsuccessfulNumbers.size()==0) + //the cellular phone succeeded in sending the SMS to the desired number (s) + DisplayText3.setText("Your messages was Routed Successfully."); + //the cellular phone failed to send SMS to all or some of the numbers + DisplayText3.setText("Your message to the following Recipient(s) failed\n " + "\n"); + for(int i = 0 ; i < client.unsuccessfulNumbers.size() ; i++) + DisplayText3.setText(DisplayText3.getText() + client.unsuccessfulNumbers.elementAt(i) + "\n"); + * startClient. Starts bluetooth client thread. + private void startClient() + client = new Client (); + client.run_client(blue.getOneDiscoveredService()); + public static void main(String args[]) + //the default look and feel + javax.swing.UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.Motif.LookAndFeel"); + PCapplication application = new PCapplication(); + application.setSize(510,510); + application.startApp(); + //does not spawn other clients until this current client is completely served + Object obj = new Object(); + catch (InterruptedException ex) + *Class responsible for displaying the background + class Background extends JPanel + public void paint(Graphics g) + g.drawImage(bi , 0, 0, null); Binary file htdocs/summerofcode/mel/RoutingSMS/client/babyblue.jpg has changed
Binary file htdocs/summerofcode/mel/RoutingSMS/client/contacts.gif has changed