All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.royale.compiler.clients.COMPJSCRoyale Maven / Gradle / Ivy

The newest version!
/*
 *
 *  Licensed to the Apache Software Foundation (ASF) under one or more
 *  contributor license agreements.  See the NOTICE file distributed with
 *  this work for additional information regarding copyright ownership.
 *  The ASF licenses this file to You 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 org.apache.royale.compiler.clients;

import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.*;
import java.util.zip.CRC32;
import java.util.zip.Deflater;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;

import com.google.debugging.sourcemap.SourceMapConsumerV3;
import com.google.debugging.sourcemap.SourceMapGeneratorV3;
import com.google.debugging.sourcemap.SourceMapParseException;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.royale.compiler.clients.MXMLJSC.JSTargetType;
import org.apache.royale.compiler.clients.problems.ProblemQuery;
import org.apache.royale.compiler.codegen.js.IJSWriter;
import org.apache.royale.compiler.driver.IBackend;
import org.apache.royale.compiler.driver.js.IJSApplication;
import org.apache.royale.compiler.exceptions.ConfigurationException;
import org.apache.royale.compiler.exceptions.ConfigurationException.IOError;
import org.apache.royale.compiler.exceptions.ConfigurationException.MustSpecifyTarget;
import org.apache.royale.compiler.internal.driver.mxml.royale.MXMLRoyaleSWCBackend;
import org.apache.royale.compiler.internal.parsing.as.RoyaleASDocDelegate;
import org.apache.royale.compiler.internal.projects.CompilerProject;
import org.apache.royale.compiler.internal.projects.RoyaleJSProject;
import org.apache.royale.compiler.internal.targets.RoyaleSWCTarget;
import org.apache.royale.compiler.internal.units.SWCCompilationUnit;
import org.apache.royale.compiler.internal.watcher.WatchThread;
import org.apache.royale.compiler.internal.watcher.WatchThread.IWatchWriter;
import org.apache.royale.compiler.internal.targets.JSTarget;
import org.apache.royale.compiler.internal.workspaces.Workspace;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.compiler.problems.InternalCompilerProblem;
import org.apache.royale.compiler.problems.LibraryNotFoundProblem;
import org.apache.royale.compiler.problems.UnableToBuildSWFProblem;
import org.apache.royale.compiler.targets.ITarget.TargetType;
import org.apache.royale.compiler.targets.ITargetSettings;
import org.apache.royale.compiler.units.ICompilationUnit;
import org.apache.royale.compiler.units.ICompilationUnit.UnitType;
import org.apache.royale.compiler.utils.SourceMapUtils;
import org.apache.royale.swc.ISWCFileEntry;
import org.apache.royale.swc.io.SWCReader;

/**
 * @author Erik de Bruin
 * @author Michael Schmalle
 */
public class COMPJSCRoyale extends MXMLJSCRoyale
{
    /*
     * Exit code enumerations.
     */
    static enum ExitCode
    {
        SUCCESS(0),
        PRINT_HELP(1),
        FAILED_WITH_ERRORS(2),
        FAILED_WITH_EXCEPTIONS(3),
        FAILED_WITH_CONFIG_PROBLEMS(4),
        WATCHING(1000);

        ExitCode(int code)
        {
            this.code = code;
        }

        final int code;
        
        int getCode()
        {
        	return code;
        }
    }

    @Override
    public String getName()
    {
        return FLEX_TOOL_COMPC;
    }

    @Override
    public int execute(String[] args)
    {
        return staticMainNoExit(args);
    }

    /**
     * Java program entry point.
     * 
     * @param args command line arguments
     */
    public static void main(final String[] args)
    {
        int exitCode = staticMainNoExit(args);
        if (exitCode != ExitCode.WATCHING.getCode())
        {
            System.exit(exitCode);
        }
    }

    /**
     * Entry point for the {@code } Ant task.
     *
     * @param args Command line arguments.
     * @return An exit code.
     */
    public static int staticMainNoExit(final String[] args)
    {
        long startTime = System.nanoTime();

        final COMPJSCRoyale mxmlc = new COMPJSCRoyale();
        final List problems = new ArrayList();
        final int exitCode = mxmlc.mainNoExit(args, problems, true);

        long endTime = System.nanoTime();
        System.out.println((endTime - startTime) / 1e9 + " seconds");

        return exitCode;
    }

    public COMPJSCRoyale()
    {
        IBackend backend = new MXMLRoyaleSWCBackend();

        workspace = new Workspace();
        workspace.setASDocDelegate(new RoyaleASDocDelegate());
        project = new RoyaleJSProject(workspace, backend);
        problems = new ProblemQuery(); // this gets replaced in configure().  Do we need it here?
        asFileHandler = backend.getSourceFileHandlerInstance();
    }

    /**
     * Main body of this program. This method is called from the public static
     * method's for this program.
     * 
     * @return true if compiler succeeds
     * @throws IOException
     * @throws InterruptedException
     */
    @Override
    protected boolean compile()
    {
        boolean compilationSuccess = false;

        try
        {
            project.getSourceCompilationUnitFactory().addHandler(asFileHandler);

            if (setupTargetFile())
                buildArtifact();

            if (jsTarget != null)
            {
                if (!writeSWC())
                {
                    return false;
                }
                compilationSuccess = true;
            }
        }
        catch (Exception e)
        {
            System.out.println(e);
            final ICompilerProblem problem = new InternalCompilerProblem(e);
            problems.add(problem);
        }

        return compilationSuccess;
    }

    private boolean writeSWC() throws IOException, InterruptedException
    {
        Collection errors = new ArrayList();
        Collection warnings = new ArrayList();

        if (!config.getCreateTargetWithErrors())
        {
            problems.getErrorsAndWarnings(errors, warnings);
            if (errors.size() > 0)
                return false;
        }

        boolean packingSWC = false;
        String outputFolderName = getOutputFilePath();
        File swcFile = new File(outputFolderName);
        File jsOut = new File("js/out");
        File externsOut = new File("externs");
        ZipFile zipFile = null;
        ZipOutputStream zipOutputStream = null;
        String catalog = null;
        StringBuilder fileList = new StringBuilder();
        if (outputFolderName.endsWith(".swc"))
        {
            packingSWC = true;
            if (!swcFile.exists())
            {
                problems.add(new LibraryNotFoundProblem(outputFolderName));
                return false;
            }
            zipFile = new ZipFile(swcFile, ZipFile.OPEN_READ);
            final InputStream catalogInputStream = SWCReader.getInputStream(zipFile, SWCReader.CATALOG_XML);
            
            catalog = IOUtils.toString(catalogInputStream);
            catalogInputStream.close();
            zipOutputStream = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(outputFolderName + ".new")));
            zipOutputStream.setLevel(Deflater.NO_COMPRESSION);
            for (final Enumeration entryEnum = zipFile.entries(); entryEnum.hasMoreElements();)
            {
                final ZipEntry entry = entryEnum.nextElement();
                if (!entry.getName().contains("js/out") &&
                    !entry.getName().contains(SWCReader.CATALOG_XML))
                {
                    if (config.isVerbose())
                    {
                        System.out.println("Copy " + entry.getName());
                    }
                    InputStream input = zipFile.getInputStream(entry);
                    ZipEntry ze = new ZipEntry(entry.getName());
                    ze.setMethod(ZipEntry.STORED);
                    ze.setSize(entry.getSize());
                    ze.setCompressedSize(entry.getCompressedSize());
                    ze.setCrc(entry.getCrc());
                    long fileDate = System.currentTimeMillis();
                    long zipFileDate = fileDate;
                    String metadataDate = targetSettings.getSWFMetadataDate();
                    if (metadataDate != null)
                    {
                        String metadataFormat = targetSettings.getSWFMetadataDateFormat();
                        try {
                            SimpleDateFormat sdf = new SimpleDateFormat(metadataFormat);
                            Date d = sdf.parse(metadataDate);
                            Calendar cal = new GregorianCalendar();
                            cal.setTime(d);
                            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
                            d = sdf.parse(metadataDate);
                            fileDate = d.getTime();
                            ZonedDateTime zdt = ZonedDateTime.of(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), 
                                                    cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0, ZoneId.systemDefault());
                            zipFileDate = zdt.toInstant().toEpochMilli();
                        } catch (ParseException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        } catch (IllegalArgumentException e1) {
                            e1.printStackTrace();
                        }
                    }
                    ze.setTime(zipFileDate);
                    zipOutputStream.putNextEntry(ze);
                    IOUtils.copy(input, zipOutputStream);
                    zipOutputStream.flush();
                    zipOutputStream.closeEntry();
                }
            }
            int filesIndex = catalog.indexOf("");
            if (filesIndex != -1)
            {
                int filesIndex2 = catalog.indexOf("");
                String files = catalog.substring(filesIndex, filesIndex2);
                int fileIndex = files.indexOf("", fileIndex);
                    String path = files.substring(pathIndex + 6, pathIndex2);
                    if (!path.startsWith("js/out"))
                    {
                        fileList.append(files.substring(fileIndex - 8, fileIndex2 + 3));
                    }
                    pathIndex = files.indexOf("path=", pathIndex2);
                    fileIndex = files.indexOf(" externs = config.getExterns();
        Collection roots = ((RoyaleSWCTarget)target).getReachableCompilationUnits(errors);
        Collection reachableCompilationUnits = project.getReachableCompilationUnitsInSWFOrder(roots);
        for (final ICompilationUnit cu : reachableCompilationUnits)
        {
            ICompilationUnit.UnitType cuType = cu.getCompilationUnitType();

            if (cuType == ICompilationUnit.UnitType.AS_UNIT
                    || cuType == ICompilationUnit.UnitType.MXML_UNIT)
            {
                String symbol = cu.getQualifiedNames().get(0);
                if (externs.contains(symbol)) continue;
                
                if (project.isExternalLinkage(cu)) continue;
                
                if (!packingSWC)
                {
                    final File outputClassFile = getOutputClassFile(
                            cu.getQualifiedNames().get(0), outputFolder, true);

                    if (config.isVerbose())
                    {
                        System.out.println("Compiling file: " + outputClassFile);
                    }

                    ICompilationUnit unit = cu;

                    IJSWriter writer;
                    if (cuType == ICompilationUnit.UnitType.AS_UNIT)
                    {
                        writer = (IJSWriter) project.getBackend().createWriter(project,
                                (List) problems.getProblems(), unit,
                                false);
                    }
                    else
                    {
                        writer = (IJSWriter) project.getBackend().createMXMLWriter(
                                project, (List) problems.getProblems(),
                                unit, false);
                    }

                    BufferedOutputStream out = new BufferedOutputStream(
                            new FileOutputStream(outputClassFile));
                    BufferedOutputStream sourceMapOut = null;
                    File outputSourceMapFile = null;
                    if (project.config.getSourceMap())
                    {
                        outputSourceMapFile = getOutputSourceMapFile(
                                cu.getQualifiedNames().get(0), outputFolder, true);
                        sourceMapOut = new BufferedOutputStream(
                            new FileOutputStream(outputSourceMapFile));
                    }
                    writer.writeTo(out, sourceMapOut, outputSourceMapFile);
                    out.flush();
                    out.close();
                    if (sourceMapOut != null)
                    {
                        sourceMapOut.flush();
                        sourceMapOut.close();
                    }
                    writer.close();
                }
                else
                {
                    if (config.isVerbose())
                    {
                        System.out.println("Compiling file: " + cu.getQualifiedNames().get(0));
                    }
                    
                    ICompilationUnit unit = cu;

                    IJSWriter writer;
                    if (cuType == ICompilationUnit.UnitType.AS_UNIT)
                    {
                        writer = (IJSWriter) project.getBackend().createWriter(project,
                                (List) problems.getProblems(), unit,
                                false);
                    }
                    else
                    {
                        writer = (IJSWriter) project.getBackend().createMXMLWriter(
                                project, (List) problems.getProblems(),
                                unit, false);
                    }

                    ByteArrayOutputStream temp = new ByteArrayOutputStream();
                    ByteArrayOutputStream sourceMapTemp = null;
                    
                    boolean isExterns = false;
                    if(cu.getDefinitionPromises().size() > 0)
                    {
                        isExterns = project.isExterns(cu.getDefinitionPromises().get(0).getQualifiedName());
                    }
                    
                    // if the file is @externs DON'T create source map file
                    if (project.config.getSourceMap() && !isExterns)
                    {
                        sourceMapTemp = new ByteArrayOutputStream();
                    }
                    writer.writeTo(temp, sourceMapTemp, null);

                    File outputClassFile = getOutputClassFile(
                            cu.getQualifiedNames().get(0),
                            isExterns ? externsOut : jsOut,
                            false);
                    String outputClassFilePath = outputClassFile.getPath();
                    outputClassFilePath = outputClassFilePath.replace('\\', '/');
                    if (config.isVerbose())
                    {
                        System.out.println("Writing file: " + outputClassFilePath);     	
                    }
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    temp.writeTo(baos);
                    writeFileToZip(zipOutputStream, outputClassFilePath, baos, fileList);
                    
                    if(sourceMapTemp != null)
                    {
                        String sourceMapFilePath = getOutputSourceMapFile(
                            cu.getQualifiedNames().get(0),
                            isExterns ? externsOut : jsOut,
                            false).getPath();
                        sourceMapFilePath = sourceMapFilePath.replace('\\', '/');
                        if (config.isVerbose())
                        {
                            System.out.println("Writing file: " + sourceMapFilePath);
                        }
                        baos = new ByteArrayOutputStream();
                        processSourceMap(sourceMapTemp, baos, outputClassFile, symbol);
                        writeFileToZip(zipOutputStream, sourceMapFilePath, baos, fileList);
                    }
                    writer.close();
                }
            }
            else if (cuType == ICompilationUnit.UnitType.SWC_UNIT)
            {
                String symbol = cu.getQualifiedNames().get(0);
                if (externs.contains(symbol)) continue;
                if (project.isExternalLinkage(cu)) continue;
                if (!packingSWC)
                {
                    // we probably shouldn't skip this -JT
                    continue;
                }

                // if another .swc file is on our library-path, we must
                // include the .js (and .js.map) files because the
                // bytecode will also be included. if we have the
                // bytecode, but not the .js files, the compiler won't
                // know where to find the .js files. that's really bad.

                // if the bytecode and .js files should not be included,
                // then the developer is expected to use
                // external-library-path instead of library-path.

                SWCCompilationUnit swcCU = (SWCCompilationUnit) cu;
                String outputClassFile = getOutputClassFile(
                        cu.getQualifiedNames().get(0),
                        jsOut,
                        false).getPath();
                outputClassFile = outputClassFile.replace('\\', '/');
                ISWCFileEntry fileEntry = swcCU.getSWC().getFile(outputClassFile);
                if (fileEntry == null)
                {
                    continue;
                }
                if (config.isVerbose())
                {
                    System.out.println("Writing file: " + outputClassFile + " from SWC: " + swcCU.getAbsoluteFilename());
                }
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                InputStream fileStream = fileEntry.createInputStream();
                IOUtils.copy(fileStream, baos);
                fileStream.close();
                writeFileToZip(zipOutputStream, outputClassFile, baos, fileList);

                String outputMapFile = outputClassFile + ".map";
                fileEntry = swcCU.getSWC().getFile(outputMapFile);
                if (fileEntry == null)
                {
                    continue;
                }
                if (config.isVerbose())
                {
                    System.out.println("Writing file: " + outputMapFile + " from SWC: " + swcCU.getAbsoluteFilename());
                }
                baos = new ByteArrayOutputStream();
                fileStream = fileEntry.createInputStream();
                IOUtils.copy(fileStream, baos);
                fileStream.close();
                writeFileToZip(zipOutputStream, outputMapFile, baos, fileList);
            }
        }
        if (!config.getCreateTargetWithErrors())
        {
            errors.clear();
            warnings.clear();
            problems.getErrorsAndWarnings(errors, warnings);
            if (errors.size() > 0)
                return false;
        }
        if (packingSWC)
        {
            zipFile.close();
            long fileDate = System.currentTimeMillis();
            long zipFileDate = fileDate;
            String metadataDate = targetSettings.getSWFMetadataDate();
            if (metadataDate != null)
            {
                String metadataFormat = targetSettings.getSWFMetadataDateFormat();
                try {
                    SimpleDateFormat sdf = new SimpleDateFormat(metadataFormat);
                    Date d = sdf.parse(metadataDate);
                    Calendar cal = new GregorianCalendar();
                    cal.setTime(d);
                    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
                    d = sdf.parse(metadataDate);
                    fileDate = d.getTime();
                    ZonedDateTime zdt = ZonedDateTime.of(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), 
                                            cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0, ZoneId.systemDefault());
                    zipFileDate = zdt.toInstant().toEpochMilli();
                } catch (ParseException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalArgumentException e1) {
                    e1.printStackTrace();
                }
            }
            int libraryIndex = catalog.indexOf("");
            catalog = catalog.substring(0, libraryIndex + 13) +
                "    \n" + fileList.toString() + "    " + 
                catalog.substring(libraryIndex + 13);
            ZipEntry ze = new ZipEntry(SWCReader.CATALOG_XML);
            ze.setTime(zipFileDate);
            ze.setMethod(ZipEntry.STORED);
            
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            baos.write(catalog.getBytes());
            ze.setSize(baos.size());
            ze.setCompressedSize(baos.size());
            CRC32 crc = new CRC32();
            crc.reset();
            crc.update(baos.toByteArray());
            ze.setCrc(crc.getValue());
            
            zipOutputStream.putNextEntry(ze);
            baos.writeTo(zipOutputStream);
            zipOutputStream.flush();
            zipOutputStream.closeEntry();
            zipOutputStream.flush();
            zipOutputStream.close();
            swcFile.delete();
            File newSWCFile = new File(outputFolderName + ".new");
            newSWCFile.renameTo(swcFile);
        }
        return true;
    }

    private void processSourceMap(ByteArrayOutputStream sourceMapTemp, ByteArrayOutputStream baos, File outputClassFile, String symbol)
    {
        String sourceMapSourceRoot = project.config.getSourceMapSourceRoot();
        if(sourceMapSourceRoot != null && sourceMapSourceRoot.length() > 0)
        {
            String sourceMapContents = null;
            try
            {
                sourceMapContents = sourceMapTemp.toString("utf8");
            }
            catch(UnsupportedEncodingException e)
            {
                sourceMapContents = null;
            }
            if(sourceMapContents != null)
            {
                SourceMapConsumerV3 sourceMapConsumer = new SourceMapConsumerV3();
                try
                {
                    sourceMapConsumer.parse(sourceMapContents);
                }
                catch(SourceMapParseException e)
                {
                    sourceMapConsumer = null;
                }
                if (sourceMapConsumer != null && !sourceMapSourceRoot.equals(sourceMapConsumer.getSourceRoot()))
                {
                    SourceMapGeneratorV3 sourceMapGenerator = SourceMapUtils.sourceMapConsumerToGeneratorWithRemappedSourceRoot(sourceMapConsumer, sourceMapSourceRoot, symbol);
                    String newSourceMapContents = SourceMapUtils.sourceMapGeneratorToString(sourceMapGenerator, outputClassFile.getName());
                    try
                    {
                        IOUtils.write(newSourceMapContents, baos, Charset.forName("utf8"));
                    }
                    catch(IOException e)
                    {
                    }
                    return;
                }
            }
        }
        try
        {
            sourceMapTemp.writeTo(baos);
        }
        catch(IOException e)
        {

        }
    }

    private void writeFileToZip(ZipOutputStream zipOutputStream, String entryFilePath, ByteArrayOutputStream baos, StringBuilder fileList) throws IOException
    {
        long fileDate = System.currentTimeMillis();
        long zipFileDate = fileDate;
        String metadataDate = targetSettings.getSWFMetadataDate();
        if (metadataDate != null)
        {
            String metadataFormat = targetSettings.getSWFMetadataDateFormat();
            try {
                SimpleDateFormat sdf = new SimpleDateFormat(metadataFormat);
                Date d = sdf.parse(metadataDate);
                Calendar cal = new GregorianCalendar();
                cal.setTime(d);
                sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
                d = sdf.parse(metadataDate);
                fileDate = d.getTime();
                ZonedDateTime zdt = ZonedDateTime.of(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH) + 1, cal.get(Calendar.DAY_OF_MONTH), 
                                        cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0, ZoneId.systemDefault());
                zipFileDate = zdt.toInstant().toEpochMilli();
            } catch (ParseException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IllegalArgumentException e1) {
                e1.printStackTrace();
            }
        }
        ZipEntry ze = new ZipEntry(entryFilePath);
        ze.setTime(zipFileDate);
        ze.setMethod(ZipEntry.STORED);
        
        ze.setSize(baos.size());
        ze.setCompressedSize(baos.size());
        CRC32 crc = new CRC32();
        crc.reset();
        crc.update(baos.toByteArray());
        ze.setCrc(crc.getValue());

        zipOutputStream.putNextEntry(ze);
        baos.writeTo(zipOutputStream);
        zipOutputStream.flush();
        zipOutputStream.closeEntry();
        fileList.append("        \n");
    }

    @Override
    protected void setupWatcher()
    {
        if (!config.getWatch())
        {
            return;
        }
        IWatchWriter writer = new IWatchWriter()
        {
            private long startTime;

            public void rebuild(Collection units, Collection problems) throws InterruptedException, IOException
            {
                startTime = System.nanoTime();
                workspace.startBuilding();
                try
                {
                    target = project.getBackend().createTarget(project,
                            getTargetSettings(), null);
                    ((JSTarget) target).build(null, problems);
                    for (ICompilationUnit unit : units)
                    {
                        // call waitForBuildFinish() to ensure that binding data
                        // doesn't get lost when a new definition is created
                        unit.waitForBuildFinish(problems, null);
                    }
                }
                finally
                {
                    workspace.doneBuilding();
                }
            }
    
            public void write(Collection units) throws InterruptedException, IOException
            {
                try
                {
                    if (!writeSWC())
                    {
                        throw new IOException("Failed to write SWC file.");
                    }

                    long endTime = System.nanoTime();
                    System.out.println((endTime - startTime) / 1e9 + " seconds");
                }
                finally
                {
                    workspace.doneBuilding();
                }
            }
        };
        WatchThread watcherThread = new WatchThread(JSTargetType.JS_ROYALE.getText(), writer, config, project, workspace, problems);
        watcherThread.start();
    }

    /**
     * Build target artifact.
     * 
     * @throws InterruptedException threading error
     * @throws IOException IO error
     * @throws ConfigurationException
     */
    @Override
    protected void buildArtifact() throws InterruptedException, IOException,
            ConfigurationException
    {
        jsTarget = buildJSTarget();
    }

    private IJSApplication buildJSTarget() throws InterruptedException,
            FileNotFoundException, ConfigurationException
    {
        final List problemsBuildingSWF = new ArrayList();

        final IJSApplication app = buildApplication(project,
                config.getMainDefinition(), null, problemsBuildingSWF);
        problems.addAll(problemsBuildingSWF);
        if (app == null)
        {
            ICompilerProblem problem = new UnableToBuildSWFProblem(
                    getOutputFilePath());
            problems.add(problem);
        }

        return app;
    }

    /**
     * Replaces RoyaleApplicationProject::buildSWF()
     * 
     * @param applicationProject
     * @param rootClassName
     * @param problems
     * @return
     * @throws InterruptedException
     */

    private IJSApplication buildApplication(CompilerProject applicationProject,
            String rootClassName, ICompilationUnit mainCU,
            Collection problems) throws InterruptedException,
            ConfigurationException, FileNotFoundException
    {
        Collection fatalProblems = applicationProject.getFatalProblems();
        if (!fatalProblems.isEmpty())
        {
            problems.addAll(fatalProblems);
            return null;
        }

        return ((JSTarget) target).build(mainCU, problems);
    }

    /**
     * Get the output file path. If {@code -output} is specified, use its value;
     * otherwise, use the same base name as the target file.
     * 
     * @return output file path
     */
    private String getOutputFilePath()
    {
        if (config.getOutput() == null)
        {
            final String extension = "." + project.getBackend().getOutputExtension();
            return FilenameUtils.removeExtension(config.getTargetFile()).concat(
                    extension);
        }
        else
        {
            String outputFolderName = config.getOutput();
            return outputFolderName;
        }
    }

    /**
     * Get the output class file. This includes the (sub)directory in which the
     * original class file lives. If the directory structure doesn't exist, it
     * is created if specified.
     * 
     * @author Erik de Bruin
     * @param qname
     * @param outputFolder
     * @param createDirs
     * @return output class file path
     */
    private File getOutputClassFile(String qname, File outputFolder, boolean createDirs)
    {
        String[] cname = qname.split("\\.");
        String sdirPath = outputFolder + File.separator;
        if (cname.length > 0)
        {
            for (int i = 0, n = cname.length - 1; i < n; i++)
            {
                sdirPath += cname[i] + File.separator;
            }

            if (createDirs)
            {
                File sdir = new File(sdirPath);
                if (!sdir.exists())
                    sdir.mkdirs();
            }

            qname = cname[cname.length - 1];
        }

        return new File(sdirPath + qname + "." + project.getBackend().getOutputExtension());
    }

    /**
     * Similar to getOutputClassFile, but for the source map file.
     * 
     * @param qname
     * @param outputFolder
     * @param createDirs
     * @return output source map file path
     */
    private File getOutputSourceMapFile(String qname, File outputFolder, boolean createDirs)
    {
        String[] cname = qname.split("\\.");
        String sdirPath = outputFolder + File.separator;
        if (cname.length > 0)
        {
            for (int i = 0, n = cname.length - 1; i < n; i++)
            {
                sdirPath += cname[i] + File.separator;
            }

            if (createDirs)
            {
                File sdir = new File(sdirPath);
                if (!sdir.exists())
                    sdir.mkdirs();
            }

            qname = cname[cname.length - 1];
        }

        return new File(sdirPath + qname + "." + project.getBackend().getOutputExtension() + ".map");
    }

    /**
     * Mxmlc uses target file as the main compilation unit and derive the output
     * SWF file name from this file.
     * 
     * @return true if successful, false otherwise.
     * @throws InterruptedException
     */
    @Override
    protected boolean setupTargetFile() throws InterruptedException
    {
        config.getTargetFile();

        ITargetSettings settings = getTargetSettings();
        if (settings != null)
            project.setTargetSettings(settings);
        else
            return false;

        target = project.getBackend().createTarget(project,
                getTargetSettings(), null);

        return true;
    }

    private ITargetSettings getTargetSettings()
    {
        if (targetSettings == null)
            targetSettings = projectConfigurator.getTargetSettings(getTargetType());

        if (targetSettings == null)
            problems.addAll(projectConfigurator.getConfigurationProblems());

        return targetSettings;
    }

    /**
     * Validate target file.
     * 
     * @throws MustSpecifyTarget
     * @throws IOError
     */
    @Override
    protected void validateTargetFile() throws ConfigurationException
    {

    }

    protected String getProgramName()
    {
        return "compc";
    }

    protected boolean isCompc()
    {
        return true;
    }

    @Override
    protected TargetType getTargetType()
    {
        return TargetType.SWC;
    }

    @Override
    public List getSourceList()
    {
        ArrayList list = new ArrayList();
        try
        {
            Collection errors = new ArrayList();
            Collection roots = ((RoyaleSWCTarget)target).getReachableCompilationUnits(errors);
            Collection units = project.getReachableCompilationUnitsInSWFOrder(roots);
            for (ICompilationUnit unit : units)
            {
                UnitType ut = unit.getCompilationUnitType();
                if (ut == UnitType.AS_UNIT || ut == UnitType.MXML_UNIT)
                {
                    list.add(unit.getAbsoluteFilename());
                }
            }
        }
        catch (InterruptedException e)
        {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        
        return list;
    }

    @Override
    public String getMainSource()
    {
        return null;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy