/**
* Copyright (c) 2011, SOCIETIES Consortium (WATERFORD INSTITUTE OF TECHNOLOGY (TSSG), HERIOT-WATT UNIVERSITY (HWU), SOLUTA.NET
* (SN), GERMAN AEROSPACE CENTRE (Deutsches Zentrum fuer Luft- und Raumfahrt e.V.) (DLR), Zavod za varnostne tehnologije
* informacijske družbe in elektronsko poslovanje (SETCCE), INSTITUTE OF COMMUNICATION AND COMPUTER SYSTEMS (ICCS), LAKE
* COMMUNICATIONS (LAKE), INTEL PERFORMANCE LEARNING SOLUTIONS LTD (INTEL), PORTUGAL TELECOM INOVAÇÃO, SA (PTIN), IBM Corp.,
* INSTITUT TELECOM (ITSUD), AMITEC DIACHYTI EFYIA PLIROFORIKI KAI EPIKINONIES ETERIA PERIORISMENIS EFTHINIS (AMITEC), TELECOM
* ITALIA S.p.a.(TI), TRIALOG (TRIALOG), Stiftelsen SINTEF (SINTEF), NEC EUROPE LTD (NEC))
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
* conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
* disclaimer in the documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
* BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
* SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.societies.domainauthority.rest.server;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.List;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.PUT;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.FileUploadException;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.societies.api.internal.domainauthority.LocalPath;
import org.societies.api.internal.domainauthority.UrlPath;
import org.societies.api.security.digsig.DigsigException;
import org.societies.domainauthority.rest.control.ServiceClientJarAccess;
import org.societies.domainauthority.rest.util.FileName;
import org.societies.domainauthority.rest.util.Files;
import org.societies.domainauthority.rest.util.UrlParamName;
/**
* Class for hosting jar files for clients of 3rd party services.
*
* @author Mitja Vardjan
*/
@Path(UrlPath.PATH_FILES)
public class ServiceClientJar extends HttpServlet {
private static final long serialVersionUID = 4625772782444356957L;
private static Logger LOG = LoggerFactory.getLogger(ServiceClientJar.class);
public ServiceClientJar() {
LOG.info("Constructor");
}
/**
* Method processing HTTP GET requests, producing "application/java-archive" MIME media type.
* HTTP response: the requested file, e.g., service client in form of jar file.
* Error 401 if file name or signature not valid.
* Error 500 on server error.
*/
// @Path("{name}")
// @GET
// @Produces("application/java-archive")
// public byte[] doGet(@PathParam("name") String name,
// @QueryParam(UrlPath.URL_PARAM_FILE) String path,
// @QueryParam(UrlPath.URL_PARAM_SERVICE_ID) String serviceId,
// @QueryParam(UrlPath.URL_PARAM_SIGNATURE) String signature) {
@Override
public void doGet(HttpServletRequest request, HttpServletResponse response) {
//String path = name + ".jar";
if (request.getPathInfo() == null) {
LOG.warn("HTTP GET: request.getPathInfo() is null");
return;
}
String[] name = request.getPathInfo().split("/");
String path = request.getParameter(UrlPath.URL_PARAM_FILE);
String serviceId = request.getParameter(UrlPath.URL_PARAM_SERVICE_ID);
String signature = request.getParameter(UrlPath.URL_PARAM_SIGNATURE);
LOG.info("HTTP GET: path = {}, service ID = {}, signature = " + signature, path, serviceId);
byte[] file;
if (!ServiceClientJarAccess.isAuthorized(path, signature)) {
LOG.warn("Invalid filename or key");
// Return HTTP status code 401 - Unauthorized
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
return;
//throw new WebApplicationException(HttpServletResponse.SC_UNAUTHORIZED);
}
try {
file = Files.getBytesFromFile(get3PServicePath(serviceId) + path);
} catch (FileNotFoundException e) {
try {
file = Files.getBytesFromFile(path);
} catch (IOException e2) {
LOG.warn("Could not open file {}", path, e2);
// Return HTTP status code 500 - Internal Server Error
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
// throw new WebApplicationException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
} catch (IOException e) {
LOG.warn("Could not open file {}", path, e);
// Return HTTP status code 500 - Internal Server Error
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
// throw new WebApplicationException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
LOG.info("Serving {}", path);
response.setContentLength(file.length);
//response.setContentType("application/java-archive");
try {
ServletOutputStream stream = response.getOutputStream();
stream.write(file);
stream.flush();
} catch (IOException e) {
LOG.warn("Could not write response", e);
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
// throw new WebApplicationException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
/**
* Method processing HTTP POST requests.
*/
// @Path("{name}")
// @POST
// public void postIt(@PathParam("name") String name,
// InputStream is,
// @Context HttpServletRequest request,
// @QueryParam(UrlPath.URL_PARAM_FILE) String path,
// @QueryParam(UrlPath.URL_PARAM_SERVICE_ID) String serviceId,
// @QueryParam(UrlPath.URL_PARAM_PUB_KEY) String pubKey) {
@Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
String path = request.getParameter(UrlPath.URL_PARAM_FILE);
String serviceId = request.getParameter(UrlPath.URL_PARAM_SERVICE_ID);
String pubKey = request.getParameter(UrlPath.URL_PARAM_PUB_KEY);
LOG.info("HTTP POST from {}; path = {}, service ID = " + serviceId + ", pubKey = " + pubKey,
request.getRemoteHost(), path);
LOG.warn("HTTP POST is not implemented. For uploading files, use HTTP PUT instead.");
}
/**
* Method processing HTTP PUT requests.
*/
// @Path("{name}")
// @PUT
// public void puIt(@PathParam("name") String name,
// InputStream is,
// @Context HttpServletRequest request,
// @QueryParam(UrlPath.URL_PARAM_FILE) String path,
// @QueryParam(UrlPath.URL_PARAM_SERVICE_ID) String serviceId,
// @QueryParam(UrlPath.URL_PARAM_PUB_KEY) String cert) {
@Override
public void doPut(HttpServletRequest request, HttpServletResponse response) {
String path = request.getParameter(UrlPath.URL_PARAM_FILE);
String serviceId = request.getParameter(UrlPath.URL_PARAM_SERVICE_ID);
String cert = request.getParameter(UrlPath.URL_PARAM_PUB_KEY);
LOG.info("HTTP PUT from {}; path = {}, service ID = " + serviceId + ", pubKey = " + cert,
request.getRemoteHost(), path);
cert = UrlParamName.url2Base64(cert);
LOG.debug("HTTP PUT: cert fixed to {}", cert);
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
// Parse the request
List<FileItem> items;
try {
items = upload.parseRequest(request);
} catch (FileUploadException e) {
response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
return;
// throw new WebApplicationException(HttpServletResponse.SC_BAD_REQUEST);
}
// Process the uploaded items
Iterator iter = items.iterator();
while (iter.hasNext()) {
FileItem item = (FileItem) iter.next();
if (item.isFormField()) {
// Process FormField;
} else {
// Process Uploaded File
//path = path.replaceAll("[/\\\\]", File.separator);
path = get3PServicePath(serviceId) + path;
LOG.debug("Saving to file {}", path);
try {
Files.writeFile(item.getInputStream(), path);
ServiceClientJarAccess.addResource(path, cert);
} catch (IOException e) {
LOG.warn("Could not write to file {}", path, e);
// Return HTTP status code 500 - Internal Server Error
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
// throw new WebApplicationException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
} catch (DigsigException e) {
LOG.warn("Could not store public key", e);
// Return HTTP status code 500 - Internal Server Error
response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
return;
// throw new WebApplicationException(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
}
}
}
}
private String get3PServicePath(String serviceId) {
serviceId = FileName.removeUnsupportedChars(serviceId);
return LocalPath.PATH_3P_SERVICES + File.separator + serviceId + File.separator;
}
}