FileUploadServletClient.java :  » EJB-Server » geronimo » deploy-jsr88 » org » apache » geronimo » deployment » plugin » remote » Java Open Source

Java Open Source » EJB Server » geronimo 
geronimo » deploy jsr88 » org » apache » geronimo » deployment » plugin » remote » FileUploadServletClient.java
/*
 * 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 org.apache.geronimo.deployment.plugin.remote;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.URL;
import java.net.URLConnection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geronimo.gbean.AbstractName;
import org.apache.geronimo.gbean.AbstractNameQuery;
import org.apache.geronimo.kernel.Kernel;
import org.apache.geronimo.crypto.encoders.Base64;

/**
 *
 * @version $Rev:$ $Date:$
 */
public class FileUploadServletClient implements FileUploadClient {
    private static final Log log = LogFactory.getLog(FileUploadServletClient.class);

    /** Note:  The below versions should be kept in sync with those in FileUploadServlet.java **/
    // Starting RemoteDeploy datastream versions
    public static final int REMOTE_DEPLOY_REQUEST_VER_0 = 0;
    public static final int REMOTE_DEPLOY_RESPONSE_VER_0 = 0;
    // Current RemoteDeploy datastream versions
    public static final int REMOTE_DEPLOY_REQUEST_VER = 0;
    public static final int REMOTE_DEPLOY_RESPONSE_VER = 0;

    public URL getRemoteDeployUploadURL(Kernel kernel) {
        AbstractName deployerName = getDeployerName(kernel);
        String remoteDeployUpload;
        try {
            remoteDeployUpload = (String) kernel.getAttribute(deployerName, "remoteDeployUploadURL");
            return new URL(remoteDeployUpload);
        } catch (Exception e) {
            throw new AssertionError(e);
        }
     }

    protected AbstractName getDeployerName(Kernel kernel) {
        Set<AbstractName> deployerNames = kernel.listGBeans(new AbstractNameQuery("org.apache.geronimo.deployment.Deployer"));
        if (1 != deployerNames.size()) {
            throw new IllegalStateException("No Deployer GBean present in running Geronimo server. " +
                 "This usually indicates a serious problem with the configuration of " +
                 "your running Geronimo server.  If " +
                 "the deployer is present but not started, the workaround is to run " +
                 "a deploy command like 'start geronimo/geronimo-gbean-deployer/1.0/car'.  " +
                 "If the deployer service is not present at all (it was undeployed) then " +
                 "you need to either re-install Geronimo or get a deployment plan for the " +
                 "runtime deployer and distribute it while the server is not running and " +
                 "then start the server with a command like the above.  For help on this, " +
                 "write to user@geronimo.apache.org and include the contents of your " +
                 "var/config/config.xml file.");
        }
        return deployerNames.iterator().next();
    }

    public void uploadFilesToServer(URL uploadURL,
            String username,
            String password,
            File[] files,
            FileUploadProgress progress) {
        if(files == null) {
            return;
        }
        
        List valid = new LinkedList();
        for(int i=0; i<files.length; i++) {
            if(files[i] == null) {
                continue;
            }
            File file = files[i];
            if(!file.exists() || !file.canRead()) {
                continue;
            }
            valid.add(new Integer(i));
        }
        
        if(valid.size() > 0) {
            progress.updateStatus("Uploading "+valid.size()+" file(s) to server");
            if (log.isDebugEnabled()) {
                log.debug("Uploading "+valid.size()+" file(s) to server");
            }
            try {
                URLConnection con = connectToServer(uploadURL, username, password);
                writeRequest(con, files, valid, progress);
                readResponse(con, files, valid, progress);
            } catch (Exception e) {
                progress.fail(e);
            }
        }
    }

    protected void readResponse(URLConnection con, File[] files, List valid, FileUploadProgress progress)
            throws IOException {
        /* ---------------------
         * RemoteDeploy Response
         * ---------------------
         *
         * Note:  The below code has to match FileUploadServlet.java
         *
         * RemoteDeployer response stream format:
         *   It returns a serialized stream containing:
         *   0) an int, the version of this datastream format - REMOTE_DEPLOY_RESPONSE_VER
         *   1) a UTF string, the status (should be "OK")
         *   2) an int, the number of files received
         *   3) for each file:
         *     3.1) a UTF String, the path to the file as saved to the server's filesystem
         *   x) new data would be added here
         *
         *   The file positions in the response will be the same as in the request.
         *   That is, a name for upload file #2 will be in response position #2.
         */
        DataInputStream in = new DataInputStream(new BufferedInputStream(con.getInputStream()));
        // 0) an int, the version of this datastream format - REMOTE_DEPLOY_RESPONSE_VER
        int rspVer = in.readInt();
        // whenever we update the stream version, the next line needs to
        // be changed to just - (rspVer >= REMOTE_DEPLOY_RESPONSE_VER_0)
        // but until then, be more restrictive so we can handle old servers
        // that don't send a version as the first thing, but UTF instead...
        if ((rspVer >= REMOTE_DEPLOY_RESPONSE_VER_0) && (rspVer <= REMOTE_DEPLOY_RESPONSE_VER)) {
            // 1) a UTF string, the status (should be "OK")
            String status = in.readUTF();
            if(!status.equals("OK")) {
                progress.fail("Unable to upload files to server.  Server returned status="+status);
                log.error("Unable to upload files to server.  Server returned status="+status);
                return;
            }
            progress.updateStatus("File upload complete (Server status="+status+")");
            if (log.isDebugEnabled()) {
                log.debug("File upload complete (Server status="+status+")");
            }
            // 2) an int, the number of files received
            int count = in.readInt();
            if(count != valid.size()) {
                progress.fail("Server only received "+count+" of "+valid.size()+" files");
                log.warn("Server only received "+count+" of "+valid.size()+" files");
            }
            // 3) for each file:
            for (Iterator it = valid.iterator(); it.hasNext();) {
                Integer index = (Integer) it.next();
                // 3.1) a UTF String, the path to the file as saved to the server's filesystem
                String serverFileName = in.readUTF();
                if (serverFileName != null) {
                    files[index.intValue()] = new File(serverFileName);
                } else {
                    log.error("Received an invalid filename from the server");
                    files[index.intValue()] = null;
                }
                if (log.isDebugEnabled()) {
                    log.debug("Server created file="+serverFileName);
                }
            }
            // x) new data would be added here
            if (rspVer > REMOTE_DEPLOY_RESPONSE_VER_0) {
                // additions in later datastream versions would be handled here

                if (rspVer > REMOTE_DEPLOY_RESPONSE_VER) {
                    // if the server is sending a newer version than we know about
                    // just ignore it and warn the user about the mismatch
                    log.warn("Received a newer server response ("+rspVer+") than expected ("+REMOTE_DEPLOY_RESPONSE_VER+").  Ignoring any additional server response data.");
                }
            }
        } else {
            // should never happen, but handle it anyway
            progress.fail("Received unknown server response version="+rspVer);
            log.warn("Received unknown server response version="+rspVer);
        }
        in.close();
        progress.updateStatus("File(s) transferred to server.  Resuming deployment operation.");
    }

    protected void writeRequest(URLConnection con, File[] files, List valid, FileUploadProgress progress)
            throws IOException, FileNotFoundException {
        /* --------------------
         * RemoteDeploy Request
         * --------------------
         *
         * Note:  The below code has to match FileUploadServlet.java
         *
         * RemoteDeployer data stream format:
         *   0) an int, the version of this datastream format - REMOTE_DEPLOY_REQUEST_VER
         *   1) an int, the number of files being uploaded
         *   2) for each file:
         *     2.0) a UTF String, the filename of the file being uploaded
         *     2.1) a long, the length of the file in bytes
         *     2.2) byte[], byte count equal to the number above for the file
         */
        DataOutputStream out = new DataOutputStream(new BufferedOutputStream(con.getOutputStream()));
        // 0) an int, the version of this datastream format - REMOTE_DEPLOY_REQUEST_VER
        out.writeInt(REMOTE_DEPLOY_REQUEST_VER);
        // 1) an int, the number of files being uploaded
        out.writeInt(valid.size());
        byte[] buf = new byte[1024];
        int size;
        long total, length, threshold, next;
        // 2) for each file:
        for (Iterator it = valid.iterator(); it.hasNext();) {
            Integer index = (Integer) it.next();
            File file = files[index.intValue()];
            // 2.0) a UTF String, the filename of the file being uploaded
            out.writeUTF(file.getName().trim());
            // 2.1) a long, the length of the file in bytes
            out.writeLong(length = file.length());
            threshold = Math.max(length / 100, (long)10240);
            next = threshold;
            BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));
            if (log.isDebugEnabled()) {
                log.debug("Uploading "+file.getName());
            }
            total = 0;
            // 2.2) raw bytes, equal to the number above for the file
            while((size = in.read(buf)) > -1) {
                out.write(buf, 0, size);
                total += size;
                if(total > next) {
                    progress.updateStatus("Uploading "+file.getName()+": "+(total/1024)+" KB");
                    while(total > next) next += threshold;
                }
            }
            in.close();
        }
        out.flush();
        out.close();
    }

    protected URLConnection connectToServer(URL url, String username, String password) throws IOException {
        URLConnection con = url.openConnection();
        String auth = username + ":" + password;
        byte[] data = auth.getBytes();
        String s = new String(Base64.encode(data));
        while(s.length() % 4 != 0) s += "=";
        con.setRequestProperty("Authorization", "Basic "+s);
        con.setDoInput(true);
        con.setDoOutput(true);
        con.connect();
        return con;
    }

}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.