Java tutorial
/* * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with this program; if not, see <http://www.gnu.org/licenses/> * */ package net.FriendsUnited.Services; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.PrintWriter; import java.io.StringReader; import java.util.Date; import java.util.List; import java.util.Scanner; import net.FriendsUnited.CommandLineModule; import net.FriendsUnited.FriendPacket; import net.FriendsUnited.ServiceServer; import net.FriendsUnited.Util.ByteConverter; import net.FriendsUnited.Util.Tool; import org.jdom2.Document; import org.jdom2.Element; import org.jdom2.JDOMException; import org.jdom2.input.SAXBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Lars Pötter * (<a href=mailto:Lars_Poetter@gmx.de>Lars_Poetter@gmx.de</a>) */ public class FileClient implements Service, CommandLineModule { public final static int RESPONSE_PACKET_TIMEOUT = 10000; // time to wait for response packet in milliseconds private final Logger log = LoggerFactory.getLogger(this.getClass().getName()); private ServiceServer server; private static final String OPEN_SERVER_CMD = "open"; private static final String LIST_DIRECTORY_CMD = "ls"; private static final String CHNAGE_DIRECTORY_CMD = "cd"; private static final String SEND_FILE_CMD = "put"; private static final String REQUEST_FILE_CMD = "get"; private String RemoteServer = ""; private String RemotePath = ""; /** * */ public FileClient(ServiceServer server) { this.server = server; server.registerService(this); } private void receiveResponse(PrintWriter out) { server.waitForNextPacketFromNetwork(this, RESPONSE_PACKET_TIMEOUT); FriendPacket response = server.getNextPacketFromNetwork(this); if (null == response) { out.println("Got no responser from Server !"); } else { parseResponse(response, out); } } public boolean execute(final String curCmd, PrintWriter out) { final Scanner sc = new Scanner(curCmd); if (false == sc.hasNext()) { return false; } final String Command = sc.next(); if (OPEN_SERVER_CMD.equals(Command)) { RemoteServer = sc.next(); // open connection to server // request listing of root folder ByteConverter bc = new ByteConverter(); bc.add(FileServer.GET_DIRECTORY_LISTING); bc.add(RemotePath); FriendPacket pkt = new FriendPacket(server.getName(), this.getName(), // source RemoteServer, "FileServer", // target bc.toByteArray()); // payload server.sendPacketIntoNetwork(this, pkt); receiveResponse(out); } else if (LIST_DIRECTORY_CMD.equals(Command)) { ByteConverter bc = new ByteConverter(); bc.add(FileServer.GET_DIRECTORY_LISTING); bc.add(RemotePath); FriendPacket pkt = new FriendPacket(server.getName(), this.getName(), // source RemoteServer, "FileServer", // target bc.toByteArray()); // payload server.sendPacketIntoNetwork(this, pkt); receiveResponse(out); } else if (CHNAGE_DIRECTORY_CMD.equals(Command)) { log.info("old Remote Path was {}", RemotePath); String folder = sc.next(); log.info("Folder is {}", folder); if (true == "..".equals(folder)) { if (RemotePath.length() > 1) { RemotePath = RemotePath.substring(0, RemotePath.length() - 2); // Remove File.separator at end of Path int newEndIdx = RemotePath.lastIndexOf('/'); if (1 > newEndIdx) { RemotePath = ""; } else { RemotePath = RemotePath.substring(0, newEndIdx); } } // else remote Path is already the Root of the RemoteServer so "cd .." not possible } else { RemotePath = RemotePath + folder + "/"; } log.info("new Remote Path is {}", RemotePath); } else if (SEND_FILE_CMD.equals(Command)) { String LocalFileName = sc.next(); String RemoteFileName = RemotePath + LocalFileName; File f = new File(LocalFileName); if (false == f.canRead()) { out.println("ERROR: Could not read local File(" + LocalFileName + ") to send !"); return true; } ByteConverter bc = new ByteConverter(); bc.add(FileServer.PUT_FILE); bc.add(RemoteFileName); bc.add((long) 0); // We send the whole file in one go TODO send only part of File long size = f.length(); if (size > Integer.MAX_VALUE) { out.println("ERROR: File too big !"); return true; } int size_i = (int) size; bc.add(size_i); try { FileInputStream fin = new FileInputStream(f); byte[] buf = new byte[size_i]; fin.read(buf); bc.add(buf); FriendPacket pkt = new FriendPacket(server.getName(), this.getName(), // source RemoteServer, "FileServer", // target bc.toByteArray()); // payload server.sendPacketIntoNetwork(this, pkt); receiveResponse(out); return true; } catch (FileNotFoundException e) { out.println(Tool.fromExceptionToString(e)); return true; } catch (IOException e) { out.println(Tool.fromExceptionToString(e)); return true; } } else if (REQUEST_FILE_CMD.equals(Command)) { String LocalFileName = sc.next(); String RemoteFileName = RemotePath + LocalFileName; ByteConverter bc = new ByteConverter(); bc.add(FileServer.GET_FILE); bc.add(RemoteFileName); bc.add((long) 0); // whole File TODO bc.add((int) Integer.MAX_VALUE); // TODO reasonable Value FriendPacket pkt = new FriendPacket(server.getName(), this.getName(), // source RemoteServer, "FileServer", // target bc.toByteArray()); // payload server.sendPacketIntoNetwork(this, pkt); receiveResponse(out); } else { // not a valid command return false; } // one of the ifs executed return true; } private void parseResponse(FriendPacket response, PrintWriter out) { log.debug("{}", response); ByteConverter responseBc = new ByteConverter(response.getPayload()); byte type = responseBc.getByte(); log.debug("Response Type : {}", type); switch (type) { case FileServer.FAILURE: String errorMsg = responseBc.getString(); if (true == "OK".equals(errorMsg)) { out.println("OK"); } else { out.println("ERROR in Response Packet:" + errorMsg); } break; case FileServer.DIRECTORY_LISTING: out.println("Listing of " + RemoteServer + " : " + RemotePath); String xmlData = responseBc.getString(); log.info("Response String : {}", xmlData); final SAXBuilder builder = new SAXBuilder(); Document doc; try { doc = builder.build(new StringReader(xmlData)); Element root = null; root = doc.getRootElement(); List<Element> le = root.getChildren(); for (int i = 0; i < le.size(); i++) { Element curentElement = le.get(i); String date = curentElement.getChildText("lastModified"); long ms = Long.parseLong(date); Date d = new Date(ms); out.printf("%29s", d); out.print("|"); String size = curentElement.getChildText("Size"); if (null == size) { size = ""; } out.printf("%12s", size); out.print("|"); if (true == "File".equals(curentElement.getName())) { out.print("F"); } else if (true == "Directory".equals(curentElement.getName())) { out.print("D"); } else { out.print("X"); } out.print("|"); out.println(curentElement.getText()); // File Name } } catch (JDOMException e) { log.error(Tool.fromExceptionToString(e)); } catch (IOException e) { log.error(Tool.fromExceptionToString(e)); } break; default: out.println("ERROR: Receive Response of invalid Type ! " + Tool.fromByteBufferToHexString(response.getPayload())); break; } } public String[] getCommands() { return new String[] { OPEN_SERVER_CMD, LIST_DIRECTORY_CMD, CHNAGE_DIRECTORY_CMD, SEND_FILE_CMD, REQUEST_FILE_CMD }; } public String[] getCommandDescriptions() { return new String[] { "connect to a server", "show content of remote Directory", "change remote Diretory", "send local file into remote directory", "request file in remote directory" }; } public void doShutdown() { server.unregisterService(this); } @Override public String getName() { return "FileClient"; } @Override public void close() { doShutdown(); } }