/* * * 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.targets; import java.io.File; import java.util.Collection; import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.Map.Entry; import org.apache.flex.abc.ABCConstants; import org.apache.flex.abc.instructionlist.InstructionList; import org.apache.flex.abc.semantics.Label; import org.apache.flex.abc.semantics.Name; import org.apache.flex.abc.visitors.ITraitVisitor; import org.apache.flex.abc.visitors.ITraitsVisitor; import org.apache.flex.compiler.common.VersionInfo; import org.apache.flex.compiler.config.RSLSettings; import org.apache.flex.compiler.config.RSLSettings.RSLAndPolicyFileURLPair; import org.apache.flex.compiler.constants.IASLanguageConstants; import org.apache.flex.compiler.constants.IMetaAttributeConstants; import org.apache.flex.compiler.definitions.IDefinition; import org.apache.flex.compiler.definitions.metadata.IMetaTag; import org.apache.flex.compiler.definitions.references.IResolvedQualifiersReference; import org.apache.flex.compiler.definitions.references.ReferenceFactory; import org.apache.flex.compiler.internal.abc.ClassGeneratorHelper; import org.apache.flex.compiler.internal.as.codegen.LexicalScope; import org.apache.flex.compiler.internal.config.FrameInfo; import org.apache.flex.compiler.internal.definitions.NamespaceDefinition; import org.apache.flex.compiler.internal.projects.FlexProject; import org.apache.flex.compiler.internal.targets.Target.DirectDependencies; import org.apache.flex.compiler.mxml.IMXMLTypeConstants; import org.apache.flex.compiler.problems.ICompilerProblem; import org.apache.flex.compiler.problems.InvalidBackgroundColorProblem; import org.apache.flex.compiler.problems.MissingSignedDigestProblem; import org.apache.flex.compiler.problems.MissingUnsignedDigestProblem; import org.apache.flex.compiler.targets.ITargetSettings; import org.apache.flex.compiler.tree.as.IASNode; import org.apache.flex.compiler.units.ICompilationUnit; import org.apache.flex.compiler.units.requests.IFileScopeRequestResult; import org.apache.flex.swc.ISWC; import org.apache.flex.swc.ISWCDigest; import org.apache.flex.swc.ISWCLibrary; import org.apache.flex.swc.ISWCManager; import org.apache.flex.swf.ISWF; import org.apache.flex.swf.tags.ProductInfoTag; import org.apache.flex.swf.tags.ProductInfoTag.Edition; import org.apache.flex.swf.tags.ProductInfoTag.Product; import com.google.common.collect.ImmutableList; import com.google.common.collect.Iterables; import static org.apache.flex.compiler.mxml.IMXMLLanguageConstants.*; /** * Delegate class used by flex specific targets to generate flex specific code. * If we were writing this compiler in C++ this would be a mix-in class. */ public abstract class FlexTarget { FlexTarget(ITargetSettings targetSettings, FlexProject project) { flexProject = project; this.targetSettings = targetSettings; accessibleClassNames = new HashSet<String>(); } protected final FlexProject flexProject; private final ITargetSettings targetSettings; /** * {@link Set} of classes referenced from accessibility meta-data. * <p> * For Example: * <p> * {@code [AccessibilityClass(implementation="mx.accessibility.ButtonAccImpl")]} * <p> * This set is accumulated as we discover direct dependencies, which is not as * maintainable as I would like. */ protected final HashSet<String> accessibleClassNames; /** * Codegen IFlexModuleFactory.callInContext(); * * public final override function callInContext(fn:Function, thisArg:Object, argArray:Array, returns:Boolean=true) : * * { * var ret : * = fn.apply(thisArg, argArray); * if (returns) return ret; * return; * } * * @param classGen * @param isOverride true if the generated method overrides a base class * method, false otherwise. */ protected final void codegenCallInContextMethod(ClassGeneratorHelper classGen, boolean isOverride) { IResolvedQualifiersReference applyReference = ReferenceFactory.resolvedQualifierQualifiedReference(flexProject.getWorkspace(), NamespaceDefinition.getAS3NamespaceDefinition(), "apply"); InstructionList callInContext = new InstructionList(); callInContext.addInstruction(ABCConstants.OP_getlocal1); callInContext.addInstruction(ABCConstants.OP_getlocal2); callInContext.addInstruction(ABCConstants.OP_getlocal3); callInContext.addInstruction(ABCConstants.OP_callproperty, new Object[] {applyReference.getMName(), 2}); callInContext.addInstruction(ABCConstants.OP_getlocal, 4); Label callInContextReturnVoid = new Label(); callInContext.addInstruction(ABCConstants.OP_iffalse, callInContextReturnVoid); callInContext.addInstruction(ABCConstants.OP_returnvalue); callInContext.labelNext(callInContextReturnVoid); // TODO This should be OP_returnvoid, but the Boolean default value // for the 'returns' parameter isn't defaulting to true. // Fix this after CMP-936 is fixed. callInContext.addInstruction(ABCConstants.OP_returnvalue); ImmutableList<Name> callInContextParams = new ImmutableList.Builder<Name>() .add(new Name(IASLanguageConstants.Function)) .add(new Name(IASLanguageConstants.Object)) .add(new Name(IASLanguageConstants.Array)) .add(new Name(IASLanguageConstants.Boolean)) .build(); classGen.addITraitsMethod(new Name("callInContext"), callInContextParams, null, Collections.<Object> singletonList(Boolean.TRUE), false, true, isOverride, callInContext); } /** * Codegen IFlexModuleFactory.create() override public function create(... * params):Object { var mainClass : Class; if (params.length <= 0) { * mainClass = getlex MainApplicationClass } else if (params[0] is String) { * mainClass = getDefinitionByName(params[0]) } else return * super.create.apply(this, params); if (!mainClass) return null; var * instance:Object = new mainClass(); if (instance is IFlexModule) * (IFlexModule(instance)).moduleFactory = this; return instance; } * * @param classGen * @param mainApplicationName {@link Name} that will refer to the main * application class at runtme. May not be null but a library.swf for a SWC * may pass in a {@link Name} that resolves to "Object" at runtime. */ protected final void codegenCreateMethod(ClassGeneratorHelper classGen, Name mainApplicationName, boolean isFlexSDKInfo) { IResolvedQualifiersReference applyReference = ReferenceFactory.resolvedQualifierQualifiedReference(flexProject.getWorkspace(), NamespaceDefinition.getAS3NamespaceDefinition(), "apply"); IResolvedQualifiersReference getDefinitionByNameReference = ReferenceFactory.packageQualifiedReference(flexProject.getWorkspace(), IASLanguageConstants.getDefinitionByName); IResolvedQualifiersReference iFlexModule = ReferenceFactory.packageQualifiedReference(flexProject.getWorkspace(), IMXMLTypeConstants.IFlexModule); boolean codegenIFlexModule = iFlexModule.resolve(flexProject) != null && isFlexSDKInfo; Name getDefinitionByName = getDefinitionByNameReference.getMName(); InstructionList create = new InstructionList(); create.addInstruction(ABCConstants.OP_getlocal1); create.addInstruction(ABCConstants.OP_getproperty, new Name("length")); create.addInstruction(ABCConstants.OP_pushbyte, 0); Label createL1 = new Label(); create.addInstruction(ABCConstants.OP_ifgt, createL1); create.addInstruction(ABCConstants.OP_findproperty, mainApplicationName); create.addInstruction(ABCConstants.OP_getproperty, mainApplicationName); Label createL3 = new Label(); create.addInstruction(ABCConstants.OP_jump, createL3); create.labelNext(createL1); create.addInstruction(ABCConstants.OP_getlocal1); create.addInstruction(ABCConstants.OP_getproperty, new Name("0")); create.addInstruction(ABCConstants.OP_istype, new Name("String")); Label createL2 = new Label(); create.addInstruction(ABCConstants.OP_iffalse, createL2); create.addInstruction(ABCConstants.OP_finddef, getDefinitionByName); create.addInstruction(ABCConstants.OP_getlocal1); create.addInstruction(ABCConstants.OP_getproperty, new Name("0")); create.addInstruction(ABCConstants.OP_callproperty, new Object[] {getDefinitionByName, 1}); create.addInstruction(ABCConstants.OP_jump, createL3); create.labelNext(createL2); create.addInstruction(ABCConstants.OP_getlocal0); create.addInstruction(ABCConstants.OP_getsuper, new Name("create")); create.addInstruction(ABCConstants.OP_getlocal0); create.addInstruction(ABCConstants.OP_getlocal1); create.addInstruction(ABCConstants.OP_callproperty, new Object[] {applyReference.getMName(), 2}); create.addInstruction(ABCConstants.OP_returnvalue); create.labelNext(createL3); create.addInstruction(ABCConstants.OP_astype, new Name("Class")); create.addInstruction(ABCConstants.OP_dup); Label createL5 = new Label(); create.addInstruction(ABCConstants.OP_iffalse, createL5); create.addInstruction(ABCConstants.OP_construct, 0); if (codegenIFlexModule) { create.addInstruction(ABCConstants.OP_dup); create.addInstruction(ABCConstants.OP_istype, iFlexModule.getMName()); Label createL4 = new Label(); create.addInstruction(ABCConstants.OP_iffalse, createL4); create.addInstruction(ABCConstants.OP_dup); create.addInstruction(ABCConstants.OP_getlocal0); create.addInstruction(ABCConstants.OP_setproperty, new Name("moduleFactory")); create.labelNext(createL4); create.addInstruction(ABCConstants.OP_returnvalue); } create.labelNext(createL5); create.addInstruction(ABCConstants.OP_returnvalue); classGen.addITraitsMethod(new Name("create"), Collections.<Name> emptyList(), new Name("Object"), Collections.emptyList(), true, true, true, create); } /** * Codegen the IFlexModuleFactory.info() method. * * public override final function info() : Object * { * if (!_info) * { * _info = { * currentDomain : ApplicationDomain.currentDomain * . * . * . * } * } * } * * @param classGen used to create the function * @param compatibilityVersion compatibility version set in the compiler option. * May be null if not configured. * @param mainClassQName qName of the main class of the application. May be null * of library swfs. * @param preloaderReference reference to the configured preloader class. * May be null for library swfs. * @param runtimeDPIProviderReference configured runtimeDPIProvider. May be null * for library swfs. * @param splashScreen reference to the configured splash screen. * @param rootNode root node of the application. May be null for library swfs. * @param compiledLocales the locales supported by this application. May be null for * library swfs. * @param rsls legacy RSLs. May be null for library swfs. * @param problemCollection problems found when generating the info method * are added to the collection. * @throws InterruptedException */ protected final void codegenInfoMethod(ClassGeneratorHelper classGen, Integer compatibilityVersion, String mainClassQName, IResolvedQualifiersReference preloaderReference, IResolvedQualifiersReference runtimeDPIProviderReference, FlexSplashScreenImage splashScreen, IASNode rootNode, ITargetAttributes targetAttributes, Collection<String> compiledLocales, FlexFrame1Info frame1Info, Set<String> accessibilityClassNames, String flexInitClassName, String stylesClassName, List<String> rsls, FlexRSLInfo rslInfo, Collection<ICompilerProblem> problemCollection, boolean isAppFlexInfo, boolean isFlexSDKInfo) throws InterruptedException { IResolvedQualifiersReference applicationDomainRef = ReferenceFactory.packageQualifiedReference(flexProject.getWorkspace(), IASLanguageConstants.ApplicationDomain); IResolvedQualifiersReference infoSlotReference; if (isAppFlexInfo) { NamespaceDefinition.IStaticProtectedNamespaceDefinition staticNSDef = NamespaceDefinition.createStaticProtectedNamespaceDefinition(""); infoSlotReference = ReferenceFactory.resolvedQualifierQualifiedReference(flexProject.getWorkspace(), staticNSDef, "_info"); } else { NamespaceDefinition.IPrivateNamespaceDefinition privateNSDef = NamespaceDefinition.createPrivateNamespaceDefinition(""); infoSlotReference = ReferenceFactory.resolvedQualifierQualifiedReference(flexProject.getWorkspace(), privateNSDef, "info"); } Name infoSlotName = infoSlotReference.getMName(); InstructionList info = new InstructionList(); info.addInstruction(ABCConstants.OP_getlocal0); info.addInstruction(ABCConstants.OP_getproperty, infoSlotName); info.addInstruction(ABCConstants.OP_dup); Label infoL1 = new Label(); info.addInstruction(ABCConstants.OP_iftrue, infoL1); int infoEntries = 0; // currentDomain: info.addInstruction(ABCConstants.OP_pop); info.addInstruction(ABCConstants.OP_pushstring, "currentDomain"); info.addInstruction(ABCConstants.OP_getlex, applicationDomainRef.getMName()); info.addInstruction(ABCConstants.OP_getproperty, new Name("currentDomain")); infoEntries++; // frames: if (targetSettings.getFrameLabels() != null && !targetSettings.getFrameLabels().isEmpty()) { Collection<FrameInfo> frames = targetSettings.getFrameLabels(); info.addInstruction(ABCConstants.OP_pushstring, "frames"); for (FrameInfo frame : frames) { info.addInstruction(ABCConstants.OP_pushstring, frame.getLabel()); info.addInstruction(ABCConstants.OP_convert_s); info.addInstruction(ABCConstants.OP_pushstring, frame.getFrameClasses().get(0)); } info.addInstruction(ABCConstants.OP_newobject, frames.size()); infoEntries++; } // flexVersion: if (compatibilityVersion != null) { info.addInstruction(ABCConstants.OP_pushstring, "flexVersion"); info.addInstruction(ABCConstants.OP_pushstring, compatibilityVersion); infoEntries++; } // mark this SWF as being built with Falcon info.addInstruction(ABCConstants.OP_pushstring, "isMXMLC"); info.addInstruction(ABCConstants.OP_pushfalse); infoEntries++; // mainClassName: if (mainClassQName != null) { info.addInstruction(ABCConstants.OP_pushstring, "mainClassName"); info.addInstruction(ABCConstants.OP_pushstring, mainClassQName); infoEntries++; } if (!isAppFlexInfo && isFlexSDKInfo) { // preloader: if (preloaderReference != null && preloaderReference.resolve(flexProject) != null) { info.addInstruction(ABCConstants.OP_pushstring, ATTRIBUTE_PRELOADER); info.addInstruction(ABCConstants.OP_getlex, preloaderReference.getMName()); infoEntries++; } // runtimeDPIProvider: if (runtimeDPIProviderReference != null && runtimeDPIProviderReference.resolve(flexProject) != null) { info.addInstruction(ABCConstants.OP_pushstring, ATTRIBUTE_RUNTIME_DPI_PROVIDER); info.addInstruction(ABCConstants.OP_getlex, runtimeDPIProviderReference.getMName()); infoEntries++; } // splashScreenImage: if (splashScreen.generatedEmbedClassReference != null) { info.addInstruction(ABCConstants.OP_pushstring, ATTRIBUTE_SPLASH_SCREEN_IMAGE); info.addInstruction(ABCConstants.OP_getlex, splashScreen.generatedEmbedClassReference.getMName()); infoEntries++; } // Add various root node attributes: infoEntries += codegenRootNodeAttributes(targetAttributes, info, rootNode, problemCollection); // compiledLocales: if (compiledLocales != null) { info.addInstruction(ABCConstants.OP_pushstring, "compiledLocales"); for(String locale : compiledLocales) info.addInstruction(ABCConstants.OP_pushstring, locale); info.addInstruction(ABCConstants.OP_newarray, compiledLocales.size()); infoEntries++; } // compiledResourceBundleNames: if (!frame1Info.compiledResourceBundleNames.isEmpty()) { info.addInstruction(ABCConstants.OP_pushstring, "compiledResourceBundleNames"); for(String bundleName : frame1Info.compiledResourceBundleNames) info.addInstruction(ABCConstants.OP_pushstring, bundleName); info.addInstruction(ABCConstants.OP_newarray, frame1Info.compiledResourceBundleNames.size()); infoEntries++; } } // styleDataClassName if (stylesClassName != null) { info.addInstruction(ABCConstants.OP_pushstring, "styleDataClassName"); info.addInstruction(ABCConstants.OP_pushstring, stylesClassName); infoEntries++; } // mixins: if (flexInitClassName != null) { info.addInstruction(ABCConstants.OP_pushstring, "mixins"); info.addInstruction(ABCConstants.OP_pushstring, flexInitClassName); int mixinEntries = 1; final Set<String> mixinClassNames = frame1Info.getMixins(); for (String className : frame1Info.getMixins()) info.addInstruction(ABCConstants.OP_pushstring, className); mixinEntries += mixinClassNames.size(); info.addInstruction(ABCConstants.OP_newarray, mixinEntries); infoEntries++; } // fonts: if (!frame1Info.embeddedFonts.isEmpty()) { info.addInstruction(ABCConstants.OP_pushstring, "fonts"); for (Entry<String, FlexFontInfo> entry : frame1Info.embeddedFonts.entrySet()) { info.addInstruction(ABCConstants.OP_pushstring, entry.getKey()); info.addInstruction(ABCConstants.OP_convert_s); FlexFontInfo fontInfo = entry.getValue(); info.addInstruction(ABCConstants.OP_pushstring, "regular"); info.addInstruction(fontInfo.regularOp); info.addInstruction(ABCConstants.OP_pushstring, "bold"); info.addInstruction(fontInfo.boldOp); info.addInstruction(ABCConstants.OP_pushstring, "italic"); info.addInstruction(fontInfo.italicOp); info.addInstruction(ABCConstants.OP_pushstring, "boldItalic"); info.addInstruction(fontInfo.boldItalicOp); info.addInstruction(ABCConstants.OP_newobject, 4); } info.addInstruction(ABCConstants.OP_newobject, frame1Info.embeddedFonts.size()); infoEntries++; } // accessibility classes if (accessibilityClassNames != null && accessibilityClassNames.size() > 0) { info.addInstruction(ABCConstants.OP_pushstring, "accessibilityClassNames"); for (String className : accessibilityClassNames) info.addInstruction(ABCConstants.OP_pushstring, className); info.addInstruction(ABCConstants.OP_newarray, accessibilityClassNames.size()); infoEntries++; } // cdRSLs and placeholderRSLs: if (!rslInfo.requiredRSLs.isEmpty()) { // Note: The Flex framework spells this info property as Rsl, not RSL. if (codegenRSLsEntry(info, problemCollection, "cdRsls", rslInfo.requiredRSLs)) infoEntries++; // Note: The Flex framework spells this info property as Rsl, not RSL. if (codegenRSLsEntry(info, problemCollection, "placeholderRsls", rslInfo.placeholderRSLs)) infoEntries++; } // rsls: if (codegenLegacyRSLs(info, rsls)) infoEntries++; // Create a new info object from all of the entries. info.addInstruction(ABCConstants.OP_newobject, infoEntries); info.addInstruction(ABCConstants.OP_dup); info.addInstruction(ABCConstants.OP_getlocal0); info.addInstruction(ABCConstants.OP_swap); info.addInstruction(ABCConstants.OP_setproperty, infoSlotName); info.labelNext(infoL1); info.addInstruction(ABCConstants.OP_returnvalue); ITraitsVisitor itraitsVisitor; ITraitVisitor infoSlotVisitor; if (isAppFlexInfo) { classGen.addCTraitsMethod(new Name("info"), Collections.<Name> emptyList(), new Name("Object"), Collections.emptyList(), false, info); itraitsVisitor = classGen.getCTraitsVisitor(); infoSlotVisitor = itraitsVisitor.visitSlotTrait(ABCConstants.TRAIT_Var, infoSlotName, ITraitsVisitor.RUNTIME_SLOT, new Name(IASLanguageConstants.Object), LexicalScope.noInitializer); } else { classGen.addITraitsMethod(new Name("info"), Collections.<Name> emptyList(), new Name("Object"), Collections.emptyList(), false, true, true, info); itraitsVisitor = classGen.getITraitsVisitor(); infoSlotVisitor = itraitsVisitor.visitSlotTrait(ABCConstants.TRAIT_Var, infoSlotName, ITraitsVisitor.RUNTIME_SLOT, new Name(IASLanguageConstants.Object), LexicalScope.noInitializer); } infoSlotVisitor.visitStart(); infoSlotVisitor.visitEnd(); } /** * Generate code to add root node attributes to the info object that haven't * already been handled. * * @param info * @return number of entries added to the info object * @throws InterruptedException */ private int codegenRootNodeAttributes(ITargetAttributes targetAttributes, InstructionList info, IASNode rootNode, Collection<ICompilerProblem> problemCollection) throws InterruptedException { // Number of attributes added to the "info" object. int entries = 0; // Emit "info" attributes that don't require special processing. final Map<String, String> attributes = targetAttributes.getRootInfoAttributes(); for (final Map.Entry<String, String> e : attributes.entrySet()) { info.addInstruction(ABCConstants.OP_pushstring, e.getKey()); info.addInstruction(ABCConstants.OP_pushstring, e.getValue()); entries++; } // Emit "info.usePreloader" as a boolean value. final Boolean usePreloader = targetAttributes.getUsePreloader(); if (usePreloader != null) { info.addInstruction(ABCConstants.OP_pushstring, ATTRIBUTE_USE_PRELOADER); info.addInstruction(usePreloader ? ABCConstants.OP_pushtrue : ABCConstants.OP_pushfalse); entries++; } // Emit "info.backgroundColor" as a hex string value. final String backgroundColorString = targetAttributes.getBackgroundColor(); if (backgroundColorString != null) { try { final int backgroundColor = flexProject.getColorAsInt(backgroundColorString); final String hexString = "0x" + Integer.toHexString(backgroundColor).toUpperCase(); info.addInstruction(ABCConstants.OP_pushstring, ATTRIBUTE_BACKGROUND_COLOR); info.addInstruction(ABCConstants.OP_pushstring, hexString); entries++; } catch (NumberFormatException numberFormatExpression) { problemCollection.add(new InvalidBackgroundColorProblem( rootNode.getFileSpecification().getPath(), backgroundColorString)); } } return entries; } /** * Generate either the "cdRsls" or "placeholderRsls" entry in the * IFlexModuleFactory info function. * * @param info * @param problemCollection * @param entryLabel the "info" entry label * @param rslSettingsList the rsls for the entry * * @return true if instructions were added for the RSLs, false otherwise. */ private boolean codegenRSLsEntry(InstructionList info, Collection<ICompilerProblem> problemCollection, String entryLabel, List<RSLSettings> rslSettingsList) { ISWCManager swcManager = flexProject.getWorkspace().getSWCManager(); info.addInstruction(ABCConstants.OP_pushstring, entryLabel); IResolvedQualifiersReference mxCoreRSLDataReference = ReferenceFactory.packageQualifiedReference(flexProject.getWorkspace(), IMXMLTypeConstants.RSLData); Name mxCoreRSLDataSlotName = mxCoreRSLDataReference.getMName(); Object[] mxCoreRSLDataCtor = new Object[] { mxCoreRSLDataSlotName, 7 }; // Add an RSLData instance to an array for the primary RSL in RSLSettings // plus one for every failover RSL. for (RSLSettings rslSettings : rslSettingsList) { int rslCount = 0; for (RSLAndPolicyFileURLPair urls : rslSettings.getRSLURLs()) { info.addInstruction(ABCConstants.OP_findpropstrict, mxCoreRSLDataSlotName); info.addInstruction(ABCConstants.OP_pushstring, urls.getRSLURL()); info.addInstruction(ABCConstants.OP_pushstring, urls.getPolicyFileURL()); ISWC swc = swcManager.get(new File(rslSettings.getLibraryFile().getPath())); boolean isSignedRSL = RSLSettings.isSignedRSL(urls.getRSLURL()); ISWCDigest swcDigest = getSWCDigest(Iterables.getFirst(swc.getLibraries(), null), isSignedRSL); if (swcDigest == null) { if (isSignedRSL) problemCollection.add(new MissingSignedDigestProblem(swc.getSWCFile().getAbsolutePath())); else problemCollection.add(new MissingUnsignedDigestProblem(swc.getSWCFile().getAbsolutePath())); continue; } info.addInstruction(ABCConstants.OP_pushstring, swcDigest.getValue()); info.addInstruction(ABCConstants.OP_pushstring, swcDigest.getType()); info.addInstruction(isSignedRSL ? ABCConstants.OP_pushtrue : ABCConstants.OP_pushfalse); info.addInstruction(rslSettings.getVerifyDigest() ? ABCConstants.OP_pushtrue : ABCConstants.OP_pushfalse); info.addInstruction(ABCConstants.OP_pushstring, rslSettings.getApplicationDomain().getApplicationDomainValue()); info.addInstruction(ABCConstants.OP_constructprop, mxCoreRSLDataCtor); rslCount++; } info.addInstruction(ABCConstants.OP_newarray, rslCount); } info.addInstruction(ABCConstants.OP_newarray, rslSettingsList.size()); return true; } /** * Get either a signed or unsigned digest from the library. * * @param swcLibrary * @param signedDigest if true return a signed digest, otherwise an unsigned digest. * @return A signed or unsigned digest. Null if the requested digest is not * available. */ private ISWCDigest getSWCDigest(ISWCLibrary swcLibrary, boolean signedDigest) { for (ISWCDigest swcDigest : swcLibrary.getDigests()) { if (swcDigest.isSigned() == signedDigest) return swcDigest; } return null; } /** * rsls: [{url: "rsl1.swf", size: -1}, {url: "rsl2.swf", size: -1}, {url: "rsl3.swf", size: -1}] * * @param info * @return */ private boolean codegenLegacyRSLs(InstructionList info, List<String> rsls) { if (rsls != null && rsls.size() > 0) { info.addInstruction(ABCConstants.OP_pushstring, "rsls"); for (String rsl : rsls) { info.addInstruction(ABCConstants.OP_pushstring, "url"); info.addInstruction(ABCConstants.OP_pushstring, rsl); info.addInstruction(ABCConstants.OP_pushstring, "size"); info.addInstruction(ABCConstants.OP_pushbyte, -1); info.addInstruction(ABCConstants.OP_newobject, 2); } info.addInstruction(ABCConstants.OP_newarray, rsls.size()); } return rsls != null && rsls.size() > 0; } static final Target.DirectDependencies NO_DEPENDENCIES = new Target.DirectDependencies(Collections.<ICompilationUnit>emptyList(), Collections.<ICompilerProblem>emptyList()); /** * Find the accessible compilation units on a set of compilation units. The * accessible compilation units are gathered from the * {@code [AccessiblityClass]} meta-data on a class. * <p> * Unfortunately this method has a side effect, it updates the set of * accessibility classes. * * @param compilationUnit A compilation unit. * @return A {@link DirectDependencies} object with the set of compilation * units representing the new compilation units needed for accessibility. If * no accessible compilation units are found or accessibility is not enabled * on the target, then the returned {@link DirectDependencies} object will * contain an empty set. */ public Target.DirectDependencies getAccessibilityDependencies(ICompilationUnit compilationUnit) throws InterruptedException { assert targetSettings.isAccessible() : "This method should only be called if accessibility is enabled!"; Set<ICompilationUnit> accessibleCompilationUnits = new HashSet<ICompilationUnit>(); IFileScopeRequestResult result = compilationUnit.getFileScopeRequest().get(); for(IDefinition def : result.getExternallyVisibleDefinitions()) { IMetaTag md = def.getMetaTagByName(IMetaAttributeConstants.ATTRIBUTE_ACCESSIBIlITY_CLASS); if (md == null) continue; String accessibilityClass = md.getAttributeValue(IMetaAttributeConstants.NAME_ACCESSIBILITY_IMPLEMENTATION); if (accessibilityClass == null) continue; IResolvedQualifiersReference ref = ReferenceFactory.packageQualifiedReference(flexProject.getWorkspace(), accessibilityClass); assert ref != null; // Collect a list of classes to add to the info structure. accessibleClassNames.add(accessibilityClass); IDefinition accessibilityClassDefinition = ref.resolve(flexProject); if ((accessibilityClassDefinition != null) && (!accessibilityClassDefinition.isImplicit())) { ICompilationUnit cu = flexProject.getScope().getCompilationUnitForDefinition(accessibilityClassDefinition); assert cu != null : "Unable to find compilation unit for definition!"; accessibleCompilationUnits.add(cu); } } return new Target.DirectDependencies(accessibleCompilationUnits, Collections.<ICompilerProblem>emptyList()); } /** * Update the SWF model by adding a ProductInfoTag. * * @param swf the swf model to update. */ public void addProductInfoToSWF(ISWF swf) { // Add product info to the swf. ProductInfoTag productInfo = new ProductInfoTag(Product.FLEX, Edition.NONE, (byte)Integer.parseInt(VersionInfo.FLEX_MAJOR_VERSION), (byte)Integer.parseInt(VersionInfo.FLEX_MINOR_VERSION), VersionInfo.getBuildLong(), 0); swf.setProductInfo(productInfo); } }