blob: 933d9a6869ff6190cd7babc85c66ac7953ce0cbb [file] [log] [blame]
/*
*
* 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.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.royale.abc.ABCConstants;
import org.apache.royale.abc.instructionlist.InstructionList;
import org.apache.royale.abc.semantics.Label;
import org.apache.royale.abc.semantics.Name;
import org.apache.royale.abc.visitors.ITraitVisitor;
import org.apache.royale.abc.visitors.ITraitsVisitor;
import org.apache.royale.compiler.common.VersionInfo;
import org.apache.royale.compiler.config.RSLSettings;
import org.apache.royale.compiler.config.RSLSettings.RSLAndPolicyFileURLPair;
import org.apache.royale.compiler.constants.IASLanguageConstants;
import org.apache.royale.compiler.constants.IMetaAttributeConstants;
import org.apache.royale.compiler.definitions.IDefinition;
import org.apache.royale.compiler.definitions.metadata.IMetaTag;
import org.apache.royale.compiler.definitions.references.IResolvedQualifiersReference;
import org.apache.royale.compiler.definitions.references.ReferenceFactory;
import org.apache.royale.compiler.internal.abc.ClassGeneratorHelper;
import org.apache.royale.compiler.internal.as.codegen.LexicalScope;
import org.apache.royale.compiler.internal.config.FrameInfo;
import org.apache.royale.compiler.internal.definitions.ClassDefinition;
import org.apache.royale.compiler.internal.definitions.NamespaceDefinition;
import org.apache.royale.compiler.internal.projects.RoyaleProject;
import org.apache.royale.compiler.internal.targets.Target.DirectDependencies;
import org.apache.royale.compiler.mxml.IMXMLTypeConstants;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.compiler.problems.InvalidBackgroundColorProblem;
import org.apache.royale.compiler.problems.MissingSignedDigestProblem;
import org.apache.royale.compiler.problems.MissingUnsignedDigestProblem;
import org.apache.royale.compiler.targets.ITargetSettings;
import org.apache.royale.compiler.tree.as.IASNode;
import org.apache.royale.compiler.units.ICompilationUnit;
import org.apache.royale.compiler.units.requests.IFileScopeRequestResult;
import org.apache.royale.swc.ISWC;
import org.apache.royale.swc.ISWCDigest;
import org.apache.royale.swc.ISWCLibrary;
import org.apache.royale.swc.ISWCManager;
import org.apache.royale.swf.ISWF;
import org.apache.royale.swf.tags.ProductInfoTag;
import org.apache.royale.swf.tags.ProductInfoTag.Edition;
import org.apache.royale.swf.tags.ProductInfoTag.Product;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterables;
import static org.apache.royale.compiler.mxml.IMXMLLanguageConstants.*;
/**
* Delegate class used by Royale specific targets to generate Royale specific code.
* If we were writing this compiler in C++ this would be a mix-in class.
*/
public abstract class RoyaleTarget
{
public RoyaleTarget(ITargetSettings targetSettings, RoyaleProject project)
{
royaleProject = project;
this.targetSettings = targetSettings;
accessibleClassNames = new HashSet<String>();
}
protected final RoyaleProject royaleProject;
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(royaleProject.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(royaleProject.getWorkspace(),
NamespaceDefinition.getAS3NamespaceDefinition(), "apply");
IResolvedQualifiersReference getDefinitionByNameReference =
ReferenceFactory.packageQualifiedReference(royaleProject.getWorkspace(), IASLanguageConstants.getDefinitionByName);
IResolvedQualifiersReference iFlexModule =
ReferenceFactory.packageQualifiedReference(royaleProject.getWorkspace(), IMXMLTypeConstants.IFlexModule);
boolean codegenIFlexModule = iFlexModule.resolve(royaleProject) != 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.
* @param remoteClassAliasMap
* @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,
RoyaleFrame1Info frame1Info,
Set<String> accessibilityClassNames,
String royaleInitClassName,
String stylesClassName,
List<String> rsls,
FlexRSLInfo rslInfo,
Collection<ICompilerProblem> problemCollection,
boolean isAppFlexInfo,
boolean isFlexSDKInfo,
Map<ClassDefinition, String> remoteClassAliasMap)
throws InterruptedException
{
IResolvedQualifiersReference applicationDomainRef = ReferenceFactory.packageQualifiedReference(royaleProject.getWorkspace(),
IASLanguageConstants.ApplicationDomain);
IResolvedQualifiersReference infoSlotReference;
if (isAppFlexInfo)
{
NamespaceDefinition.IStaticProtectedNamespaceDefinition staticNSDef = NamespaceDefinition.createStaticProtectedNamespaceDefinition("");
infoSlotReference = ReferenceFactory.resolvedQualifierQualifiedReference(royaleProject.getWorkspace(),
staticNSDef, "_info");
}
else
{
NamespaceDefinition.IPrivateNamespaceDefinition privateNSDef = NamespaceDefinition.createPrivateNamespaceDefinition("");
infoSlotReference = ReferenceFactory.resolvedQualifierQualifiedReference(royaleProject.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++;
}
// royaleVersion:
if (compatibilityVersion != null)
{
info.addInstruction(ABCConstants.OP_pushstring, "royaleVersion");
info.addInstruction(ABCConstants.OP_pushstring, compatibilityVersion);
infoEntries++;
}
// mark this SWF as being built with Royale
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(royaleProject) != null)
{
info.addInstruction(ABCConstants.OP_pushstring, ATTRIBUTE_PRELOADER);
info.addInstruction(ABCConstants.OP_getlex, preloaderReference.getMName());
infoEntries++;
}
// runtimeDPIProvider:
if (runtimeDPIProviderReference != null && runtimeDPIProviderReference.resolve(royaleProject) != 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 (royaleInitClassName != null)
{
info.addInstruction(ABCConstants.OP_pushstring, "mixins");
info.addInstruction(ABCConstants.OP_pushstring, royaleInitClassName);
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++;
}
if (remoteClassAliasMap != null && !remoteClassAliasMap.isEmpty())
{
info.addInstruction(ABCConstants.OP_pushstring, "remoteClassAliases");
for (Map.Entry<ClassDefinition, String> classAliasEntry : remoteClassAliasMap.entrySet())
{
info.addInstruction(ABCConstants.OP_pushstring, classAliasEntry.getKey().getQualifiedName());
info.addInstruction(ABCConstants.OP_convert_s);
String value = classAliasEntry.getValue();
info.addInstruction(ABCConstants.OP_pushstring, value);
}
info.addInstruction(ABCConstants.OP_newobject, remoteClassAliasMap.size());
infoEntries++;
}
// fonts:
if (!frame1Info.embeddedFonts.isEmpty())
{
info.addInstruction(ABCConstants.OP_pushstring, "fonts");
for (Entry<String, RoyaleFontInfo> entry : frame1Info.embeddedFonts.entrySet())
{
info.addInstruction(ABCConstants.OP_pushstring, entry.getKey());
info.addInstruction(ABCConstants.OP_convert_s);
RoyaleFontInfo 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 = royaleProject.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 = royaleProject.getWorkspace().getSWCManager();
info.addInstruction(ABCConstants.OP_pushstring, entryLabel);
IResolvedQualifiersReference mxCoreRSLDataReference =
ReferenceFactory.packageQualifiedReference(royaleProject.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(royaleProject.getWorkspace(),
accessibilityClass);
assert ref != null;
// Collect a list of classes to add to the info structure.
accessibleClassNames.add(accessibilityClass);
IDefinition accessibilityClassDefinition = ref.resolve(royaleProject);
if ((accessibilityClassDefinition != null) && (!accessibilityClassDefinition.isImplicit()))
{
ICompilationUnit cu = royaleProject.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.ROYALE,
Edition.NONE,
(byte)Integer.parseInt(VersionInfo.FLEX_MAJOR_VERSION),
(byte)Integer.parseInt(VersionInfo.FLEX_MINOR_VERSION),
VersionInfo.getBuildLong(),
0);
swf.setProductInfo(productInfo);
}
}