class ApplicationArchive extends AbstractStore<ApplicationEvent, ApplicationStoreDelegate> {

    public synchronized ApplicationDescription saveApplication(InputStream stream) {
        try (InputStream ais = stream) {
            byte[] cache = toByteArray(ais);
            InputStream bis = new ByteArrayInputStream(cache);

            boolean plainXml = isPlainXml(cache);
            ApplicationDescription desc = plainXml ?
                    parsePlainAppDescription(bis) : parseZippedAppDescription(bis);
            checkState(!appFile(desc.name(), APP_XML).exists(),
                    "Application %s already installed", desc.name());

            if (plainXml) {
                expandPlainApplication(cache, desc);
            } else {
                bis.reset();
                expandZippedApplication(bis, desc);

                bis.reset();
                saveApplication(bis, desc);
            }

            installArtifacts(desc);
            return desc;
        } catch (IOException e) {
            throw new ApplicationException("Unable to save application", e);
        }
    }

}