org.apache.flex.compiler.internal.driver.JSTarget.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.flex.compiler.internal.driver.JSTarget.java

Source

/*
 *
 *  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.flex.compiler.internal.driver;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.apache.flex.abc.ABCLinker.ABCLinkerSettings;
import org.apache.flex.compiler.clients.MXMLJSC;
import org.apache.flex.compiler.definitions.IDefinition;
import org.apache.flex.compiler.exceptions.BuildCanceledException;
import org.apache.flex.compiler.internal.as.codegen.JSGeneratingReducer;
import org.apache.flex.compiler.internal.as.codegen.JSSharedData;
import org.apache.flex.compiler.internal.definitions.DefinitionBase;
import org.apache.flex.compiler.internal.projects.CompilerProject;
import org.apache.flex.compiler.internal.targets.AppSWFTarget;
import org.apache.flex.compiler.internal.targets.Target;
import org.apache.flex.compiler.internal.units.ResourceBundleCompilationUnit;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.problems.UnableToBuildSWFTagProblem;
import org.apache.flex.compiler.targets.ITargetProgressMonitor;
import org.apache.flex.compiler.targets.ITargetSettings;
import org.apache.flex.compiler.units.ICompilationUnit;
import org.apache.flex.swf.ISWF;
import org.apache.flex.swf.SWFFrame;
import org.apache.flex.swf.tags.DoABCTag;

import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;

/**
 * Concrete implementation of ITarget for building a collection of source files
 * into a SWF.
 */

public class JSTarget extends AppSWFTarget {
    private ICompilationUnit mainCU;

    /**
     * Initialize a SWF target with the owner project and root compilation
     * units.
     * 
     * @param project the owner project
     */

    public JSTarget(CompilerProject project, ITargetSettings targetSettings,
            ITargetProgressMonitor progressMonitor) {
        super(project, targetSettings, progressMonitor);
    }

    /*
     * private void printDefinitionsFromCompilationUnit( ICompilationUnit cu )
     * throws InterruptedException { final List<IDefinition> defs =
     * MXMLJSC.getDefinitions(cu, true); String s = cu.toString() + ": " +
     * cu.getShortNames(); JSSharedData.instance.verboseMessage(s); }
     */

    protected void buildAndCollectProblems(final Set<ICompilationUnit> compilationUnits,
            final Collection<ICompilerProblem> problems) throws InterruptedException {
        final JSSharedData sharedData = JSSharedData.instance;
        sharedData.beginCodeGen();

        BuiltCompilationUnitSet builtCompilationUnits = getBuiltCompilationUnitSet();

        if (JSSharedData.OUTPUT_ISOLATED) {
            final ICompilationUnit rootCU = getRootClassCompilationUnit();
            compilationUnits.clear();
            compilationUnits.add(rootCU);
        } else {
            final List<ICompilationUnit> allUnits = new ArrayList<ICompilationUnit>();
            allUnits.addAll(project.getReachableCompilationUnitsInSWFOrder(builtCompilationUnits.compilationUnits));
            final List<ICompilationUnit> cuList = sortCompilationUnits(allUnits);
            compilationUnits.clear();
            for (ICompilationUnit cu : cuList)
                compilationUnits.add(cu);
        }
        sharedData.endCodeGen();
    }

    public ISWF build(ICompilationUnit mainCU, Collection<ICompilerProblem> problems) {
        this.mainCU = mainCU;
        return build(problems);
    }

    @Override
    public ISWF build(Collection<ICompilerProblem> problems) {
        buildStarted();
        try {
            Iterable<ICompilerProblem> fatalProblems = getFatalProblems();
            if (!Iterables.isEmpty(fatalProblems)) {
                Iterables.addAll(problems, fatalProblems);
                return null;
            }

            Set<ICompilationUnit> compilationUnitSet = new HashSet<ICompilationUnit>();
            Target.RootedCompilationUnits rootedCompilationUnits = getRootedCompilationUnits();
            Iterables.addAll(problems, rootedCompilationUnits.getProblems());

            compilationUnitSet.addAll(rootedCompilationUnits.getUnits());

            buildAndCollectProblems(compilationUnitSet, problems);

            List<ICompilationUnit> reachableCompilationUnits = project
                    .getReachableCompilationUnitsInSWFOrder(rootedCompilationUnits.getUnits());
            ISWF swf = initializeSWF(reachableCompilationUnits);

            // make main frame for DoABC tags
            final SWFFrame mainFrame = new SWFFrame();
            swf.addFrame(mainFrame);

            // Add definitions.
            for (final ICompilationUnit cu : compilationUnitSet) {
                // ignore externals
                if (isLinkageExternal(cu, targetSettings))
                    continue;

                // ignore any resource bundles
                if (cu instanceof ResourceBundleCompilationUnit)
                    continue;

                // Create a DoABC tag per compilation unit.

                // Please add this API to SWFTarget. Thx.
                // protected Boolean addToFrame(ICompilationUnit cu, SWFFrame mainFrame) throws InterruptedException
                // final boolean tagsAdded = cu.getSWFTagsRequest().get().addToFrame(mainFrame);
                final boolean tagsAdded = addToFrame(cu, mainFrame);
                if (!tagsAdded) {
                    ICompilerProblem problem = new UnableToBuildSWFTagProblem(cu.getAbsoluteFilename());
                    problems.add(problem);
                }
            }

            createLinkReport(problems);

            return swf;
        } catch (BuildCanceledException bce) {
            return null;
        } catch (InterruptedException ie) {
            return null;
        } finally {
            buildFinished();
        }
    }

    // Please add this API to SWFTarget. Thx.
    protected Boolean addToFrame(ICompilationUnit cu, SWFFrame mainFrame) throws InterruptedException {
        // SWFTarget's implementation:
        // return cu.getSWFTagsRequest().get().addToFrame(mainFrame);

        final JSSharedData sharedData = JSSharedData.instance;

        String code = "";
        final List<IDefinition> defs = MXMLJSC.getDefinitions(cu, false);
        for (IDefinition def : defs) {
            final String fullName = def.getQualifiedName();
            if (sharedData.hasJavaScript(fullName)) {
                final String jsCode = sharedData.getJavaScript(fullName);
                code += jsCode;
            }
        }

        if (!code.isEmpty()) {
            final DoABCTag abcTag = new DoABCTag();
            abcTag.setABCData(code.getBytes());
            mainFrame.addTag(abcTag);
        } else {
            return cu.getSWFTagsRequest().get().addToFrame(mainFrame);
        }
        sharedData.registerSWFFrame(mainFrame, cu);
        return true;
    }

    /**
     * sortCompilationUnits() is a workaround for DependencyGraph bugs. There
     * are three problem areas: 1. The order of the CUs is somewhat random
     * depending on the thread that compiled a CU. 2. Dependencies through
     * static initializers are not always correctly detected. 3. Dependencies to
     * classes provided by SWCs are not correctly detected.
     */
    public static List<ICompilationUnit> sortCompilationUnits(List<ICompilationUnit> frameCompilationUnits)
            throws InterruptedException {
        ICompilationUnit frameWorkCU = null;
        ICompilationUnit xmlCU = null;
        ICompilationUnit xmlListCU = null;

        // extract framework CU, AS3XML CU, and AS3XMLList CU from frameCompilationUnits
        Iterator<ICompilationUnit> it = frameCompilationUnits.iterator();
        while (it.hasNext()) {
            // get class name for compilation unit.
            ICompilationUnit cu = it.next();
            final List<IDefinition> defs = MXMLJSC.getDefinitions(cu, false);
            for (IDefinition def : defs) {
                final String fullName = JSGeneratingReducer.createFullNameFromDefinition(cu.getProject(), def);
                if (frameWorkCU == null && fullName.equals(JSSharedData.JS_FRAMEWORK_NAME)) {
                    frameWorkCU = cu;
                    it.remove();
                } else if (xmlCU == null && fullName.equals(JSSharedData.AS3XML)) {
                    xmlCU = cu;
                    it.remove();
                } else if (xmlListCU == null && fullName.equals(JSSharedData.AS3XMLList)) {
                    xmlListCU = cu;
                    it.remove();
                }

                if (def instanceof DefinitionBase) {
                    JSSharedData.instance.registerReferencedDefinition(def.getQualifiedName());
                }

                JSSharedData.instance.registerPackage(def.getPackageName());
            }
        }

        // insist on framework CU
        if (frameWorkCU == null)
            throw JSSharedData.backend.createException(
                    "JSTarget: cannot find " + JSSharedData.JS_FRAMEWORK_NAME + " compilation unit.");

        // add the framework CU at pos 0
        frameCompilationUnits.add(0, frameWorkCU);

        // add AS3XML and AS3XMLList framework CUs if necessary
        if (xmlCU != null) {
            // add the AS3XML CU at pos 1
            frameCompilationUnits.add(1, xmlCU);

            // insist on AS3XMLList CU
            if (xmlListCU == null)
                throw JSSharedData.backend
                        .createException("JSTarget: cannot find " + JSSharedData.AS3XMLList + " compilation unit.");

            // add the AS3XMLList CU at pos 2
            frameCompilationUnits.add(2, xmlListCU);
        }

        return frameCompilationUnits;
    }

    @Override
    public Target.RootedCompilationUnits computeRootedCompilationUnits() throws InterruptedException {
        if (mainCU != null) {
            return new Target.RootedCompilationUnits(ImmutableSet.of(mainCU),
                    Collections.<ICompilerProblem>emptyList());
        }

        assert false;
        return new Target.RootedCompilationUnits(Collections.<ICompilationUnit>emptySet(),
                Collections.<ICompilerProblem>emptyList());
    }

    @Override
    protected FramesInformation computeFramesInformation() throws InterruptedException {
        assert false;
        return null;
    }

    @Override
    protected void addLinkedABCToFrame(SWFFrame targetFrame, Iterable<DoABCTag> inputABCs,
            ABCLinkerSettings linkSettings) throws Exception {
        assert false;
    }

    @Override
    protected void setKeepAS3MetadataLinkerSetting(ABCLinkerSettings linkSettings) {
        assert false;
    }

}