Package com.atlassian.labs.speakeasy.manager.convention

Source Code of com.atlassian.labs.speakeasy.manager.convention.ZipTransformer

package com.atlassian.labs.speakeasy.manager.convention;

import com.atlassian.labs.speakeasy.manager.convention.external.ConventionDescriptorGenerator;
import com.atlassian.labs.speakeasy.manager.PluginOperationFailedException;
import com.atlassian.labs.speakeasy.model.JsonManifest;
import com.atlassian.plugin.JarPluginArtifact;
import com.atlassian.plugin.PluginArtifact;
import com.atlassian.plugin.osgi.factory.OsgiPlugin;
import com.atlassian.plugin.util.PluginUtils;
import org.apache.commons.io.IOUtils;
import org.osgi.framework.Constants;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.*;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import static com.google.common.collect.Maps.newHashMap;

/**
*
*/
@Component
public class ZipTransformer
{

    private final JsonManifestHandler jsonHandler;
    private final JsonToElementParser jsonToElementParser;

    @Autowired
    public ZipTransformer(JsonManifestHandler jsonHandler, JsonToElementParser jsonToElementParser)
    {
        this.jsonHandler = jsonHandler;
        this.jsonToElementParser = jsonToElementParser;
    }

    public JarPluginArtifact convertConventionZipToPluginJar(JsonManifest descriptor, PluginArtifact artifact)
    {
        Map<String,byte[]> additions = newHashMap();

        additions.put("META-INF/MANIFEST.MF", generateManifest(descriptor));
        additions.put("META-INF/spring/speakeasy-context.xml", getResourceContents("speakeasy-context.xml"));

        // this exists to force parse errors to happen earlier
        jsonToElementParser.createWebItems(artifact.getResourceAsStream("ui/web-items.json"));

        try
        {
            return new JarPluginArtifact(addFilesToExistingZip(artifact.toFile(), additions));
        }
        catch (IOException e)
        {
            throw new PluginOperationFailedException("Unable to transform zip", e, descriptor.getKey());
        }
    }

    public String extractPluginKey(PluginArtifact pluginArtifact)
    {
        if (pluginArtifact.doesResourceExist(JsonManifest.ATLASSIAN_EXTENSION_PATH))
        {
            JsonManifest descriptor = jsonHandler.read(pluginArtifact);
            return descriptor.getKey();
        }
        return null;
    }
    public JsonManifest readManifest(String key, InputStream in)
    {
        return jsonHandler.read(key, in);
    }

    public void writeManifest(JsonManifest manifest, OutputStream out) throws IOException
    {
        jsonHandler.write(manifest, out);
    }

    private byte[] getResourceContents(String path)
    {
        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        InputStream in = null;
        try
        {
            in = getClass().getResourceAsStream(path);
            IOUtils.copy(in, bout);
            return bout.toByteArray();
        }
        catch (IOException e)
        {
            throw new RuntimeException("Should never happen", e);
        }
        finally
        {
            IOUtils.closeQuietly(in);
        }
    }

    private byte[] generateManifest(JsonManifest descriptor)
    {
        Manifest mf = new Manifest();
        mf.getMainAttributes().putValue(Attributes.Name.MANIFEST_VERSION.toString(), "1.0");
        mf.getMainAttributes().putValue(Constants.BUNDLE_MANIFESTVERSION, "2");
        mf.getMainAttributes().putValue(OsgiPlugin.ATLASSIAN_PLUGIN_KEY, descriptor.getKey());
        mf.getMainAttributes().putValue(Constants.BUNDLE_SYMBOLICNAME, descriptor.getKey());
        mf.getMainAttributes().putValue(Constants.BUNDLE_VERSION, cleanManifestValue(descriptor.getVersion()));
        mf.getMainAttributes().putValue(Constants.BUNDLE_NAME, cleanManifestValue(descriptor.getName()));
        mf.getMainAttributes().putValue(Constants.BUNDLE_DESCRIPTION, cleanManifestValue(descriptor.getDescription()));
        mf.getMainAttributes().putValue(Constants.IMPORT_PACKAGE, ConventionDescriptorGenerator.class.getPackage().getName());
        mf.getMainAttributes().putValue("Spring-Context", "*;timeout:=" + PluginUtils.getDefaultEnablingWaitPeriod());

        if (descriptor.getVendor() != null)
        {
            mf.getMainAttributes().putValue(Constants.BUNDLE_VENDOR, descriptor.getVendor().getName());
        }

        ByteArrayOutputStream bout = new ByteArrayOutputStream();
        try
        {
            mf.write(bout);
        }
        catch (IOException e)
        {
            throw new RuntimeException("Should never happen", e);
        }
        return bout.toByteArray();
    }

    private String cleanManifestValue(String name)
    {
        return name == null ? null : name.replaceAll("\n|\r", " ");
    }

    /**
     * Creates a new jar by overriding the specified files in the existing one
     *
     * @param zipFile The existing zip file
     * @param files   The files to override
     * @return The new zip
     * @throws IOException If there are any problems processing the streams
     */
    File addFilesToExistingZip(File zipFile,
                                      Map<String, byte[]> files) throws IOException
    {
        File tempFile = new File(zipFile.getPath() + ".jar");

        byte[] buf = new byte[64 * 1024];
        ZipInputStream zin = null;
        ZipOutputStream out = null;
        try
        {
            zin = new ZipInputStream(new FileInputStream(zipFile));
            out = new ZipOutputStream(new FileOutputStream(tempFile));
            out.setLevel(Deflater.NO_COMPRESSION);

            ZipEntry entry = zin.getNextEntry();
            while (entry != null)
            {
                String name = entry.getName();
                if (!files.containsKey(name))
                {
                    // Add ZIP entry to output stream.
                    out.putNextEntry(new ZipEntry(name));
                    // Transfer bytes from the ZIP file to the output file
                    int len;
                    while ((len = zin.read(buf)) > 0)
                        out.write(buf, 0, len);
                }
                entry = zin.getNextEntry();
            }
            // Close the streams
            zin.close();
            // Compress the files
            for (Map.Entry<String, byte[]> fentry : files.entrySet())
            {
                InputStream in = null;
                try
                {
                    in = new ByteArrayInputStream(fentry.getValue());
                    // Add ZIP entry to output stream.
                    out.putNextEntry(new ZipEntry(fentry.getKey()));
                    // Transfer bytes from the file to the ZIP file
                    int len;
                    while ((len = in.read(buf)) > 0)
                    {
                        out.write(buf, 0, len);
                    }
                    // Complete the entry
                    out.closeEntry();
                }
                finally
                {
                    IOUtils.closeQuietly(in);
                }
            }
            // Complete the ZIP file
            out.close();
            zipFile.delete();
        }
        finally
        {
            // Close just in case
            IOUtils.closeQuietly(zin);
            IOUtils.closeQuietly(out);
        }
        return tempFile;
    }

}
TOP

Related Classes of com.atlassian.labs.speakeasy.manager.convention.ZipTransformer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.