net.FriendsUnited.Services.FileClient.java Source code

Java tutorial

Introduction

Here is the source code for net.FriendsUnited.Services.FileClient.java

Source

/*
 * 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&ouml;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();
    }

}