1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.jclouds.logging.internal;
20
21 import static com.google.common.base.Preconditions.checkNotNull;
22 import static com.google.common.io.Closeables.closeQuietly;
23 import static org.jclouds.io.Payloads.newPayload;
24
25 import java.io.ByteArrayInputStream;
26 import java.io.File;
27 import java.io.FileInputStream;
28 import java.io.FileNotFoundException;
29 import java.io.IOException;
30 import java.io.InputStream;
31
32 import javax.annotation.Resource;
33
34 import org.jclouds.io.MutableContentMetadata;
35 import org.jclouds.io.Payload;
36 import org.jclouds.io.PayloadEnclosing;
37 import org.jclouds.logging.Logger;
38
39 import com.google.common.io.ByteStreams;
40 import com.google.common.io.FileBackedOutputStream;
41
42
43
44
45
46
47 public abstract class Wire {
48
49 @Resource
50 protected Logger logger = Logger.NULL;
51
52 protected abstract Logger getWireLog();
53
54 private void wire(String header, InputStream instream) {
55 StringBuilder buffer = new StringBuilder();
56 int ch;
57 try {
58 while ((ch = instream.read()) != -1) {
59 if (ch == 13) {
60 buffer.append("[\\r]");
61 } else if (ch == 10) {
62 buffer.append("[\\n]\"");
63 buffer.insert(0, "\"");
64 buffer.insert(0, header);
65 getWireLog().debug(buffer.toString());
66 buffer.setLength(0);
67 } else if ((ch < 32) || (ch > 127)) {
68 buffer.append("[0x");
69 buffer.append(Integer.toHexString(ch));
70 buffer.append("]");
71 } else {
72 buffer.append((char) ch);
73 }
74 }
75 if (buffer.length() > 0) {
76 buffer.append('\"');
77 buffer.insert(0, '\"');
78 buffer.insert(0, header);
79 getWireLog().debug(buffer.toString());
80 }
81 } catch (IOException e) {
82 logger.error(e, "Error tapping line");
83 }
84 }
85
86 public boolean enabled() {
87 return getWireLog().isDebugEnabled();
88 }
89
90 public InputStream copy(final String header, InputStream instream) {
91 int limit = 256 * 1024;
92 FileBackedOutputStream out = null;
93 try {
94 out = new FileBackedOutputStream(limit);
95 long bytesRead = ByteStreams.copy(instream, out);
96 if (bytesRead >= limit)
97 logger.debug("over limit %d/%d: wrote temp file", bytesRead, limit);
98 wire(header, out.getSupplier().getInput());
99 return out.getSupplier().getInput();
100 } catch (IOException e) {
101 throw new RuntimeException("Error tapping line", e);
102 } finally {
103 closeQuietly(out);
104 closeQuietly(instream);
105 }
106 }
107
108 public InputStream input(InputStream instream) {
109 return copy("<< ", checkNotNull(instream, "input"));
110 }
111
112 public void input(PayloadEnclosing request) {
113 Payload oldContent = request.getPayload();
114 Payload wiredPayload = newPayload(input(oldContent.getInput()));
115 copyPayloadMetadata(oldContent, wiredPayload);
116 request.setPayload(wiredPayload);
117 }
118
119 public void output(PayloadEnclosing request) {
120 Payload oldContent = request.getPayload();
121 Payload wiredPayload;
122 try {
123 wiredPayload = newPayload(output(oldContent.getRawContent()));
124 } catch (UnsupportedOperationException e) {
125 wiredPayload = newPayload(output(oldContent.getInput()));
126 }
127 copyPayloadMetadata(oldContent, wiredPayload);
128 request.setPayload(wiredPayload);
129 }
130
131 private void copyPayloadMetadata(Payload oldContent, Payload wiredPayload) {
132 MutableContentMetadata oldMd = oldContent.getContentMetadata();
133 MutableContentMetadata wiredMd = wiredPayload.getContentMetadata();
134 if (oldMd.getContentLength() != null)
135 wiredMd.setContentLength(oldMd.getContentLength());
136 wiredMd.setContentType(oldMd.getContentType());
137 wiredMd.setContentMD5(oldMd.getContentMD5());
138 wiredMd.setContentDisposition(oldMd.getContentDisposition());
139 wiredMd.setContentEncoding(oldMd.getContentEncoding());
140 wiredMd.setContentLanguage(oldMd.getContentLanguage());
141 }
142
143 @SuppressWarnings("unchecked")
144 public <T> T output(T data) {
145 checkNotNull(data, "data");
146 if (data instanceof InputStream) {
147 return (T) copy(">> ", (InputStream) data);
148 } else if (data instanceof byte[]) {
149 output((byte[]) data);
150 return data;
151 } else if (data instanceof String) {
152 output((String) data);
153 return data;
154 } else if (data instanceof File) {
155 output(((File) data));
156 return data;
157 }
158 throw new UnsupportedOperationException("Content not supported " + data.getClass());
159 }
160
161 private void output(final File out) {
162 checkNotNull(out, "output");
163 InputStream in = null;
164 try {
165 in = new FileInputStream(out);
166 wire(">> ", in);
167 } catch (FileNotFoundException e) {
168 logger.error(e, "Error tapping file: %s", out);
169 } finally {
170 closeQuietly(in);
171 }
172 }
173
174 private void output(byte[] b) {
175 wire(">> ", new ByteArrayInputStream(checkNotNull(b, "output")));
176 }
177
178 private void output(final String s) {
179 output(checkNotNull(s, "output").getBytes());
180 }
181
182 }