/******************************************************************************* * Copyright (c) 2008, 2011 VMware Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VMware Inc. - initial contribution *******************************************************************************/ package org.eclipse.virgo.management.console; import java.io.File; import java.io.IOException; import java.io.PrintWriter; import java.lang.management.ManagementFactory; import java.net.URI; import java.util.ArrayList; import java.util.List; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.openmbean.CompositeDataSupport; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.fileupload.FileItem; import org.apache.commons.fileupload.FileItemFactory; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.servlet.ServletFileUpload; import org.osgi.framework.BundleContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * * */ public class UploadServlet extends HttpServlet { private static final String[] DEPLOYMENT_IDENTITY_FIELDS = new String[]{"type", "symbolicName", "version"}; private static final int HTTP_RESPONSE_INTERNAL_SERVER_ERROR = 500; private static final String ORG_ECLIPSE_VIRGO_KERNEL_HOME = "org.eclipse.virgo.kernel.home"; private static final String DEPLOYER_MBEAN_NAME = "org.eclipse.virgo.kernel:category=Control,type=Deployer"; private static final long serialVersionUID = 1L; private static final String STAGING_DIR = "/work/org.eclipse.virgo.apps.admin.web.UploadServlet"; private static final Logger log = LoggerFactory.getLogger(UploadServlet.class); private MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer(); private String serverHome = null; private BundleContext bundleContext = null; public UploadServlet() { } public UploadServlet(BundleContext bundleContext) { this.bundleContext = bundleContext; } /** * Do not use this method with the HTTPService unless the BundleContext has already been set. */ public void init(ServletConfig config) throws ServletException { super.init(config); if(bundleContext == null){ this.bundleContext = (BundleContext) config.getServletContext().getAttribute("osgi-bundlecontext"); } this.serverHome = this.bundleContext.getProperty(ORG_ECLIPSE_VIRGO_KERNEL_HOME); } protected void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException { try { File stagingDir = createStagingDirectory(); FileItemFactory factory = new DiskFileItemFactory(); ServletFileUpload upload = new ServletFileUpload(factory); response.setContentType("text/html"); List<FileItem> items = (List<FileItem>) upload.parseRequest(request); List<File> uploadedFiles = new ArrayList<File>(); for (FileItem fileItem : items) { File uploadedFile = this.doUpload(fileItem, stagingDir); if(uploadedFile != null){ uploadedFiles.add(uploadedFile); } } doDeployment(uploadedFiles, response); } catch (IllegalArgumentException ea){ PrintWriter writer = response.getWriter(); writer.append("<ol id=\"uploadResults\"><li>File name contains '/' or '\\', this is not allowed.</ol>"); writer.close(); } catch (Exception e) { log.error(e.toString()); response.sendError(HTTP_RESPONSE_INTERNAL_SERVER_ERROR, e.toString()); } } File doUpload(FileItem fileItem, File stagingDir) throws Exception{ if (!fileItem.isFormField()) { String name = fileItem.getName(); if(name != null && name.length() > 0){ if(name.contains("\\") || name.contains("/")){ throw new IllegalArgumentException("Security violation, file name contains '/' or '\\'"); } File uploadedFile = new File(stagingDir, name); fileItem.write(uploadedFile); log.info(String.format("Uploaded artifact of size (%db) to %s", fileItem.getSize(), uploadedFile.getPath())); return uploadedFile; } } return null; } private void doDeployment(List<File> uploadedFiles, HttpServletResponse response) throws MalformedObjectNameException, NullPointerException, IOException{ ObjectName objectName = new ObjectName(DEPLOYER_MBEAN_NAME); PrintWriter writer = response.getWriter(); writer.append("<ol id=\"uploadResults\">"); for (File file : uploadedFiles) { URI uri = file.toURI(); try { Object invoke = this.mBeanServer.invoke(objectName, "deploy", new Object[]{uri.toString()}, new String[]{String.class.getName()}); writer.append("<li>" + file.getName() + " deployed as " + getDeploymentIdentity(invoke) + "</li>"); } catch (Exception e) { writer.append("<li>" + file.getName() + " failed to deploy '" + e.getMessage() + "'</li>"); } writer.append("<li />"); } writer.append("</ol>"); writer.close(); } private String getDeploymentIdentity(Object deploymentIdentity) { StringBuilder builder = new StringBuilder(); if(deploymentIdentity instanceof CompositeDataSupport){ CompositeDataSupport deploymentIdentityInstance = (CompositeDataSupport) deploymentIdentity; Object[] all = deploymentIdentityInstance.getAll(DEPLOYMENT_IDENTITY_FIELDS); builder.append(all[0]); builder.append(" - ").append(all[1]); builder.append(": ").append(all[2]); } return builder.toString(); } private File createStagingDirectory() throws IOException { File pathReference = new File(String.format("%s%s", this.serverHome, STAGING_DIR)); if (!pathReference.exists()) { if (!pathReference.mkdirs()) { throw new IOException("Unable to create directory " + pathReference.getAbsolutePath()); } } return pathReference.getAbsoluteFile(); } }