001package csheets.ext.share.core; 002 003import java.io.*; 004import java.net.*; 005import java.util.*; 006import java.util.logging.*; 007 008import csheets.core.Cell; 009import csheets.core.formula.compiler.FormulaCompilationException; 010 011/** 012 * Class that implement the client in the extension 013 * 014 * @see Runnable 015 * @author Andre 016 * 017 */ 018public class Client extends Observable implements Runnable { 019 /** the ip of the server */ 020 private String IP; 021 /** the port of the connection */ 022 private int port; 023 /** the cell where the program will copy */ 024 private Cell cellStart; 025 /** the connection to the server */ 026 private Connections connection; 027 /** the connection password */ 028 private String password; 029 /** the observer class */ 030 private Observer observer; 031 /** the cell listener */ 032 private final CellNetworkListenerClient listener = new CellNetworkListenerClient(); 033 034 /** share properties (writable wr) or read-only(r) */ 035 private String properties; 036 037 /** 038 * Create a new client 039 */ 040 public Client() { 041 } 042 043 /** 044 * Create internaly a new client 045 * 046 * @param IP 047 * of the server 048 * @param port 049 * the port of the connection 050 * @param cellStart 051 * the cell where the program will copy 052 * @param password 053 * the connection password 054 * @param observer 055 * the observer class 056 */ 057 private Client(String IP, int port, Cell cellStart, String password, 058 Observer observer) { 059 this.IP = IP; 060 this.port = port; 061 this.cellStart = cellStart; 062 this.password = password; 063 this.observer = observer; 064 } 065 066 /** 067 * Create internaly a new client 068 * 069 * @param connection 070 * the connection to the server 071 * @param cellStart 072 * the cell where the program will copy 073 * @param observer 074 * the connection observer 075 * @param password 076 * the password connection 077 */ 078 private Client(Connections connection, Cell cellStart, Observer observer, 079 String password) { 080 this.connection = connection; 081 this.cellStart = cellStart; 082 this.observer = observer; 083 this.password = password; 084 } 085 086 /** 087 * Method that will start the client and receive cells throw network 088 * 089 * @param IP 090 * the server ip 091 * @param port 092 * the connection port of the server 093 * @param cellStart 094 * cell where we paste the content of the shared cells 095 * @param password 096 * the connection password 097 * @param observer 098 * the observer class 099 */ 100 public void startClient(String IP, int port, Cell cellStart, 101 String password, Observer observer) { 102 Thread thr = new Thread(new Client(IP, port, cellStart, password, 103 observer)); 104 thr.start(); 105 } 106 107 /** 108 * Method that will start the client and receive cells throw network 109 * 110 * @param connection 111 * the connection to the server 112 * @param cellStart 113 * cell where we paste the content of the shared cells 114 * @param observer 115 * the observer class 116 * @param password 117 * the password connection 118 */ 119 public void startClient(Connections connection, Cell cellStart, 120 Observer observer, String password) { 121 Thread thr = new Thread(new Client(connection, cellStart, observer, 122 password)); 123 thr.start(); 124 } 125 126 /** 127 * The method that will treat the incoming cells 128 * 129 * @param cellStart 130 * cell where we paste the content 131 * @param cli 132 * the socket of connection 133 * @param password 134 * the connection password 135 * @throws IOException 136 * throw this exception if the I/O have errors 137 * @throws ClassNotFoundException 138 * throw this exception if the object passed throw network was 139 * invalid 140 * @throws FormulaCompilationException 141 * throw if the cell does not respect the formula compiler 142 */ 143 private synchronized void receive(Cell cellStart, Socket cli, 144 String password) throws IOException, ClassNotFoundException, 145 FormulaCompilationException { 146 boolean isCell = true; 147 int cellStartRow = cellStart.getAddress().getRow(); 148 int cellStartColumn = cellStart.getAddress().getColumn(); 149 OutputStream out = cli.getOutputStream(); 150 DataOutputStream outStream = new DataOutputStream(out); 151 outStream.writeUTF(password); 152 DataInputStream receiveProps = new DataInputStream(cli.getInputStream()); 153 this.properties = receiveProps.readUTF(); 154 155 while (isCell) { 156 ObjectInputStream inStream = new ObjectInputStream( 157 cli.getInputStream()); 158 CellNetwork cell = (CellNetwork) inStream.readObject(); 159 if (cell.isCell()) { 160 161 this.cellStart 162 .getSpreadsheet() 163 .getCell(cellStartColumn + cell.getColumn(), 164 cellStartRow + cell.getRow()) 165 .setContent(cell.getContent()); 166 167 this.cellStart 168 .getSpreadsheet() 169 .getCell(cellStartColumn + cell.getColumn(), 170 cellStartRow + cell.getRow()) 171 .addCellListener(listener); 172 173 } else { 174 isCell = false; 175 } 176 } 177 outStream.writeUTF("Close yourself"); 178 179 } 180 181 /** 182 * Method that when changes occurred on cells of client's share, listener 183 * changes a flag value and this method can run and send that update to the 184 * server 185 * 186 * @param sock 187 * the client socket 188 * @exception IOException 189 * of a I/O exception occurs 190 */ 191 public synchronized void sendToServer(Socket sock) throws IOException, 192 InterruptedException { 193 194 while (true) { 195 Thread.sleep(100); 196 197 if (listener.getFlag() == true) { 198 199 OutputStream out = sock.getOutputStream(); 200 DataOutputStream outStream = new DataOutputStream(out); 201 outStream.writeUTF("send me updated data"); 202 203 CellNetwork cell = new CellNetwork(listener.getCell() 204 .getContent(), listener.getCell().getAddress().getRow() 205 - cellStart.getAddress().getRow(), listener.getCell() 206 .getAddress().getColumn() 207 - cellStart.getAddress().getColumn(), true); 208 209 ObjectOutputStream objectOut = new ObjectOutputStream( 210 sock.getOutputStream()); 211 objectOut.writeObject(cell); 212 213 } 214 listener.setFlag(false); 215 216 } 217 218 } 219 220 /** 221 * Running thread 222 */ 223 @Override 224 public void run() { 225 try { 226 227 addObserver(observer); 228 Socket cli; 229 if (IP != null) { 230 cli = new Socket(IP, port); 231 } else 232 cli = new Socket(connection.getIP(), connection.getPort()); 233 receive(cellStart, cli, password); 234 Thread thr = new Thread(new ThreadClient(cellStart, cli, listener, 235 observer)); 236 thr.start(); 237 238 while (true) { 239 if (this.properties.equals("wr")) 240 241 sendToServer(cli); 242 } 243 244 } catch (UnknownHostException e) { 245 246 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, e); 247 setChanged(); 248 notifyObservers(); 249 clearChanged(); 250 } catch (IOException e) { 251 252 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, e); 253 setChanged(); 254 notifyObservers(); 255 clearChanged(); 256 } catch (ClassNotFoundException e) { 257 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, e); 258 setChanged(); 259 notifyObservers(); 260 clearChanged(); 261 } catch (FormulaCompilationException e) { 262 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, e); 263 setChanged(); 264 notifyObservers(); 265 clearChanged(); 266 } catch (InterruptedException e) { 267 Logger.getLogger(Client.class.getName()).log(Level.SEVERE, null, e); 268 setChanged(); 269 notifyObservers(); 270 clearChanged(); 271 } 272 } 273}