001    /**
002     *  Licensed to the Apache Software Foundation (ASF) under one or more
003     *  contributor license agreements.  See the NOTICE file distributed with
004     *  this work for additional information regarding copyright ownership.
005     *  The ASF licenses this file to You under the Apache License, Version 2.0
006     *  (the "License"); you may not use this file except in compliance with
007     *  the License.  You may obtain a copy of the License at
008     *
009     *     http://www.apache.org/licenses/LICENSE-2.0
010     *
011     *  Unless required by applicable law or agreed to in writing, software
012     *  distributed under the License is distributed on an "AS IS" BASIS,
013     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     *  See the License for the specific language governing permissions and
015     *  limitations under the License.
016     */
017    package org.apache.geronimo.deployment.remote;
018    
019    import javax.servlet.http.HttpServlet;
020    import javax.servlet.http.HttpServletRequest;
021    import javax.servlet.http.HttpServletResponse;
022    import javax.servlet.ServletException;
023    import java.io.DataOutputStream;
024    import java.io.DataInputStream;
025    import java.io.File;
026    import java.io.IOException;
027    import java.io.BufferedOutputStream;
028    import java.io.FileOutputStream;
029    
030    /**
031     * A servlet that accepts file uploads.  It takes only POST requests, which should
032     * contain a Java "DataOutput" formatted stream containing:
033     *
034     * 1) an int, the number of files being uploaded
035     * 2) for each file:
036     *    1) an int, the length of the file in bytes
037     *    2) a number of raw bytes equal to the above for the file
038     *
039     * It returns a serialized stream containing:
040     *
041     * 1) a UTF string, the status (should be "OK")
042     * 2) an int, the number of files received
043     * 3) for each file:
044     *    1) a UTF String, the path to the file as saved to the server's filesystem
045     *
046     * The file positions in the response will be the same as in the request.
047     * The is, a name for upload file #2 will be in response position #2.
048     *
049     * @version $Rev: 476061 $ $Date: 2006-11-17 01:36:50 -0500 (Fri, 17 Nov 2006) $
050     */
051    public class FileUploadServlet extends HttpServlet {
052        protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
053            int fileCount;
054            String names[];
055            try {
056                DataInputStream in = new DataInputStream(request.getInputStream());
057                fileCount = in.readInt();
058                names = new String[fileCount];
059                for(int i=0; i<fileCount; i++) {
060                    int length = in.readInt();
061                    File temp = File.createTempFile("remote-deploy", "");
062                    temp.deleteOnExit();
063                    names[i] = temp.getAbsolutePath();
064                    readToFile(in, temp, length);
065                }
066                in.close();
067            } catch (IOException e) {
068                DataOutputStream out = new DataOutputStream(response.getOutputStream());
069                out.writeUTF("ERROR: "+e.getMessage());
070                out.close();
071                return;
072            }
073            DataOutputStream out = new DataOutputStream(response.getOutputStream());
074            out.writeUTF("OK");
075            out.writeInt(fileCount);
076            for (int i = 0; i < names.length; i++) {
077                out.writeUTF(names[i]);
078            }
079            out.flush();
080            out.close();
081        }
082    
083        private static void readToFile(DataInputStream in, File temp, int length) throws IOException {
084            BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(temp));
085            int total, read;
086            try {
087                byte[] buf = new byte[1024];
088                total = 0;
089                while((read = in.read(buf, 0, Math.min(buf.length, length - total))) > -1) {
090                    out.write(buf, 0, read);
091                    total += read;
092                    if(total == length) {
093                        break;
094                    }
095                }
096            } finally {
097                try {out.flush();} catch (IOException e) {}
098                out.close();
099            }
100            if(total != length) {
101                throw new IOException("Unable to read entire upload file ("+total+"b expecting "+length+"b)");
102            }
103        }
104    }
105