/* * Copyright Siemens AG, 2014-2015. Part of the SW360 Portal Project. * * 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 */ package org.eclipse.sw360.datahandler.common; import java.io.IOException; import java.io.InputStream; import java.util.Collections; import java.util.Iterator; /** * @author daniele.fognini@tngtech.com */ public class ConcatClosingInputStream extends InputStream { private final Iterator<InputStream> streams; private boolean closed = false; private InputStream current; /* streams.next() and .hasNext() must not throw exceptions */ public ConcatClosingInputStream(Iterator<InputStream> streams) { if (streams == null) streams = Collections.emptyIterator(); if (streams.hasNext()) { this.current = streams.next(); } else { this.closed = true; } this.streams = streams; } @Override public int read() throws IOException { if (closed) return -1; if (current == null) { return safeCloseAndThrow(new IOException("cannot read from null Stream")); } int read; try { read = current.read(); } catch (IOException e) { return safeCloseAndThrow(e); } if (read >= 0) return read; else { try { current.close(); } catch (IOException e) { return safeCloseAndThrow(e); } if (streams.hasNext()) { current = streams.next(); return read(); } else { closed = true; return -1; } } } private int safeCloseAndThrow(IOException e) throws IOException { try { close(); } catch (IOException close) { e.addSuppressed(close); } throw e; } @Override public void close() throws IOException { if (closed) return; IOException ioException = tryClose(current); while (streams.hasNext()) { IOException exception = tryClose(streams.next()); ioException = asSuppressedOf(ioException, exception); } closed = true; if (ioException != null) throw ioException; } private IOException asSuppressedOf(IOException ioException, IOException exception) { if (exception != null) { if (ioException == null) { ioException = exception; } else { ioException.addSuppressed(exception); } } return ioException; } private IOException tryClose(InputStream stream) { if (stream != null) { try { stream.close(); } catch (IOException e) { return e; } } return null; } }