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();
                boolean isSelfContainedJar = expandZippedApplication(bis, desc);

                if (isSelfContainedJar) {
                    bis.reset();
                    stageSelfContainedJar(bis, desc);
                }

                /*
                 * Reset the ZIP file and reparse the app description now
                 * that the ZIP is expanded onto the filesystem. This way any
                 * file referenced as part of the description (i.e. app.png)
                 * can be loaded into the app description.
                 */
                bis.reset();
                desc = parseZippedAppDescription(bis);

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

            installArtifacts(desc);
            return desc;
        } catch (IOException e) {
            throw new ApplicationException("Unable to save application", e);
        }
    }
@Test
    public void saveSelfContainedApp() throws IOException {
        InputStream stream = getClass().getResourceAsStream("app.scj");
        ApplicationDescription app = aar.saveApplication(stream);
        validate(app);
        stream.close();
    }