/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.plugin.docker.client.connection;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
/**
* @author andrew00x
*/
public class UnixSocketDockerResponse implements DockerResponse {
private static final InputStream EMPTY = new InputStream() {
@Override
public int read() throws IOException {
return -1;
}
};
private final InputStream rawData;
private InputStream data;
private String[] headersFields;
private int status;
UnixSocketDockerResponse(InputStream input) {
rawData = input;
status = -1;
}
@Override
public int getStatus() throws IOException {
if (status != -1) {
return status;
}
getInputStream();
final String statusLine = headersFields[0];
if (statusLine.startsWith("HTTP/1.")) {
int startCode = statusLine.indexOf(' ');
if (startCode > 0) {
int endCode = statusLine.indexOf(' ', startCode + 1);
if (endCode < 0) {
endCode = statusLine.length();
}
try {
return status = Integer.parseInt(statusLine.substring(startCode + 1, endCode));
} catch (NumberFormatException ignored) {
}
}
}
return -1;
}
@Override
public int getContentLength() throws IOException {
final String header = getHeader("Content-Length");
if (header != null) {
try {
return Integer.parseInt(header);
} catch (NumberFormatException ignored) {
}
}
return -1;
}
@Override
public String getContentType() throws IOException {
return getHeader("Content-Type");
}
@Override
public String getHeader(String name) throws IOException {
getInputStream();
final String lowerCaseName = name.toLowerCase();
for (String field : headersFields) {
if (field.toLowerCase().startsWith(lowerCaseName)) {
int colonPos = field.indexOf(':');
if (colonPos > 0) {
return field.substring(colonPos + 1).trim();
}
}
}
return null;
}
@Override
public String[] getHeaders(String name) throws IOException {
getInputStream();
final String lowerCaseName = name.toLowerCase();
final List<String> headers = new ArrayList<>(4);
for (String field : headersFields) {
if (field.toLowerCase().startsWith(lowerCaseName)) {
int colonPos = field.indexOf(':');
if (colonPos > 0) {
headers.add(field.substring(colonPos + 1).trim());
}
}
}
return headers.toArray(new String[headers.size()]);
}
@Override
public synchronized InputStream getInputStream() throws IOException {
if (this.headersFields != null) {
// already parsed
return data;
}
final StringBuilder lineBuf = new StringBuilder();
for (int i = 0; i < 8; i++) {
int c = rawData.read();
if (c == -1) {
break;
}
lineBuf.append((char)c);
}
if (!lineBuf.toString().startsWith("HTTP/1.")) {
throw new IOException("Invalid status line of HTTP response from docker API");
}
final List<String> headerFields = new ArrayList<>(4);
for (; ; ) {
int c = rawData.read();
if (c == -1) {
throw new IOException("Unexpected end of file from docker API");
} else if (c == '\n') {
if (lineBuf.length() == 0) {
break;
}
headerFields.add(lineBuf.toString());
lineBuf.setLength(0);
} else if (c != '\r') {
lineBuf.append((char)c);
}
}
this.headersFields = headerFields.toArray(new String[headerFields.size()]);
final int contentLength = getContentLength();
if (contentLength == 0) {
return data = EMPTY;
}
if (contentLength > 0) {
return data = new LimitedInputStream(rawData, contentLength);
}
return data = "chunked".equals(getHeader("Transfer-Encoding")) ? new ChunkedInputStream(rawData) : rawData;
}
}