@Override
    public long addEntry(final String entryName,
                         final InputStream inputStream,
                         final Consumer<Long> progressHandler) throws IOException {
        long bytesWritten;
        LOGGER.debug(() -> "addEntry() - " + entryName);

        final StroomZipEntry entry = stroomZipEntries.addFile(entryName);
        final String baseName = entry.getBaseName();
        final StroomZipFileType stroomZipFileType = entry.getStroomZipFileType();

        // We don't want to aggregate reference feeds.
        final boolean singleEntry = feedProperties.isReference(currentFeedName);

        // If the base name changes then reset and we will treat this as a new layer.
        final boolean requiresNewLayer = layer.hasType(stroomZipFileType) || (lastBaseName != null &&
                !lastBaseName.equals(baseName));
        if (requiresNewLayer) {
            reset();
            if (singleEntry) {
                closeCurrentFeed();
            }
        }

        lastBaseName = baseName;
        // Tell the new layer that it will contain the requested type.
        layer.addType(stroomZipFileType);

        if (StroomZipFileType.MANIFEST.equals(stroomZipFileType)) {
            manifestAttributeMap = new AttributeMap();
            final byte[] bytes = readAttributes(inputStream, manifestAttributeMap, progressHandler);
            bytesWritten = bytes.length;
            putAll(globalAttributeMap, manifestAttributeMap);

            // Are we switching feed?
            final String feedName = getCurrentAttributeMap().get(StandardHeaderArguments.FEED);
            if (feedName != null && !feedName.equals(currentFeedName)) {
                if (layer.hasType(StroomZipFileType.DATA) || layer.hasType(StroomZipFileType.CONTEXT)) {
                    throw new IOException("Header and Data out of order for multiple feed data");
                }
                currentFeedName = feedName;
            }

        } else if (StroomZipFileType.META.equals(stroomZipFileType)) {
            metaAttributeMap = new AttributeMap();
            putAll(manifestAttributeMap, metaAttributeMap);
            final byte[] bytes = readAttributes(inputStream, metaAttributeMap, progressHandler);
            bytesWritten = bytes.length;
            putAll(globalAttributeMap, metaAttributeMap);

            if (metaDataStatistics != null) {
                metaDataStatistics.recordStatistics(metaAttributeMap);
            }

            // Are we switching feed?
            final String feedName = getCurrentAttributeMap().get(StandardHeaderArguments.FEED);
            if (feedName != null && !feedName.equals(currentFeedName)) {
                if (layer.hasType(StroomZipFileType.DATA) || layer.hasType(StroomZipFileType.CONTEXT)) {
                    throw new IOException("Header and Data out of order for multiple feed data");
                }
                currentFeedName = feedName;
            }

            final OutputStreamProvider outputStreamProvider = getOutputStreamProvider(currentFeedName, typeName);
            try (final OutputStream outputStream = outputStreamProvider.get(StreamTypeNames.META)) {
                AttributeMapUtil.write(metaAttributeMap, outputStream);
            }

        } else if (StroomZipFileType.CONTEXT.equals(stroomZipFileType)) {
            final OutputStreamProvider outputStreamProvider = getOutputStreamProvider(currentFeedName, typeName);
            try (final OutputStream currentOutputStream = outputStreamProvider.get(StreamTypeNames.CONTEXT)) {
                bytesWritten = StreamUtil.streamToStream(
                        inputStream,
                        currentOutputStream,
                        buffer,
                        progressHandler);
            }

        } else {
            final OutputStreamProvider outputStreamProvider = getOutputStreamProvider(currentFeedName, typeName);
            try (final OutputStream currentOutputStream = outputStreamProvider.get()) {
                bytesWritten = StreamUtil.streamToStream(
                        inputStream,
                        currentOutputStream,
                        buffer,
                        progressHandler);
            }
        }

        return bytesWritten;
    }
Type of {@link StreamHandler} that store the entries in the stream store.
There are some special rules about how this works.
<p>
This is fine if all the meta data indicates they belong to the same feed
001.meta, 002.meta, 001.dat, 002.dat
<p>
This is also fine if 001.meta indicates 001 belongs to feed X and 002.meta
indicates 001 belongs to feed Y 001.meta, 002.meta, 001.dat, 002.dat
<p>
However if the global header map indicates feed Z and the files are send in
the following order 001.dat, 002.dat, 001.meta, 002.meta this is invalid ....
I.E. as soon as we add non header stream for a feed if the header turns out
to be different we must throw an exception.
stroom-receive/stroom-receive-common/src/main/java/stroom/receive/common/StreamTargetStreamHandler.java