randori.plugin.compiled.RblFileDecompiler.java Source code

Java tutorial

Introduction

Here is the source code for randori.plugin.compiled.RblFileDecompiler.java

Source

/*
 * Copyright 2013 original Randori IntelliJ Plugin authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */

package randori.plugin.compiled;

import com.intellij.lang.javascript.flex.importer.FlexImporter;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileTypes.BinaryFileDecompiler;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.ArrayUtil;
import com.intellij.util.Consumer;
import de.schlichtherle.truezip.file.TArchiveDetector;
import de.schlichtherle.truezip.file.TConfig;
import de.schlichtherle.truezip.file.TFile;
import de.schlichtherle.truezip.file.TFileInputStream;
import de.schlichtherle.truezip.fs.archive.zip.ZipDriver;
import de.schlichtherle.truezip.rof.ByteArrayReadOnlyFile;
import de.schlichtherle.truezip.socket.sl.IOPoolLocator;
import de.schlichtherle.truezip.zip.ZipEntry;
import de.schlichtherle.truezip.zip.ZipFile;
import org.apache.commons.io.IOUtils;
import org.jetbrains.annotations.NotNull;
import randori.compiler.bundle.Bundle;
import randori.compiler.bundle.IBundle;
import randori.compiler.bundle.IBundleLibrary;
import randori.compiler.bundle.io.BundleReader;
import randori.compiler.bundle.io.StAXManifestReader;

import javax.xml.stream.XMLStreamException;
import java.io.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

/**
 * @author Frdric THOMAS Date: 27/04/13 Time: 15:57
 */
public class RblFileDecompiler implements BinaryFileDecompiler {
    private static final Logger LOG = Logger.getInstance(RblFileDecompiler.class);
    private static final String MANIFEST_XML = "manifest.xml";
    private static final String libSeparator = "\n";

    @NotNull
    public CharSequence decompile(VirtualFile file) {
        TConfig.get().setArchiveDetector(new TArchiveDetector("rbl|swc", new ZipDriver(IOPoolLocator.SINGLETON)));

        final StringBuilder libraryInterface = new StringBuilder(ArrayUtil.EMPTY_CHAR_SEQUENCE);
        Project project = findProject();

        if (project != null)
            try {
                final Consumer<InputStream> extractedLibraryConsumer = new Consumer<InputStream>() {

                    @Override
                    public void consume(InputStream libraryInputStream) {
                        if (libraryInputStream != null)
                            libraryInterface.append(FlexImporter.buildInterfaceFromStream(libraryInputStream));
                    }
                };
                extractLibraries(file, extractedLibraryConsumer);
            } catch (Exception e) {
                LOG.warn(file.getPath(), e);
            }

        return libraryInterface.toString();
    }

    /**
     * Extract the library for each declared bundle in the RBL.
     *
     * @param rblFile The RBL file.
     * @param result The processor used to consume the resulting extracted library.
     * @throws Exception
     */
    public static void extractLibraries(VirtualFile rblFile, final Consumer<InputStream> result) throws Exception {
        IBundle bundle = new BundleReader(rblFile.getPath()).getBundle();

        for (IBundleLibrary iBundleLibrary : bundle.getLibraries()) {
            File library = new TFile(rblFile.getPath() + File.separator + iBundleLibrary.getName() + File.separator
                    + "bin" + File.separator + "swc" + File.separator + iBundleLibrary.getName() + ".swc"
                    + File.separator + "library.swf");

            InputStream inputStream = new TFileInputStream(library);
            result.consume(inputStream);
        }
    }

    /**
     * Extract the library for each declared bundle in the RBL.
     * It doesn't extract it from the rblFile itself but from its content.
     *
     * @param rblFile The RBL file.
     * @param content The content of the RBL file.
     * @return An InputStream sequence of the extracted libraries.
     * @throws IOException
     * @throws XMLStreamException
     */
    public static InputStream extractLibraries(VirtualFile rblFile, byte[] content)
            throws IOException, XMLStreamException {
        final List<InputStream> libraries = new ArrayList<InputStream>();
        SequenceInputStream librariesInputStream = null;
        InputStream swcInputStream;
        byte[] swcBytes;
        ZipFile swc;
        InputStream library;
        ZipEntry entry;

        final Bundle bundle = new Bundle(new File(rblFile.getPath()));
        final ByteArrayReadOnlyFile rof = new ByteArrayReadOnlyFile(content);
        final ZipFile rbl = new ZipFile(rof);

        readCatalog(rbl, bundle);

        for (IBundleLibrary iBundleLibrary : bundle.getLibraries()) {
            entry = rbl.getEntry(iBundleLibrary.getName() + "/bin/swc/" + iBundleLibrary.getName() + ".swc");
            swcInputStream = rbl.getInputStream(entry);

            if (swcInputStream != null) {
                swcBytes = IOUtils.toByteArray(swcInputStream);

                if (swcBytes != null && swcBytes.length > 0) {
                    swc = new ZipFile(new ByteArrayReadOnlyFile(swcBytes));
                    library = swc.getInputStream("library.swf");
                    libraries.add(library);
                    libraries.add(new ByteArrayInputStream(libSeparator.getBytes()));
                }
            }
        }

        if (libraries.size() > 0)
            librariesInputStream = new SequenceInputStream(Collections.enumeration(libraries));

        return librariesInputStream;
    }

    private static InputStream readCatalog(ZipFile rbl, Bundle bundle) throws XMLStreamException, IOException {
        InputStream catalogInputStream;
        StAXManifestReader catalogReader;

        catalogInputStream = getInputStream(rbl);
        if (catalogInputStream != null) {
            catalogReader = new StAXManifestReader(new BufferedInputStream(catalogInputStream), bundle);
            catalogReader.parse();
            catalogReader.close();
        }

        return catalogInputStream;
    }

    private static InputStream getInputStream(ZipFile zipFile) throws IOException {
        ZipEntry zipEntry = null;
        for (final Enumeration<? extends ZipEntry> entryEnum = zipFile.entries(); entryEnum.hasMoreElements();) {
            final ZipEntry entry = entryEnum.nextElement();
            if (entry.getName().equals(RblFileDecompiler.MANIFEST_XML)) {
                zipEntry = entry;
                break;
            }
        }

        return (zipEntry == null) ? null : zipFile.getInputStream(zipEntry);
    }

    private static Project findProject() {
        Project projects[] = ProjectManager.getInstance().getOpenProjects();

        if (projects.length > 0)
            return projects[0];

        return null;
    }
}