org.jboss.ejb3.examples.ch06.filetransfer.FileTransferBean.java Source code

Java tutorial

Introduction

Here is the source code for org.jboss.ejb3.examples.ch06.filetransfer.FileTransferBean.java

Source

/*
 * JBoss, Home of Professional Open Source.
 * Copyright 2009, Red Hat Middleware LLC, and individual contributors
 * as indicated by the @author tags. See the copyright.txt file in the
 * distribution for a full listing of individual contributors.
  *
 * This is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
package org.jboss.ejb3.examples.ch06.filetransfer;

import java.io.File;
import java.io.IOException;
import java.io.Serializable;
import java.util.logging.Logger;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.ejb.Local;
import javax.ejb.PostActivate;
import javax.ejb.PrePassivate;
import javax.ejb.Remove;
import javax.ejb.Stateful;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;

/**
 * Bean Implementation class of the FileTransferEJB, modeled
 * as a Stateful Session Bean
 *
 * @author <a href="mailto:andrew.rubinger@jboss.org">ALR</a>
 */
@Stateful(name = FileTransferBean.EJB_NAME)
@Local(FileTransferLocalBusiness.class)
public class FileTransferBean implements FileTransferLocalBusiness, Serializable {

    //-------------------------------------------------------------------------------------||
    // Class Members ----------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||

    /**
     * Serial Version UID
     */
    private static final long serialVersionUID = 1L;

    /**
     * Logger
     */
    private static final Logger log = Logger.getLogger(FileTransferBean.class.getName());

    /**
     * Name of the EJB, used in Global JNDI addresses
     */
    public static final String EJB_NAME = "FileTransferEJB";

    /**
     * The name of the host to which we'll connect.
     * In production systems would typically be externalized
     * via configurable environment entry
     */
    private static String CONNECT_HOST = "localhost";

    /**
     * The port to which we'll connect.
     * In production systems would typically be externalized
     * via configurable environment entry.  IANA standard
     * for FTP ports is 21, though this requires root access
     * on *nix for testing, so we'll use the nonstandard 12345.
     */
    private static int CONNECT_PORT = 12345;

    //-------------------------------------------------------------------------------------||
    // Instance Members -------------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||

    /**
     * The underlying FTP Client.  We don't want its state
     * getting Serialized during passivation.  We'll
     * reinitialize this client and its connections
     * upon activation.
     */
    private FTPClient client;

    /**
     * Name of the present working directory.  In cases where
     * we're passivated, if this is specified
     * we'll change into this directory upon activation.
     */
    private String presentWorkingDirectory;

    //-------------------------------------------------------------------------------------||
    // Lifecycle Callbacks ----------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||

    /**
     * Called by the container when the instance is about to be passivated or brought
     * out of service entirely.
     *
     * @see org.jboss.ejb3.examples.ch06.filetransfer.FileTransferCommonBusiness#disconnect()
     */
    @PrePassivate
    @PreDestroy
    @Override
    public void disconnect() {
        // Obtain FTP Client
        final FTPClient client = this.getClient();

        // If exists
        if (client != null) {
            // If connected
            if (client.isConnected()) {
                // Logout
                try {
                    client.logout();
                    log.info("Logged out of: " + client);
                } catch (final IOException ioe) {
                    log.warning("Exception encountered in logging out of the FTP client: " + ioe.getMessage());
                }

                // Disconnect
                try {
                    log.fine("Disconnecting: " + client);
                    client.disconnect();
                    log.info("Disconnected: " + client);
                } catch (final IOException ioe) {
                    log.warning("Exception encountered in disconnecting the FTP client: " + ioe.getMessage());
                }

                // Null out the client so it's not serialized
                this.client = null;
            }
        }
    }

    /**
     * Called by the container when the instance has been created or re-activated
     * (brought out of passivated state).  Will construct the underlying FTP Client
     * and open all appropriate connections.
     *
     * @see org.jboss.ejb3.examples.ch06.filetransfer.FileTransferCommonBusiness#connect()
     */
    @PostConstruct
    @PostActivate
    @Override
    public void connect() throws IllegalStateException, FileTransferException {
        /*
         * Precondition checks
         */
        final FTPClient clientBefore = this.getClient();
        if (clientBefore != null && clientBefore.isConnected()) {
            throw new IllegalStateException("FTP Client is already initialized");
        }

        // Get the connection properties
        final String connectHost = this.getConnectHost();
        final int connectPort = this.getConnectPort();

        // Create the client
        final FTPClient client = new FTPClient();
        final String canonicalServerName = connectHost + ":" + connectPort;
        log.fine("Connecting to FTP Server at " + canonicalServerName);
        try {
            client.connect(connectHost, connectPort);
        } catch (final IOException ioe) {
            throw new FileTransferException("Error in connecting to " + canonicalServerName, ioe);
        }

        // Set
        log.info("Connected to FTP Server at: " + canonicalServerName);
        this.setClient(client);

        // Check that the last operation succeeded
        this.checkLastOperation();

        try {
            // Login
            client.login("user", "password");

            // Check that the last operation succeeded
            this.checkLastOperation();
        } catch (final Exception e) {
            throw new FileTransferException("Could not log in", e);
        }

        // If there's a pwd defined, cd into it.
        final String pwd = this.getPresentWorkingDirectory();
        if (pwd != null) {
            this.cd(pwd);
        }

    }

    //-------------------------------------------------------------------------------------||
    // Required Implementations -----------------------------------------------------------||
    //-------------------------------------------------------------------------------------||

    /* (non-Javadoc)
     * @see org.jboss.ejb3.examples.ch06.filetransfer.FileTransferCommonBusiness#cd(java.lang.String)
     */
    @Override
    public void cd(final String directory) {
        // Get the client
        final FTPClient client = this.getClient();

        // Exec cd
        try {
            // Exec cd
            client.changeWorkingDirectory(directory);

            // Check reply for success
            this.checkLastOperation();
        } catch (final Exception e) {
            throw new FileTransferException("Could not change working directory to \"" + directory + "\"", e);
        }

        // Set the pwd (used upon activation)
        log.info("cd > " + directory);
        this.setPresentWorkingDirectory(directory);
    }

    /* (non-Javadoc)
     * @see org.jboss.ejb3.examples.ch06.filetransfer.FileTransferCommonBusiness#mkdir(java.lang.String)
     */
    @Override
    public void mkdir(final String directory) {
        // Get the client
        final FTPClient client = this.getClient();

        // Exec cd
        try {
            // Exec mkdir
            client.makeDirectory(directory);

            // Check reply for success
            this.checkLastOperation();
        } catch (final Exception e) {
            throw new FileTransferException("Could not make directory \"" + directory + "\"", e);
        }

    }

    /* (non-Javadoc)
     * @see org.jboss.ejb3.examples.ch06.filetransfer.FileTransferCommonBusiness#pwd()
     */
    @Override
    public String pwd() {
        // Get the client
        final FTPClient client = this.getClient();

        // Exec pwd
        try {
            final FTPFile[] files = client.listFiles();
            for (final FTPFile file : files) {
                log.info(file.toString());
            }

            // Exec pwd
            String dir = client.printWorkingDirectory();
            String separator = File.separator;

            if ("\\".equals(separator)) {
                // reformat to use for windows
                if (dir.startsWith("/")) {
                    dir = dir.substring(1);
                }
                dir = dir.replaceAll("/", "\\" + separator);
            }

            return dir;

        } catch (final IOException ioe) {
            throw new FileTransferException("Could not print working directory", ioe);
        }
    }

    //-------------------------------------------------------------------------------------||
    // Internal Helper Methods ------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||

    /**
     * Ensures that the last operation succeeded with a positive
     * reply code.  Otherwise a {@link FileTransferException} 
     * is raised, noting the reply code denoting the error.
     * 
     * @throws FileTransferException
     */
    protected void checkLastOperation() throws FileTransferException {
        // Get the client
        final FTPClient client = this.getClient();

        // Obtain and check the reply from the connection
        final int connectReply = client.getReplyCode();
        if (!FTPReply.isPositiveCompletion(connectReply)) {
            // Indicate the problem
            throw new FileTransferException(
                    "Did not receive positive completion code from server, instead code was: " + connectReply);
        }

    }

    /* (non-Javadoc)
     * @see org.jboss.ejb3.examples.ch06.filetransfer.FileTransferRemoteBusiness#endSession()
     */
    @Remove
    @Override
    public void endSession() {
        log.info("Session Ending...");
    }

    //-------------------------------------------------------------------------------------||
    // Accessors / Mutators ---------------------------------------------------------------||
    //-------------------------------------------------------------------------------------||

    /**
     * @return the connectHost
     */
    public String getConnectHost() {
        return CONNECT_HOST;
    }

    /**
     * @return the connectPort
     */
    public int getConnectPort() {
        return CONNECT_PORT;
    }

    /**
     * @return the client
     */
    protected final FTPClient getClient() {
        return client;
    }

    /**
     * @param client the client to set
     */
    private void setClient(final FTPClient client) {
        this.client = client;
    }

    /**
     * @return the presentWorkingDirectory
     */
    private String getPresentWorkingDirectory() {
        return presentWorkingDirectory;
    }

    /**
     * @param presentWorkingDirectory the presentWorkingDirectory to set
     */
    private void setPresentWorkingDirectory(String presentWorkingDirectory) {
        this.presentWorkingDirectory = presentWorkingDirectory;
    }

}