| /* |
| * |
| * 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.projects; |
| |
| import static org.apache.royale.abc.ABCConstants.CONSTANT_PackageNs; |
| import static org.apache.royale.abc.ABCConstants.CONSTANT_Qname; |
| |
| import java.io.File; |
| import java.util.*; |
| |
| import org.apache.royale.abc.semantics.Name; |
| import org.apache.royale.abc.semantics.Namespace; |
| import org.apache.royale.abc.semantics.Nsset; |
| import org.apache.royale.compiler.config.Configuration; |
| import org.apache.royale.compiler.config.Configurator; |
| import org.apache.royale.compiler.fxg.flex.FlexFXG2SWFTranscoder; |
| import org.apache.royale.compiler.internal.as.codegen.BindableHelper; |
| import org.apache.royale.compiler.internal.config.RoyaleTargetSettings; |
| import org.apache.royale.compiler.internal.definitions.ClassDefinition; |
| import org.apache.royale.compiler.internal.embedding.transcoders.DataTranscoder; |
| import org.apache.royale.compiler.internal.units.FXGCompilationUnit; |
| import org.apache.royale.compiler.mxml.IMXMLTypeConstants; |
| import org.apache.royale.compiler.mxml.IMXMLNamespaceMapping; |
| import org.apache.royale.compiler.problems.ANELibraryNotAllowedProblem; |
| import org.apache.royale.compiler.projects.IRoyaleProject; |
| import org.apache.royale.compiler.projects.ICompilerProject; |
| import org.apache.royale.compiler.targets.ITargetSettings; |
| import org.apache.royale.swc.ISWC; |
| import org.apache.royale.utils.FilenameNormalization; |
| |
| /** |
| * This class applies configuration settings to a RoyaleProject. |
| * Currently the settings are hard-coded |
| * and only applied when the project is originally created. |
| * Eventually they will come from royale-config.xml |
| * and this class will support updating with new configuration values. |
| */ |
| public class RoyaleProjectConfigurator extends Configurator |
| { |
| /** |
| * These imports will eventually come from royale-config.xml. |
| * <p> |
| * Note taht we include AIR-specific imports even for non-AIR projects. |
| * This does not cause compiler warnings about unknown imports |
| * in non-AIR projects because the implicit imports don't get |
| * semantically checked. |
| * The AIR imports don't increase SWF size if they don't get used |
| * because the new compiler resolves multinames down to qnames. |
| */ |
| private static final String[] IMPLICIT_IMPORTS_FOR_MXML = new String[] |
| { |
| "flash.accessibility.*", |
| "flash.data.*", // needed only for AIR |
| "flash.debugger.*", |
| "flash.desktop.*", // needed only for AIR |
| "flash.display.*", |
| "flash.errors.*", |
| "flash.events.*", |
| "flash.external.*", |
| "flash.filesystem.*", // needed only for AIR |
| "flash.geom.*", |
| "flash.html.*", // needed only for AIR |
| "flash.html.script.*", // needed only for AIR |
| "flash.media.*", |
| "flash.net.*", |
| "flash.printing.*", |
| "flash.profiler.*", |
| "flash.system.*", |
| "flash.text.*", |
| "flash.ui.*", |
| "flash.utils.*", |
| "flash.xml.*", |
| "mx.binding.*", |
| "mx.core.ClassFactory", |
| "mx.core.DeferredInstanceFromClass", |
| "mx.core.DeferredInstanceFromFunction", |
| "mx.core.IDeferredInstance", |
| "mx.core.IFactory", |
| "mx.core.IFlexModuleFactory", |
| "mx.core.IPropertyChangeNotifier", |
| "mx.core.mx_internal", |
| "mx.styles.*" |
| }; |
| |
| private static final Map<String, Integer> NAMED_COLORS = new HashMap<String, Integer>(); |
| |
| static |
| { |
| NAMED_COLORS.put("aqua", 0x00FFFF); |
| NAMED_COLORS.put("black", 0x000000); |
| NAMED_COLORS.put("blue", 0x0000FF); |
| NAMED_COLORS.put("cyan", 0x00FFFF); // nonstandard |
| NAMED_COLORS.put("fuchsia", 0xFF00FF); |
| NAMED_COLORS.put("gray", 0x808080); |
| NAMED_COLORS.put("green", 0x008000); |
| NAMED_COLORS.put("lime", 0x00FF00); |
| NAMED_COLORS.put("magenta", 0xFF00FF); // nonstandard |
| NAMED_COLORS.put("maroon", 0x800000); |
| NAMED_COLORS.put("navy", 0x000080); |
| NAMED_COLORS.put("olive", 0x808000); |
| NAMED_COLORS.put("purple", 0x800080); |
| NAMED_COLORS.put("red", 0xFF0000); |
| NAMED_COLORS.put("silver", 0xC0C0C0); |
| NAMED_COLORS.put("teal", 0x008080); |
| NAMED_COLORS.put("white", 0xFFFFFF); |
| NAMED_COLORS.put("yellow", 0xFFFF00); |
| |
| NAMED_COLORS.put("haloBlue", 0x009DFF); |
| NAMED_COLORS.put("haloGreen", 0x80FF4D); |
| NAMED_COLORS.put("haloOrange", 0xFFB600); |
| NAMED_COLORS.put("haloSilver", 0xAECAD9); |
| |
| } |
| |
| public static void configure(RoyaleProject project) |
| { |
| configure(project, null); |
| } |
| |
| public static void configure(RoyaleProject project, Configuration configuration) |
| { |
| String[] imports = null; |
| if (configuration != null) |
| imports = configuration.getCompilerMxmlImplicitImports(); |
| if (imports == null) |
| imports = IMPLICIT_IMPORTS_FOR_MXML; |
| project.setImplicitImportsForMXML(imports); |
| |
| // Set the qualified names of various runtime types |
| // that the compiler needs to know about. |
| // They will also eventually come from royale-config.xml. |
| project.setComponentTagType(IMXMLTypeConstants.IFactory); |
| project.setStateClass(IMXMLTypeConstants.State); |
| project.setStateClientInterface(IMXMLTypeConstants.StateClient); |
| project.setInstanceOverrideClass(IMXMLTypeConstants.AddItems); |
| project.setPropertyOverrideClass(IMXMLTypeConstants.SetProperty); |
| project.setStyleOverrideClass(IMXMLTypeConstants.SetStyle); |
| project.setEventOverrideClass(IMXMLTypeConstants.SetEventHandler); |
| project.setDeferredInstanceInterface(IMXMLTypeConstants.IDeferredInstance); |
| project.setTransientDeferredInstanceInterface(IMXMLTypeConstants.ITransientDeferredInstance); |
| project.setDeferredInstanceFromClassClass(IMXMLTypeConstants.DeferredInstanceFromClass); |
| project.setDeferredInstanceFromFunctionClass(IMXMLTypeConstants.DeferredInstanceFromFunction); |
| project.setFactoryInterface(IMXMLTypeConstants.IFactory); |
| project.setClassFactoryClass(IMXMLTypeConstants.ClassFactory); |
| project.setMXMLObjectInterface(IMXMLTypeConstants.IMXMLObject); |
| project.setContainerInterface(IMXMLTypeConstants.IContainer); |
| project.setVisualElementContainerInterface(IMXMLTypeConstants.IVisualElementContainer); |
| project.setResourceBundleClass(IMXMLTypeConstants.ResourceBundle); |
| project.setResourceManagerClass(IMXMLTypeConstants.ResourceManager); |
| project.setResourceModuleBaseClass(IMXMLTypeConstants.ResourceModuleBase); |
| project.setBindingManagerClass(IMXMLTypeConstants.BindingManager); |
| project.setCSSStyleDeclarationClass(IMXMLTypeConstants.CSSStyleDeclaration); |
| project.setFlexModuleInterface(IMXMLTypeConstants.IFlexModule); |
| project.setDeferredInstantiationUIComponentInterface(IMXMLTypeConstants.IDeferredInstantiationUIComponent); |
| |
| project.setXMLUtilClass(IMXMLTypeConstants.XMLUtil); |
| project.setUIComponentDescriptorClass(IMXMLTypeConstants.UIComponentDescriptor); |
| project.setModelClass(IMXMLTypeConstants.ObjectProxy); |
| project.setBindingClass(IMXMLTypeConstants.Binding); |
| project.setPropertyWatcherClass(IMXMLTypeConstants.PropertyWatcher); |
| project.setObjectProxyClass(IMXMLTypeConstants.ObjectProxy); |
| project.setStaticPropertyWatcherClass(IMXMLTypeConstants.StaticPropertyWatcher); |
| project.setFunctionReturnWatcherClass(IMXMLTypeConstants.FunctionReturnWatcher); |
| project.setXMLWatcherClass(IMXMLTypeConstants.XMLWatcherClass); |
| |
| project.setWebServiceClass(IMXMLTypeConstants.WebService); |
| project.setWebServiceOperationClass(IMXMLTypeConstants.WebServiceOperation); |
| project.setRemoteObjectClass(IMXMLTypeConstants.RemoteObject); |
| project.setRemoteObjectMethodClass(IMXMLTypeConstants.RemoteObjectOperation); |
| project.setHTTPServiceClass(IMXMLTypeConstants.HTTPService); |
| project.setDesignLayerClass(IMXMLTypeConstants.DesignLayer); |
| project.setRepeaterClass(IMXMLTypeConstants.Repeater); |
| |
| project.setNamedColors(NAMED_COLORS); |
| |
| if (configuration != null) |
| { |
| String configValue = configuration.getBindingEventHandlerEvent(); |
| ClassDefinition.Event = configValue; |
| int dotIndex; |
| dotIndex = configValue.lastIndexOf("."); |
| String packageName = configValue.substring(0, dotIndex); |
| String className = configValue.substring(dotIndex + 1); |
| BindableHelper.NAME_EVENT = new Name(CONSTANT_Qname, new Nsset(new Namespace(CONSTANT_PackageNs, packageName)), className); |
| BindableHelper.STRING_EVENT = configValue; |
| |
| configValue = configuration.getBindingEventHandlerClass(); |
| dotIndex = configValue.lastIndexOf("."); |
| packageName = configValue.substring(0, dotIndex); |
| className = configValue.substring(dotIndex + 1); |
| BindableHelper.NAME_EVENT_DISPATCHER = new Name(CONSTANT_Qname, new Nsset(new Namespace(CONSTANT_PackageNs, packageName)), className); |
| BindableHelper.STRING_EVENT_DISPATCHER = configValue; |
| |
| configValue = configuration.getBindingEventHandlerInterface(); |
| dotIndex = configValue.lastIndexOf("."); |
| packageName = configValue.substring(0, dotIndex); |
| className = configValue.substring(dotIndex + 1); |
| BindableHelper.NAME_IEVENT_DISPATCHER = new Name(CONSTANT_Qname, new Nsset(new Namespace(CONSTANT_PackageNs, packageName)), className); |
| BindableHelper.STRING_IEVENT_DISPATCHER = configValue; |
| |
| configValue = configuration.getBindingValueChangeEvent(); |
| dotIndex = configValue.lastIndexOf("."); |
| packageName = configValue.substring(0, dotIndex); |
| className = configValue.substring(dotIndex + 1); |
| BindableHelper.NAME_PROPERTY_CHANGE_EVENT = new Name(CONSTANT_Qname, new Nsset(new Namespace(CONSTANT_PackageNs, packageName)), className); |
| BindableHelper.NAMESPACE_MX_EVENTS = new Namespace(CONSTANT_PackageNs, packageName); |
| BindableHelper.PROPERTY_CHANGE_EVENT = configValue; |
| |
| configValue = configuration.getBindingValueChangeEventKind(); |
| dotIndex = configValue.lastIndexOf("."); |
| packageName = configValue.substring(0, dotIndex); |
| className = configValue.substring(dotIndex + 1); |
| BindableHelper.NAME_PROPERTY_CHANGE_EVENT_KIND = new Name(CONSTANT_Qname, new Nsset(new Namespace(CONSTANT_PackageNs, packageName)), className); |
| |
| configValue = configuration.getBindingValueChangeEventType(); |
| BindableHelper.PROPERTY_CHANGE = configValue; |
| |
| configValue = configuration.getFxgBaseClass(); |
| FlexFXG2SWFTranscoder.packageSpriteVisualElement = configValue; |
| FXGCompilationUnit.fxgBaseClassName = configValue; |
| |
| configValue = configuration.getStatesClass(); |
| project.setStateClass(configValue); |
| |
| configValue = configuration.getStatesInstanceOverrideClass(); |
| project.setInstanceOverrideClass(configValue); |
| |
| configValue = configuration.getStatesPropertyOverrideClass(); |
| project.setPropertyOverrideClass(configValue); |
| |
| configValue = configuration.getStatesEventOverrideClass(); |
| project.setEventOverrideClass(configValue); |
| |
| configValue = configuration.getStatesStyleOverrideClass(); |
| project.setStyleOverrideClass(configValue); |
| |
| configValue = configuration.getComponentFactoryInterface(); |
| project.setFactoryInterface(configValue); |
| |
| configValue = configuration.getComponentFactoryClass(); |
| project.setClassFactoryClass(configValue); |
| |
| configValue = configuration.getProxyBaseClass(); |
| project.setProxyBaseClass(configValue); |
| |
| project.setStrictXML(configuration.isStrictXML()); |
| project.setAllowPrivateNameConflicts(configuration.getCompilerAllowPrivateNameConflicts()); |
| |
| DataTranscoder.embedClassName = configuration.getByteArrayEmbedClass(); |
| } |
| } |
| |
| /** |
| * Constructor |
| */ |
| public RoyaleProjectConfigurator(Class<? extends Configuration> configurationClass) |
| { |
| super(configurationClass); |
| } |
| |
| @Override |
| public boolean applyToProject(ICompilerProject project) |
| { |
| boolean success = super.applyToProject(project); |
| if (success && !setupSources((IRoyaleProject)project)) |
| success = false; |
| return success; |
| } |
| |
| @Override |
| protected boolean applyConfiguration() |
| { |
| boolean success = true; |
| |
| RoyaleProject royaleProject = (RoyaleProject)project; |
| RoyaleProjectConfigurator.configure(royaleProject, configuration); |
| setupCompatibilityVersion(royaleProject); |
| setupConfigVariables(royaleProject); |
| setupLocaleSettings(royaleProject); |
| setupServices(royaleProject); |
| setupThemeFiles(royaleProject); |
| setupRoyale(royaleProject); |
| setupCodegenOptions(royaleProject); |
| royaleProject.setRuntimeSharedLibraryPath(getRSLSettingsFromConfiguration(configuration)); |
| |
| if (!setupProjectLibraries(royaleProject)) |
| success = false; |
| |
| setupNamespaces(royaleProject); |
| return success; |
| } |
| |
| /** |
| * Setup {@code -compatibility-version} level. Royale only support Flex 3+. |
| * @param project |
| */ |
| protected void setupCompatibilityVersion(RoyaleProject project) |
| { |
| final int compatibilityVersion = configuration.getCompilerMxmlCompatibilityVersion(); |
| if (compatibilityVersion < Configuration.MXML_VERSION_3_0) |
| throw new UnsupportedOperationException("Unsupported compatibility version: " + configuration.getCompilerCompatibilityVersionString()); |
| project.setCompatibilityVersion(configuration.getCompilerMxmlMajorCompatibilityVersion(), |
| configuration.getCompilerMxmlMinorCompatibilityVersion(), |
| configuration.getCompilerMxmlRevisionCompatibilityVersion()); |
| } |
| |
| /** |
| * Transfers configuration settings to the project. Handles: |
| * -services |
| * -context-root |
| * |
| */ |
| protected void setupServices(RoyaleProject project) |
| { |
| if (configuration.getCompilerServices() != null) |
| project.setServicesXMLPath(configuration.getCompilerServices().getPath(), configuration.getCompilerContextRoot()); |
| } |
| |
| protected void setupConfigVariables(IRoyaleProject project) |
| { |
| final Map<String, String> compilerDefine = project.getCompilerDefine(configuration); |
| if (compilerDefine != null) |
| project.setDefineDirectives(compilerDefine); |
| } |
| |
| /** |
| * Setup the source paths. |
| * |
| * @return true if successful, false otherwise. |
| */ |
| protected boolean setupSources(IRoyaleProject project) |
| { |
| // -source-path |
| List<String> sourcePath = new ArrayList<String>(); |
| applySourcePathRules(sourcePath); |
| |
| project.setSourcePath(toFiles(sourcePath)); |
| |
| // -include-sources |
| try |
| { |
| project.setIncludeSources(toFileList(configuration.getIncludeSources())); |
| } |
| catch (InterruptedException e) |
| { |
| assert false : "InterruptedException should never be thrown here"; |
| return false; |
| } |
| |
| return true; |
| } |
| |
| /** |
| * Collect all of the different library paths and set them in the project. |
| * The libraries are ordered with RSL and external libraries having the |
| * highest priority. |
| * |
| * <p>Libraries are ordered highest to lowest priority: |
| * <ol> |
| * <li>External Library Path |
| * <li>RSL Library Path |
| * <li>Include Library Path |
| * <li>Library Path |
| * </ol> |
| * </p> |
| * @param project |
| * @return true if successful, false if there is an error. |
| */ |
| protected boolean setupProjectLibraries(IRoyaleProject project) |
| { |
| LinkedHashSet<File> libraries = new LinkedHashSet<File>(); |
| |
| // add External Library Path |
| List<File> externalLibraryFiles = toFileList(project.getCompilerExternalLibraryPath(configuration)); |
| libraries.addAll(externalLibraryFiles); |
| |
| // add RSLs |
| libraries.addAll(configuration.getRslExcludedLibraries()); |
| |
| // add Include Library Path |
| libraries.addAll(toFileList(configuration.getCompilerIncludeLibraries())); |
| |
| // add Library Path |
| libraries.addAll(toFileList(project.getCompilerLibraryPath(configuration))); |
| |
| List<String> themes = configuration.getCompilerThemeFiles(); |
| for (String theme : themes) |
| { |
| if (theme.endsWith(".swc")) |
| { |
| File f = new File(theme); |
| libraries.add(f); |
| } |
| } |
| |
| project.setLibraries(new ArrayList<File>(libraries)); |
| |
| // After we set the library path we can check for ANE files more |
| // accurately because the library path manager in the project |
| // will read in all the swc files found in directories on the |
| // paths. |
| return validateNoANEFiles(project, externalLibraryFiles); |
| } |
| |
| /** |
| * Validate all of the ANE files are on the external library path. |
| * |
| * @param project the project being configured. |
| * @param externalLibraryFiles the external library path. |
| * @return true if successful, false if there is an error. |
| */ |
| private boolean validateNoANEFiles(IRoyaleProject project, |
| List<File>externalLibraryFiles) |
| { |
| // Get all the library files in the project. |
| List<ISWC> libraries = project.getLibraries(); |
| for (ISWC library : libraries) |
| { |
| if (library.isANE()) |
| { |
| // must be on the external library path |
| if (!isOnExternalLibrayPath(library, externalLibraryFiles)) |
| { |
| configurationProblems.add( |
| new ANELibraryNotAllowedProblem( |
| library.getSWCFile().getAbsolutePath())); |
| return false; |
| } |
| } |
| } |
| |
| return true; |
| } |
| |
| protected void setupNamespaces(IRoyaleProject project) |
| { |
| final List<? extends IMXMLNamespaceMapping> configManifestMappings = |
| project.getCompilerNamespacesManifestMappings(configuration); |
| if (configManifestMappings != null) |
| { |
| project.setNamespaceMappings(configManifestMappings); |
| } |
| } |
| |
| /** |
| * Setups the locale related settings. |
| */ |
| protected void setupLocaleSettings(IRoyaleProject project) |
| { |
| project.setLocales(configuration.getCompilerLocales()); |
| project.setLocaleDependentResources(configuration.getLocaleDependentSources()); |
| } |
| |
| private void setupRoyale(RoyaleProject royaleProject) |
| { |
| royaleProject.setRoyale(configuration.isRoyale()); |
| } |
| |
| private void setupCodegenOptions(RoyaleProject royaleProject) |
| { |
| royaleProject.setEnableInlining(configuration.isInliningEnabled()); |
| } |
| |
| /** |
| * Setup theme files. |
| */ |
| protected void setupThemeFiles(RoyaleProject project) |
| { |
| project.setThemeFiles(toFileSpecifications(configuration.getCompilerThemeFiles(), |
| project.getWorkspace())); |
| |
| } |
| |
| @Override |
| protected ITargetSettings instantiateTargetSettings() |
| { |
| return new RoyaleTargetSettings(configuration, project); |
| } |
| |
| @Override |
| protected String computeQNameForTargetFile() |
| { |
| List<String> computedSourcePath = new ArrayList<String>(); |
| applySourcePathRules(computedSourcePath); |
| String targetSourceFileName = configuration.getTargetFile(); |
| if (targetSourceFileName == null) |
| return null; |
| final File targetSourceFile = FilenameNormalization.normalize(new File(configuration.getTargetFile())); |
| for (final String sourcePathEntry : computedSourcePath) |
| { |
| final String computedQName = SourcePathManager.computeQName(new File(sourcePathEntry), targetSourceFile); |
| if (computedQName != null) |
| return computedQName; |
| |
| } |
| return null; |
| } |
| |
| /** |
| * Test if the SWC is explicitly on the external library path. |
| * |
| * @param library |
| * @param externalLibraryFiles |
| * @return true if the library is on the external library path, false otherwise. |
| */ |
| private boolean isOnExternalLibrayPath(ISWC library, List<File> externalLibraryFiles) |
| { |
| File aneFile = library.getSWCFile(); |
| |
| for (File file : externalLibraryFiles) |
| { |
| if (file.equals(aneFile)) |
| return true; |
| } |
| |
| return false; |
| } |
| |
| |
| } |