raymond.mockftpserver.S3CachedFtpServer.java Source code

Java tutorial

Introduction

Here is the source code for raymond.mockftpserver.S3CachedFtpServer.java

Source

/**
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package raymond.mockftpserver;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;

import org.mockftpserver.core.command.Command;
import org.mockftpserver.core.command.CommandNames;
import org.mockftpserver.core.session.Session;
import org.mockftpserver.core.session.SessionKeys;
import org.mockftpserver.fake.FakeFtpServer;
import org.mockftpserver.fake.UserAccount;
import org.mockftpserver.fake.command.StorCommandHandler;
import org.mockftpserver.fake.filesystem.FileEntry;
import org.mockftpserver.fake.filesystem.FileSystemEntry;
import org.mockftpserver.stub.command.UserCommandHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import raymond.mockftpserver.Encryptor.EncryptionException;

import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;

/**
 * Main class that can download files from an existing FTP server.
 */
public final class S3CachedFtpServer extends FakeFtpServer {

    private File _accessFile;

    private String charset;
    private String keyBase;
    private String apiKey;
    private String apiKeySecret;
    private String chave;
    private String bucket;
    private Region region = Region.getRegion(Regions.SA_EAST_1);

    private CachedFileSystem localFileSystem;
    private UserCommandHandler loginCommand;
    // private CommandHandler size;
    private StorCommandHandler stor;
    private UserAccount login;

    final Logger logger = LoggerFactory.getLogger(this.getClass());

    public S3CachedFtpServer() {

    }

    public void init(File _accessFile, String chave, String charset, String keyBase, String bucket, Region region)
            throws UnsupportedEncodingException {

        this._accessFile = _accessFile;
        this.chave = chave;
        this.charset = charset;
        this.keyBase = keyBase;
        this.bucket = bucket;
        this.region = region;

        login = new UserAccount() {
            @Override
            public boolean canExecute(FileSystemEntry entry) {
                return true;
            }

            @Override
            public boolean canRead(FileSystemEntry entry) {
                return true;
            }

            @Override
            public boolean canWrite(FileSystemEntry entry) {
                return true;
            }
        };
        loginCommand = new UserCommandHandler() {
            public void handleCommand(org.mockftpserver.core.command.Command command,
                    org.mockftpserver.core.session.Session session,
                    org.mockftpserver.core.command.InvocationRecord invocationRecord) {
                super.handleCommand(command, session, invocationRecord);
                String username = command.getRequiredParameter(0);
                session.setAttribute(SessionKeys.USERNAME, username);
                session.setAttribute(SessionKeys.USER_ACCOUNT, login);
                session.setAttribute(SessionKeys.CURRENT_DIRECTORY, "/");
            };
        };
        loginCommand.setPasswordRequired(false);
        setCommandHandler(CommandNames.USER, loginCommand);
        // size = new AbstractFakeCommandHandler() {
        //
        // @Override
        // protected void handle(Command command, Session session) {
        // verifyLoggedIn(session);
        // this.replyCodeForFileSystemException = ReplyCodes.READ_FILE_ERROR;
        //
        // String path = getRealPath(session, command.getRequiredParameter(0));
        // String size;
        // if (localFileSystem.isRoot(path)) {
        // size = quotes("0");
        // } else {
        // FileSystemEntry entry = getFileSystem().getEntry(path);
        // verifyFileSystemCondition(entry != null, path,
        // "filesystem.doesNotExist");
        // if (entry.isDirectory()) {
        // size = quotes("0");
        // } else {
        // size = quotes(Long.toString(entry.getSize()));
        // }
        // }
        // sendReply(session, ReplyCodes.TRANSFER_DATA_FINAL_OK, size);
        // }
        // };
        // setCommandHandler("SIZE", size);
        stor = new StorCommandHandler() {
            @Override
            protected void handle(Command command, Session session) {
                super.handle(command, session);
                String filename = getOutputFile(command);
                String path = getRealPath(session, filename);
                FileEntry file = (FileEntry) getFileSystem().getEntry(path);
                ((CachedFileSystem) getFileSystem()).s3.add(file);
            }
        };
        setCommandHandler(CommandNames.STOR, stor);
    }

    public void go() throws EncryptionException, IOException {
        readKeyFile(_accessFile);

        logger.info("inicializando");
        // S3BucketFileSystem s3 = new S3BucketFileSystem();
        // s3.init(apiKey, apiKeySecret, bucket, region);
        // setFileSystem(s3);
        localFileSystem = new CachedFileSystem();
        localFileSystem.init(apiKey, apiKeySecret, bucket, region);
        setFileSystem(localFileSystem);
        logger.info("fim inicializacao");

        start();
    }

    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");

        String identityPath = (String) ctx.getBean("identityPath");
        String charset = (String) ctx.getBean("charset");
        String keyBase = (String) ctx.getBean("keyBase");
        // String host = (String) ctx.getBean("s3Host");
        String bucket = (String) ctx.getBean("s3Bucket");
        String chave = (String) ctx.getBean("chave");
        Region region = (Region) ctx.getBean("s3Region");

        ctx.close();

        // check if user wants to create credentials
        File _accessFile = new File(identityPath);

        S3CachedFtpServer s3FtpServer = new S3CachedFtpServer();
        s3FtpServer.init(_accessFile, chave, charset, keyBase, bucket, region);

        if (!_accessFile.exists() && args.length != 2) {
            throw new RuntimeException("sem credenciais");
        } else if (!_accessFile.exists()) {
            s3FtpServer.writeKeyFile(args[0], args[1].toCharArray());
        }

        s3FtpServer.go();
    }

    private void writeKeyFile(String accessKey, char[] secretKey)
            throws UnsupportedEncodingException, IOException, EncryptionException {
        byte[] nameRaw = chave.getBytes(charset);
        byte[] accessKeyRaw = accessKey.getBytes(charset);

        if (nameRaw.length > 0xff) {
            throw new RuntimeException("name too long");
        }
        if (accessKeyRaw.length > 0xff) {
            throw new RuntimeException("accessKey too long");
        }

        byte[] cleartext = new byte[2 + nameRaw.length + accessKeyRaw.length + secretKey.length * 2];
        cleartext[0] = (byte) nameRaw.length;
        cleartext[1] = (byte) accessKeyRaw.length;
        for (int i = 0; i < nameRaw.length; i++) {
            cleartext[i + 2] = nameRaw[i];
        }
        int offset = nameRaw.length + 2;
        for (int i = 0; i < accessKeyRaw.length; i++) {
            cleartext[i + offset] = accessKeyRaw[i];
        }
        offset += accessKeyRaw.length;
        for (int i = 0; i < secretKey.length; i++) {
            char ch = secretKey[i];
            int spot = i + i;
            cleartext[offset + spot] = (byte) (ch >> 8); // msb
            cleartext[offset + spot + 1] = (byte) (ch); // lsb
        }

        Encryptor crypt = new ThreeDESEncryptor(chave + keyBase);
        byte[] cipher = crypt.encrypt(cleartext);

        logger.info("@@ writing cypher in:" + _accessFile);
        logger.info("@@ len written is:" + cipher.length);

        _accessFile.createNewFile();
        OutputStream out = new FileOutputStream(_accessFile);
        out.write(cipher);
        out.close();

        readKeyFile(_accessFile);
    }

    private void readKeyFile(File _accessFile) throws IOException, EncryptionException {
        logger.info("@@ reading cypher from:" + _accessFile);
        BufferedInputStream in = new BufferedInputStream(new FileInputStream(_accessFile));
        int len = in.available();
        byte[] buffer = new byte[len];
        in.read(buffer);
        in.close();
        logger.info("@@ len read is:" + len);

        byte[] cleartext;

        Encryptor crypt = new ThreeDESEncryptor(chave + keyBase);
        cleartext = crypt.decrypt(buffer);

        int nameLen = cleartext[0];
        int accessKeyLen = cleartext[1];
        int secretKeyLen = cleartext.length - 2 - nameLen - accessKeyLen;
        if (secretKeyLen % 2 != 0) {
            throw new RuntimeException("internal error: secret key has odd bytecount");
        }

        byte[] nameRaw = new byte[nameLen];
        for (int i = 0; i < nameLen; i++) {
            nameRaw[i] = cleartext[i + 2];
        }
        String nameCheck = new String(nameRaw, charset);
        if (!chave.equals(nameCheck)) {
            throw new RuntimeException("internal error: secret key name mismatch");
        }

        // Get the Access Key
        int offset = 2 + nameLen;
        byte[] accessKeyRaw = new byte[accessKeyLen];
        for (int i = 0; i < accessKeyLen; i++) {
            accessKeyRaw[i] = cleartext[i + offset];
        }
        apiKey = new String(accessKeyRaw, charset);

        // Get the Secret Key
        char[] secretKey = new char[secretKeyLen / 2];
        offset += accessKeyLen;
        for (int i = 0; i < secretKeyLen / 2; i++) {
            int spot = i + i + offset;
            char ch = (char) ((cleartext[spot] << 8) + cleartext[spot + 1]);
            secretKey[i] = ch;
        }
        apiKeySecret = new String(secretKey);
    }
}