2 * ============LICENSE_START=======================================================
4 * ================================================================================
5 * Copyright (C) 2017 AT&T Intellectual Property. All rights reserved.
6 * ================================================================================
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
11 * http://www.apache.org/licenses/LICENSE-2.0
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 * ============LICENSE_END=========================================================
20 package com.woorea.openstack.connector;
22 import java.io.ByteArrayInputStream;
23 import java.io.ByteArrayOutputStream;
24 import java.io.IOException;
25 import java.io.InputStream;
26 import java.io.OutputStream;
27 import java.util.List;
29 import java.util.concurrent.atomic.AtomicLong;
30 import java.util.logging.Logger;
32 import com.sun.jersey.api.client.AbstractClientRequestAdapter;
33 import com.sun.jersey.api.client.ClientHandlerException;
34 import com.sun.jersey.api.client.ClientRequest;
35 import com.sun.jersey.api.client.ClientRequestAdapter;
36 import com.sun.jersey.api.client.ClientResponse;
37 import com.sun.jersey.api.client.filter.ClientFilter;
38 import com.sun.jersey.core.util.ReaderWriter;
41 * A Jersey client filter that writes the request and response to a specified logger.
43 public class JerseyLoggingFilter extends ClientFilter {
45 private final AtomicLong counter = new AtomicLong(0);
46 private final Logger logger;
50 * @param logger the logger to which the request and response are written.
52 public JerseyLoggingFilter(Logger logger) {
57 public ClientResponse handle(ClientRequest request) throws ClientHandlerException {
58 long id = counter.incrementAndGet();
59 logRequest(id, request);
60 ClientResponse response = getNext().handle(request);
61 logResponse(id, response);
67 * @param id the request id (counter)
68 * @param request the request
70 private void logRequest(long id, ClientRequest request) {
71 StringBuilder builder = new StringBuilder();
73 builder.append(String.valueOf(id));
74 builder.append(" * Client out-bound request\n");
76 builder.append(String.valueOf(id));
77 builder.append(" > ");
78 builder.append(request.getMethod());
80 builder.append(request.getURI().toASCIIString());
85 for (Map.Entry<String, List<Object>> entry : request.getHeaders().entrySet()) {
86 String header = entry.getKey();
87 List<Object> values = entry.getValue();
89 if (values.size() == 1) {
90 builder.append(String.valueOf(id));
91 builder.append(" > ");
92 builder.append(header);
94 builder.append(ClientRequest.getHeaderValue(values.get(0)));
97 StringBuilder buf = new StringBuilder();
100 for(Object value : values) {
107 buf.append(ClientRequest.getHeaderValue(value));
110 builder.append(String.valueOf(id));
111 builder.append(" > ");
112 builder.append(header);
113 builder.append(": ");
114 builder.append(buf.toString());
115 builder.append("\n");
121 if (request.getEntity() != null) {
122 request.setAdapter(new JerseyLoggingAdapter(request.getAdapter(), builder));
124 logger.info(builder.toString());
130 * @param id the request id (counter)
131 * @param response the response
133 private void logResponse(long id, ClientResponse response) {
134 StringBuilder builder = new StringBuilder();
136 builder.append(String.valueOf(id));
137 builder.append(" * Client in-bound response\n");
139 builder.append(String.valueOf(id));
140 builder.append(" < ");
141 builder.append(String.valueOf(response.getStatus()));
142 builder.append("\n");
146 for (Map.Entry<String, List<String>> entry : response.getHeaders().entrySet()) {
147 String header = entry.getKey();
148 for (String value : entry.getValue()) {
149 builder.append(String.valueOf(id));
150 builder.append(" < ");
151 builder.append(header);
152 builder.append(": ");
153 builder.append(value).append("\n");
159 ByteArrayOutputStream out = new ByteArrayOutputStream();
160 InputStream in = response.getEntityInputStream();
162 ReaderWriter.writeTo(in, out);
164 byte[] requestEntity = out.toByteArray();
165 appendToBuffer(builder, requestEntity);
166 response.setEntityInputStream(new ByteArrayInputStream(requestEntity));
167 } catch (IOException ex) {
168 throw new ClientHandlerException(ex);
171 logger.info(builder.toString());
175 * Appends bytes to the builder. If the bytes contain the password pattern,
176 * the password is obliterated.
177 * @param builder the builder
178 * @param bytes the bytes to append
180 private void appendToBuffer(StringBuilder builder, byte[] bytes) {
181 if (bytes.length != 0) {
182 String s = new String(bytes);
183 builder.append(s.replaceAll("\"password\".*:.*\"(.*)\"", "\"password\" : \"******\""));
184 builder.append("\n");
188 private class JerseyLoggingAdapter extends AbstractClientRequestAdapter {
189 private final StringBuilder builder;
191 JerseyLoggingAdapter(ClientRequestAdapter adapter, StringBuilder builder) {
193 this.builder = builder;
197 public OutputStream adapt(ClientRequest request, OutputStream out) throws IOException {
198 return new JerseyLoggingOutputStream(getAdapter().adapt(request, out), builder);
202 private class JerseyLoggingOutputStream extends OutputStream {
203 private final OutputStream stream;
204 private final StringBuilder builder;
205 private final ByteArrayOutputStream logStream = new ByteArrayOutputStream();
207 JerseyLoggingOutputStream(OutputStream stream, StringBuilder builder) {
208 this.stream = stream;
209 this.builder = builder;
213 public void write(int value) throws IOException {
214 logStream.write(value);
219 public void close() throws IOException {
220 appendToBuffer(builder, logStream.toByteArray());
221 logger.info(builder.toString());