/* * * 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.config; import java.io.*; import java.text.DateFormat; import java.util.*; import java.util.regex.Pattern; import javax.xml.stream.XMLOutputFactory; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.apache.commons.io.FilenameUtils; import org.apache.commons.io.IOUtils; import org.apache.flex.compiler.common.IPathResolver; import org.apache.flex.compiler.common.VersionInfo; import org.apache.flex.compiler.exceptions.ConfigurationException; import org.apache.flex.compiler.exceptions.ConfigurationException.*; import org.apache.flex.compiler.filespecs.FileSpecification; import org.apache.flex.compiler.filespecs.IFileSpecification; import org.apache.flex.compiler.internal.config.*; import org.apache.flex.compiler.internal.config.annotations.*; import org.apache.flex.compiler.internal.config.localization.LocalizationManager; import org.apache.flex.compiler.internal.mxml.MXMLNamespaceMapping; import org.apache.flex.compiler.mxml.IMXMLTypeConstants; import org.apache.flex.compiler.problems.*; import org.apache.flex.swc.catalog.XMLFormatter; import org.apache.flex.utils.FileUtils; import org.apache.flex.utils.FilenameNormalization; import com.google.common.base.Function; import com.google.common.base.Splitter; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; /** * The model for all the configuration options supported by the compiler. Each option is stored in a private field. It * usually has a getter method, a setter method and a configuration method (started with "cfg"). The configuration * methods are used by the configurators to set the values of a given option name. * <p> * This class is currently being reviewed and refactored. See CMP-471 as the master bug for the tasks. * <p> * Steps to refactor: * <ol> * <li>Check "mxmlc" manual (http://adobe.ly/bffN8A) and copy documents to Javadoc on setters of options.</li> * <li>Check "configuration support" WIKI (http://bit.ly/oAI8gj) to see if an option should be deprecated.</li> * <li>Merge {@code cfgXXX} to {@code setXXX}, and annotate the setter.</li> * <li>Remove {@code getXXXInfo()} static method.</li> * </ol> * * @see "http://bugs.adobe.com/jira/browse/CMP-471" */ public class Configuration { private static final int DEFAULT_HEIGHT_MAX = 4096; private static final int DEFAULT_HEIGHT_MIN = 1; private static final int DEFAULT_WIDTH_MAX = 4096; private static final int DEFAULT_WIDTH_MIN = 1; public static final String DEFAULT_OUTPUT_DIRECTORY_TOKEN = "org.apache.flex.default.output.directory"; public static final String SWC_AIRGLOBAL = "airglobal.swc"; /** * Singleton empty string list. All getters returning a list of string should return this object when the field is * null. */ private static final List<String> EMPTY_STRING_LIST = Collections.emptyList(); private static final List<String> compcOnlyOptions = new ArrayList<String>(9); static { compcOnlyOptions.add("directory"); compcOnlyOptions.add("include-classes"); compcOnlyOptions.add("include-file"); compcOnlyOptions.add("include-lookup-only"); compcOnlyOptions.add("include-namespaces"); compcOnlyOptions.add("include-sources"); compcOnlyOptions.add("include-stylesheet"); compcOnlyOptions.add("include-inheritance-dependencies-only"); } /** * Validate configuration options values. * * @param configurationBuffer Configuration buffer. * @throws ConfigurationException Error. */ public void validate(ConfigurationBuffer configurationBuffer) throws ConfigurationException { // process the merged configuration buffer. right, can't just process the args. processDeprecatedAndRemovedOptions(configurationBuffer); validateDumpConfig(configurationBuffer); } private String[] removeNativeJSLibrariesIfNeeded(String[] libraryPaths) { List<String> libraryPathList = new ArrayList<String>(Arrays.asList(libraryPaths)); String appHome = System.getProperty("application.home"); if (appHome == null) return libraryPaths; appHome = appHome.replace("\\", "/"); if (isExcludeNativeJSLibraries) { Iterator<String> pathIterator = libraryPathList.iterator(); while (pathIterator.hasNext()) { final String path = pathIterator.next().replace("\\", "/"); final boolean isNativeJS = path.contains(appHome + "/js/libs") && path.lastIndexOf(".swc") == path.length() - ".swc".length(); if (isNativeJS) { pathIterator.remove(); } } } return libraryPathList.toArray(new String[libraryPathList.size()]); } /** * Validate that no compc-only options are used in a given configuration buffer. Use this method to verify no * compc-only args are used in mxmlc. * * @param configurationBuffer the configuration buffer to check for compc-only options. * * @throws ConfigurationException if a compc-only option is found in the configuration buffer. */ public static void validateNoCompcOnlyOptions(ConfigurationBuffer configurationBuffer) throws ConfigurationException { for (String option : compcOnlyOptions) { List<ConfigurationValue> values = configurationBuffer.getVar(option); if (values != null && values.size() > 0) throw new ConfigurationException.UnknownVariable(values.get(0).getVar(), values.get(0).getSource(), values.get(0).getLine()); } } /** * The path of a given file name based on the context of the configuration value or the default output directory * token. * * @param cv * @param fileName * @return the full path of the file. */ protected String getOutputPath(ConfigurationValue cv, String fileName) { String result = fileName; if (fileName != null) { File file = new File(fileName); if (!FileUtils.isAbsolute(file)) { String directory = cv.getBuffer().getToken(DEFAULT_OUTPUT_DIRECTORY_TOKEN); // if no default output directory, then use the configuration context. if (directory == null) { directory = cv.getContext(); } if (directory != null) { result = FileUtils.addPathComponents(directory, fileName, File.separatorChar); } } } return pathResolver.resolve(result).getAbsolutePath(); } private static Map<String, String> aliases = null; public static Map<String, String> getAliases() { if (aliases == null) { aliases = new HashMap<String, String>(); aliases.put("l", "compiler.library-path"); aliases.put("el", "compiler.external-library-path"); aliases.put("fb", "use-flashbuilder-project-files"); aliases.put("is", "include-sources"); aliases.put("sp", "compiler.source-path"); aliases.put("rsl", "runtime-shared-libraries"); aliases.put("keep", "compiler.keep-generated-actionscript"); aliases.put("o", "output"); aliases.put("rslp", "runtime-shared-library-path"); aliases.put("static-rsls", "static-link-runtime-shared-libraries"); } return aliases; } // // PathResolver // private IPathResolver pathResolver; /** * Set a path resolver to resolver files relative to a configuration. Files inside of configuration files are * resolved relative to those configuration files and files on the command line are resolved relative to the root * directory of the compile. * * @param pathResolver a path resolver for this configuration. May not be null. */ public void setPathResolver(IPathResolver pathResolver) { this.pathResolver = pathResolver; } // // mainDefinition // private String mainDefinition; /** * Main definition is the root class of a SWF. {@code mxmlc} only takes one file in the source list. The main * definition name is the main source file name. * * @return main definition */ public String getMainDefinition() { return mainDefinition; } public void setMainDefinition(String mainDefinition) { assert mainDefinition != null : "main definition can't be null"; assert!"".equals(mainDefinition) : "main definition can't be empty"; this.mainDefinition = mainDefinition; } // // 'benchmark' option // @Config(removed = true) @Mapping("benchmark") public void setBenchmark(ConfigurationValue cv, boolean b) { } // // 'debug-password' option // private String debugPassword; /** * Lets you engage in remote debugging sessions with the Flash IDE. */ public String getDebugPassword() { return debugPassword; } @Config(advanced = true) @Mapping("debug-password") @DefaultArgumentValue("") public void setDebugPassword(ConfigurationValue cv, String debugPassword) { this.debugPassword = debugPassword; } // // 'default-background-color' option // private int backgroundColor = 0x50727E; public int getDefaultBackgroundColor() { return this.backgroundColor; } @Config(advanced = true) @Mapping("default-background-color") public void setDefaultBackgroundColor(ConfigurationValue cv, int backgroundColor) { this.backgroundColor = backgroundColor; } // // 'default-frame-rate' option // private int frameRate = 24; public int getDefaultFrameRate() { return frameRate; } @Config(advanced = true) @Mapping("default-frame-rate") public void setDefaultFrameRate(ConfigurationValue cv, int rate) throws ConfigurationException { if (rate <= 0) throw new ConfigurationException.GreaterThanZero(cv.getVar(), cv.getSource(), cv.getLine()); frameRate = rate; } // // 'default-script-limits' option // private int scriptLimit = 60; private int scriptRecursionLimit = 1000; private boolean scriptLimitsSet = false; public int getScriptTimeLimit() { return scriptLimit; } public int getScriptRecursionLimit() { return scriptRecursionLimit; } public boolean scriptLimitsSet() { return scriptLimitsSet; } @Config(advanced = true) @Mapping("default-script-limits") @Arguments({ "max-recursion-depth", "max-execution-time" }) public void setDefaultScriptLimits(ConfigurationValue cv, int scriptLimit, int scriptRecursionLimit) throws ConfigurationException { if (scriptLimit <= 0) throw new ConfigurationException.GreaterThanZero(cv.getVar(), cv.getSource(), cv.getLine()); if (scriptRecursionLimit <= 0) throw new ConfigurationException.GreaterThanZero(cv.getVar(), cv.getSource(), cv.getLine()); this.scriptLimitsSet = true; this.scriptLimit = scriptRecursionLimit; this.scriptRecursionLimit = scriptLimit; } // // 'default-size' option // private int defaultWidth = 500; private int defaultHeight = 375; public int getDefaultWidth() { return defaultWidth; } public int getDefaultHeight() { return defaultHeight; } @Config(advanced = true) @Arguments({ "width", "height" }) @Mapping("default-size") public void setDefaultSize(ConfigurationValue cv, int width, int height) throws ConfigurationException { if (width < DEFAULT_WIDTH_MIN || width > DEFAULT_WIDTH_MAX || height < DEFAULT_HEIGHT_MIN || height > DEFAULT_HEIGHT_MAX) throw new ConfigurationException.IllegalDimensions(width, height, cv.getVar(), cv.getSource(), cv.getLine()); this.defaultWidth = width; this.defaultHeight = height; } // // 'externs' option // private final Set<String> externs = new LinkedHashSet<String>(); public Set<String> getExterns() { return externs; } /** * Sets a list of classes to exclude from linking when compiling a SWF file. This option provides compile-time link * checking for external references that are dynamically linked. */ @Config(advanced = true, allowMultiple = true) @Mapping("externs") @Arguments("symbol") @InfiniteArguments public void setExterns(ConfigurationValue cfgval, List<String> vals) { externs.addAll(QNameNormalization.normalize(vals)); } // // 'includes' option // private final Set<String> includes = new LinkedHashSet<String>(); public Set<String> getIncludes() { return includes; } /** * Links one or more classes to the resulting application SWF file, whether or not those classes are required at * compile time. To link an entire SWC file rather than individual classes, use the include-libraries option. */ @Config(allowMultiple = true, advanced = true) @Mapping("includes") @Arguments("symbol") @InfiniteArguments public void setIncludes(ConfigurationValue cfgval, List<String> vals) { includes.addAll(QNameNormalization.normalize(vals)); } // // 'framework' option // // @Config(allowMultiple = true, advanced = true, removed = true) @Mapping("framework") public void setFramework(ConfigurationValue cfgval, String value) { } // 'link-report' option // private String linkReportFileName = null; public File getLinkReport() { return linkReportFileName != null ? new File(linkReportFileName) : null; } /** * Prints linking information to the specified output file. This file is an XML file that contains {@code def} tags, * {@code pre} tags and {@code ext} tags showing linker dependencies in the final SWF file. The file format output * by this command can be used to write a file for input to the {@code load-externs} option. */ @Config(advanced = true) @Mapping("link-report") @Arguments("filename") public void setLinkReport(ConfigurationValue cv, String filename) { this.linkReportFileName = getOutputPath(cv, filename); } // // 'size-report' option // private String sizeReportFileName = null; public File getSizeReport() { return sizeReportFileName != null ? new File(sizeReportFileName) : null; } @Config(advanced = true) @Mapping("size-report") @Arguments("filename") public void setSizeReport(ConfigurationValue cv, String filename) { this.sizeReportFileName = getOutputPath(cv, filename); } // // 'load-externs' option // /** * Specifies the location of an XML file that contains def, pre, and ext symbols to omit from linking when compiling * a SWF file. The XML file uses the same syntax as the one produced by the link-report option. * <p> * This option provides compile-time link checking for external components that are dynamically linked. */ @Config(allowMultiple = true, advanced = true) @Mapping("load-externs") @Arguments("filename") public void setLoadExterns(ConfigurationValue cfgval, String filename) throws ConfigurationException { final String path = resolvePathStrict(filename, cfgval); final FileSpecification f = new FileSpecification(path); final List<String> externsFromFile = LoadExternsParser.collectExterns(cfgval, f); externs.addAll(externsFromFile); } // // 'raw-metadata' option // private String metadata = null; public String getRawMetadata() { if (metadata != null) return metadata; return generateMetadata(); } private static final String RDF_URI = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"; private static final String DC_URI = "http://purl.org/dc/elements/1.1"; /** * @return Metadata XML string. */ private final String generateMetadata() { final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance(); assert xmlOutputFactory != null : "Expect XMLOutputFactory implementation."; final StringWriter stringWriter = new StringWriter(); XMLStreamWriter xmlWriter = null; try { xmlWriter = new XMLFormatter(xmlOutputFactory.createXMLStreamWriter(stringWriter)); xmlWriter.writeStartDocument(); xmlWriter.writeStartElement("rdf", "RDF", RDF_URI); xmlWriter.setPrefix("rdf", RDF_URI); xmlWriter.writeNamespace("rdf", RDF_URI); // write rdf:Description xmlWriter.writeStartElement(RDF_URI, "Description"); xmlWriter.setPrefix("dc", DC_URI); xmlWriter.setPrefix(VersionInfo.COMPILER_NAMESPACE_PREFIX, VersionInfo.COMPILER_NAMESPACE_URI); xmlWriter.writeNamespace("dc", DC_URI); xmlWriter.writeNamespace(VersionInfo.COMPILER_NAMESPACE_PREFIX, VersionInfo.COMPILER_NAMESPACE_URI); // write dc:format xmlWriter.writeStartElement(DC_URI, "format"); xmlWriter.writeCharacters("application/x-shockwave-flash"); xmlWriter.writeEndElement(); if (isFlex()) { // write localizedTitles writeMap(xmlWriter, DC_URI, "description", localizedDescriptions); // write localizedDescription writeMap(xmlWriter, DC_URI, "title", localizedTitles); // write publisher writeCollection(xmlWriter, DC_URI, "publisher", publishers); // write creators writeCollection(xmlWriter, DC_URI, "creator", creators); // write contributor writeCollection(xmlWriter, DC_URI, "contributor", contributors); // write language writeCollection(xmlWriter, DC_URI, "language", langs); // write date writeDate(xmlWriter); } // write compiledBy writeCompiledBy(xmlWriter); // write xmlWriter.writeEndElement(); // Description xmlWriter.writeEndDocument(); } catch (XMLStreamException e) { return ""; } return stringWriter.toString(); } /** * Write information about the compiler that compiled the swf. * * @param writer * @throws XMLStreamException */ private void writeCompiledBy(XMLStreamWriter writer) throws XMLStreamException { writer.writeEmptyElement(VersionInfo.COMPILER_NAMESPACE_URI, VersionInfo.COMPILER_ELEMENT); writer.writeAttribute(VersionInfo.COMPILER_NAME_ATTRIBUTE, VersionInfo.getCompilerName()); writer.writeAttribute(VersionInfo.COMPILER_VERSION_ATTRIBUTE, VersionInfo.getCompilerVersion()); writer.writeAttribute(VersionInfo.COMPILER_BUILD_ATTRIBUTE, VersionInfo.getCompilerBuild()); writer.writeEndElement(); // compiledBy } /** * Write the data to rdf/xml * * @param writer * @throws XMLStreamException */ private void writeDate(XMLStreamWriter writer) throws XMLStreamException { if (date == null) { date = DateFormat.getDateInstance().format(new Date()); } writer.writeStartElement(DC_URI, "date"); writer.writeCharacters(date); writer.writeEndElement(); } /** * Write a map of values to rdf/xml * * @param writer * @param namespaceURI * @param localName * @param mapData * @throws XMLStreamException */ private void writeMap(XMLStreamWriter writer, String namespaceURI, String localName, Map<String, String> mapData) throws XMLStreamException { if (mapData.size() > 0) { writer.writeStartElement(namespaceURI, localName); if ((mapData.size() == 1) && (mapData.get("x-default") != null)) { String data = mapData.get("x-default"); writer.writeCharacters(data); } else { writer.writeStartElement(RDF_URI, "Alt"); for (final String key : mapData.keySet()) { final String value = mapData.get(key); writer.writeStartElement(RDF_URI, "li"); writer.writeAttribute("xml", "", "lang", key); writer.writeCharacters(value); writer.writeEndElement(); } writer.writeEndElement(); } writer.writeEndElement(); } } /** * Write a collection values to rdf/xml. * * @param writer * @param namespaceURI * @param localName * @param values * @throws XMLStreamException */ private void writeCollection(XMLStreamWriter writer, String namespaceURI, String localName, Collection<String> values) throws XMLStreamException { if (values.isEmpty()) return; writer.writeStartElement(namespaceURI, localName); if (values.size() > 1) writer.writeStartElement(RDF_URI, "Bag"); for (String value : values) { writer.writeCharacters(value); } if (values.size() > 1) writer.writeEndElement(); writer.writeEndElement(); } /** * Defines the metadata for the resulting SWF file. The value of this option overrides any metadata-related compiler * options such as contributor, creator, date, and description. */ @Config(advanced = true) @Mapping("raw-metadata") @Arguments("text") public void setRawMetadata(ConfigurationValue cv, String xml) throws ConfigurationException { if (metadata != null) { throw new ConfigurationException.BadMetadataCombo(cv.getVar(), cv.getSource(), cv.getLine()); } this.metadata = xml; } // // 'resource-bundle-list' option // private String rbListFileName = null; public String getResourceBundleList() { return rbListFileName; } // // 'include-resource-bundles' option // /** * include-resource-bundles [...] */ private List<String> includeResourceBundles = new ArrayList<String>(); /** * @return a list of resource bundles to include in the swc */ public List<String> getIncludeResourceBundles() { return includeResourceBundles; } /** * Sets the resource bundles that should be included in this SWC or SWF. This list can have locale independent * qualified name for property files (with the name not including the suffix) or qualified name for classes that * extend ResourceBundle. * <p> * Qualified name of a properties file is determined by its relative path to its parent source folder. Such as: * <p> * Source path: locale/{locale} * <p> * Path of properties file 1: locale/en_US/A.properties Qualified name of properties file 1: A * <p> * Path of properties file 2: locale/en_US/com/resources/B.properties Qualified name of properties file 1: * com.resources.B * <p> * Note: Source folders of all the properties files passed using this argument should be in the project's source * path list. * * @param cv configuration value objects * @param values list of resource bundles to include in the swc or swf */ @Config(allowMultiple = true) @Mapping("include-resource-bundles") @Arguments("bundle") @FlexOnly public void setIncludeResourceBundles(ConfigurationValue cv, List<String> values) { includeResourceBundles.addAll(values); } /** * Prints a list of resource bundles that are used by the current application to a file named with the filename * argument. You then use this list as input that you specify with the include-resource-bundles option to create a * resource module. */ @Config(advanced = true) @Mapping("resource-bundle-list") @Arguments("filename") @FlexOnly public void setResourceBundleList(ConfigurationValue cv, String filename) { this.rbListFileName = getOutputPath(cv, filename); } // // 'runtime-shared-libraries' option // private List<String> rslList = new LinkedList<String>(); public List<String> getRuntimeSharedLibraries() { return rslList; } /** * Specifies a list of runtime shared libraries (RSLs) to use for this application. RSLs are dynamically-linked at * run time. The compiler externalizes the contents of the application that you are compiling that overlap with the * RSL. * <p> * You specify the location of the SWF file relative to the deployment location of the application. For example, if * you store a file named library.swf file in the web_root/libraries directory on the web server, and the * application in the web root, you specify libraries/library.swf. */ @Config(allowMultiple = true) @Mapping("runtime-shared-libraries") @Arguments("url") @InfiniteArguments @FlexOnly public void setRuntimeSharedLibraries(ConfigurationValue cfgval, List<String> urls) throws ConfigurationException { rslList.addAll(urls); } // // 'use-network' option // private boolean useNetwork = true; public boolean getUseNetwork() { return useNetwork; } /** * Specifies that the current application uses network services. * <p> * The default value is true. * <p> * When the use-network property is set to false, the application can access the local filesystem (for example, use * the XML.load() method with file: URLs) but not network services. In most circumstances, the value of this * property should be true. */ @Config @Mapping("use-network") public void setUseNetwork(ConfigurationValue cv, boolean b) { this.useNetwork = b; } // // runtime-shared-library-path // private List<RuntimeSharedLibraryPathInfo> rslPathInfoList; /** * @return List of of all the -runtime-shared-libraries-path options. Each-runtime-shared-libraries-path option * supplied results in a RslPathInfo object. Each object in the list is of type RslPathInfo. * <p> * The list will be empty if -static-link-runtime-shared-libraries=true. * <p> * TODO Verify if this is still true and make the code do what it says. */ public List<RuntimeSharedLibraryPathInfo> getRslPathInfo() { if (rslPathInfoList == null) return Collections.emptyList(); else return rslPathInfoList; } public List<File> getRslExcludedLibraries() { if (rslPathInfoList == null || getStaticLinkRsl()) return Collections.emptyList(); return Lists.transform(rslPathInfoList, new Function<RuntimeSharedLibraryPathInfo, File>() { @Override public File apply(RuntimeSharedLibraryPathInfo info) { return info.getSWCFile(); } }); } /** * Specifies the location of a runtime shared library (RSL). The compiler externalizes the contents of the * application that you are compiling that overlap with the RSL. * <p> * The path-element argument is the location of the SWC file or open directory to compile against. For example, * c:\flexsdk\frameworks\libs\framework.swc. This is the equivalent of the using the external-library-path option * when compiling against an RSL using the runtime-shared-libraries option. * <p> * The rsl-url argument is the URL of the RSL that will be used to load the RSL at runtime. The compiler does not * verify the existence of the SWF file at this location at compile time. It does store this string in the * application, however, and uses it at run time. As a result, the SWF file must be available at run time but * necessarily not at compile time. * <p> * The policy-file-url is the location of the crossdomain.xml file that gives permission to read the RSL from the * server. This might be necessary because the RSL can be on a separate server as the application. For example, * http://www.mydomain.com/rsls/crossdomain.xml. * <p> * The failover-url and second policy-file-url arguments specify the location of the secondary RSL and * crossdomain.xml file if the first RSL cannot be loaded. This most commonly happens when the client Player version * does not support cross-domain RSLs. You can add any number of failover RSLs, but must include a policy file URL * for each one. * <p> * Do not include spaces between the comma-separated values. The following example shows how to use this option: * * <pre> * mxmlc -o=../lib/app.swf -runtime-shared-library-path=../lib/mylib.swc,../bin/myrsl.swf Main.mxml * </pre> * * You can specify more than one library file to be used as an RSL. You do this by adding additional * runtime-shared-library-path options. * <p> * You can also use the runtime-shared-libraries command to use RSLs with your applications. However, the * runtime-shared-library-path option lets you also specify the location of the policy file and failover RSL. * <p> */ // NOTE: if the annotations are modified, then also modify the annotations // in COMPCConfiguration. @Config(allowMultiple = true) @Mapping({ "runtime-shared-library-path" }) @SoftPrerequisites({ "static-link-runtime-shared-libraries" }) @ArgumentNameGenerator(RSLArgumentNameGenerator.class) @InfiniteArguments @FlexOnly public void setRuntimeSharedLibraryPath(ConfigurationValue cfgval, List<String> urls) throws ConfigurationException { if (urls.isEmpty()) return; // Usage rule: if you use -rslp on the command line // it will take effect unless you also specify -static-rsls=true on the command line. if (CommandLineConfigurator.SOURCE_COMMAND_LINE.equals(cfgval.getSource())) { setOverrideStaticLinkRsl(false); } // ignore rsl if told to if (getStaticLinkRsl()) { return; } if (urls.size() < 2) { // insufficent arguments throw new ConfigurationException.MissingArgument("rsl-url", "runtime-shared-library-path", cfgval.getSource(), cfgval.getLine()); } RuntimeSharedLibraryPathInfo info = new RuntimeSharedLibraryPathInfo(); // validate the first argument, the swc or open directory, required. String include = resolvePathStrict(urls.get(0), cfgval, true); info.setSWCPath(urls.get(0)); info.setSWCFile(new File(include)); // the rest of the args are: rsl-url, policy-file-url, rsl-url, policy-file-url,... for (int i = 1; i < urls.size(); ++i) { final String url = urls.get(i); if ((i + 1) % 2 == 0) { if ("".equals(url.length())) { // rsl urls is required throw new ConfigurationException.MissingArgument("rsl-url", "runtime-shared-library-path", cfgval.getSource(), cfgval.getLine()); } info.addRSLURL(url); } else { info.addPolicyFileURL(url); } } // if the last policy file was not specified, then add an empty one so // there are always the same number of rsls and policy files. if ((urls.size() % 2) == 0) { info.addPolicyFileURL(""); } // take local variables and add to overall arguments. if (rslPathInfoList == null) { rslPathInfoList = new ArrayList<RuntimeSharedLibraryPathInfo>(); } rslPathInfoList.add(info); } // // 'static-link-runtime-shared-libraries' option // private boolean staticLinkRsl = true; private String staticLinkRslSource; /** * @return true if -cd-rsl option should be used. False otherwise. */ public boolean getStaticLinkRsl() { return staticLinkRsl; } /** * Allow another option, namely -rslp to override the value of static-rsls. But you can not override a -static-rsls * option that came from the command line. * * @param staticLinkRsl */ protected void setOverrideStaticLinkRsl(boolean staticLinkRsl) { if (CommandLineConfigurator.SOURCE_COMMAND_LINE.equals(staticLinkRslSource)) { return; } this.staticLinkRsl = staticLinkRsl; } /** * Determines whether to compile against libraries statically or use RSLs. Set this option to true to ignore the * RSLs specified by the runtime-shared-library-path option. Set this option to false to use the RSLs. * <p> * This option is useful so that you can quickly switch between a statically and dynamically linked application * without having to change the runtime-shared-library-path option, which can be verbose, or edit the configuration * files. */ @Config @Mapping("static-link-runtime-shared-libraries") @FlexOnly public void setStaticLinkRuntimeSharedLibraries(ConfigurationValue cv, boolean b) { staticLinkRsl = b; staticLinkRslSource = cv.getSource(); } // // 'use-flashbuilder-project-files' option // private Boolean useFlashBuilderProjectFiles = false; public Boolean getUseFlashBuilderProjectFiles() { return useFlashBuilderProjectFiles; } @Config @Mapping({ "use-flashbuilder-project-files" }) @FlexOnly public void setUseFlashBuilderProjectFiles(ConfigurationValue cv, Boolean useFiles) throws ConfigurationException { useFlashBuilderProjectFiles = useFiles; } // // 'verify-digests' options // private boolean verifyDigests = true; /** * @return true if digest information associated with the -cd-rsl option is used by the application at runtime. * False otherwise. */ public boolean getVerifyDigests() { return verifyDigests; } /** * Instructs the application to check the digest of the RSL SWF file against the digest that was compiled into the * application at compile time. This is a security measure that lets you load RSLs from remote domains or different * sub-domains. It also lets you enforce versioning of your RSLs by forcing an application's digest to match the * RSL's digest. If the digests are out of sync, you must recompile your application or load a different RSL SWF * file. */ @Config(advanced = true) @FlexOnly public void setVerifyDigests(ConfigurationValue cv, boolean b) { verifyDigests = b; } // // 'remove-unused-rsls' option // private boolean removeUnusedRSLs = false; /** * @return true if the user wants to remove unused RSLs. Otherwise false. */ public boolean getRemoveUnusedRsls() { return removeUnusedRSLs; } @Config(advanced = true) @FlexOnly public void setRemoveUnusedRsls(ConfigurationValue cv, boolean b) { removeUnusedRSLs = b; } // // '-include-inheritance-dependencies-only' option // private boolean includeInheritanceDependenciesOnly = false; /** * @return true if the user want to include inheritance dependencies only. */ public boolean getIncludeInheritanceDependenciesOnly() { return includeInheritanceDependenciesOnly; } @Config(advanced = true) public void setIncludeInheritanceDependenciesOnly(ConfigurationValue cv, boolean b) { includeInheritanceDependenciesOnly = b; } // // 'target-player' option // // targeted player version (also set in DefaultsConfigurator) private int majorVersionTarget = 11; private int minorVersionTarget = 1; private int revisionTarget = 0; /** * The major part the earliest player version that this compiler can target. The code generator generates bytecode * which will not pass verification on players earlier than 10.1. */ public static final int TARGET_PLAYER_MAJOR_VERSION_MIN = 10; /** * The minor part the earliest player version that this compiler can target. The code generator generates bytecode * which will not pass verification on players earlier than 10.1. */ public static final int TARGET_PLAYER_MINOR_VERSION_MIN = 1; /** * @return The major version of the player targeted by this application. The returned value will be greater to or * equal to 9. */ public int getTargetPlayerMajorVersion() { return majorVersionTarget; } /** * @return The minor version of the player targeted by this application. The returned value will be greater to or * equal to 0. */ public int getTargetPlayerMinorVersion() { return minorVersionTarget; } /** * @return The revision of the player targeted by this application. The returned value will be greater to or equal * to 0. */ public int getTargetPlayerRevision() { return revisionTarget; } /** * Specifies the version of Flash Player that you want to target with the application. Features requiring a later * version of Flash Player are not compiled into the application. * <p> * The player_version parameter has the following format:<br> * <code>major_version.minor_version.revision</code> * <p> * The major_version is required while minor_version and revision are optional. The minimum value is 10.0.0. If you * do not specify the minor_version or revision, then the compiler uses zeros. * <p> * The value of major_version is also used by the {targetPlayerMajorVersion} token in the flex-config.xml file. This * token can be used in any <path-element> element. * <p> * If you do not explicitly set the value of this option, the compiler uses the default from the flex-config.xml * file. The value in flex-config.xml is the version of Flash Player that shipped with the SDK. * <p> * This option is useful if your application's audience has a specific player and cannot upgrade. You can use this * to "downgrade" your application for that audience. */ @Config @Arguments("version") public void setTargetPlayer(ConfigurationValue cv, String version) throws ConfigurationException { if (version == null || version.equals("")) return; final String[] results = Iterables.toArray(Splitter.on(".").omitEmptyStrings().trimResults().split(version), String.class); // major.minor.revision // major is required, minor and revision are optional if (results.length < 1 || results.length > 3) throw new ConfigurationException.BadVersion(version, "target-player"); final String majorVersion = results[0]; final String minorVersion; if (results.length > 1) minorVersion = results[1]; else minorVersion = "0"; final String revision; if (results.length > 2) revision = results[2]; else revision = "0"; try { majorVersionTarget = Integer.parseInt(majorVersion); minorVersionTarget = Integer.parseInt(minorVersion); revisionTarget = Integer.parseInt(revision); } catch (NumberFormatException e) { throw new ConfigurationException.BadVersion(version, "target-player"); } if (majorVersionTarget < TARGET_PLAYER_MAJOR_VERSION_MIN || majorVersionTarget == TARGET_PLAYER_MAJOR_VERSION_MIN && minorVersionTarget < TARGET_PLAYER_MINOR_VERSION_MIN) { throw new ConfigurationException.BadVersion(version, "target-player"); } } // // 'swf-version' option // // swf version 13 is what shipped with player 11, and is the min version for // LZMA compression private static final Map<String, Integer> targetPlayerToSWFVersionMap = getSwfVersionMap(); private static Map<String, Integer> getSwfVersionMap() { // Player 9 and below are not supported. // 10.0 -> 10 // 10.1 -> 10 // 10.2 -> 11 // 10.3 -> 12 // 11.0 -> 13 // 11.1 -> 14 // 11.2 -> 15 // 11.3 -> 16 // 11.4 -> 17 // 11.5 -> 18 // 11.6 -> 19 // 11.7 -> 20 // 11.8 -> 21 // 11.9 -> 22 Map<String, Integer> map = new HashMap<String, Integer>(10); map.put("10.0", 10); map.put("10.1", 10); map.put("10.2", 11); map.put("10.3", 12); map.put("11.0", 13); map.put("11.1", 14); map.put("11.2", 15); map.put("11.3", 16); map.put("11.4", 17); map.put("11.5", 18); map.put("11.6", 19); map.put("11.7", 20); map.put("11.8", 21); map.put("11.9", 22); return map; } private int lookupSwfVersion() { int swfVersion = DEFAULT_SWF_VERSION; Integer lookupVersion = targetPlayerToSWFVersionMap.get(Integer.toString(getTargetPlayerMajorVersion()) + "." + Integer.toString(getTargetPlayerMinorVersion())); if (lookupVersion != null) swfVersion = lookupVersion; return swfVersion; } private final int UNSET_SWF_VERSION = -1; private final int DEFAULT_SWF_VERSION = 14; // matches default target-player private final int MINIMUM_SWF_VERSION = 10; // matches minimum target-player private int swfVersion = UNSET_SWF_VERSION; public int getSwfVersion() { if (swfVersion == UNSET_SWF_VERSION) swfVersion = lookupSwfVersion(); return swfVersion; } @Config @Mapping("swf-version") public void setSwfVersion(ConfigurationValue cv, int version) throws ConfigurationException { if (version < MINIMUM_SWF_VERSION) throw new ConfigurationException.BadVersion(Integer.toString(version), "swf-version"); swfVersion = version; } // // 'use-direct-blit' option // private boolean useDirectBlit = true; public boolean getUseDirectBlit() { return useDirectBlit; } @Config public void setUseDirectBlit(ConfigurationValue cv, boolean value) { useDirectBlit = value; } // // 'use-gpu' option // private boolean useGpu = true; public boolean getUseGpu() { return useGpu; } @Config public void setUseGpu(ConfigurationValue cv, boolean value) { useGpu = value; } // // 'tools-locale' options // private Locale toolsLocale = null; /** * @return locale to use when reporting compile time errors, or <code>null</code> if not specified. In that case, * system's locale is used. */ public Locale getToolsLocale() { return toolsLocale; } /** * Configures the LocalizationManager's locale, which is used when reporting compile time errors, warnings, and * info. * * @param toolsLocale A locale in Java format. For example, "en" or "ja_JP". * @throws ConfigurationException When the specified toolsLocale is not available a ToolsLocaleNotAvailable error is * reported. */ @Config @Mapping("tools-locale") public void setToolsLocale(ConfigurationValue cv, String toolsLocale) throws ConfigurationException { Locale[] locales = Locale.getAvailableLocales(); for (int i = 0; i < locales.length; i++) { if (locales[i].toString().equals(toolsLocale)) { this.toolsLocale = locales[i]; LocalizationManager.get().setLocale(locales[i]); return; } } throw new ConfigurationException.ToolsLocaleNotAvailable(cv.getVar(), cv.getSource(), cv.getLine()); } // // 'compiler.accessible' option // private boolean accessible = false; public boolean getCompilerAccessible() { return accessible; } /** * Enables accessibility features when compiling the application or SWC file. */ @Config @Mapping({ "compiler", "accessible" }) @FlexOnly public void setCompilerAccessible(ConfigurationValue cv, boolean accessible) { this.accessible = accessible; } // // 'compiler.actionscript-file-encoding' option // private String actionscriptFileEncoding = null; public String getCompilerActionscriptFileEncoding() { return actionscriptFileEncoding; } /** * Sets the file encoding for ActionScript files. */ @Config @Mapping({ "compiler", "actionscript-file-encoding" }) public void setCompilerActionscriptFileEncoding(ConfigurationValue cv, String encoding) { actionscriptFileEncoding = encoding; } // // 'compiler.adjust-opdebugline' option (hidden) // private boolean adjustOpDebugLine = true; public boolean getAdjustOpDebugLine() { return adjustOpDebugLine; } /** * For internal use only. Set it to false so that debugging mxmlc auto-generated code is easier. */ @Config(advanced = true, hidden = true) public void setCompilerAdjustOpdebugline(ConfigurationValue cv, boolean b) { adjustOpDebugLine = b; } // // 'compiler.allow-source-path-overlap' option // private boolean allowSourcePathOverlap = false; public boolean getAllowSourcePathOverlap() { return allowSourcePathOverlap; } /** * Checks if a source-path entry is a sub-directory of another source-path entry. It helps make the package names of * MXML components unambiguous. */ @Config(advanced = true) public void setCompilerAllowSourcePathOverlap(ConfigurationValue cv, boolean b) { allowSourcePathOverlap = b; } // // 'compiler.binding-value-change-event' option // private String bindingValueChangeEvent = "mx.events.PropertyChangeEvent"; public String getBindingValueChangeEvent() { return bindingValueChangeEvent; } /** * The change event class for generated binding code */ @Config(advanced = true) public void setCompilerBindingValueChangeEvent(ConfigurationValue cv, String b) { bindingValueChangeEvent = b; } // // 'compiler.binding-value-change-event-kind' option // private String bindingValueChangeEventKind = "mx.events.PropertyChangeEventKind"; public String getBindingValueChangeEventKind() { return bindingValueChangeEventKind; } /** * The change event kind for generated binding code */ @Config(advanced = true) public void setCompilerBindingValueChangeEventKind(ConfigurationValue cv, String b) { bindingValueChangeEventKind = b; } // // 'compiler.binding-value-change-event-type' option // private String bindingValueChangeEventType = "propertyChange"; public String getBindingValueChangeEventType() { return bindingValueChangeEventType; } /** * The change event type for generated binding code */ @Config(advanced = true) public void setCompilerBindingValueChangeEventType(ConfigurationValue cv, String b) { bindingValueChangeEventType = b; } // // 'compiler.binding-event-handler-event' option // private String bindingEventHandlerEvent = "flash.events.Event"; public String getBindingEventHandlerEvent() { return bindingEventHandlerEvent; } /** * The event handler event for generated binding code */ @Config(advanced = true) public void setCompilerBindingEventHandlerEvent(ConfigurationValue cv, String b) { bindingEventHandlerEvent = b; } // // 'compiler.binding-event-handler-class' option // private String bindingEventHandlerClass = "flash.events.EventDispatcher"; public String getBindingEventHandlerClass() { return bindingEventHandlerClass; } /** * The event handler class for generated binding code */ @Config(advanced = true) public void setCompilerBindingEventHandlerClass(ConfigurationValue cv, String b) { bindingEventHandlerClass = b; } // // 'compiler.binding-event-handler-interface' option // private String bindingEventHandlerInterface = "flash.events.IEventDispatcher"; public String getBindingEventHandlerInterface() { return bindingEventHandlerInterface; } /** * The event handler interface for generated binding code */ @Config(advanced = true) public void setCompilerBindingEventHandlerInterface(ConfigurationValue cv, String b) { bindingEventHandlerInterface = b; } // // 'compiler.byte-array-embed-class' option // private String byteArrayEmbedClass = "mx.core.ByteArrayAsset"; public String getByteArrayEmbedClass() { return byteArrayEmbedClass; } /** * The class for embedded byte arrays */ @Config(advanced = true) public void setCompilerByteArrayEmbedClass(ConfigurationValue cv, String b) { byteArrayEmbedClass = b; } // // 'compiler.states-class' option // private String statesClass = "mx.states.State"; public String getStatesClass() { return statesClass; } /** * The class for states */ @Config(advanced = true) public void setCompilerStatesClass(ConfigurationValue cv, String b) { statesClass = b; } // // 'compiler.states-instance-override-class' option // private String statesInstanceOverrideClass = "mx.states.AddItems"; public String getStatesInstanceOverrideClass() { return statesInstanceOverrideClass; } /** * The class for state-dependent instances */ @Config(advanced = true) public void setCompilerStatesInstanceOverrideClass(ConfigurationValue cv, String b) { statesInstanceOverrideClass = b; } // // 'compiler.states-property-override-class' option // private String statesPropertyOverrideClass = "mx.states.SetProperty"; public String getStatesPropertyOverrideClass() { return statesPropertyOverrideClass; } /** * The class for state-dependent properties */ @Config(advanced = true) public void setCompilerStatesPropertyOverrideClass(ConfigurationValue cv, String b) { statesPropertyOverrideClass = b; } // // 'compiler.states-event-override-class' option // private String statesEventOverrideClass = "mx.states.SetEventHandler"; public String getStatesEventOverrideClass() { return statesEventOverrideClass; } /** * The class for state-dependent events */ @Config(advanced = true) public void setCompilerStatesEventOverrideClass(ConfigurationValue cv, String b) { statesEventOverrideClass = b; } // // 'compiler.states-style-override-class' option // private String statesStyleOverrideClass = "mx.states.SetStyle"; public String getStatesStyleOverrideClass() { return statesStyleOverrideClass; } /** * The class for state-dependent styles */ @Config(advanced = true) public void setCompilerStatesStyleOverrideClass(ConfigurationValue cv, String b) { statesStyleOverrideClass = b; } // // 'compiler.proxy-base-class' option // private String proxyBaseClass = "org.apache.flex.utils.Proxy"; public String getProxyBaseClass() { return proxyBaseClass; } /** * The class for proxy code generation */ @Config(advanced = true) public void setCompilerProxyBaseClass(ConfigurationValue cv, String b) { proxyBaseClass = b; } // // 'compiler.component-factory-class' option // private String componentFactoryClass = "mx.core.ClassFactory"; public String getComponentFactoryClass() { return componentFactoryClass; } /** * The class for inline component factories */ @Config(advanced = true) public void setCompilerComponentFactoryClass(ConfigurationValue cv, String b) { componentFactoryClass = b; } // // 'compiler.component-factory-interface' option // private String componentFactoryInterface = "mx.core.IFactory"; public String getComponentFactoryInterface() { return componentFactoryInterface; } /** * The interface for inline component factories */ @Config(advanced = true) public void setCompilerComponentFactoryInterface(ConfigurationValue cv, String b) { componentFactoryInterface = b; } /** * Syntax:<br/> * <code>-define=<name>,<value></code> where name is <code>NAMESPACE::name</code> and value is a legal * definition value (e.g. <code>true</code> or <code>1</code> or <code>!CONFIG::debugging</code>) * * Example: <code>-define=CONFIG::debugging,true</code> * * In <code>flex-config.xml</code>:<br/> * * <pre> * <flex-config> * <compiler> * <define> * <name>CONFIG::debugging</name> * <value>true</value> * </define> * ... * </compile> * </flex-config> * </pre> * * Values:<br/> * Values are ActionScript expressions that must coerce and evaluate to constants at compile-time. Effectively, they * are replaced in AS code, verbatim, so <code>-define=TEST::oneGreaterTwo,"1>2"</code> will getCompiler coerced and * evaluated, at compile-time, to <code>false</code>. * * It is good practice to wrap values with double-quotes, so that MXMLC correctly parses them as a single argument: * <br/> * <code>-define=TEST::oneShiftRightTwo,"1 >> 2"</code> * * Values may contain compile-time constants and other configuration values:<br/> * <code>-define=CONFIG::bool2,false -define=CONFIG::and1,"CONFIG::bool2 && false" TestApp.mxml</code> * * String values on the command-line <i>must</i> be surrounded by double-quotes, and either escape-quoted ( * <code>"\"foo\""</code> or <code>"\'foo\'"</code>) or single-quoted (<code>"'foo'"</code>). * * String values in configuration files need only be single- or double- quoted:<br/> * * <pre> * <flex-config> * <compiler> * <define> * <name>NAMES::Organization</name> * <value>'Apache Software Foundation'</value> * </define> * <define> * <name>NAMES::Application</name> * <value>"Flex 4.8.0"</value> * </define> * ... * </compile> * </flex-config> * </pre> * * Empty strings <i>must</i> be passed as <code>"''"</code> on the command-line, and <code>''</code> or * <code>""</code> in configuration files. * * Finally, if you have existing definitions in a configuration file, and you would like to add to them with the * command-line (let's say most of your build setCompilertings are in the configuration, and that you are adding one * temporarily using the command-line), you use the following syntax: <code>-define+=TEST::temporary,false</code> * (noting the plus sign) * * Note that definitions can be overridden/redefined if you use the append ("+=") syntax (on the commandline or in a * user config file, for instance) with the same namespace and name, and a new value. * * Definitions cannot be removed/undefined. You can undefine ALL existing definitions from (e.g. from * flex-config.xml) if you do not use append syntax ("=" or append="false"). * * IMPORTANT FOR FLEXBUILDER If you are using "Additional commandline arguments" to "-define", don't use the * following syntax though I suggest it above: -define+=CONFIG::foo,"'value'" The trouble is that FB parses the * double quotes incorrectly as <"'value'> -- the trailing double-quote is dropped. The solution is to avoid inner * double-quotes and put them around the whole expression: -define+="CONFIG::foo,'value'" */ private Map<String, String> configVars; /** * @return A list of ConfigVars */ public Map<String, String> getCompilerDefine() { return configVars; } @Config(advanced = true, allowMultiple = true) @Arguments({ "name", "value" }) public void setCompilerDefine(ConfigurationValue cv, String name, String value) throws ConfigurationException { if (configVars == null) configVars = new LinkedHashMap<String, String>(); configVars.put(name, value); } // // 'compiler.conservative' option (hidden) // private boolean useConservativeAlgorithm = false; public boolean useConservativeAlgorithm() { return useConservativeAlgorithm; } @Config(advanced = true, hidden = true) @Mapping({ "compiler", "conservative" }) public void setCompilerConservative(ConfigurationValue cv, boolean c) { useConservativeAlgorithm = c; } // // 'compiler.context-root' option // private String contextRoot = null; public String getCompilerContextRoot() { return contextRoot; } /** * "Context root" is used to resolve {context.root} tokens in services configuration files to improve portability. */ @Config @Mapping({ "compiler", "context-root" }) @Arguments("context-path") @FlexOnly public void setCompilerContextRoot(ConfigurationValue cv, String contextRoot) { this.contextRoot = contextRoot; } // // 'compiler.debug' option // private boolean generateDebugTags = false; public boolean isDebuggingEnabled() { return generateDebugTags; } protected void setDebug(boolean value) { generateDebugTags = value; } @Config @Mapping({ "compiler", "debug" }) public void setCompilerDebug(ConfigurationValue cv, boolean generateDebugTags) { this.generateDebugTags = generateDebugTags; } // // 'compiler.defaults-css-url' option // /** * Location of defaults stylesheet. */ private String defaultsCssUrl; public String getCompilerDefaultsCssUrl() { return defaultsCssUrl; } /** * Defines the location of the default style sheet. Setting this option overrides the implicit use of the * defaults.css style sheet in the framework.swc file. */ @Config(advanced = true) @Mapping({ "compiler", "defaults-css-url" }) @FlexOnly public void setCompilerDefaultsCssUrl(ConfigurationValue cv, String defaultsCssUrlPath) throws CannotOpen { defaultsCssUrl = resolvePathStrict(defaultsCssUrlPath, cv); } // // 'compiler.doc' option (hidden) // private boolean doc = false; public boolean getCompilerDoc() { return this.doc; } @Config(advanced = true, hidden = true) @Mapping({ "compiler", "doc" }) public void setCompilerDoc(ConfigurationValue cv, boolean doc) { this.doc = doc; } // // 'compiler.external-library-path' option // private final List<String> externalLibraryPath = new ArrayList<String>(); public List<String> getCompilerExternalLibraryPath() { return externalLibraryPath; } private boolean compilingForAIR = false; /** * @return True if AIR libraries are included in the {@code external-library-path}. */ public boolean getCompilingForAIR() { return compilingForAIR; } @Config(allowMultiple = true, isPath = true) @Mapping({ "compiler", "external-library-path" }) @Arguments(Arguments.PATH_ELEMENT) @SoftPrerequisites({ "target-player", "exclude-native-js-libraries" }) @InfiniteArguments public void setCompilerExternalLibraryPath(ConfigurationValue cv, String[] pathlist) throws ConfigurationException { pathlist = removeNativeJSLibrariesIfNeeded(pathlist); final ImmutableList<String> pathElements = ImmutableList.copyOf(pathlist); final ImmutableList<String> resolvedPaths = expandTokens(pathElements, locales, cv, !reportMissingCompilerLibraries); externalLibraryPath.addAll(resolvedPaths); // TODO: Review usages of "compilingForAIR", because only looking at path elements // on library path isn't enough. There might be a folder on the library path that // contains AIR libraries. compilingForAIR = containsAIRLibraries(pathElements); } /** * Returns true if there's AIR libraries on the library paths. * * @param libraryPaths Library paths. * @return True if there's AIR libraries on the library paths. */ private static boolean containsAIRLibraries(final ImmutableList<String> libraryPaths) { for (final String path : libraryPaths) { if (path.equals(SWC_AIRGLOBAL) || path.endsWith("/" + SWC_AIRGLOBAL) || path.endsWith("\\" + SWC_AIRGLOBAL)) { return true; } } return false; } // // 'compiler.generated-directory' option // This can only be configured using getter and setter. // private String generatedDir = null; public String getCompilerGeneratedDirectory() { return generatedDir; } public void setCompilerGeneratedDirectory(String generatedDir) { this.generatedDir = generatedDir; } // // 'compiler.headless-server' option // private boolean headlessServer; public boolean isHeadlessServer() { return headlessServer; } @Config(advanced = true) @Mapping({ "compiler", "headless-server" }) @FlexOnly public void setCompilerHeadlessServer(ConfigurationValue cv, boolean headlessServer) { this.headlessServer = headlessServer; } // // 'compiler.include-libraries' option // private final List<String> includeLibraries = new ArrayList<String>(); public List<String> getCompilerIncludeLibraries() { return includeLibraries; } /** * Links all classes inside a SWC file to the resulting application SWF file, regardless of whether or not they are * used. * <p> * Contrast this option with the library-path option that includes only those classes that are referenced at compile * time. * <p> * To link one or more classes whether or not they are used and not an entire SWC file, use the includes option. * <p> * This option is commonly used to specify resource bundles. */ @Config(allowMultiple = true, isPath = true) @Mapping({ "compiler", "include-libraries" }) @Arguments("library") @InfiniteArguments public void setCompilerIncludeLibraries(ConfigurationValue cv, String[] pathlist) throws CannotOpen { final ImmutableList<String> resolvedPaths = expandTokens(Arrays.asList(pathlist), locales, cv, !reportMissingCompilerLibraries); includeLibraries.addAll(resolvedPaths); } // // 'compiler.incremental' option // @Config(removed = true) @Mapping({ "compiler", "incremental" }) public void setCompilerIncremental(ConfigurationValue cv, boolean b) { } // // 'compiler.keep-all-type-selectors' option. /** * This was initially used by Flex Builder when building design view, but they no longer use it. */ private boolean keepAllTypeSelectors; public boolean keepAllTypeSelectors() { return keepAllTypeSelectors; } @Config(advanced = true) @Mapping({ "compiler", "keep-all-type-selectors" }) @FlexOnly public void setCompilerKeepAllTypeSelectors(ConfigurationValue cv, boolean keepAllTypeSelectors) { this.keepAllTypeSelectors = keepAllTypeSelectors; } // // 'compiler.keep-as3-metadata' option // private Set<String> as3metadata = null; public Set<String> getCompilerKeepAs3Metadata() { return as3metadata == null ? Collections.<String> emptySet() : as3metadata; } @Config(advanced = true, allowMultiple = true) @Mapping({ "compiler", "keep-as3-metadata" }) @Arguments("name") @InfiniteArguments public void setCompilerKeepAs3Metadata(ConfigurationValue cv, List<String> values) { if (as3metadata == null) as3metadata = new HashSet<String>(); as3metadata.addAll(values); } // // 'compiler.keep-generated-actionscript' option (removed) // @Config(removed = true) @Mapping({ "compiler", "keep-generated-actionscript" }) public void setCompilerKeepGeneratedActionscript(ConfigurationValue cv, boolean keep) { } // // 'compiler.keep-generated-signatures' option (removed) // @Config(removed = true) @Mapping({ "compiler", "keep-generated-signatures" }) public void setCompilerKeepGeneratedSignatures(ConfigurationValue cv, boolean keep) { } // // 'compiler.enable-runtime-design-layers' option // private boolean enableRuntimeDesignLayers = true; public boolean getEnableRuntimeDesignLayers() { return enableRuntimeDesignLayers; } @Config @Mapping({ "compiler", "enable-runtime-design-layers" }) @FlexOnly public void setCompilerEnableRuntimeDesignLayers(ConfigurationValue cv, boolean enable) { enableRuntimeDesignLayers = enable; } // // 'compiler.enable-swc-version-filtering' option // private boolean enableSwcVersionFiltering = true; public boolean getEnableSwcVersionFiltering() { return enableSwcVersionFiltering; } @Config(advanced = true, hidden = true) @Mapping({ "compiler", "enable-swc-version-filtering" }) public void setCompilerEnableSwcVersionFiltering(ConfigurationValue cv, boolean enable) { this.enableSwcVersionFiltering = enable; } // // 'compiler.library-path' option // private final List<String> libraryPath = new ArrayList<String>(); private boolean reportMissingCompilerLibraries = true; /** * Sets whether to report missing libraries in the configuration. If this is false any missing libraries will not be * warned about, and the filename will also be added to list of libraries in the project when it doesn't exist. If * reportMissingCompilerLibraries is true, any missing libraries will not be added to the project. * * @param reportMissingCompilerLibraries true to report missing libraries */ public void setReportMissingCompilerLibraries(boolean reportMissingCompilerLibraries) { this.reportMissingCompilerLibraries = reportMissingCompilerLibraries; } public List<String> getCompilerLibraryPath() { return libraryPath; } /** * Links SWC files to the resulting application SWF file. The compiler only links in those classes for the SWC file * that are required. You can specify a directory or individual SWC files. */ @Config(allowMultiple = true, isPath = true) @Mapping({ "compiler", "library-path" }) @Arguments(Arguments.PATH_ELEMENT) @InfiniteArguments @SoftPrerequisites({ "locale", "target-player", "exclude-native-js-libraries" }) public void setCompilerLibraryPath(ConfigurationValue cv, String[] pathlist) throws CannotOpen { pathlist = removeNativeJSLibrariesIfNeeded(pathlist); final ImmutableList<String> resolvedPaths = expandTokens(Arrays.asList(pathlist), locales, cv, !reportMissingCompilerLibraries); libraryPath.addAll(resolvedPaths); } // // 'compiler.locale' option // private final List<String> locales = new ArrayList<String>(); public List<String> getCompilerLocales() { return locales; } /** * Specifies one or more locales to be compiled into the SWF file. If you do not specify a locale, then the compiler * uses the default locale from the flex-config.xml file. The default value is en_US. You can append additional * locales to the default locale by using the += operator. If you remove the default locale from the flex-config.xml * file, and do not specify one on the command line, then the compiler will use the machine's locale. */ @Config(allowMultiple = true) @Mapping({ "compiler", "locale" }) @Arguments("locale-element") @InfiniteArguments @FlexOnly public void setCompilerLocale(ConfigurationValue cv, String[] newLocales) { locales.addAll(Arrays.asList(newLocales)); } // // 'compiler.metadata-export' option (incomplete) // private boolean metadataExport; public boolean metadataExport() { return metadataExport; } // metadataExport does not have the normal configuration setCompilerter because it is not // a normal configuration value but rather something setCompiler by the compiler public void setCompilerMetadataExport(boolean metadataExport) { this.metadataExport = metadataExport; } // // 'compiler.mxml.children-as-data' option // private Boolean childrenAsData = false; public Boolean getCompilerMxmlChildrenAsData() { return childrenAsData; } @Config @Mapping({ "compiler", "mxml", "children-as-data" }) @FlexOnly public void setCompilerMxmlChildrenAsData(ConfigurationValue cv, Boolean asData) throws ConfigurationException { childrenAsData = asData; } // // 'compiler.info.flex' option // used to suppress some of info() fields // private Boolean infoFlex = true; public Boolean getCompilerInfoFlex() { return infoFlex; } @Config @Mapping({ "compiler", "info", "flex" }) @FlexOnly public void setCompilerInfoFlex(ConfigurationValue cv, Boolean asData) throws ConfigurationException { infoFlex = asData; } // // 'compiler.allow-subclass-overrides' option // private Boolean allowSubclassOverrides = false; public Boolean getCompilerAllowSubclassOverrides() { return allowSubclassOverrides; } @Config @Mapping({ "compiler", "allow-subclass-overrides" }) @FlexOnly public void setCompilerAllowSubclassOverrides(ConfigurationValue cv, Boolean allow) throws ConfigurationException { allowSubclassOverrides = allow; } // // 'compiler.mxml.implicitImports' option // private String[] implicitImports; public String[] getCompilerMxmlImplicitImports() { return implicitImports; } @Config(allowMultiple = true) @Mapping({ "compiler", "mxml", "imports" }) @Arguments("implicit-import") @InfiniteArguments @FlexOnly public void setCompilerMxmlImplicitImports(ConfigurationValue cv, String[] imports) throws ConfigurationException { implicitImports = imports; } // // 'compiler.mxml.compatibility-version' option // public String getCompilerCompatibilityVersionString() { return getCompilerMxmlCompatibilityVersionString(); } public int getCompilerCompatibilityVersion() { return getCompilerMxmlCompatibilityVersion(); } // // 'compiler.mxml.minimum-supported-version' option // public String getCompilerMinimumSupportedVersionString() { return getCompilerMxmlMinimumSupportedVersionString(); } public int getCompilerMinimumSupportedVersion() { return getCompilerMxmlMinimumSupportedVersion(); } @Config @Mapping({ "compiler", "minimum-supported-version" }) @FlexOnly public void setCompilerMinimumSupportedVersion(ConfigurationValue cv, String version) throws ConfigurationException { setCompilerMxmlMinimumSupportedVersion(cv, version); } // // 'qualified-type-selectors' option // @Config(advanced = true, removed = true) @Mapping({ "compiler", "mxml", "qualified-type-selectors" }) public void setCompilerMxmlQualifiedTypeSelectors(ConfigurationValue cv, boolean b) { } // // 'compiler.omit-trace-statements' option // private boolean omitTraceStatements = true; public boolean omitTraceStatements() { return omitTraceStatements; } @Config @Mapping({ "compiler", "omit-trace-statements" }) public void setCompilerOmitTraceStatements(ConfigurationValue cv, boolean b) { omitTraceStatements = b; } // // 'compiler.optimize' option // private boolean optimize = false; public boolean optimize() { return optimize; } public boolean getCompilerOptimize() { return optimize; } @Config @Mapping({ "compiler", "optimize" }) public void setCompilerOptimize(ConfigurationValue cv, boolean b) { optimize = b; } // // 'compiler.preloader' option // private String preloader = null; /** * * @return Returns the preloader class configured by the user. If the user did not configure a preloader, the * "mx.preloader.DownloaderProgressBar" preloader will be returned if the compatibility version is less than * 4.0. Otherwise the "mx.preloaders.SparkDownloadProgressBar" preloader will be returned. */ public String getPreloader() { if (preloader != null) return preloader; if (getCompilerMxmlCompatibilityVersion() < MXML_VERSION_4_0) return IMXMLTypeConstants.DownloadProgressBar; else return IMXMLTypeConstants.SparkDownloadProgressBar; } public String getCompilerPreloader() { return preloader; } @Config @Mapping({ "compiler", "preloader" }) @FlexOnly public void setCompilerPreloader(ConfigurationValue cv, String value) { preloader = value; } // // 'compiler.services' option // private File servicesConfigFile; //protected ServicesDependencies servicesDependencies; public File getCompilerServices() { return servicesConfigFile; } /** * Used by the compiler to record the client dependencies from the Flex Data Services configuration file. */ /* * public ServicesDependencies getCompilerServicesDependencies() { if * (servicesDependencies == null && servicesConfigFile != null) { String * servicesPath = servicesConfigFile.getName(); servicesDependencies = new * ServicesDependencies(servicesPath, null, getCompilerContextRoot()); } * return servicesDependencies; } public void * setCompilerServicesDependencies(ServicesDependencies deps) { * servicesDependencies = deps; } */ @Config @Mapping({ "compiler", "services" }) @Arguments("filename") @FlexOnly public void setCompilerServices(ConfigurationValue cv, String servicesPath) throws ConfigurationException { try { servicesConfigFile = new File(resolvePathStrict(servicesPath, cv)); } catch (Exception e) { throw new ConfigurationException.CannotOpen(servicesPath, cv.getVar(), cv.getSource(), cv.getLine()); } } // // 'compiler.show-actionscript-warnings' option // /** * Enable asc -warnings */ private boolean ascWarnings; public boolean warnings() { return this.ascWarnings; } @Config @Mapping({ "compiler", "show-actionscript-warnings" }) public void setCompilerShowActionscriptWarnings(ConfigurationValue cv, boolean ascWarnings) { this.ascWarnings = ascWarnings; } // // 'compiler.show-binding-warnings' option // /** * Controls whether binding warnings are displayed. */ private boolean showBindingWarnings = true; public boolean showBindingWarnings() { return showBindingWarnings; } @Config @Mapping({ "compiler", "show-binding-warnings" }) public void setCompilerShowBindingWarnings(ConfigurationValue cv, boolean show) { this.showBindingWarnings = show; } @Config @Mapping({ "compiler", "show-multiple-definition-warnings" }) public void setCompilerShowMultipleDefinitionWarnings(ConfigurationValue cv, boolean show) { this.showMultipleDefinitionWarnings = show; } // // 'compiler.show-dependency-warnings' option (hidden) // private boolean showDependencyWarnings = false; public boolean showDependencyWarnings() { return showDependencyWarnings; } @Config(advanced = true, hidden = true) @Mapping({ "compiler", "show-dependency-warnings" }) public void setCompilerShowDependencyWarnings(ConfigurationValue cv, boolean show) { this.showDependencyWarnings = show; } // // 'compiler.report-invalid-styles-as-warnings' option // /** * Controls whether invalid styles are report as errors or warnings. */ private boolean reportInvalidStylesAsWarnings = false; /** * Get value of {@code compiler.report-invalid-styles-as-warnings} option value. * <p> * <h2>What's "invalid styles"?</h2> The term "invalid style" only applies to MXML style specifier (a.k.a. inline * style). If a style of a component is defined with "theme" attribute, the style is only effective with such theme. * If a theme-specific style is used in an application who doesn't use the required theme, the style is considered * invalid. * <p> * For example, style "fooStyle" is defined to used only with theme called "fooTheme": * * <pre> * [Style(name="fooStyle", type="uint", format="Color", inherit="yes", theme="fooTheme")] * public class MyComponent extends UIComponent * </pre> * * If "fooTheme" isn't used by the current application, the following style specifier is considered "invalid styles" * . <br> * {@code <local:MyComponent fooStyle="white" />} * * @return True if invalid styles are reported as warnings instead of errors. */ public boolean getReportInvalidStylesAsWarnings() { return reportInvalidStylesAsWarnings; } @Config @Mapping({ "compiler", "report-invalid-styles-as-warnings" }) @FlexOnly public void setCompilerReportInvalidStylesAsWarnings(ConfigurationValue cv, boolean show) { this.reportInvalidStylesAsWarnings = show; } // // 'compiler.report-missing-required-skin-parts-as-warnings' option // private boolean reportMissingRequiredSkinPartsAsWarnings = false; /** * Allow the user to configure whether it should be considered an error to not create a required skin part or if it * should just be a warning. */ public boolean reportMissingRequiredSkinPartsAsWarnings() { return reportMissingRequiredSkinPartsAsWarnings; } @Config(advanced = true) @Mapping({ "compiler", "report-missing-required-skin-parts-as-warnings" }) @FlexOnly public void setCompilerReportMissingRequiredSkinPartsAsWarnings(ConfigurationValue cv, boolean b) { reportMissingRequiredSkinPartsAsWarnings = b; } // // 'compiler.show-invalid-css-property-warnings' option // private boolean showInvalidCSSPropertyWarnings = true; /** * Controls whether warnings are displayed when styles, which don't apply to the current theme(s), are used in CSS. * <p> * See {@link #getReportInvalidStylesAsWarnings()} for definition of "invalid style". * <p> * This option applies to <i>invalid styles</i> in a {@code <fx:Style>} block. */ public boolean getShowInvalidCSSPropertyWarnings() { return showInvalidCSSPropertyWarnings; } @Config @Mapping({ "compiler", "show-invalid-css-property-warnings" }) @FlexOnly public void setShowInvalidCssPropertyWarnings(ConfigurationValue cv, boolean show) { this.showInvalidCSSPropertyWarnings = show; } // // 'compiler.show-deprecation-warnings' option // /** * Controls whether warnings are displayed when a deprecated API is used. */ private boolean showDeprecationWarnings = false; public boolean showDeprecationWarnings() { return showDeprecationWarnings; } @Config(advanced = true, hidden = true) @Mapping({ "compiler", "show-deprecation-warnings" }) public void setCompilerShowDeprecationWarnings(ConfigurationValue cv, boolean show) { this.showDeprecationWarnings = show; } // // 'compiler.show-shadowed-device-font-warnings' option // @Config @Mapping({ "compiler", "show-shadowed-device-font-warnings" }) @FlexOnly public void setCompilerShowShadowedDeviceFontWarnings(ConfigurationValue cv, boolean show) { // intentionally do nothing here as feature removed, but don't annotate as removed // as to not generate warnings for flex-config's which still set this options } // // 'compiler.show-unused-type-selector-warnings' option // private boolean showUnusedTypeSelectorWarnings = true; public boolean showUnusedTypeSelectorWarnings() { return showUnusedTypeSelectorWarnings; } // // 'compiler.show-multiple-definition-warnings' option // private boolean showMultipleDefinitionWarnings = true; public boolean showMultipleDefinitionWarnings() { return showMultipleDefinitionWarnings; } @Config @Mapping({ "compiler", "show-unused-type-selector-warnings" }) @FlexOnly public void setCompilerShowUnusedTypeSelectorWarnings(ConfigurationValue cv, boolean show) { this.showUnusedTypeSelectorWarnings = show; } // // 'compiler.source-path' option // /** * Source path elements searched for ActionScript class files, possibly containing a {locale} token. */ private final List<String> unexpandedSourcePath = new ArrayList<String>(); /** * Directories searched for ActionScript class files. The specified compiler.source-path can have path elements * which contain a special {locale} token. If you compile for a single locale, this token is replaced by the * specified locale. If you compile for multiple locales, any path element with the {locale} token is ignored, * because we do not support compiling, for example, both en_US and ja_JP versions of MyComponent into the same SWF. * A path element with {locale} is similarly ignored if you compile for no locale. */ private final List<String> sourcePath = new ArrayList<String>(); /** Context object for "source-path" option. */ private ConfigurationValue sourcePathContext = null; public List<String> getCompilerSourcePath() { return sourcePath; } /** * Get the source paths computed from the given {@code locale}. The locale must be included in the configuration. * * @param locale Locale name. * @return Source paths computed from the given {@code locale}. * @throws CannotOpen Error resolving one of the paths from this locale. */ public ImmutableList<String> getCompilerResourceBundlePathForLocale(String locale) throws CannotOpen { assert locales.contains(locale) : "Locale is not configured: " + locale; return expandTokens(unexpandedSourcePath, ImmutableSet.of(locale), sourcePathContext, !reportMissingCompilerLibraries); } @Config(allowMultiple = true) @Arguments(Arguments.PATH_ELEMENT) @SoftPrerequisites("locale") public void setCompilerSourcePath(ConfigurationValue cv, String[] paths) throws ConfigurationException { final List<String> pathList = Arrays.asList(paths); unexpandedSourcePath.addAll(pathList); final ImmutableList<String> resolvedSourcePaths = expandTokens(pathList, locales, cv); assertThatAllPathsAreDirectories(resolvedSourcePaths, cv); sourcePath.addAll(resolvedSourcePaths); sourcePathContext = cv; } /** * Check that all paths in the path list are directories. * * @param paths A list of paths. * @param cv Context. * @throws NotDirectory Path is not a directory exception. */ public static void assertThatAllPathsAreDirectories(final List<String> paths, final ConfigurationValue cv) throws NotDirectory { assert paths != null : "Expected path list."; assert cv != null : "Expected ConfigurationValue as context."; for (final String path : paths) { final File file = new File(path); if (!file.isDirectory()) throw new NotDirectory(path, cv.getVar(), cv.getSource(), cv.getLine()); } } public static ConfigurationInfo getCompilerSourcePathInfo() { return new ConfigurationInfo(-1, new String[] { "path-element" }) { @Override public boolean allowMultiple() { return true; } @Override public boolean isPath() { return true; } }; } // // 'compiler.strict' option // /** * Run the AS3 compiler in strict mode */ private boolean strict; public boolean strict() { return this.strict; } @Config @Mapping({ "compiler", "strict" }) public void setCompilerStrict(ConfigurationValue cv, boolean strict) { this.strict = strict; } // // 'compiler.suppress-warnings-in-incremental' option (incomplete) // // for Zorn // // When doing incremental compilation, the compiler doesn't recompile codes that are previously compiled with // warnings. It only outputs the warning messages so as to remind users of the warnings. // // The command-line tool and Zorn work differently in that Zorn keeps the warning logger while the commnad-line // tool, of course, can't keep the warning logger alive... // // Zorn needs this flag to tell the compiler not to output warnings again in incremental compilations because // it keeps its own log. private boolean suppressWarningsInIncremental = false; public boolean suppressWarningsInIncremental() { return suppressWarningsInIncremental; } public void setCompilerSuppressWarningsInIncremental(boolean b) { suppressWarningsInIncremental = b; } // // 'compiler.theme' option // private List<String> themeFiles = null; /** * Get normalized theme file paths. If a the compiler is in "Flex 3 compatibility" mode and only "Spark" theme is * used, it will be replaced with the legacy "Halo" theme. * * @return A list of normalized paths to the theme files. */ public List<String> getCompilerThemeFiles() { if (themeFiles == null) return EMPTY_STRING_LIST; final boolean isVersion3OrEarlier = getCompilerMxmlCompatibilityVersion() <= MXML_VERSION_3_0; final boolean hasOnlyOneThemeFile = themeFiles.size() == 1; if (isVersion3OrEarlier && hasOnlyOneThemeFile) { // Swap in the default Flex 3 theme of Halo. final String path = FilenameUtils.normalize(themeFiles.get(0), true); final String sparkPath = "/themes/Spark/spark.css"; if (path.endsWith(sparkPath)) { int index = path.indexOf(sparkPath); final String haloPath = path.substring(0, index) + "/themes/Halo/halo.swc"; themeFiles.set(0, FilenameNormalization.normalize(haloPath)); } } return themeFiles; } @Config(allowMultiple = true) @Mapping({ "compiler", "theme" }) @Arguments("filename") @InfiniteArguments @FlexOnly public void setCompilerTheme(ConfigurationValue cv, List<String> paths) throws CannotOpen { // Use "resolvePathsStrict()" if invalid theme file can't be ignored. final ImmutableList<String> resolved = resolvePathsStrict(ImmutableList.copyOf(paths), cv); if (themeFiles == null) themeFiles = new ArrayList<String>(); themeFiles.addAll(resolved); } // // 'compiler.defaults-css-files' option // private Deque<String> defaultsCSSFiles = new ArrayDeque<String>(); /** * List of filenames of defaults style stylesheets (css only). * <p> * <b>For example:</b><br> * <code>-defaults-css-files=[A, B, C]</code><br> * Then, 'A' should have precedence over 'B', then 'C', then SWCs defaultsCssFiles should have the order: SWCS, C, * B, A * * @see #setDefaultsCSSFiles */ public Deque<String> getDefaultsCSSFiles() { return defaultsCSSFiles; } /** * Inserts CSS files into the output the same way that a per-SWC defaults.css file works, but without having to * re-archive the SWC file to test each change. * <p> * CSS files included in the output with this option have a higher precedence than default CSS files in existing * SWCs. For example, a CSS file included with this option overrides definitions in framework.swc's defaults.css * file, but it has the same overall precedence as other included CSS files inside the SWC file. * <p> * This option does not actually insert the CSS file into the SWC file; it simulates it. When you finish developing * the CSS file, you should rebuild the SWC file with the new integrated CSS file. * <p> * This option takes one or more files. The precedence for multiple CSS files included with this option is from * first to last. */ @Config(allowMultiple = true, advanced = true) @Mapping({ "compiler", "defaults-css-files" }) @Arguments("filename") @InfiniteArguments @FlexOnly public void setDefaultsCSSFiles(ConfigurationValue cv, List<String> paths) throws CannotOpen { final ImmutableList<String> resolved = resolvePathsStrict(ImmutableList.copyOf(paths), cv); for (final String path : resolved) { defaultsCSSFiles.addFirst(path); } } // // 'compiler.exclude-defaults-css-files' option // private Deque<String> excludeDefaultsCSSFiles = new ArrayDeque<String>(); /** * List of filenames to exclude from list of defaults style stylesheets (css only). * For defaults.css files in a SWC, use HTML.swc:defaults.css where HTML is the * name of a SWC. * <p> * <b>For example:</b><br> * <code>-exclude-defaults-css-files=[A, B, C]</code><br> * Then, 'A' should have precedence over 'B', then 'C', then SWCs defaultsCssFiles should have the order: SWCS, C, * B, A * * @see #setExcludeDefaultsCSSFiles */ public Deque<String> getExcludeDefaultsCSSFiles() { return excludeDefaultsCSSFiles; } /** * Excludes CSS files from the output. * <p> * This option takes one or more files. The precedence for multiple CSS files included with this option is from * first to last. */ @Config(allowMultiple = true, advanced = true) @Mapping({ "compiler", "exclude-defaults-css-files" }) @Arguments("filename") @InfiniteArguments @FlexOnly public void setExcludeDefaultsCSSFiles(ConfigurationValue cv, List<String> paths) throws CannotOpen { final ImmutableList<String> resolved = resolvePathsStrict(ImmutableList.copyOf(paths), cv, true); for (final String path : resolved) { excludeDefaultsCSSFiles.addFirst(path); } } /** * Location of theme style stylesheets (css only, configured via themefiles above). */ private List<IFileSpecification> themeCssFiles = new LinkedList<IFileSpecification>(); public List<IFileSpecification> getCompilerThemeCssFiles() { return themeCssFiles; } public void addThemeCssFiles(List<IFileSpecification> files) { themeCssFiles.addAll(files); } // // 'compiler.use-resource-bundle-metadata' option // @Config(removed = true) @Mapping({ "compiler", "use-resource-bundle-metadata" }) public void setCompilerUseResourceBundleMetadata(ConfigurationValue cv, boolean b) { } // // 'compiler.verbose-stacktraces' option // private boolean verboseStacktraces; // from as3 and mxml configuration interface public boolean debug() { // the debug() in as3 and mxml configuration maps to stacktraceLineNumbers return verboseStacktraces; } public boolean release() { return !verboseStacktraces; } @Config @Mapping({ "compiler", "verbose-stacktraces" }) public void setCompilerVerboseStacktraces(ConfigurationValue cv, boolean verboseStacktraces) { if (generateDebugTags) { this.verboseStacktraces = true; } else { this.verboseStacktraces = verboseStacktraces; } } // // 'compiler.warn-array-tostring-changes' option // private boolean warn_array_tostring_changes = false; public boolean warn_array_tostring_changes() { return warn_array_tostring_changes; } @Config(advanced = true) @Mapping({ "compiler", "warn-array-tostring-changes" }) public void setCompilerWarnArrayTostringChanges(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_array_tostring_changes) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-assignment-within-conditional' option // private boolean warn_assignment_within_conditional = true; public boolean warn_assignment_within_conditional() { return warn_assignment_within_conditional; } @Config(advanced = true) @Mapping({ "compiler", "warn-assignment-within-conditional" }) public void setCompilerWarnAssignmentWithinConditional(ConfigurationValue cv, boolean b) { warn_assignment_within_conditional = b; } // // 'compiler.warn-bad-array-cast' option // private boolean warn_bad_array_cast = true; public boolean warn_bad_array_cast() { return warn_bad_array_cast; } @Config(advanced = true) @Mapping({ "compiler", "warn-bad-array-cast" }) public void setCompilerWarnBadArrayCast(ConfigurationValue cv, boolean b) { warn_bad_array_cast = b; } // // 'compiler.warn-bad-bool-assignment' option // private boolean warn_bad_bool_assignment = true; public boolean warn_bad_bool_assignment() { return warn_bad_bool_assignment; } @Config(advanced = true) @Mapping({ "compiler", "warn-bad-bool-assignment" }) public void setCompilerWarnBadBoolAssignment(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_bad_bool_assignment) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-bad-date-cast' option // private boolean warn_bad_date_cast = true; public boolean warn_bad_date_cast() { return warn_bad_date_cast; } @Config(advanced = true) @Mapping({ "compiler", "warn-bad-date-cast" }) public void setCompilerWarnBadDateCast(ConfigurationValue cv, boolean b) { warn_bad_date_cast = b; } // // 'compiler.warn-bad-es3-type-method' option // private boolean warn_bad_es3_type_method = true; public boolean warn_bad_es3_type_method() { return warn_bad_es3_type_method; } @Config(advanced = true) @Mapping({ "compiler", "warn-bad-es3-type-method" }) public void setCompilerWarnBadEs3TypeMethod(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_bad_es3_type_method) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-bad-es3-type-prop' option // private boolean warn_bad_es3_type_prop = true; public boolean warn_bad_es3_type_prop() { return warn_bad_es3_type_prop; } @Config(advanced = true) @Mapping({ "compiler", "warn-bad-es3-type-prop" }) public void setCompilerWarnBadEs3TypeProp(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_bad_es3_type_prop) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-bad-nan-comparison' option // private boolean warn_bad_nan_comparison = true; public boolean warn_bad_nan_comparison() { return warn_bad_nan_comparison; } @Config(advanced = true) @Mapping({ "compiler", "warn-bad-nan-comparison" }) public void setCompilerWarnBadNanComparison(ConfigurationValue cv, boolean b) { warn_bad_nan_comparison = b; } // // 'compiler.warn-bad-null-assignment' option // private boolean warn_bad_null_assignment = true; public boolean warn_bad_null_assignment() { return warn_bad_null_assignment; } @Config(advanced = true) @Mapping({ "compiler", "warn-bad-null-assignment" }) public void setCompilerWarnBadNullAssignment(ConfigurationValue cv, boolean b) { warn_bad_null_assignment = b; } // // 'compiler.warn-bad-null-comparison' option // private boolean warn_bad_null_comparison = true; public boolean warn_bad_null_comparison() { return warn_bad_null_comparison; } @Config(advanced = true) @Mapping({ "compiler", "warn-bad-null-comparison" }) public void setCompilerWarnBadNullComparison(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_bad_null_comparison) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-bad-undefined-comparison' option // private boolean warn_bad_undefined_comparison = true; public boolean warn_bad_undefined_comparison() { return warn_bad_undefined_comparison; } @Config(advanced = true) @Mapping({ "compiler", "warn-bad-undefined-comparison" }) public void setCompilerWarnBadUndefinedComparison(ConfigurationValue cv, boolean b) { warn_bad_undefined_comparison = b; } // // 'compiler.warn-boolean-constructor-with-no-args' option // private boolean warn_boolean_constructor_with_no_args = false; public boolean warn_boolean_constructor_with_no_args() { return warn_boolean_constructor_with_no_args; } @Config(advanced = true) @Mapping({ "compiler", "warn-boolean-constructor-with-no-args" }) public void setCompilerWarnBooleanConstructorWithNoArgs(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_boolean_constructor_with_no_args) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-changes-in-resolve' option // private boolean warn_changes_in_resolve = false; public boolean warn_changes_in_resolve() { return warn_changes_in_resolve; } @Config(advanced = true) @Mapping({ "compiler", "warn-changes-in-resolve" }) public void setCompilerWarnChangesInResolve(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_changes_in_resolve) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-class-is-sealed' option // private boolean warn_class_is_sealed = true; public boolean warn_class_is_sealed() { return warn_class_is_sealed; } @Config(advanced = true) @Mapping({ "compiler", "warn-class-is-sealed" }) public void setCompilerWarnClassIsSealed(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_class_is_sealed) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-const-not-initialized' option // private boolean warn_const_not_initialized = true; public boolean warn_const_not_initialized() { return warn_const_not_initialized; } @Config(advanced = true) @Mapping({ "compiler", "warn-const-not-initialized" }) public void setCompilerWarnConstNotInitialized(ConfigurationValue cv, boolean b) { warn_const_not_initialized = b; } // // 'compiler.warn-constructor-returns-value' option // private boolean warn_constructor_returns_value = false; public boolean warn_constructor_returns_value() { return warn_constructor_returns_value; } @Config(advanced = true) @Mapping({ "compiler", "warn-constructor-returns-value" }) public void setCompilerWarnConstructorReturnsValue(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_constructor_returns_value) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-deprecated-event-handler-error' option // private boolean warn_deprecated_event_handler_error = false; public boolean warn_deprecated_event_handler_error() { return warn_deprecated_event_handler_error; } @Config(advanced = true) @Mapping({ "compiler", "warn-deprecated-event-handler-error" }) public void setCompilerWarnDeprecatedEventHandlerError(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_deprecated_event_handler_error) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-deprecated-function-error' option // private boolean warn_deprecated_function_error = true; public boolean warn_deprecated_function_error() { return warn_deprecated_function_error; } @Config(advanced = true) @Mapping({ "compiler", "warn-deprecated-function-error" }) public void setCompilerWarnDeprecatedFunctionError(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_deprecated_function_error) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-deprecated-property-error' option // private boolean warn_deprecated_property_error = true; public boolean warn_deprecated_property_error() { return warn_deprecated_property_error; } @Config(advanced = true) @Mapping({ "compiler", "warn-deprecated-property-error" }) public void setCompilerWarnDeprecatedPropertyError(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_deprecated_property_error) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-duplicate-argument-names' option // private boolean warn_duplicate_argument_names = true; public boolean warn_duplicate_argument_names() { return warn_duplicate_argument_names; } @Config(advanced = true) @Mapping({ "compiler", "warn-duplicate-argument-names" }) public void setCompilerWarnDuplicateArgumentNames(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_duplicate_argument_names) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-duplicate-variable-def' option // private boolean warn_duplicate_variable_def = true; public boolean warn_duplicate_variable_def() { return warn_duplicate_variable_def; } @Config(advanced = true) @Mapping({ "compiler", "warn-duplicate-variable-def" }) public void csetCompilerWarnDuplicateVariableDef(ConfigurationValue cv, boolean b) { warn_duplicate_variable_def = b; } // // 'compiler.warn-for-var-in-changes' option // private boolean warn_for_var_in_changes = false; public boolean warn_for_var_in_changes() { return warn_for_var_in_changes; } @Config(advanced = true) @Mapping({ "compiler", "warn-for-var-in-changes" }) public void setCompilerWarnForVarInChanges(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_for_var_in_changes) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-import-hides-class' option // private boolean warn_import_hides_class = true; public boolean warn_import_hides_class() { return warn_import_hides_class; } @Config(advanced = true) @Mapping({ "compiler", "warn-import-hides-class" }) public void setCompilerWarnImportHidesClass(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_import_hides_class) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-instance-of-changes' option // private boolean warn_instance_of_changes = true; public boolean warn_instance_of_changes() { return warn_instance_of_changes; } @Config(advanced = true) @Mapping({ "compiler", "warn-instance-of-changes" }) public void setCompilerWarnInstanceOfChanges(ConfigurationValue cv, boolean b) { warn_instance_of_changes = b; } // // 'compiler.warn-internal-error' option // private boolean warn_internal_error = true; public boolean warn_internal_error() { return warn_internal_error; } @Config(advanced = true) @Mapping({ "compiler", "warn-internal-error" }) public void setCompilerWarnInternalError(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_internal_error) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-level-not-supported' option // private boolean warn_level_not_supported = true; public boolean warn_level_not_supported() { return warn_level_not_supported; } @Config(advanced = true) @Mapping({ "compiler", "warn-level-not-supported" }) public void setCompilerWarnLevelNotSupported(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_level_not_supported) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-missing-namespace-decl' option // private boolean warn_missing_namespace_decl = true; public boolean warn_missing_namespace_decl() { return warn_missing_namespace_decl; } @Config(advanced = true) @Mapping({ "compiler", "warn-missing-namespace-decl" }) public void setCompilerWarnMissingNamespaceDecl(ConfigurationValue cv, boolean b) { warn_missing_namespace_decl = b; } // // 'compiler.warn-negative-uint-literal' option // private boolean warn_negative_uint_literal = true; public boolean warn_negative_uint_literal() { return warn_negative_uint_literal; } @Config(advanced = true) @Mapping({ "compiler", "warn-negative-uint-literal" }) public void setCompilerWarnNegativeUintLiteral(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_negative_uint_literal) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-no-constructor' option // private boolean warn_no_constructor = false; public boolean warn_no_constructor() { return warn_no_constructor; } @Config(advanced = true) @Mapping({ "compiler", "warn-no-constructor" }) public void setCompilerWarnNoConstructor(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_no_constructor) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-no-explicit-super-call-in-constructor' option // private boolean warn_no_explicit_super_call_in_constructor = false; public boolean warn_no_explicit_super_call_in_constructor() { return warn_no_explicit_super_call_in_constructor; } @Config(advanced = true) @Mapping({ "compiler", "warn-no-explicit-super-call-in-constructor" }) public void setCompilerWarnNoExplicitSuperCallInConstructor(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_no_explicit_super_call_in_constructor) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-no-type-decl' option // private boolean warn_no_type_decl = true; public boolean warn_no_type_decl() { return warn_no_type_decl; } @Config(advanced = true) @Mapping({ "compiler", "warn-no-type-decl" }) public void setCompilerWarnNoTypeDecl(ConfigurationValue cv, boolean b) { warn_no_type_decl = b; } // // 'compiler.warn-number-from-string-changes' option // private boolean warn_number_from_string_changes = false; public boolean warn_number_from_string_changes() { return warn_number_from_string_changes; } @Config(advanced = true) @Mapping({ "compiler", "warn-number-from-string-changes" }) public void setCompilerWarnNumberFromStringChanges(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_number_from_string_changes) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-scoping-change-in-this' option // private boolean warn_scoping_change_in_this = false; public boolean warn_scoping_change_in_this() { return warn_scoping_change_in_this; } @Config(advanced = true) @Mapping({ "compiler", "warn-scoping-change-in-this" }) public void setCompilerWarnScopingChangeInThis(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_scoping_change_in_this) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-slow-text-field-addition' option // private boolean warn_slow_text_field_addition = true; public boolean warn_slow_text_field_addition() { return warn_slow_text_field_addition; } @Config(advanced = true) @Mapping({ "compiler", "warn-slow-text-field-addition" }) public void setCompilerWarnSlowTextFieldAddition(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_slow_text_field_addition) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-unlikely-function-value' option // private boolean warn_unlikely_function_value = true; public boolean warn_unlikely_function_value() { return warn_unlikely_function_value; } @Config(advanced = true) @Mapping({ "compiler", "warn-unlikely-function-value" }) public void setCompilerWarnUnlikelyFunctionValue(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_unlikely_function_value) addRemovedConfigurationOptionProblem(cv); } // // 'compiler.warn-xml-class-has-changed' option // private boolean warn_xml_class_has_changed = false; public boolean warn_xml_class_has_changed() { return warn_xml_class_has_changed; } @Config(advanced = true) @Mapping({ "compiler", "warn-xml-class-has-changed" }) public void setCompilerWarnXmlClassHasChanged(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != warn_xml_class_has_changed) addRemovedConfigurationOptionProblem(cv); } // // compiler.generate-abstract-syntax-tree // private boolean generateAbstractSyntaxTree = true; @Config(hidden = true) @Mapping({ "compiler", "generate-abstract-syntax-tree" }) public void setCompilerGenerateAbstractSyntaxTree(ConfigurationValue cv, boolean b) { generateAbstractSyntaxTree = b; } public boolean getCompilerGenerateAbstractSyntaxTree() { return generateAbstractSyntaxTree; } // // 'compiler.isolateStyles' option // /** * Allow the user to decide if the compiled application/module should have its own style manager. Turn off isolate * styles for compatibility less than 4.0. */ private boolean isolateStyles = true; public boolean getCompilerIsolateStyles() { return isolateStyles && (getCompilerCompatibilityVersion() >= MXML_VERSION_4_0); } @Config(advanced = true) @Mapping({ "compiler", "isolate-styles" }) @FlexOnly public void setCompilerIsolateStyles(ConfigurationValue cv, boolean isolateStyles) { this.isolateStyles = isolateStyles; } // // 'compiler.compress' option (default is true) // private boolean useCompression = true; @Config @Mapping({ "compiler", "compress" }) public void setCompress(ConfigurationValue cv, boolean useCompression) { this.useCompression = useCompression; } /** * Setting {@code -compiler.compress=false} will force compiler not to compress the output SWF. */ public boolean useCompression() { return this.useCompression; } // ATTENTION: Please set default values in DefaultsConfigurator. private static final String LOCALE_TOKEN = "{locale}"; private static final String TARGET_PLAYER_MAJOR_VERSION_TOKEN = "{targetPlayerMajorVersion}"; private static final String TARGET_PLAYER_MINOR_VERSION_TOKEN = "{targetPlayerMinorVersion}"; private static final String TARGET_PLAYER_MAJOR_VERSION_TOKEN_REGEX_ESCAPED = Pattern.quote( TARGET_PLAYER_MAJOR_VERSION_TOKEN); private static final String TARGET_PLAYER_MINOR_VERSION_TOKEN_REGEX_ESCAPED = Pattern.quote( TARGET_PLAYER_MINOR_VERSION_TOKEN); // Special Case for Apache. These are not currently exposed with command line options. public static final String PLAYERGLOBAL_HOME_TOKEN = "{playerglobalHome}"; public static final String AIR_HOME_TOKEN = "{airHome}"; public static final String FLEX_VERSION_TOKEN = "{flexVersion}"; public static final String STRICT = "compiler.strict"; public static final String AS3 = "compiler.as3"; public static final String ES = "compiler.es"; public ImmutableList<String> expandTokens(final Iterable<String> pathElements, final Iterable<String> locales, final ConfigurationValue configurationValue) { return expandTokens(pathElements, locales, configurationValue, false); } /** * All path-tokens get expanded from this method, as of now, {locale} and {targetPlayerMajorVersion} Replaces * instances of "{targetPlayerMajorVersion}" and "{targetPlayerMinorVersion}" with configured value. Expands the * {locale} token in a list of path elements for the source-path or library-path. The treatment of a path element * containing "{locale}" depends on whether we are processing a source-path or a library-path, and on whether we are * compiling for a single locale, multiple locales, or no locale: * * <pre> * -source-path=foo,bar/{locale},baz -locale=en_US * -> foo,bar/en_US,baz * * -source-path=foo,bar/{locale},baz -locale=en_US,ja_JP * -> foo,bar/en_US,bar/ja_JP,baz * * -source-path=foo,bar/{locale},baz -locale= * -> foo,baz * * -library-path=foo,bar/{locale},baz -locale=en_US * -> foo,bar/en_US,baz * * -library-path=foo,bar/{locale},baz -locale=en_US,ja_JP * -> foo,bar/en_US,bar/ja_JP,baz * * -library-path=foo,bar/{locale},baz -locale= * -> foo,baz * </pre> * * @param pathElements A list of unprocessed paths from configuration values. * @param locales A set of locales. * @param configurationValue Context. * @param returnMissingFiles controls whether or not files that do not exist are included in the list of expanded * files. Pass true to include files that do not exist, false otherwise. * @return A list of normalized and resolved file paths. * @throws CannotOpen */ protected ImmutableList<String> expandTokens(final Iterable<String> pathElements, final Iterable<String> locales, final ConfigurationValue configurationValue, final boolean returnMissingFiles) { assert pathElements != null : "Expected path list."; assert locales != null : "Expected locales."; assert configurationValue != null : "Expected ConfigurationValue as a context."; String targetPlayerMajorVersion = String.valueOf(getTargetPlayerMajorVersion()); String targetPlayerMinorVersion = String.valueOf(getTargetPlayerMinorVersion()); // Expand target player and locale tokens. final ImmutableList.Builder<String> resolvedPaths = new ImmutableList.Builder<String>(); for (String pathElement : pathElements) { pathElement = expandRuntimeTokens(pathElement, configurationValue.getBuffer()); String flexVersion = getClass().getPackage().getImplementationVersion(); if (flexVersion != null) { pathElement = pathElement.replace(FLEX_VERSION_TOKEN, flexVersion); } String playerExpandedPath = pathElement.replaceAll(TARGET_PLAYER_MAJOR_VERSION_TOKEN_REGEX_ESCAPED, targetPlayerMajorVersion).replaceAll(TARGET_PLAYER_MINOR_VERSION_TOKEN_REGEX_ESCAPED, targetPlayerMinorVersion); try { if (playerExpandedPath.contains(LOCALE_TOKEN)) { for (final String locale : locales) { final String expandedPath = playerExpandedPath.replace(LOCALE_TOKEN, locale); String resolvedPath = resolvePathStrict(expandedPath, configurationValue); resolvedPaths.add(resolvedPath); //Add this to the locale dependent sources map localeDependentSources.put(resolvedPath, locale); } } else { String resolvedPath = resolvePathStrict(playerExpandedPath, configurationValue, returnMissingFiles); resolvedPaths.add(resolvedPath); } } catch (CannotOpen e) { // Making an exception here and catching this fatal error. // This is an exception because library paths come thru this // code path and we don't want to throw all of the libraries // out because one of the paths is bad. We want to load as // many libraries as we can an report the ones we couldn't load. configurationProblems.add(new ConfigurationProblem(e)); } } return resolvedPaths.build(); } /** * Replaces instances of {playerglobalHome} and {airHome}. Values can come from either ../env.properties (relative * to jar file) or environment variables. The property file values have precedence. The pairs are * env.PLAYERGLOBAL_HOME and PLAYERGLOBAL_HOME, and, env.AIR_HOME and AIR_HOME. */ private String expandRuntimeTokens(String pathElement, ConfigurationBuffer buffer) { // Look at property file first, if it exists, and see if the particular property // is defined. If not found, then look for the environment variable. // If there is neither leave the token in place since it is easier to // diagnose the problem with a token in the error message path then it is with // a "" in the path. Properties envProperties = loadEnvPropertyFile(); String playerglobalHome = envProperties != null ? envProperties.getProperty("env.PLAYERGLOBAL_HOME", System.getenv("PLAYERGLOBAL_HOME")) : System.getenv("PLAYERGLOBAL_HOME"); if (playerglobalHome == null) playerglobalHome = buffer.getToken("env.PLAYERGLOBAL_HOME"); if (playerglobalHome == null) playerglobalHome = PLAYERGLOBAL_HOME_TOKEN; String airHome = envProperties != null ? envProperties.getProperty("env.AIR_HOME", System.getenv("AIR_HOME")) : System.getenv("AIR_HOME"); if (airHome == null) airHome = buffer.getToken("env.AIR_HOME"); if (airHome == null) airHome = AIR_HOME_TOKEN; pathElement = pathElement.replace(PLAYERGLOBAL_HOME_TOKEN, playerglobalHome); pathElement = pathElement.replace(AIR_HOME_TOKEN, airHome); return pathElement; } /** * Load the env.properties file from the classpath. * * @return null if env.properties does not exist in classpath or could not be loaded */ private Properties loadEnvPropertyFile() { Properties properties = null; InputStream in = null; try { in = getClass().getClassLoader().getResourceAsStream("env.properties"); if (in == null) { try { File f = new File("../env.properties"); in = new FileInputStream(f); properties = new Properties(); properties.load(in); in.close(); return properties; } catch (FileNotFoundException e) { try { File f = new File("unittest.properties"); in = new FileInputStream(f); properties = new Properties(); properties.load(in); in.close(); properties.setProperty("env.PLAYERGLOBAL_HOME", properties.getProperty("PLAYERGLOBAL_HOME")); properties.setProperty("env.AIR_HOME", properties.getProperty("AIR_HOME")); properties.setProperty("env.PLAYERGLOBAL_VERSION", properties.getProperty("PLAYERGLOBAL_VERSION")); return properties; } catch (FileNotFoundException e1) { return null; } catch (IOException e1) { return null; } } catch (IOException e) { return null; } } properties = new Properties(); properties.load(in); in.close(); } catch (Exception e) { } return properties; } private Map<String, String> localeDependentSources = new HashMap<String, String>(); /** * Returns a map that stores locale dependent files. For each item in this map, key is the path of the resource and * value id the locale it belongs to. */ public Map<String, String> getLocaleDependentSources() { return localeDependentSources; } /** * * @param path A path to resolve. * @param cv Configuration context. * @return A single normalized resolved file. If the path could be expanded into more than one path, then use * {@link resolvePathsStrict} * @throws CannotOpen */ protected String resolvePathStrict(final String path, final ConfigurationValue cv) throws CannotOpen { return resolvePathStrict(path, cv, false); } /** * Resolve a single path. This is a more strict version of {@link #resolvePaths()} in that it throws * {@link CannotOpen} exception when a file path element can't be resolved. * * @param path A path to resolve. * @param cv Configuration context. * @param returnMissingFiles Determines if the CannotOpen exception is thrown if a file does not exist. Pass true to * disable exceptions and return files that do not exist. Pass false to throw exceptions. * @return A single normalized resolved file. If the path could be expanded into more than one path, then use * {@link resolvePathsStrict}. * @throws CannotOpen error * @see #resolvePaths(ImmutableList, ConfigurationValue) */ private String resolvePathStrict(final String path, final ConfigurationValue cv, final boolean returnMissingFiles) throws CannotOpen { ImmutableList<String> singletonPath = ImmutableList.of(path); ImmutableList<String> results = resolvePathsStrict(singletonPath, cv, returnMissingFiles); return results.get(0); } /** * Resolve a list of paths. This is a more strict version of {@link #resolvePaths()} in that it throws * {@link CannotOpen} exception when a file path element can't be resolved. * * @param paths A list of paths to resolve. * @param cv Configuration context. * @return A list of normalized resolved file paths. * @throws CannotOpen error * @see #resolvePaths(ImmutableList, ConfigurationValue) */ private ImmutableList<String> resolvePathsStrict(final ImmutableList<String> paths, final ConfigurationValue cv) throws CannotOpen { return resolvePathsStrict(paths, cv, false); } /** * Resolve a list of paths. This is a more strict version of {@link #resolvePaths()} in that it throws * {@link CannotOpen} exception when a file path element can't be resolved. * * @param paths A list of paths to resolve. * @param cv Configuration context. * @param returnMissingFiles Determines if the CannotOpen exception is thrown if a file does not exist. Pass true to * disable exceptions and return files that do not exist. Pass false to throw exceptions. * @return A list of normalized resolved file paths. * @throws CannotOpen error * @see #resolvePaths(ImmutableList, ConfigurationValue) */ private ImmutableList<String> resolvePathsStrict(final ImmutableList<String> paths, final ConfigurationValue cv, final boolean returnMissingFiles) throws CannotOpen { assert paths != null : "Expected paths"; assert cv != null : "Require ConfigurationValue as context."; final ImmutableList.Builder<String> resolvedPathsBuilder = new ImmutableList.Builder<String>(); for (String processedPath : paths) { if (cv.getContext() != null) { boolean isAbsolute = new File(processedPath).isAbsolute(); if (!isAbsolute) processedPath = new File(cv.getContext(), processedPath).getAbsolutePath(); } if (processedPath.contains("*")) { // if contains wild card, just prove the part before the wild card is valid int c = processedPath.lastIndexOf(File.separator, processedPath.indexOf("*")); if (c != -1) processedPath = processedPath.substring(0, c); } if (!processedPath.contains(".swc:")) { final File fileSpec = pathResolver.resolve(processedPath); if (!returnMissingFiles && !fileSpec.exists()) { throw new CannotOpen(FilenameNormalization.normalize(processedPath), cv.getVar(), cv.getSource(), cv.getLine()); } resolvedPathsBuilder.add(fileSpec.getAbsolutePath()); } else resolvedPathsBuilder.add(processedPath); } return resolvedPathsBuilder.build(); } ////////////////////////////////////////////////////////////////////////// // compiler.extensions.* ////////////////////////////////////////////////////////////////////////// // // 'compiler.extensions.extension' option // /** * Configures a list of many extensions mapped to a single Extension URI. * <extension> <extension>something-extension.jar</extension> * <parameters>version=1.1,content=1.2</parameters> </extension> * * @param cv The configuration value context. * @param pathlist A List of values for the Extension element, with the first item expected to be the uri and the * remaining are extension paths. * @throws CannotOpen When no arg is provided or when the jar does not exist. */ @Config(allowMultiple = true, removed = true) @Mapping({ "compiler", "extensions", "extension" }) @Arguments({ "extension", "parameters" }) @InfiniteArguments public void setExtension(ConfigurationValue cv, String[] pathlist) throws CannotOpen { } ////////////////////////////////////////////////////////////////////////// // compiler.fonts.* ////////////////////////////////////////////////////////////////////////// @Config @Mapping({ "compiler", "fonts", "advanced-anti-aliasing" }) @FlexOnly public void setCompilerFontsAdvancedAntiAliasing(ConfigurationValue cv, boolean val) { // intentionally do nothing here as feature removed, but don't annotate as removed // as to not generate warnings for flex-config's which still set this options } @Config(allowMultiple = true, advanced = true) @Mapping({ "compiler", "fonts", "languages", "language-range" }) @Arguments({ "lang", "range" }) @FlexOnly public void setCompilerFontsLanguagesLanguageRange(ConfigurationValue cv, String lang, String range) { // intentionally do nothing here as feature removed, but don't annotate as removed // as to not generate warnings for flex-config's which still set this options } @Config @Mapping({ "compiler", "fonts", "local-fonts-snapshot" }) @FlexOnly public void setCompilerFontsLocalFontsSnapshot(ConfigurationValue cv, String localFontsSnapshotPath) throws CannotOpen { // intentionally do nothing here as feature removed, but don't annotate as removed // as to not generate warnings for flex-config's which still set this options } @Config @Mapping({ "compiler", "fonts", "local-font-paths" }) @Arguments(Arguments.PATH_ELEMENT) @InfiniteArguments @FlexOnly public void setCompilerFontsLocalFontPaths(ConfigurationValue cv, List<String> list) throws CannotOpen { // intentionally do nothing here as feature removed, but don't annotate as removed // as to not generate warnings for flex-config's which still set this options } @Config(advanced = true) @Mapping({ "compiler", "fonts", "managers" }) @Arguments("manager-class") @InfiniteArguments @FlexOnly public void setCompilerFontsManagers(ConfigurationValue cv, List<String> list) { // intentionally do nothing here as feature removed, but don't annotate as removed // as to not generate warnings for flex-config's which still set this options } @Config @Mapping({ "compiler", "fonts", "max-cached-fonts" }) @FlexOnly public void setCompilerFontsMaxCachedFonts(ConfigurationValue cv, String val) { // intentionally do nothing here as feature removed, but don't annotate as removed // as to not generate warnings for flex-config's which still set this options } @Config @Mapping({ "compiler", "fonts", "max-glyphs-per-face" }) @FlexOnly public void setCompilerFontsMaxGlyphsPerFace(ConfigurationValue cv, String val) { // intentionally do nothing here as feature removed, but don't annotate as removed // as to not generate warnings for flex-config's which still set this options } ////////////////////////////////////////////////////////////////////////// // compiler.namespaces ////////////////////////////////////////////////////////////////////////// private List<MXMLNamespaceMapping> manifestMappings; public List<MXMLNamespaceMapping> getCompilerNamespacesManifestMappings() { return manifestMappings; } /** * Configures a list of many manifests mapped to a single namespace URI. * <namespace> <uri>library:adobe/flex/something</uri> <manifest>something-manifest.xml</manifest> * <manifest>something-else-manifest.xml</manifest> ... </namespace> * * @param cfgval The configuration value context. * @param args A List of values for the namespace element, with the first item expected to be the uri and the * remaining are manifest paths. */ @Config(allowMultiple = true) @Mapping({ "compiler", "namespaces", "namespace" }) @Arguments({ "uri", "manifest" }) @InfiniteArguments @FlexOnly public void setCompilerNamespacesNamespace(ConfigurationValue cfgval, List<String> args) throws ConfigurationException { if (args == null) throw new ConfigurationException.CannotOpen(null, cfgval.getVar(), cfgval.getSource(), cfgval.getLine()); // allow -compiler.namespaces.namespace= which means don't add // anything, which matches the behavior of things like -compiler.library-path // which don't throw an error in this case either. if (args.isEmpty()) return; if (args.size() < 2) throw new ConfigurationException.NamespaceMissingManifest("namespace", cfgval.getSource(), cfgval.getLine()); if (args.size() % 2 != 0) throw new ConfigurationException.IncorrectArgumentCount(args.size() + 1, args.size(), cfgval.getVar(), cfgval.getSource(), cfgval.getLine()); if (manifestMappings == null) manifestMappings = new ArrayList<MXMLNamespaceMapping>(); for (int i = 0; i < args.size() - 1; i += 2) { final String uri = args.get(i); final String manifestFile = args.get(i + 1); final String path = resolvePathStrict(manifestFile, cfgval); manifestMappings.add(new MXMLNamespaceMapping(uri, path)); } } /////////////////////////////////////////////////////////////////////////// // metadata.* /////////////////////////////////////////////////////////////////////////// // // 'metadata.contributor' option // private final Set<String> contributors = new TreeSet<String>(); @Config(allowMultiple = true) @Mapping({ "metadata", "contributor" }) @Arguments("name") public void setMetadataContributor(ConfigurationValue cv, String name) { contributors.add(name); } // // 'metadata.creator' option // private final Set<String> creators = new TreeSet<String>(); @Config(allowMultiple = true) @Mapping({ "metadata", "creator" }) @Arguments("name") public void setMetadataCreator(ConfigurationValue cv, String name) { creators.add(name); } // // 'metadata.date' option // public String date = null; @Config @Mapping({ "metadata", "date" }) @Arguments("text") public void setMetadataDate(ConfigurationValue cv, String text) { date = text; } // // 'metadata.description' option // private final Map<String, String> localizedDescriptions = new LinkedHashMap<String, String>(); @Config @Mapping({ "metadata", "description" }) @Arguments("text") public void setMetadataDescription(ConfigurationValue cv, String text) { localizedDescriptions.put("x-default", text); } // // 'metadata.language' option // public final Set<String> langs = new TreeSet<String>(); @Config(allowMultiple = true) @Mapping({ "metadata", "language" }) @Arguments("code") public void setMetadataLanguage(ConfigurationValue cv, String code) { langs.add(code); } // // 'metadata.localized-description' option // @Config(allowMultiple = true) @Mapping({ "metadata", "localized-description" }) @Arguments({ "text", "lang" }) public void setMetadataLocalizedDescription(ConfigurationValue cv, String text, String lang) { localizedDescriptions.put(lang, text); } // // 'metadata.localized-title' option // @Config(allowMultiple = true) @Mapping({ "metadata", "localized-title" }) @Arguments({ "title", "lang" }) public void setMetadataLocalizedTitle(ConfigurationValue cv, String title, String lang) { localizedTitles.put(lang, title); } // // 'metadata.publisher' option // private final Set<String> publishers = new TreeSet<String>(); @Config(allowMultiple = true) @Mapping({ "metadata", "publisher" }) @Arguments("name") public void setMetadataPublisher(ConfigurationValue cv, String name) { publishers.add(name); } // // 'metadata.title' option // private final Map<String, String> localizedTitles = new LinkedHashMap<String, String>(); @Config @Mapping({ "metadata", "title" }) @Arguments("text") public void setMetadataTitle(ConfigurationValue cv, String title) { localizedTitles.put("x-default", title); } ////////////////////////////////////////////////////////////////////////// // runtime-shared-library-settings ////////////////////////////////////////////////////////////////////////// // // 'force-rsl' option // private Set<String> forceRsls; /** * Get the array of SWCs that should have their RSLs loaded, even if the compiler detects no classes being used from * the SWC. * * @return Array of SWCs that should have their RSLs loaded. */ public Set<String> getForceRsls() { if (forceRsls == null) { return Collections.emptySet(); } return forceRsls; } @Config(advanced = true, allowMultiple = true) @Mapping({ "runtime-shared-library-settings", "force-rsls" }) @SoftPrerequisites({ "runtime-shared-library-path" }) @Arguments(Arguments.PATH_ELEMENT) @InfiniteArguments @FlexOnly public void setForceRsls(ConfigurationValue cfgval, String[] args) throws ConfigurationException { if (forceRsls == null) { forceRsls = new HashSet<String>(); } // Add swc to the forceRsls set. for (String arg : args) { // path-element parameter (swc) // verify path exists and the swc has an // existing -rslp option specified. String swcPath = resolvePathStrict(arg, cfgval); // verify the swc is used in an the RSL configuration. if (!doesSwcHaveRSLInfo(swcPath)) { throw new ConfigurationException.SwcDoesNotHaveRslData(swcPath, cfgval.getVar(), cfgval.getSource(), cfgval.getLine()); } forceRsls.add(swcPath); } } // // 'application-domain' option // /* * Key: swc file path; Value: application domain target */ private HashMap<String, ApplicationDomainTarget> applicationDomains; /** * Get the application domain an RSL should be loaded into. The default is the current application domain but the * user can override this setting. * * @param swcPath The full path of the swc file. * * @return The application domain the RSL should be loaded into. If the swc is not found, then 'default' is * returned. */ public ApplicationDomainTarget getApplicationDomain(String swcPath) { if (applicationDomains == null || swcPath == null) { return ApplicationDomainTarget.DEFAULT; } for (Map.Entry<String, ApplicationDomainTarget> entry : applicationDomains.entrySet()) { if (entry.getKey().equals(swcPath)) { return entry.getValue(); } } return ApplicationDomainTarget.DEFAULT; } @Config(advanced = true, allowMultiple = true) @SoftPrerequisites({ "runtime-shared-library-path" }) @Mapping({ "runtime-shared-library-settings", "application-domain" }) @Arguments({ "path-element", "application-domain-target" }) @InfiniteArguments @FlexOnly // TODO: need to create an argument name generator for the args. public void setApplicationDomain(ConfigurationValue cfgval, String[] args) throws ConfigurationException { // ignore the force option if we are static linking if (getStaticLinkRsl()) return; if (applicationDomains == null) { applicationDomains = new HashMap<String, ApplicationDomainTarget>(); } // Add swc and application domain target to the map. // The args are: swc file path, application domain type, ... for (int i = 0; i < args.length; i++) { String arg = args[i++]; // path-element parameter (swc) // verify path exists and the swc has an // existing -rslp option specified. String swcPath = resolvePathStrict(arg, cfgval); // verify the swc is used in an the RSL configuration. if (!doesSwcHaveRSLInfo(swcPath)) { throw new ConfigurationException.SwcDoesNotHaveRslData(swcPath, cfgval.getVar(), cfgval.getSource(), cfgval.getLine()); } // Verify the application domain target is valid. arg = args[i]; ApplicationDomainTarget adTarget = getApplicationDomainTarget(arg); if (adTarget == null) { // throw a configuration exception that the application domain // type is incorrect. throw new ConfigurationException.BadApplicationDomainValue(swcPath, arg, cfgval.getVar(), cfgval.getSource(), cfgval.getLine()); } applicationDomains.put(swcPath, adTarget); } } /** * Test if the specified parameter is a valid application domain type. If it is then return the corresponding enum. * * @param arg String value representing an ApplicationDomainTarget. * @return An ApplicationDomainTarget enum if the parameter is a valid application domain target, null otherwise. */ private ApplicationDomainTarget getApplicationDomainTarget(String arg) { for (ApplicationDomainTarget appDomain : ApplicationDomainTarget.values()) { if (appDomain.getApplicationDomainValue().equals(arg)) return appDomain; } return null; } /** * Check if the SWC has any RSL info associated with it. * * @param swcPath * @return true if the swc has RSL info, false otherwise. */ private boolean doesSwcHaveRSLInfo(String swcPath) { if (swcPath == null) return false; List<RuntimeSharedLibraryPathInfo> rslInfoList = getRslPathInfo(); for (RuntimeSharedLibraryPathInfo rslInfo : rslInfoList) { if (swcPath.equals(rslInfo.getSWCFile().getPath())) return true; } return false; } ////////////////////////////////////////////////////////////////////////// // compiler.mxml ////////////////////////////////////////////////////////////////////////// // // 'compiler.mxml.compatibility-version' option // public static final int MXML_VERSION_4_7 = 0x04070000; public static final int MXML_VERSION_4_6 = 0x04060000; public static final int MXML_VERSION_4_5 = 0x04050000; public static final int MXML_VERSION_4_0 = 0x04000000; public static final int MXML_VERSION_3_0 = 0x03000000; public static final int MXML_VERSION_2_0_1 = 0x02000001; public static final int MXML_VERSION_2_0 = 0x02000000; public static final int MXML_CURRENT_VERSION = MXML_VERSION_4_7; public static final int MXML_EARLIEST_MAJOR_VERSION = 3; public static final int MXML_LATEST_MAJOR_VERSION = 4; public static final int MXML_LATEST_MINOR_VERSION = 7; private int mxml_major = MXML_LATEST_MAJOR_VERSION; private int mxml_minor = MXML_LATEST_MINOR_VERSION; private int mxml_revision; private int mxmlMinMajor = MXML_EARLIEST_MAJOR_VERSION; private int mxmlMinMinor; private int mxmlMinRevision; public int getCompilerMxmlMajorCompatibilityVersion() { return mxml_major; } public int getCompilerMxmlMinorCompatibilityVersion() { return mxml_minor; } public int getCompilerMxmlRevisionCompatibilityVersion() { return mxml_revision; } /* * Unlike the framework's FlexVersion.compatibilityVersionString, this * returns null rather than a string like "3.0.0" for the current version. * But if a -compatibility-version was specified, this string will always be * of the form N.N.N. For example, if -compatibility-version=2, this string * is "2.0.0", not "2". */ public String getCompilerMxmlCompatibilityVersionString() { return (mxml_major == 0 && mxml_minor == 0 && mxml_revision == 0) ? null : mxml_major + "." + mxml_minor + "." + mxml_revision; } /* * This returns an int that can be compared with version constants such as * MxmlConfiguration.VERSION_3_0. */ public int getCompilerMxmlCompatibilityVersion() { int version = (mxml_major << 24) + (mxml_minor << 16) + mxml_revision; return version != 0 ? version : MXML_CURRENT_VERSION; } @Config @Mapping({ "compiler", "mxml", "compatibility-version" }) @Arguments("version") @FlexOnly public void setCompilerMxmlCompatibilityVersion(ConfigurationValue cv, String version) throws ConfigurationException { if (version == null) { return; } String[] results = version.split("\\."); if (results.length == 0) { throw new ConfigurationException.BadVersion(version, "compatibility-version"); } // Set minor and revision numbers to zero in case only a major number // was specified. this.mxml_minor = 0; this.mxml_revision = 0; for (int i = 0; i < results.length; i++) { int versionNum = 0; try { versionNum = Integer.parseInt(results[i]); } catch (NumberFormatException e) { throw new ConfigurationException.BadVersion(version, "compatibility-version"); } if (i == 0) { if (versionNum >= MXML_EARLIEST_MAJOR_VERSION && versionNum <= MXML_LATEST_MAJOR_VERSION) { this.mxml_major = versionNum; } else { throw new ConfigurationException.BadVersion(version, "compatibility-version"); } } else { if (versionNum >= 0) { if (i == 1) { this.mxml_minor = versionNum; } else { this.mxml_revision = versionNum; } } else { throw new ConfigurationException.BadVersion(version, "compatibility-version"); } } } } /* * Minimum supported SDK version for this library. This string will always * be of the form N.N.N. For example, if -minimum-supported-version=2, this * string is "2.0.0", not "2". */ public String getCompilerMxmlMinimumSupportedVersionString() { return (mxmlMinMajor == 0 && mxmlMinMinor == 0 && mxmlMinRevision == 0) ? null : mxmlMinMajor + "." + mxmlMinMinor + "." + mxmlMinRevision; } /* * This returns an int that can be compared with version constants such as * MxmlConfiguration.VERSION_3_0. */ public int getCompilerMxmlMinimumSupportedVersion() { int version = (mxmlMinMajor << 24) + (mxmlMinMinor << 16) + mxmlMinRevision; return version != 0 ? version : (MXML_EARLIEST_MAJOR_VERSION << 24); } public void setCompilerMxmlMinimumSupportedVersion(int version) { mxmlMinMajor = version >> 24 & 0xFF; mxmlMinMinor = version >> 16 & 0xFF; mxmlMinRevision = version & 0xFF; } @Config @Mapping({ "compiler", "mxml", "minimum-supported-version" }) @FlexOnly public void setCompilerMxmlMinimumSupportedVersion(ConfigurationValue cv, String version) throws ConfigurationException { if (version == null) { return; } String[] results = version.split("\\."); if (results.length == 0) { throw new ConfigurationException.BadVersion(version, "minimum-supported-version"); } for (int i = 0; i < results.length; i++) { int versionNum = 0; try { versionNum = Integer.parseInt(results[i]); } catch (NumberFormatException e) { throw new ConfigurationException.BadVersion(version, "minimum-supported-version"); } if (i == 0) { if (versionNum >= MXML_EARLIEST_MAJOR_VERSION && versionNum <= MXML_LATEST_MAJOR_VERSION) { this.mxmlMinMajor = versionNum; } else { throw new ConfigurationException.BadVersion(version, "minimum-supported-version"); } } else { if (versionNum >= 0) { if (i == 1) { mxmlMinMinor = versionNum; } else { mxmlMinRevision = versionNum; } } else { throw new ConfigurationException.BadVersion(version, "minimum-supported-version"); } } } isMinimumSupportedVersionConfigured = true; } private boolean isMinimumSupportedVersionConfigured = false; public boolean isCompilerMxmlMinimumSupportedVersionConfigured() { return isMinimumSupportedVersionConfigured; } // // 'compiler.mobile' option // private boolean mobile = false; /** * @return determines whether the target runtime is a mobile device. This may alter the features available, such as * certain blend-modes when compiling FXG. */ public boolean getMobile() { return mobile; } @Config() @Mapping({ "compiler", "mobile" }) public void setMobile(ConfigurationValue cv, boolean b) { mobile = b; } //////////////////////////////////////////////////////////////////////////// // licenses.* //////////////////////////////////////////////////////////////////////////// // // 'license' option // @Config(allowMultiple = true, displayed = false, removed = true) @Mapping({ "licenses", "license" }) @Arguments({ "product", "serial-number" }) public void setLicensesLicense(ConfigurationValue cfgval, String product, String serialNumber) throws ConfigurationException { } //////////////////////////////////////////////////////////////////////////// // frames.* //////////////////////////////////////////////////////////////////////////// private List<FrameInfo> frameList = new LinkedList<FrameInfo>(); public List<FrameInfo> getFrameList() { return frameList; } @Config(advanced = true, allowMultiple = true) @Mapping({ "frames", "frame" }) @Arguments({ "label", "classname" }) @InfiniteArguments public void setFramesFrame(ConfigurationValue cv, List<String> args) throws ConfigurationException { // "args" are [label, qname, qname, qname, ...] final FrameInfo info = new FrameInfo(); if (args.size() < 2) throw new ConfigurationException.BadFrameParameters(cv.getVar(), cv.getSource(), cv.getLine()); for (final String next : args) { if (info.getLabel() == null) { info.setLabel(next); } else { info.getFrameClasses().add(next); } } frameList.add(info); } // // -as3 // private boolean as3 = true; @Config(advanced = true) @Mapping({ "compiler", "as3" }) @DeprecatedConfig public void setAS3(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != as3) addRemovedConfigurationOptionProblem(cv); } // // -es // private boolean es = false; @Config(advanced = true) @Mapping({ "compiler", "es" }) @DeprecatedConfig public void setES(ConfigurationValue cv, boolean b) { // This option is set in flex-config.xml so only warn // if the user sets a non-default value. if (b != es) addRemovedConfigurationOptionProblem(cv); } //////////////////////////////////////////////////////////////////////////// // Compc Options //////////////////////////////////////////////////////////////////////////// // // compute-digest=true|false // /** * Writes a digest to the catalog.xml of a library. Use this when the library will be used as a cross-domain RSL or * when you want to enforce the versioning of RSLs. The default value is true. */ @Config(compcOnly = true, removed = true) @Mapping("compute-digest") public void setComputeDigest(ConfigurationValue cv, boolean value) { } /** * directory=false|true */ private boolean outputSwcAsDirectory = false; /** * Outputs the SWC file in an open directory format rather than a SWC file. You use this option with the output * option to specify a destination directory, as the following example shows: * * <pre> * compc -directory=true -output=destination_directory * </pre> */ @Config(compcOnly = true) @Mapping("directory") public void setOutputSwcAsDirectory(ConfigurationValue cv, boolean value) { outputSwcAsDirectory = value; } /** * @return True if the compiler will build the SWC file in an open directory format rather than a SWC file. */ public boolean getOutputSwcAsDirectory() { return outputSwcAsDirectory; } /** * include-classes class [...] */ private final List<String> includeClasses = new ArrayList<String>(); /** * Specifies classes to include in the SWC file. You provide the class name (for example, MyClass) rather than the * file name (for example, MyClass.as) to the file for this option. As a result, all classes specified with this * option must be in the compiler's source path. You specify this by using the source-path compiler option. * <p> * You can use packaged and unpackaged classes. To use components in namespaces, use the include-namespaces option. * <p> * If the components are in packages, ensure that you use dot-notation rather than slashes to separate package * levels. * <p> * This is the default option for the component compiler. */ @Config(compcOnly = true, allowMultiple = true) @Arguments(Arguments.CLASS) @Mapping("include-classes") public void setIncludeClasses(ConfigurationValue cv, List<String> values) { includeClasses.addAll(values); } /** * @return A list of class names to be included in the target. */ public List<String> getIncludeClasses() { return includeClasses; } /** * include-file name path [...] */ public final Map<String, String> includeFilesNamePath = new LinkedHashMap<String, String>(); /** * Adds the file to the SWC file. This option does not embed files inside the library.swf file. This is useful for * adding graphics files, where you want to add non-compiled files that can be referenced in a style sheet or * embedded as assets in MXML files. * <p> * If you add a stylesheet that references compiled resources such as programmatic skins, use the include-stylesheet * option. * <p> * If you use the [Embed] syntax to add a resource to your application, you are not required to use this option to * also link it into the SWC file. */ @Config(compcOnly = true, allowMultiple = true) @Mapping("include-file") @Arguments({ "name", "path" }) public void setIncludeFiles(ConfigurationValue cv, List<String> values) throws IncorrectArgumentCount, CannotOpen, RedundantFile { // Expect name-path pairs in the arguments. final int size = values.size(); if (size % 2 != 0) throw new IncorrectArgumentCount(size + 1, size, cv.getVar(), cv.getSource(), cv.getLine()); for (int nameIndex = 0; nameIndex < size - 1; nameIndex += 2) { final String name = values.get(nameIndex); final String path = resolvePathStrict(values.get(nameIndex + 1), cv); if (includeFilesNamePath.containsKey(name)) { throw new ConfigurationException.RedundantFile(name, cv.getVar(), cv.getSource(), cv.getLine()); } includeFilesNamePath.put(name, path); } } /** * @return A map of included files. The keys are file entry names; The values are file paths. */ public Map<String, String> getIncludeFiles() { return includeFilesNamePath; } /** * include-lookup-only=false|true */ private boolean includeLookupOnly = false; /** * If true, only manifest entries with lookupOnly=true are included in the SWC catalog. */ @Config(compcOnly = true, advanced = true) @Mapping("include-lookup-only") @FlexOnly public void setIncludeLookupOnly(ConfigurationValue cv, boolean value) { includeLookupOnly = value; } /** * @return If true, only manifest entries with lookupOnly=true are included in the SWC catalog. */ public boolean getIncludeLookupOnly() { return includeLookupOnly; } /** * include-namespaces uri [...] */ private final List<String> includeNamespaces = new ArrayList<String>(); /** * Specifies namespace-style components in the SWC file. You specify a list of URIs to include in the SWC file. The * uri argument must already be defined with the namespace option. * <p> * To use components in packages, use the include-classes option. */ @Config(compcOnly = true, allowMultiple = true) @Mapping("include-namespaces") @Arguments({ "uri" }) @FlexOnly public void setIncludeNamespaces(ConfigurationValue cv, List<String> values) { includeNamespaces.addAll(values); } /** * @return A list of URIs to include in the SWC file. */ public List<String> getIncludeNamespaces() { return includeNamespaces; } /** * include-sources path-element */ private final List<String> includeSources = new ArrayList<String>(); /** * Specifies classes or directories to add to the SWC file. When specifying classes, you specify the path to the * class file (for example, MyClass.as) rather than the class name itself (for example, MyClass). This lets you add * classes to the SWC file that are not in the source path. In general, though, use the include-classes option, * which lets you add classes that are in the source path. * <p> * If you specify a directory, this option includes all files with an MXML or AS extension, and ignores all other * files. * <p> * If you use this option to include MXML components that are in a non-default package, you must include the source * folder in the source path. */ @Config(compcOnly = true, allowMultiple = true) @Mapping("include-sources") @Arguments(Arguments.PATH_ELEMENT) public void setIncludeSources(ConfigurationValue cv, List<String> values) throws NotAFile { fillListWithResolvedPaths(values, includeSources, cv); } /** * @return Normalized file paths of the included source files. */ public List<String> getIncludeSources() { return includeSources; } /** * Add resolved file paths from {@code source} list to {@code target} list. * * @param source Source list with un-resolved file paths. * @param target Target list. * @param cv Context. * @throws CannotOpen */ private void fillListWithResolvedPaths(final List<String> source, final List<String> target, final ConfigurationValue cv) throws NotAFile { for (final String path : source) { String resolvedPath; try { resolvedPath = resolvePathStrict(path, cv); target.add(resolvedPath); } catch (CannotOpen e) { throw new ConfigurationException.NotAFile(path, cv.getVar(), cv.getSource(), cv.getLine()); } } } /** * include-stylesheet namepath [...] */ private final List<String> includeStyleSheets = new ArrayList<String>(); /** * Specifies stylesheets to add to the SWC file. This option compiles classes that are referenced by the stylesheet * before including the stylesheet in the SWC file. * <p> * You do not need to use this option for all stylesheets; only stylesheets that reference assets that need to be * compiled such as programmatic skins or other class files. If your stylesheet does not reference compiled assets, * you can use the include-file option. * <p> * This option does not compile the stylesheet into a SWF file before including it in the SWC file. You compile a * CSS file into a SWF file when you want to load it at run time. */ @Config(compcOnly = true, allowMultiple = true) @Mapping("include-stylesheet") @Arguments({ "name", "path" }) @FlexOnly public void setIncludeStyleSheets(ConfigurationValue cv, List<String> values) throws NotAFile { fillListWithResolvedPaths(values, includeStyleSheets, cv); } /** * @return A list of the normalized file path of stylesheets to add to the SWC file. */ public List<String> getIncludeStyleSheets() { return includeStyleSheets; } private File dependencyGraphOutput; /** * Specifies a file name that a graphml version of the dependency graph should be written to. * */ @Config(advanced = true) @Mapping("dependency-graph") @Arguments("filename") public void setDependencyGraphOutput(ConfigurationValue cv, String fileName) { dependencyGraphOutput = new File(getOutputPath(cv, fileName)); } /** * Gets the location the graphml version of the dependency graph should be written to, null if no dependecy graph * should be written. * * @return The location the dependency graph should be written to. */ public File getDependencyGraphOutput() { return dependencyGraphOutput; } // // 'output' option // private String output; public String getOutput() { return output; } @Config @Arguments("filename") public void setOutput(ConfigurationValue val, String output) throws ConfigurationException { this.output = getOutputPath(val, output); } // // 'dump-config-file' option from ToolsConfiguration // private String dumpConfigFile = null; /** * @return filename of the configuration dump */ public String getDumpConfig() { return dumpConfigFile; } @Config(advanced = true, displayed = false) @Arguments("filename") @Mapping("dump-config") public void setDumpConfig(ConfigurationValue cv, String filename) { dumpConfigFile = getOutputPath(cv, filename); } // // 'warnings' option from ToolsConfiguration // private boolean warnings = true; public boolean getWarnings() { return warnings; } @Config @Mapping("warnings") public void setWarnings(ConfigurationValue cv, boolean b) { warnings = b; } // // 'error-problems' // private Collection<Class<ICompilerProblem>> errorClasses; /** * Get the collection of user specified problem classes that should be treated as errors. * * @return list of problem classes that should be treated as errors. */ public Collection<Class<ICompilerProblem>> getErrorProblems() { return errorClasses != null ? errorClasses : Collections.<Class<ICompilerProblem>> emptyList(); } @Config(allowMultiple = true) @Arguments(Arguments.CLASS) @InfiniteArguments public void setErrorProblems(ConfigurationValue cv, List<String> classNames) throws ConfigurationException { if (errorClasses == null) errorClasses = new HashSet<Class<ICompilerProblem>>(); // Convert string to a class and save. for (String className : classNames) { Class<ICompilerProblem> resolvedClass = resolveProblemClassName(className); if (resolvedClass == null) { throw new ConfigurationException.CompilerProblemClassNotFound(className, cv.getVar(), cv.getSource(), cv.getLine()); } errorClasses.add(resolvedClass); } } // // 'warning-problems' // private Collection<Class<ICompilerProblem>> warningClasses; /** * Get the collection of user specified problem classes that should be treated as warnings. * * @return list of problem classes that should be treated as warnings. */ public Collection<Class<ICompilerProblem>> getWarningProblems() { return warningClasses != null ? warningClasses : Collections.<Class<ICompilerProblem>> emptyList(); } @Config(allowMultiple = true) @Arguments(Arguments.CLASS) @InfiniteArguments public void setWarningProblems(ConfigurationValue cv, List<String> classNames) throws ConfigurationException { if (warningClasses == null) warningClasses = new HashSet<Class<ICompilerProblem>>(); // Convert string to a class and save. for (String className : classNames) { Class<ICompilerProblem> resolvedClass = resolveProblemClassName(className); if (resolvedClass == null) { throw new ConfigurationException.CompilerProblemClassNotFound(className, cv.getVar(), cv.getSource(), cv.getLine()); } warningClasses.add(resolvedClass); } } // // 'ignore-problems' // private Collection<Class<ICompilerProblem>> ignoreClasses; /** * Get the collection of user specified problem classes that should be ignored. * * @return list of problem classes that should be ignored. */ public Collection<Class<ICompilerProblem>> getIgnoreProblems() { return ignoreClasses != null ? ignoreClasses : Collections.<Class<ICompilerProblem>> emptyList(); } @Config(allowMultiple = true) @Arguments(Arguments.CLASS) @InfiniteArguments public void setIgnoreProblems(ConfigurationValue cv, List<String> classNames) throws ConfigurationException { if (ignoreClasses == null) ignoreClasses = new HashSet<Class<ICompilerProblem>>(); // Convert string to a class and save. for (String className : classNames) { Class<ICompilerProblem> resolvedClass = resolveProblemClassName(className); if (resolvedClass == null) { throw new ConfigurationException.CompilerProblemClassNotFound(className, cv.getVar(), cv.getSource(), cv.getLine()); } ignoreClasses.add(resolvedClass); } } // // 'legacy-message-format' // private boolean legacyMessageFormat = true; public boolean useLegacyMessageFormat() { return legacyMessageFormat; } @Config(hidden = true) public void setLegacyMessageFormat(ConfigurationValue cv, boolean value) throws ConfigurationException { legacyMessageFormat = value; } // // 'create-target-with-errors' // private boolean createTargetWithErrors = false; public boolean getCreateTargetWithErrors() { return createTargetWithErrors; } @Config(hidden = true) public void setCreateTargetWithErrors(ConfigurationValue cv, boolean value) throws ConfigurationException { createTargetWithErrors = value; } // // 'flex' // private boolean isFlex = false; public boolean isFlex() { return isFlex; } /** * Option to enable or prevent various Flex compiler behaviors. This is currently used to enable/disable the * generation of a root class for library swfs and generation of Flex specific code for application swfs. */ @Config(hidden = true) public void setFlex(ConfigurationValue cv, boolean value) throws ConfigurationException { isFlex = value; } private boolean isExcludeNativeJSLibraries = false; public boolean isExcludeNativeJSLibraries() { return isExcludeNativeJSLibraries; } /** * Option to remove the Native JS libraries from external-library-path and library-path as they shouldn't be any * when compiling SWFs / SWCs. */ @Config() @Mapping("exclude-native-js-libraries") public void setExcludeNativeJSLibraries(ConfigurationValue cv, boolean value) throws ConfigurationException { isExcludeNativeJSLibraries = value; } /** * Resolve a problem class name to a Java Class. * * @param className May be fully qualified. If the class name is not fully qualified, it is assumed to live in the * "org.apache.flex.compiler.problems" package. * * @return A class corresponding to the className or null if the class name was not found. */ @SuppressWarnings("unchecked") private Class<ICompilerProblem> resolveProblemClassName(String className) { if (className == null) return null; Class<?> resolvedClass = null; try { resolvedClass = Class.forName(className); } catch (ClassNotFoundException e) { return null; } if (ICompilerProblem.class.isAssignableFrom(resolvedClass)) return (Class<ICompilerProblem>) resolvedClass; else return null; } // // 'file-specs' option // private List<String> fileSpecs = new ArrayList<String>(); /** * Get target file path. Target file is the last file in the {@link #getFileSpecs()}. * FIXME: Calling this target file is a bit misleading as it's sort of the "main" source file */ public String getTargetFile() { if (fileSpecs.isEmpty()) return null; else return Iterables.getLast(fileSpecs); } /** * @return Path of the target's parent directory. */ public String getTargetFileDirectory() { final String targetFile = getTargetFile(); if (targetFile == null) return null; final String normalizedTargetFile = FilenameNormalization.normalize(targetFile); return FilenameUtils.getFullPathNoEndSeparator(normalizedTargetFile); } /** * This has been added so that unit tests can change the target file. It isn't normally called when running the * command line compiler. */ public void setTargetFile(String mainFile) { fileSpecs.clear(); fileSpecs.add(mainFile); } /** * @return A list of filespecs. It's the default variable for command line. */ public List<String> getFileSpecs() { return fileSpecs; } @Config(allowMultiple = true, hidden = true) @Arguments(Arguments.PATH_ELEMENT) @InfiniteArguments @SoftPrerequisites("flex") public void setFileSpecs(ConfigurationValue cv, List<String> args) throws ConfigurationException { this.fileSpecs.addAll(args); checkForMxmlFiles(args); } private void checkForMxmlFiles(List<String> paths) { // If there are mxml or css files then we are compiling a flex // application so enable "flex". for (String path : paths) { if (path.endsWith(".mxml") || path.endsWith(".css")) isFlex = true; } } // // 'help' option from CommandLineConfiguration // /** * dummy, just a trigger for help text */ @Config(displayed = false, greedy = true) @Arguments("keyword") @InfiniteArguments public void setHelp(ConfigurationValue cv, String[] keywords) { } // // 'load-config' option from CommandLineConfiguration // private String configFile = null; /** * @return Normalized path to a Flex configuration file. */ public String getLoadConfig() { return configFile; } /** * Since {@link ConfigurationBuffer} loads the "load-config" files, the value of this configuration option isn't * intersting to the rest part of the compiler. */ @Config(allowMultiple = true) @Arguments("filename") public void setLoadConfig(ConfigurationValue cv, String filename) throws ConfigurationException { configFile = resolvePathStrict(filename, cv); } // // 'version' option from CommandLineConfiguration // /** * Dummy option. Just a trigger for version info. */ @Config public void setVersion(ConfigurationValue cv, boolean value) { } // // 'verbose' option from CommandLineConfiguration // private boolean verbose = false; public boolean isVerbose() { return verbose; } @Config(hidden = true) public void setVerbose(ConfigurationValue cfgval, boolean b) { verbose = b; } // // 'dump-ast' option from CommandLineConfiguration // private boolean dumpAst; public boolean isDumpAst() { return dumpAst; } @Config(hidden = true) public void setDumpAst(ConfigurationValue cfgval, boolean b) { dumpAst = b; } // // 'enable-inlining' option from CommandLineConfiguration // private boolean enableInlining = false; /** * @return true if function inlining has been enabled. */ public boolean isInliningEnabled() { return enableInlining; } /** * Enable or disable function inlining. * * @param cfgval The configuration value context. * @param b true to enable inlining, false otherwise. */ @Config(hidden = true) @Mapping({ "compiler", "inline" }) public void setEnableInlining(ConfigurationValue cfgval, boolean b) { enableInlining = b; } // // 'remove-dead-code' option from CommandLineConfiguration // private boolean removeDeadCode = false; /** * @return true if dead code removal has been enabled. */ public boolean getRemoveDeadCode() { return this.removeDeadCode; } /** * Enable or disable dead code removal. * * @param cfgval the configuration value context. * @param b true to enable dead code removal, false to disable. */ @Config(advanced = true) @Mapping({ "compiler", "remove-dead-code" }) public void setRemoveDeadCode(ConfigurationValue cfgval, boolean b) { this.removeDeadCode = b; } // // Validation methods from ToolsConfiguration // void validateDumpConfig(ConfigurationBuffer configurationBuffer) throws ConfigurationException { if (dumpConfigFile != null) { final String text = FileConfigurator.formatBuffer(configurationBuffer, "flex-config", LocalizationManager.get(), "flex2.configuration"); try { final Writer writer = new FileWriter(dumpConfigFile); IOUtils.write(text, writer); IOUtils.closeQuietly(writer); } catch (IOException e) { throw new ConfigurationException.IOError(dumpConfigFile); } } } /** * Collection of fatal and non-fatal configuration problems. */ private Collection<ICompilerProblem> configurationProblems = new ArrayList<ICompilerProblem>(); /** * Get the configuration problems. This should be called after the configuration has been processed. * * @return a collection of fatal and non-fatal configuration problems. */ public Collection<ICompilerProblem> getConfigurationProblems() { return configurationProblems; } private boolean warnOnFlexOnlyOptionUsage = false; /** * @return True if warnings are generated when "Flex only" options are used, false otherwise. */ public boolean getWarnOnFlexOnlyOptionUsage() { return warnOnFlexOnlyOptionUsage; } /** * Controls if the compiler warns when "Flex only" configuration options are used in the compiler. * * @param value True to enable warnings, false to disable warnings. The default is to not warn. */ public void setWarnOnFlexOnlyOptionUsage(boolean value) { this.warnOnFlexOnlyOptionUsage = value; } private boolean enableTelemetry = false; /** * * @return True if telemetry is enabled, false otherwise. */ public boolean isEnableTelemetry() { return enableTelemetry; } /** * Controls if the flash runtime should allow providing advanced telemetry options to external tools. * * @param enableTelemetry True to enable telemetry, false to disable. The default ist to disable. */ public void setEnableTelemetry(boolean enableTelemetry) { this.enableTelemetry = enableTelemetry; } /** * Turns on the advanced telemetry options of the flash runtime to allow clients like scout to connect. * * Remark: Internally and in the spec this option is called "enable telemetry" but by tools and the commandline it's * referenced by advanced-telemetry. */ @Config(advanced = true) @Mapping({ "compiler", "advanced-telemetry" }) @FlexOnly public void setEnableTelemetry(ConfigurationValue cv, boolean enableTelemetry) throws CannotOpen { this.enableTelemetry = enableTelemetry; } private void processDeprecatedAndRemovedOptions(ConfigurationBuffer configurationBuffer) { for (final String var : configurationBuffer.getVars()) { ConfigurationInfo info = configurationBuffer.getInfo(var); List<ConfigurationValue> values = configurationBuffer.getVar(var); if (values != null) { for (final ConfigurationValue cv : values) { if (info.isRemoved()) { //addRemovedConfigurationOptionProblem(cv); } else if (info.isDeprecated() && configurationBuffer.getVar(var) != null) { String replacement = info.getDeprecatedReplacement(); String since = info.getDeprecatedSince(); DeprecatedConfigurationOptionProblem problem = new DeprecatedConfigurationOptionProblem(var, replacement, since, cv.getSource(), cv.getLine()); configurationProblems.add(problem); } else if (warnOnFlexOnlyOptionUsage && info.isFlexOnly()) { FlexOnlyConfigurationOptionNotSupported problem = new FlexOnlyConfigurationOptionNotSupported( var, cv.getSource(), cv.getLine()); configurationProblems.add(problem); } } } } } /** * Add a RemovedConfigurationOptionProblem to the list of configuration problems. * * @param cv */ private void addRemovedConfigurationOptionProblem(ConfigurationValue cv) { RemovedConfigurationOptionProblem problem = new RemovedConfigurationOptionProblem(cv.getVar(), cv.getSource(), cv.getLine()); configurationProblems.add(problem); } private boolean strictXML = false; /** * * @return True if strictXML is enabled, false otherwise. */ public boolean isStrictXML() { return strictXML; } /** * Controls if the compiler should try to resolve XML methods. Enabling this makes it * possible to write new XML implementations but causes more warnings. Default is false. * * @param strictXML True to enable strict XML checking, false to disable. The default is to disable. */ public void setStrictXML(boolean strictXML) { this.strictXML = strictXML; } /** * Turns on the strict XML checking in the compiler. Enabling this makes it * possible to write new XML implementations but causes more warnings. * */ @Config(advanced = true) @Mapping({ "compiler", "strict-xml" }) @FlexOnly public void setStrictXML(ConfigurationValue cv, boolean strictXML) throws CannotOpen { this.strictXML = strictXML; } }