org.jboss.weld.probe.Resource Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of weld-servlet-shaded Show documentation
Show all versions of weld-servlet-shaded Show documentation
This jar bundles all the bits of Weld and CDI required for running in a Servlet container.
/*
* JBoss, Home of Professional Open Source
* Copyright 2014, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* 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.jboss.weld.probe;
import static org.jboss.weld.probe.Strings.APPLICATION_FONT_MS;
import static org.jboss.weld.probe.Strings.APPLICATION_FONT_SFNT;
import static org.jboss.weld.probe.Strings.APPLICATION_FONT_WOFF;
import static org.jboss.weld.probe.Strings.ENCODING_UTF8;
import static org.jboss.weld.probe.Strings.FILE_CLIENT_HTML;
import static org.jboss.weld.probe.Strings.FILTERS;
import static org.jboss.weld.probe.Strings.HTTP_HEADER_CACHE_CONTROL;
import static org.jboss.weld.probe.Strings.IMG_ICO;
import static org.jboss.weld.probe.Strings.IMG_PNG;
import static org.jboss.weld.probe.Strings.IMG_SVG;
import static org.jboss.weld.probe.Strings.PAGE;
import static org.jboss.weld.probe.Strings.PAGE_SIZE;
import static org.jboss.weld.probe.Strings.PARAM_TRANSIENT_DEPENDENCIES;
import static org.jboss.weld.probe.Strings.PARAM_TRANSIENT_DEPENDENTS;
import static org.jboss.weld.probe.Strings.PATH_META_INF_CLIENT;
import static org.jboss.weld.probe.Strings.REPRESENTATION;
import static org.jboss.weld.probe.Strings.RESOURCE_PARAM_END;
import static org.jboss.weld.probe.Strings.RESOURCE_PARAM_START;
import static org.jboss.weld.probe.Strings.SLASH;
import static org.jboss.weld.probe.Strings.SUFFIX_CSS;
import static org.jboss.weld.probe.Strings.SUFFIX_EOT;
import static org.jboss.weld.probe.Strings.SUFFIX_HTML;
import static org.jboss.weld.probe.Strings.SUFFIX_ICO;
import static org.jboss.weld.probe.Strings.SUFFIX_JS;
import static org.jboss.weld.probe.Strings.SUFFIX_OTF;
import static org.jboss.weld.probe.Strings.SUFFIX_PNG;
import static org.jboss.weld.probe.Strings.SUFFIX_SVG;
import static org.jboss.weld.probe.Strings.SUFFIX_TTF;
import static org.jboss.weld.probe.Strings.SUFFIX_WOFF;
import static org.jboss.weld.probe.Strings.TEXT_CSS;
import static org.jboss.weld.probe.Strings.TEXT_HTML;
import static org.jboss.weld.probe.Strings.TEXT_JAVASCRIPT;
import static org.jboss.weld.probe.Strings.TEXT_PLAIN;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.inject.Vetoed;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.jboss.weld.probe.Queries.Filters;
/**
* REST API resources.
*
* @author Martin Kouba
*/
@Vetoed
enum Resource {
/**
* A deployment info.
*/
DEPLOYMENT("/deployment", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
append(resp, jsonDataProvider.receiveDeployment());
}
}),
/**
* A collection of beans.
*/
BEANS("/beans", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
append(resp, jsonDataProvider.receiveBeans(getPage(req), getPageSize(req), req.getParameter(FILTERS), req.getParameter(REPRESENTATION)));
}
}),
/**
* A single bean detail.
*/
BEAN("/beans/{.+}", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
appendFound(resp, jsonDataProvider.receiveBean(resourcePathParts[1], Boolean.valueOf(req.getParameter(PARAM_TRANSIENT_DEPENDENCIES)),
Boolean.valueOf(req.getParameter(PARAM_TRANSIENT_DEPENDENTS))));
}
}),
/**
* A contextual instance of a bean. This is only supported for a limited set of scopes.
*/
BEAN_INSTANCE("/beans/{.+}/instance", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
appendFound(resp, jsonDataProvider.receiveBeanInstance(resourcePathParts[1]));
}
}),
/**
* A collection of observers methods.
*/
OBSERVERS("/observers", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
append(resp, jsonDataProvider.receiveObservers(getPage(req), getPageSize(req), req.getParameter(FILTERS), req.getParameter(REPRESENTATION)));
}
}),
/**
* A single observer.
*/
OBSERVER("/observers/{.+}", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
appendFound(resp, jsonDataProvider.receiveObserver(resourcePathParts[1]));
}
}),
/**
* A collection of inspectable contexts.
*/
CONTEXTS("/contexts", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
append(resp, jsonDataProvider.receiveContexts());
}
}),
/**
* A collection of contextual instances for the given inspectable context.
*/
CONTEXT("/contexts/{[a-zA-Z_0]+}", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
appendFound(resp, jsonDataProvider.receiveContext(resourcePathParts[1]));
}
}),
/**
* A collection of invocation trees.
*/
INVOCATIONS("/invocations", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
append(resp, jsonDataProvider.receiveInvocations(getPage(req), getPageSize(req), req.getParameter(FILTERS), req.getParameter(REPRESENTATION)));
}
@Override
protected void delete(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp)
throws IOException {
append(resp, jsonDataProvider.clearInvocations());
}
}),
/**
* A single invocation tree.
*/
INVOCATION("/invocations/{.+}", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
appendFound(resp, jsonDataProvider.receiveInvocation(resourcePathParts[1]));
}
}),
/**
* The event bus
*/
EVENTS("/events", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
append(resp, jsonDataProvider.receiveEvents(getPage(req), getPageSize(req), req.getParameter(FILTERS)));
}
@Override
protected void delete(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp)
throws IOException {
append(resp, jsonDataProvider.clearEvents());
}
}),
MONITORING_STATS("/monitoring", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
append(resp, jsonDataProvider.receiveMonitoringStats());
}
}),
AVAILABLE_BEANS("/availableBeans", new Handler() {
@Override
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
append(resp, jsonDataProvider.receiveAvailableBeans(getPage(req), getPageSize(req), req.getParameter(FILTERS), req.getParameter(REPRESENTATION)));
}
}),
/**
* A default HTML client resource.
*/
CLIENT_RESOURCE("/client/{[a-zA-Z_0-9-]+\\.\\w+}", new Handler() {
@Override
protected void handle(HttpMethod method, JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req,
HttpServletResponse resp) throws IOException {
if (!HttpMethod.GET.equals(method)) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
String resourceName = PATH_META_INF_CLIENT + (resourcePathParts.length == 0 ? FILE_CLIENT_HTML : resourcePathParts[resourcePathParts.length - 1]);
String contentType = detectContentType(resourceName);
setHeaders(resp, contentType);
if (isCachableContentType(contentType)) {
// Set Cache-Control header - 24 hours
resp.setHeader(HTTP_HEADER_CACHE_CONTROL, "max-age=86400");
}
if (isTextBasedContenType(contentType)) {
String content = IOUtils.getResourceAsString(resourceName);
if (content == null) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
content = content.replace("${contextPath}", req.getServletContext().getContextPath() + ProbeFilter.REST_URL_PATTERN_BASE + SLASH);
resp.getWriter().append(content);
} else {
if (!IOUtils.writeResource(resourceName, resp.getOutputStream())) {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
}
}),
EXPORT("/export", new Handler() {
@Override
protected void handle(HttpMethod method, JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req,
HttpServletResponse resp) throws IOException {
if (!HttpMethod.GET.equals(method)) {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
return;
}
setHeaders(resp, "application/zip");
resp.setHeader("Content-disposition", "attachment; filename=\"weld-probe-export.zip\"");
ServletOutputStream out = resp.getOutputStream();
out.write(Exports.exportJsonData(jsonDataProvider));
out.flush();
}
}),
;
// --- Instance variables
private final String[] parts;
private final Handler handler;
Resource(String path, Handler handler) {
this.parts = splitPath(path);
this.handler = handler;
}
protected void handle(HttpMethod method, JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp)
throws IOException {
handler.handle(method, jsonDataProvider, resourcePathParts, req, resp);
}
/**
* @param resourcePathParts
* @return true
if the resource matches the given path, false
otherwise
*/
boolean matches(String[] resourcePathParts) {
if (resourcePathParts.length != parts.length) {
return false;
}
for (int i = 0; i < parts.length; i++) {
if (isParam(parts[i])) {
if (!resourcePathParts[i].matches(parts[i].substring(1, parts[i].length() - 1))) {
return false;
}
} else if (!parts[i].equals(resourcePathParts[i])) {
return false;
}
}
return true;
}
/**
* @return the parts of the path
*/
String[] getParts() {
return parts;
}
static boolean isParam(String part) {
return part.startsWith(RESOURCE_PARAM_START) && part.endsWith(RESOURCE_PARAM_END);
}
static String[] splitPath(String path) {
List parts = new ArrayList();
StringBuilder builder = null;
for (int i = 0; i < path.length(); i++) {
char c = path.charAt(i);
if (c == '/') {
if (builder != null) {
parts.add(builder.toString());
builder = null;
}
} else {
if (builder == null) {
builder = new StringBuilder();
}
builder.append(c);
}
}
if (builder != null) {
parts.add(builder.toString());
}
return parts.toArray(new String[parts.size()]);
}
static String detectContentType(String resourceName) {
if (resourceName.endsWith(SUFFIX_HTML)) {
return TEXT_HTML;
} else if (resourceName.endsWith(SUFFIX_CSS)) {
return TEXT_CSS;
} else if (resourceName.endsWith(SUFFIX_JS)) {
return TEXT_JAVASCRIPT;
} else if (resourceName.endsWith(SUFFIX_PNG)) {
return IMG_PNG;
} else if (resourceName.endsWith(SUFFIX_TTF) || resourceName.endsWith(SUFFIX_OTF)) {
return APPLICATION_FONT_SFNT;
} else if (resourceName.endsWith(SUFFIX_EOT)) {
return APPLICATION_FONT_MS;
} else if (resourceName.endsWith(SUFFIX_WOFF)) {
return APPLICATION_FONT_WOFF;
} else if (resourceName.endsWith(SUFFIX_SVG)) {
return IMG_SVG;
} else if (resourceName.endsWith(SUFFIX_ICO)) {
return IMG_ICO;
} else {
return TEXT_PLAIN;
}
}
static boolean isCachableContentType(String contentType) {
return TEXT_CSS.equals(contentType) || TEXT_JAVASCRIPT.equals(contentType) || IMG_ICO.equals(contentType) || IMG_PNG.equals(contentType)
|| IMG_SVG.equals(contentType);
}
static boolean isTextBasedContenType(String contentType) {
return !(IMG_PNG.equals(contentType) || IMG_ICO.equals(contentType) || APPLICATION_FONT_SFNT.equals(contentType)
|| APPLICATION_FONT_WOFF.equals(contentType) || APPLICATION_FONT_MS.equals(contentType));
}
abstract static class Handler implements Serializable {
private static final long serialVersionUID = 5253937931990206305L;
protected void handle(HttpMethod method, JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req,
HttpServletResponse resp) throws IOException {
setHeaders(resp, getContentType());
switch (method) {
case GET:
get(jsonDataProvider, resourcePathParts, req, resp);
break;
case POST:
post(jsonDataProvider, resourcePathParts, req, resp);
break;
case DELETE:
delete(jsonDataProvider, resourcePathParts, req, resp);
break;
case OPTIONS:
options(jsonDataProvider, resourcePathParts, req, resp);
break;
default:
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
}
protected void get(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp) throws IOException {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
protected void post(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
protected void delete(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp)
throws IOException {
resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
}
protected void options(JsonDataProvider jsonDataProvider, String[] resourcePathParts, HttpServletRequest req, HttpServletResponse resp)
throws IOException {
setCorsHeaders(resp);
}
protected void append(HttpServletResponse resp, String content) throws IOException {
resp.getWriter().append(content);
}
protected void appendFound(HttpServletResponse resp, String content) throws IOException {
if (content != null) {
resp.getWriter().append(content);
} else {
resp.sendError(HttpServletResponse.SC_NOT_FOUND);
}
}
protected int getPage(HttpServletRequest req) {
String pageParam = req.getParameter(PAGE);
if (pageParam == null) {
return 1;
}
try {
return Integer.parseInt(pageParam);
} catch (NumberFormatException e) {
return 1;
}
}
protected int getPageSize(HttpServletRequest req) {
String pageSizeParam = req.getParameter(PAGE_SIZE);
if (pageSizeParam == null) {
return Queries.DEFAULT_PAGE_SIZE;
} else {
try {
int result = Integer.parseInt(pageSizeParam);
return result > 0 ? result : 0;
} catch (NumberFormatException e) {
return 0;
}
}
}
protected > T initFilters(HttpServletRequest req, T filters) {
return Queries.initFilters(req.getParameter(FILTERS), filters);
}
protected String getContentType() {
return Strings.APPLICATION_JSON;
}
static void setHeaders(HttpServletResponse resp, String contentType) {
resp.setCharacterEncoding(ENCODING_UTF8);
resp.setContentType(contentType);
setCorsHeaders(resp);
}
static void setCorsHeaders(HttpServletResponse resp) {
// Support cross-site HTTP requests - we want to support external HTML5 clients
// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Access_control_CORS
resp.setHeader("Access-Control-Allow-Origin", "*");
resp.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE");
}
}
static enum HttpMethod {
GET, POST, DELETE, OPTIONS;
static HttpMethod from(String method) {
for (HttpMethod httpMethod : values()) {
if (httpMethod.toString().equalsIgnoreCase(method)) {
return httpMethod;
}
}
return null;
}
}
static enum Representation {
SIMPLE, BASIC, FULL,
;
static Representation from(String value) {
for (Representation representation : values()) {
if (representation.toString().equalsIgnoreCase(value)) {
return representation;
}
}
return null;
}
}
}