summaryrefslogtreecommitdiffstats
path: root/openstack-client-connectors/jersey-connector/src/main/java
diff options
context:
space:
mode:
authorRob Daugherty <rd472p@att.com>2018-04-10 17:54:48 -0400
committerRob Daugherty <rd472p@att.com>2018-04-10 18:07:15 -0400
commitb580226698d07964241b24dae6b0e522050e42f3 (patch)
treef40d188e38c628c85317b8828066c23d04556db1 /openstack-client-connectors/jersey-connector/src/main/java
parent84f5bbb63a065af8a65e07c6a3fdbdf3345ba50a (diff)
Non-GPL implementation of JerseyLoggingFilter
Does the same thing, and can carry the Apache 2.0 license. 97.3% unit test coverage. Change-Id: I5ebe78616af2c0e4402deb30a165b3c62ed2efd8 Issue-ID: SO-398 Signed-off-by: Rob Daugherty <rd472p@att.com>
Diffstat (limited to 'openstack-client-connectors/jersey-connector/src/main/java')
-rw-r--r--openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java444
1 files changed, 184 insertions, 260 deletions
diff --git a/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java
index 43323f8..6d98005 100644
--- a/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java
+++ b/openstack-client-connectors/jersey-connector/src/main/java/com/woorea/openstack/connector/JerseyLoggingFilter.java
@@ -3,13 +3,12 @@
* ONAP - SO
* ================================================================================
* Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
- * Copyright (C) 2017 Huawei Intellectual Property. All rights reserved.
* ================================================================================
* 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
+ * 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,
@@ -18,46 +17,6 @@
* limitations under the License.
* ============LICENSE_END=========================================================
*/
-
-/**
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
- *
- * Copyright (c) 2010-2011 Oracle and/or its affiliates. All rights reserved.
- *
- * The contents of this file are subject to the terms of either the GNU
- * General Public License Version 2 only ("GPL") or the Common Development
- * and Distribution License("CDDL") (collectively, the "License"). You
- * may not use this file except in compliance with the License. You can
- * obtain a copy of the License at
- * http://glassfish.java.net/public/CDDL+GPL_1_1.html
- * or packager/legal/LICENSE.txt. See the License for the specific
- * language governing permissions and limitations under the License.
- *
- * When distributing the software, include this License Header Notice in each
- * file and include the License file at packager/legal/LICENSE.txt.
- *
- * GPL Classpath Exception:
- * Oracle designates this particular file as subject to the "Classpath"
- * exception as provided by Oracle in the GPL Version 2 section of the License
- * file that accompanied this code.
- *
- * Modifications:
- * If applicable, add the following below the License Header, with the fields
- * enclosed by brackets [] replaced by your own identifying information:
- * "Portions Copyright [year] [name of copyright owner]"
- *
- * Contributor(s):
- * If you wish your version of this file to be governed by only the CDDL or
- * only the GPL Version 2, indicate your decision by adding "[Contributor]
- * elects to include this software in this distribution under the [CDDL or GPL
- * Version 2] license." If you don't indicate a single choice of license, a
- * recipient has the option to distribute your version of this file under
- * either the CDDL, the GPL Version 2 or to extend the choice of license to
- * its licensees as provided above. However, if you add GPL Version 2 code
- * and therefore, elected the GPL Version 2 license, then the option applies
- * only if the new code is made subject to such option by the copyright
- * holder.
- */
package com.woorea.openstack.connector;
import java.io.ByteArrayInputStream;
@@ -65,237 +24,202 @@ import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
-import java.io.PrintStream;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Logger;
-import javax.ws.rs.core.MultivaluedMap;
-
import com.sun.jersey.api.client.AbstractClientRequestAdapter;
import com.sun.jersey.api.client.ClientHandlerException;
import com.sun.jersey.api.client.ClientRequest;
import com.sun.jersey.api.client.ClientRequestAdapter;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.filter.ClientFilter;
-import com.sun.jersey.api.client.filter.LoggingFilter;
import com.sun.jersey.core.util.ReaderWriter;
/**
- * A logging filter.
- *
+ * A Jersey client filter that writes the request and response to a specified logger.
*/
public class JerseyLoggingFilter extends ClientFilter {
- private static final Logger LOGGER = Logger.getLogger(LoggingFilter.class.getName());
-
- private static final String NOTIFICATION_PREFIX = "* ";
-
- private static final String REQUEST_PREFIX = "> ";
-
- private static final String RESPONSE_PREFIX = "< ";
-
- private static final String PASSWORD_PATTERN = "\"password\".*:.*\"(.*)\"";
-
- private final class Adapter extends AbstractClientRequestAdapter {
- private final StringBuilder b;
-
- Adapter(ClientRequestAdapter cra, StringBuilder b) {
- super(cra);
- this.b = b;
- }
-
- @Override
- public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException {
- return new LoggingOutputStream(getAdapter().adapt(request, out), b);
- }
-
- }
-
- private final class LoggingOutputStream extends OutputStream {
- private final OutputStream out;
-
- private final ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- private final StringBuilder b;
-
- LoggingOutputStream(OutputStream out, StringBuilder b) {
- this.out = out;
- this.b = b;
- }
-
- @Override
- public void write(byte[] b) throws IOException {
- baos.write(b);
- out.write(b);
- }
-
- @Override
- public void write(byte[] b, int off, int len) throws IOException {
- baos.write(b, off, len);
- out.write(b, off, len);
- }
-
- @Override
- public void write(int b) throws IOException {
- baos.write(b);
- out.write(b);
- }
-
- @Override
- public void close() throws IOException {
- printEntity(b, baos.toByteArray());
- log(b);
- out.close();
- }
- }
-
- private final PrintStream loggingStream;
-
- private final Logger logger;
-
- private long _id = 0;
-
- /**
- * Create a logging filter logging the request and response to
- * a default JDK logger, named as the fully qualified class name of this
- * class.
- */
- public JerseyLoggingFilter() {
- this(LOGGER);
- }
-
- /**
- * Create a logging filter logging the request and response to
- * a JDK logger.
- *
- * @param logger the logger to log requests and responses.
- */
- public JerseyLoggingFilter(Logger logger) {
- this.loggingStream = null;
- this.logger = logger;
- }
-
- /**
- * Create a logging filter logging the request and response to
- * print stream.
- *
- * @param loggingStream the print stream to log requests and responses.
- */
- public JerseyLoggingFilter(PrintStream loggingStream) {
- this.loggingStream = loggingStream;
- this.logger = null;
- }
-
- private void log(StringBuilder b) {
- if (logger != null) {
- logger.info(b.toString());
- } else {
- loggingStream.print(b);
- }
- }
-
- private StringBuilder prefixId(StringBuilder b, long id) {
- b.append(Long.toString(id)).append(" ");
- return b;
- }
-
- @Override
- public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
- long id = ++this._id;
-
- logRequest(id, request);
-
- ClientResponse response = getNext().handle(request);
-
- logResponse(id, response);
-
- return response;
- }
-
- private void logRequest(long id, ClientRequest request) {
- StringBuilder b = new StringBuilder();
-
- printRequestLine(b, id, request);
- printRequestHeaders(b, id, request.getHeaders());
-
- if (request.getEntity() != null) {
- request.setAdapter(new Adapter(request.getAdapter(), b));
- } else {
- log(b);
- }
- }
-
- private void printRequestLine(StringBuilder b, long id, ClientRequest request) {
- prefixId(b, id).append(NOTIFICATION_PREFIX).append("Client out-bound request").append("\n");
- prefixId(b, id).append(REQUEST_PREFIX).append(request.getMethod()).append(" ").
- append(request.getURI().toASCIIString()).append("\n");
- }
-
- private void printRequestHeaders(StringBuilder b, long id, MultivaluedMap<String, Object> headers) {
- for (Map.Entry<String, List<Object>> e : headers.entrySet()) {
- List<Object> val = e.getValue();
- String header = e.getKey();
-
- if(val.size() == 1) {
- prefixId(b, id).append(REQUEST_PREFIX).append(header).append(": ").append(ClientRequest.getHeaderValue(val.get(0))).append("\n");
- } else {
- StringBuilder sb = new StringBuilder();
- boolean add = false;
- for(Object o : val) {
- if(add) sb.append(',');
- add = true;
- sb.append(ClientRequest.getHeaderValue(o));
- }
- prefixId(b, id).append(REQUEST_PREFIX).append(header).append(": ").append(sb.toString()).append("\n");
- }
- }
- }
-
- private void logResponse(long id, ClientResponse response) {
- StringBuilder b = new StringBuilder();
-
- printResponseLine(b, id, response);
- printResponseHeaders(b, id, response.getHeaders());
-
- ByteArrayOutputStream out = new ByteArrayOutputStream();
- InputStream in = response.getEntityInputStream();
- try {
- ReaderWriter.writeTo(in, out);
-
- byte[] requestEntity = out.toByteArray();
- printEntity(b, requestEntity);
- response.setEntityInputStream(new ByteArrayInputStream(requestEntity));
- } catch (IOException ex) {
- throw new ClientHandlerException(ex);
- }
- log(b);
- }
-
- private void printResponseLine(StringBuilder b, long id, ClientResponse response) {
- prefixId(b, id).append(NOTIFICATION_PREFIX).
- append("Client in-bound response").append("\n");
- prefixId(b, id).append(RESPONSE_PREFIX).
- append(Integer.toString(response.getStatus())).
- append("\n");
- }
-
- private void printResponseHeaders(StringBuilder b, long id, MultivaluedMap<String, String> headers) {
- for (Map.Entry<String, List<String>> e : headers.entrySet()) {
- String header = e.getKey();
- for (String value : e.getValue()) {
- prefixId(b, id).append(RESPONSE_PREFIX).append(header).append(": ").
- append(value).append("\n");
- }
- }
- prefixId(b, id).append(RESPONSE_PREFIX).append("\n");
- }
-
- private void printEntity(StringBuilder b, byte[] entity) throws IOException {
- if (entity.length == 0)
- return;
- String entityString = new String(entity);
- entityString = entityString.replaceAll(PASSWORD_PATTERN, "\"password\" : \"******\"");
- b.append(entityString).append("\n");
- }
-}
+ private final AtomicLong counter = new AtomicLong(0);
+ private final Logger logger;
+
+ /**
+ * Constructor
+ * @param logger the logger to which the request and response are written.
+ */
+ public JerseyLoggingFilter(Logger logger) {
+ this.logger = logger;
+ }
+
+ @Override
+ public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
+ long id = counter.incrementAndGet();
+ logRequest(id, request);
+ ClientResponse response = getNext().handle(request);
+ logResponse(id, response);
+ return response;
+ }
+
+ /**
+ * Logs a request.
+ * @param id the request id (counter)
+ * @param request the request
+ */
+ private void logRequest(long id, ClientRequest request) {
+ StringBuilder builder = new StringBuilder();
+
+ builder.append(String.valueOf(id));
+ builder.append(" * Client out-bound request\n");
+
+ builder.append(String.valueOf(id));
+ builder.append(" > ");
+ builder.append(request.getMethod());
+ builder.append(" ");
+ builder.append(request.getURI().toASCIIString());
+ builder.append("\n");
+
+ // Request headers
+
+ for (Map.Entry<String, List<Object>> entry : request.getHeaders().entrySet()) {
+ String header = entry.getKey();
+ List<Object> values = entry.getValue();
+
+ if (values.size() == 1) {
+ builder.append(String.valueOf(id));
+ builder.append(" > ");
+ builder.append(header);
+ builder.append(": ");
+ builder.append(ClientRequest.getHeaderValue(values.get(0)));
+ builder.append("\n");
+ } else {
+ StringBuilder buf = new StringBuilder();
+ boolean first = true;
+
+ for(Object value : values) {
+ if (first) {
+ first = false;
+ } else {
+ buf.append(",");
+ }
+
+ buf.append(ClientRequest.getHeaderValue(value));
+ }
+
+ builder.append(String.valueOf(id));
+ builder.append(" > ");
+ builder.append(header);
+ builder.append(": ");
+ builder.append(buf.toString());
+ builder.append("\n");
+ }
+ }
+
+ // Request body
+
+ if (request.getEntity() != null) {
+ request.setAdapter(new JerseyLoggingAdapter(request.getAdapter(), builder));
+ } else {
+ logger.info(builder.toString());
+ }
+ }
+
+ /**
+ * Logs a response.
+ * @param id the request id (counter)
+ * @param response the response
+ */
+ private void logResponse(long id, ClientResponse response) {
+ StringBuilder builder = new StringBuilder();
+
+ builder.append(String.valueOf(id));
+ builder.append(" * Client in-bound response\n");
+
+ builder.append(String.valueOf(id));
+ builder.append(" < ");
+ builder.append(String.valueOf(response.getStatus()));
+ builder.append("\n");
+
+ // Response headers
+
+ for (Map.Entry<String, List<String>> entry : response.getHeaders().entrySet()) {
+ String header = entry.getKey();
+ for (String value : entry.getValue()) {
+ builder.append(String.valueOf(id));
+ builder.append(" < ");
+ builder.append(header);
+ builder.append(": ");
+ builder.append(value).append("\n");
+ }
+ }
+
+ // Response body
+
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ InputStream in = response.getEntityInputStream();
+ try {
+ ReaderWriter.writeTo(in, out);
+
+ byte[] requestEntity = out.toByteArray();
+ appendToBuffer(builder, requestEntity);
+ response.setEntityInputStream(new ByteArrayInputStream(requestEntity));
+ } catch (IOException ex) {
+ throw new ClientHandlerException(ex);
+ }
+
+ logger.info(builder.toString());
+ }
+
+ /**
+ * Appends bytes to the builder. If the bytes contain the password pattern,
+ * the password is obliterated.
+ * @param builder the builder
+ * @param bytes the bytes to append
+ */
+ private void appendToBuffer(StringBuilder builder, byte[] bytes) {
+ if (bytes.length != 0) {
+ String s = new String(bytes);
+ builder.append(s.replaceAll("\"password\".*:.*\"(.*)\"", "\"password\" : \"******\""));
+ builder.append("\n");
+ }
+ }
+
+ private class JerseyLoggingAdapter extends AbstractClientRequestAdapter {
+ private final StringBuilder builder;
+
+ JerseyLoggingAdapter(ClientRequestAdapter adapter, StringBuilder builder) {
+ super(adapter);
+ this.builder = builder;
+ }
+
+ @Override
+ public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException {
+ return new JerseyLoggingOutputStream(getAdapter().adapt(request, out), builder);
+ }
+ }
+
+ private class JerseyLoggingOutputStream extends OutputStream {
+ private final OutputStream stream;
+ private final StringBuilder builder;
+ private final ByteArrayOutputStream logStream = new ByteArrayOutputStream();
+
+ JerseyLoggingOutputStream(OutputStream stream, StringBuilder builder) {
+ this.stream = stream;
+ this.builder = builder;
+ }
+
+ @Override
+ public void write(int value) throws IOException {
+ logStream.write(value);
+ stream.write(value);
+ }
+
+ @Override
+ public void close() throws IOException {
+ appendToBuffer(builder, logStream.toByteArray());
+ logger.info(builder.toString());
+ stream.close();
+ }
+ }
+} \ No newline at end of file