Java tutorial
/* * Copyright (c) 2012-2018 Red Hat, Inc. * This program and the accompanying materials are made * available under the terms of the Eclipse Public License 2.0 * which is available at https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * Red Hat, Inc. - initial API and implementation */ package org.eclipse.che.infrastructure.docker.client; import com.google.gson.Gson; import com.google.gson.JsonIOException; import com.google.gson.JsonParseException; import com.google.gson.JsonStreamParser; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.PushbackReader; /** * Docker daemon sends chunked data in response. One chunk isn't always one JSON object so need to * read full chunk at once to be able restore JSON object. This reader merges (if needs) few chunks * until get full JSON object that we can parse. Parameter of this class is class where JSON message * should be parsed. * * @author Alexander Garagatyi */ public class JsonMessageReader<T> { private static final Gson GSON = new Gson(); private final JsonStreamParser streamParser; private final Class<T> messageClass; private final PushbackReader reader; private boolean firstRead = true; /** * @param source source of messages in JSON format * @param messageClass class of the message object where JSON messages should be parsed. Because * of erasure of generic information in runtime in some cases we can't get parameter class of * current class. */ public JsonMessageReader(InputStream source, Class<T> messageClass) { // we need to push back only 1 char, read more further this.reader = new PushbackReader(new InputStreamReader(source), 1); this.streamParser = new JsonStreamParser(reader); this.messageClass = messageClass; } /** * Returns message parsed from JSON stream. * * @return object of class passed as parameter of constructor or null if stream is empty * @throws IOException if error occurs on reading stream */ public T next() throws IOException { // on first read we check if this stream is empty with reading of the first byte of stream // if so we do not call JsonStreamParser.hasNext() because it will throw exception // if not we return read byte to stream using PushbackInputStream if (firstRead) { int firstChar = reader.read(); if (firstChar == -1) { return null; } else { reader.unread(firstChar); firstRead = false; } } try { if (streamParser.hasNext()) { return GSON.fromJson(streamParser.next(), messageClass); } } catch (JsonIOException e) { throw new IOException(e); } catch (JsonParseException ignore) { } return null; } }