/* * Copyright 2011 Future Systems * * Licensed 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.krakenapps.webconsole.servlet; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.net.URLEncoder; import javax.servlet.ServletException; import javax.servlet.ServletOutputStream; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.felix.ipojo.annotations.Component; import org.apache.felix.ipojo.annotations.Requires; import org.apache.felix.ipojo.annotations.Validate; import org.krakenapps.dom.api.FileUploadApi; import org.krakenapps.dom.model.UploadedFile; import org.krakenapps.httpd.HttpContext; import org.krakenapps.httpd.HttpService; import org.krakenapps.httpd.MimeTypes; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component(name = "webconsole-file-upload-servlet") public class FileUploadServlet extends HttpServlet { private static final long serialVersionUID = 1L; private final Logger logger = LoggerFactory.getLogger(FileUploadServlet.class.getName()); @Requires private HttpService httpd; @Requires private FileUploadApi upload; /** * Register servlet to servlet registry of webconsole */ @Validate public void start() { HttpContext ctx = httpd.ensureContext("webconsole"); ctx.addServlet("upload", this, "/upload"); } @Override public void log(String message, Throwable t) { logger.warn("kraken webconsole: upload servlet error", t); } public void setFileUploadApi(FileUploadApi upload) { this.upload = upload; } @Override protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException { UploadedFile f = null; FileInputStream is = null; ServletOutputStream os = null; String downloadToken = null; String fileGuid = null; logger.trace("kraken webconsole: jsession [{}]", req.getSession().getId()); try { downloadToken = getDownloadToken(req); fileGuid = req.getParameter("resource"); if (downloadToken == null) { resp.sendError(HttpServletResponse.SC_FORBIDDEN); return; } f = upload.getFileMetadataWithToken(downloadToken, fileGuid); is = new FileInputStream(f.getFile()); os = resp.getOutputStream(); logger.trace("kraken webconsole: open downstream for {}", f.getFile().getAbsolutePath()); String mimeType = MimeTypes.instance().getByFile(f.getFileName()); resp.setHeader("Content-Type", mimeType); String dispositionType = null; if (req.getParameter("force_download") != null) dispositionType = "attachment"; else dispositionType = "inline"; String encodedFilename = URLEncoder.encode(f.getFileName(), "UTF-8").replaceAll("\\+", "%20"); resp.setHeader("Content-Disposition", dispositionType + "; filename*=UTF-8''" + encodedFilename); resp.setStatus(200); resp.setContentLength((int) f.getFileSize()); byte[] b = new byte[8096]; while (true) { int readBytes = is.read(b); if (readBytes <= 0) break; os.write(b, 0, readBytes); } } catch (Exception e) { resp.setStatus(500); logger.warn("kraken webconsole: cannot download id " + fileGuid, e); } finally { if (is != null) try { is.close(); } catch (IOException e) { } if (os != null) try { os.close(); } catch (IOException e) { } } } private String getDownloadToken(HttpServletRequest req) { Cookie[] cookies = req.getCookies(); if (cookies != null) { for (Cookie cookie : cookies) { logger.trace("kraken webconsole: checking all cookie for download, {} = {}", cookie.getName(), cookie.getValue()); if (cookie.getName().equals("kraken_session")) return cookie.getValue(); } } return req.getParameter("session"); } @Override protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException { logger.debug("kraken webconsole: received post request from [{}]", req.getRemoteAddr()); String token = req.getHeader("X-Upload-Token"); if (token == null) { logger.warn("kraken webconsole: upload token header not found for [{}] stream", req.getRemoteAddr()); return; } String range = req.getHeader("X-Upload-Range"); String[] ranges = null; InputStream is = null; try { is = req.getInputStream(); if (range == null) { upload.writeFile(token, is); } else { if (range != null) ranges = range.split(","); Long begin = Long.valueOf(ranges[0]); Long end = Long.valueOf(ranges[1]); if (begin >= end) throw new IllegalArgumentException("begin should be smaller than end range"); logger.info("kraken webconsole: partial upload, token [{}], [{}~{}]", new Object[] { token, begin, end }); // TODO: after complete dom porting // upload.writePartialFile(token, begin, end, is); } resp.setStatus(200); } catch (Exception e) { try { resp.sendError(500, e.toString()); } catch (IOException e1) { } logger.warn("kraken webconsole: upload post failed", e); } finally { if (is == null) return; try { is.close(); } catch (IOException e) { } try { resp.getOutputStream().close(); } catch (IOException e) { } } } }