| /* |
| * 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.storm.daemon.logviewer.utils; |
| |
| import static j2html.TagCreator.body; |
| import static j2html.TagCreator.h2; |
| import static javax.ws.rs.core.Response.Status.FORBIDDEN; |
| import static javax.ws.rs.core.Response.Status.OK; |
| import static org.apache.commons.lang.StringEscapeUtils.escapeHtml; |
| |
| import com.codahale.metrics.Meter; |
| import com.google.common.io.ByteStreams; |
| |
| import java.io.BufferedOutputStream; |
| import java.io.File; |
| import java.io.FileInputStream; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.nio.file.Files; |
| import java.util.HashMap; |
| import java.util.Map; |
| |
| import javax.ws.rs.core.MediaType; |
| import javax.ws.rs.core.Response; |
| import javax.ws.rs.core.StreamingOutput; |
| |
| import org.apache.storm.daemon.common.JsonResponseBuilder; |
| import org.apache.storm.daemon.ui.UIHelpers; |
| |
| public class LogviewerResponseBuilder { |
| |
| private LogviewerResponseBuilder() { |
| } |
| |
| /** |
| * Build a Response object representing success response with HTML entity. |
| * |
| * @param content HTML entity content, String type |
| */ |
| public static Response buildSuccessHtmlResponse(String content) { |
| return Response.status(OK).entity(content) |
| .type(MediaType.TEXT_HTML_TYPE).build(); |
| } |
| |
| /** |
| * Build a Response object representing success response with JSON entity. |
| * |
| * @param entity entity object to represent it as JSON |
| * @param callback callbackParameterName for JSONP |
| * @param origin origin |
| * @see {@link JsonResponseBuilder} |
| */ |
| public static Response buildSuccessJsonResponse(Object entity, String callback, String origin) { |
| return new JsonResponseBuilder().setData(entity).setCallback(callback) |
| .setHeaders(LogviewerResponseBuilder.getHeadersForSuccessResponse(origin)).build(); |
| } |
| |
| /** |
| * Build a Response object representing download a file. |
| * |
| * @param host host address |
| * @param file file to download |
| */ |
| public static Response buildDownloadFile(String host, File file, Meter numFileDownloadExceptions) throws IOException { |
| String fname; |
| try { |
| String topoInfo = file.getParentFile().getParentFile().getName(); |
| String port = file.getParentFile().getName(); |
| fname = String.format("%s-%s-%s-%s", host, port, topoInfo, file.getName()); |
| } catch (NullPointerException e) { |
| fname = file.getName(); |
| } |
| try { |
| // do not close this InputStream in method: it will be used from jetty server |
| InputStream is = Files.newInputStream(file.toPath()); |
| return Response.status(OK) |
| .entity(wrapWithStreamingOutput(is)) |
| .type(MediaType.APPLICATION_OCTET_STREAM_TYPE) |
| .header("Content-Disposition", "attachment; filename=\"" + fname + "\"") |
| .build(); |
| } catch (IOException e) { |
| numFileDownloadExceptions.mark(); |
| throw e; |
| } |
| } |
| |
| /** |
| * Build a Response object representing unauthorized user, with HTML response. |
| * |
| * @param user username |
| */ |
| public static Response buildResponseUnauthorizedUser(String user) { |
| String entity = buildUnauthorizedUserHtml(user); |
| return Response.status(FORBIDDEN) |
| .entity(entity) |
| .type(MediaType.TEXT_HTML_TYPE) |
| .build(); |
| } |
| |
| /** |
| * Build a Response object representing page not found. |
| */ |
| public static Response buildResponsePageNotFound() { |
| return Response.status(404) |
| .entity("Page not found") |
| .type(MediaType.TEXT_HTML_TYPE) |
| .build(); |
| } |
| |
| /** |
| * Build a Response object representing unauthorized user, with JSON response. |
| * |
| * @param user username |
| * @param callback callbackParameterName for JSONP |
| */ |
| public static Response buildUnauthorizedUserJsonResponse(String user, String callback) { |
| return new JsonResponseBuilder().setData(UIHelpers.unauthorizedUserJson(user)) |
| .setCallback(callback).setStatus(403).build(); |
| } |
| |
| /** |
| * Build a Response object representing exception, with JSON response. |
| * |
| * @param ex Exception object |
| * @param callback callbackParameterName for JSONP |
| */ |
| public static Response buildExceptionJsonResponse(Exception ex, String callback) { |
| int statusCode = 500; |
| return new JsonResponseBuilder().setData(UIHelpers.exceptionToJson(ex, statusCode)) |
| .setCallback(callback).setStatus(statusCode).build(); |
| } |
| |
| private static Map<String, Object> getHeadersForSuccessResponse(String origin) { |
| Map<String, Object> headers = new HashMap<>(); |
| headers.put("Access-Control-Allow-Origin", origin); |
| headers.put("Access-Control-Allow-Credentials", "true"); |
| return headers; |
| } |
| |
| private static String buildUnauthorizedUserHtml(String user) { |
| String content = "User '" + escapeHtml(user) + "' is not authorized."; |
| return body(h2(content)).render(); |
| } |
| |
| private static StreamingOutput wrapWithStreamingOutput(final InputStream inputStream) { |
| return os -> { |
| OutputStream wrappedOutputStream = os; |
| if (!(os instanceof BufferedOutputStream)) { |
| wrappedOutputStream = new BufferedOutputStream(os); |
| } |
| |
| ByteStreams.copy(inputStream, wrappedOutputStream); |
| |
| wrappedOutputStream.flush(); |
| }; |
| } |
| |
| } |