
org.apache.royale.compiler.config.Configurator Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of compiler-common Show documentation
Show all versions of compiler-common Show documentation
The Apache Royale Compiler Common classes
The newest version!
/*
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.royale.compiler.config;
import java.io.File;
import java.util.*;
import org.apache.royale.compiler.common.IPathResolver;
import org.apache.royale.compiler.common.VersionInfo;
import org.apache.royale.compiler.config.RSLSettings.RSLAndPolicyFileURLPair;
import org.apache.royale.compiler.exceptions.ConfigurationException;
import org.apache.royale.compiler.filespecs.FileSpecification;
import org.apache.royale.compiler.filespecs.IFileSpecification;
import org.apache.royale.compiler.internal.config.CompilerProblemSettings;
import org.apache.royale.compiler.internal.config.DefaultsConfigurator;
import org.apache.royale.compiler.internal.config.FileConfigurator;
import org.apache.royale.compiler.internal.config.ICompilerSettings;
import org.apache.royale.compiler.internal.config.IConfigurator;
import org.apache.royale.compiler.internal.config.RuntimeSharedLibraryPathInfo;
import org.apache.royale.compiler.internal.config.SystemPropertyConfigurator;
import org.apache.royale.compiler.internal.config.TargetSettings;
import org.apache.royale.compiler.internal.config.localization.LocalizationManager;
import org.apache.royale.compiler.internal.config.localization.ResourceBundleLocalizer;
import org.apache.royale.compiler.mxml.IMXMLNamespaceMapping;
import org.apache.royale.compiler.problems.ConfigurationProblem;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.compiler.projects.ICompilerProject;
import org.apache.royale.compiler.targets.ITargetSettings;
import org.apache.royale.compiler.targets.ITarget.TargetType;
import org.apache.royale.compiler.workspaces.IWorkspace;
import org.apache.royale.utils.FileUtils;
import org.apache.royale.utils.FilenameNormalization;
import org.apache.royale.utils.Trace;
import com.google.common.base.Function;
import com.google.common.collect.Lists;
/**
* A class that allows a client change compiler settings and to
* configure projects and targets from those settings.
*/
public class Configurator implements ICompilerSettings, IConfigurator, ICompilerSettingsConstants, Cloneable
{
/**
* Marker class for RSLSettings because RSLSettings need special handling
* in getOptions().
*/
static class RSLSettingsList extends ArrayList
{
public RSLSettingsList(int size)
{
super(size);
}
public RSLSettingsList(Collection extends RSLSettings> c)
{
super(c);
}
private static final long serialVersionUID = 0L;
}
/**
* Ditto for conditional compilation
*/
static class CompilerDefinitionMap extends TreeMap
{
private static final long serialVersionUID = 0L;
}
static class ApplicationDomainsList extends ArrayList
{
private static final long serialVersionUID = 0L;
}
static class MXMLNamespaceMappingList extends ArrayList
{
public MXMLNamespaceMappingList(int size)
{
super(size);
}
public MXMLNamespaceMappingList(Collection extends IMXMLNamespaceMapping> namespaceMappings)
{
super(namespaceMappings);
}
private static final long serialVersionUID = 0L;
}
static class ServicesContextRoot
{
public ServicesContextRoot(String path, String contextRoot)
{
this.path = path;
this.contextRoot = contextRoot;
}
public String path;
public String contextRoot;
}
/**
* Ditto for conditional compilation
*/
static class FrameLabelMap extends TreeMap>
{
private static final long serialVersionUID = 0L;
}
/**
* Convert file path strings to {@code File} objects. Null values are
* discarded.
*
* @param paths List of file paths
* @return List of File objects. No null values will be returned.
*/
public static List toFiles(final List paths)
{
final List result = new ArrayList();
for (final String path : paths)
{
if (path != null)
result.add(new File(path));
}
return result;
}
/**
* Convert file path strings to {@code File} objects. Null values are
* discarded.
*
* @param paths List of file paths
* @return Array of File objects. No null values will be returned.
*/
public static List toFileList(final List paths)
{
final List result = new ArrayList();
for (final String path : paths)
{
if (path != null)
result.add(FilenameNormalization.normalize(new File(path)));
}
return result;
}
/**
* Convert {@code File} objects to {@code String}, where each {@code String} is
* the absolute file path of the file. Null values are discarded.
*
* @param files file specifications
* @return Array of File objects. No null values will be returned.
*/
public static String[] toPaths(File[] files)
{
final List result = new ArrayList();
for (final File file : files)
{
if (file != null)
result.add(file.getAbsolutePath());
}
return result.toArray(new String[0]);
}
/**
* Resolve a list of normalized paths to {@link IFileSpecification} objects
* from the given {@code workspace}.
*
* @param paths A list of normalized paths.
* @param workspace IWorkspace.
* @return A list of file specifications.
*/
public static List toFileSpecifications(
final List paths,
final IWorkspace workspace)
{
return Lists.transform(paths, new Function()
{
@Override
public IFileSpecification apply(final String path)
{
if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.WORKSPACE) == CompilerDiagnosticsConstants.WORKSPACE)
System.out.println("Configurator waiting for lock in toFileSpecifications");
IFileSpecification fs = workspace.getFileSpecification(path);
if ((CompilerDiagnosticsConstants.diagnostics & CompilerDiagnosticsConstants.WORKSPACE) == CompilerDiagnosticsConstants.WORKSPACE)
System.out.println("Configurator done with lock in toFileSpecifications");
return fs;
}
});
}
// Used to generate the command line
private static final String EQUALS_STRING = "=";
private static final String PLUS_EQUALS_STRING = "+=";
private static final String COMMA_STRING = ",";
private static final String PLUS_STRING = "+";
private static final Set excludes = new HashSet();
static
{
excludes.add("output");
excludes.add("warnings");
excludes.add("compiler.debug");
excludes.add("compiler.profile");
excludes.add("compiler.accessible");
excludes.add("compiler.strict");
excludes.add("compiler.show-actionscript-warnings");
excludes.add("compiler.show-unused-type-selector-warnings");
excludes.add("compiler.show-deprecation-warnings");
excludes.add("compiler.show-shadowed-device-font-warnings");
excludes.add("compiler.show-binding-warnings");
excludes.add("compiler.verbose-stacktraces");
excludes.add("royale");
}
/**
* Constructor
*/
public Configurator()
{
this(Configuration.class);
}
/**
* Constructor
*/
public Configurator(Class extends Configuration> configurationClass)
{
this.configurationClass = configurationClass;
args = new LinkedHashMap();
more = new LinkedHashMap();
tokens = new TreeMap();
keepLinkReport = false;
keepSizeReport = false;
keepConfigurationReport = false;
reportMissingLibraries = true;
warnOnRoyaleOnlyOptionUsage = false;
isConfigurationDirty = true;
configurationDefaultVariable = ICompilerSettingsConstants.FILE_SPECS_VAR; // the default variable of the configuration.
configurationPathResolver = new ConfigurationPathResolver(System.getProperty("user.dir"));
configurationProblems = new ArrayList();
// initialize the localization manager.
LocalizationManager.get().addLocalizer(new ResourceBundleLocalizer());
}
private ConfigurationBuffer cfgbuf;
protected Configuration configuration;
private Class extends Configuration> configurationClass;
private Map args, more;
private String[] extras;
private String configurationDefaultVariable;
private boolean keepLinkReport, keepSizeReport, keepConfigurationReport;
private String mainDefinition;
private boolean reportMissingLibraries;
private boolean warnOnRoyaleOnlyOptionUsage;
private List loadedConfigFiles;
private List missingConfigFiles;
private Map tokens;
private boolean isConfigurationDirty;
private boolean configurationSuccess;
protected Collection configurationProblems;
private boolean extrasRequireDefaultVariable;
private IPathResolver configurationPathResolver;
protected ICompilerProject project;
//
// IConfigurator related methods
//
@Override
public List getLoadedConfigurationFiles()
{
return loadedConfigFiles != null ? loadedConfigFiles :
Collections.emptyList();
}
@Override
public List getMissingConfigurationFiles()
{
return missingConfigFiles != null ? missingConfigFiles :
Collections.emptyList();
}
@Override
public boolean applyToProject(ICompilerProject project)
{
this.project = project;
final IWorkspace workspace = project.getWorkspace();
boolean success = processConfiguration();
workspace.startIdleState();
try
{
if (configuration == null)
return false;
applyConfiguration();
}
finally
{
workspace.endIdleState(IWorkspace.NIL_COMPILATIONUNITS_TO_UPDATE);
}
return success;
}
protected boolean applyConfiguration()
{
return false; // don't call this, just override it
}
protected String computeQNameForTargetFile()
{
List computedSourcePath = new ArrayList();
applySourcePathRules(computedSourcePath);
String targetSourceFileName = configuration.getTargetFile();
if (targetSourceFileName == null)
return null;
final File targetSourceFile = FilenameNormalization.normalize(new File(configuration.getTargetFile()));
return targetSourceFile.getName();
}
@Override
public ITargetSettings getTargetSettings(TargetType targetType)
{
boolean wasConfigurationDirty = isConfigurationDirty;
if (!processConfiguration())
return null;
// Special handling for dump config. If dump config was specified then
// dump it out again if the configuration was not dirty. The config is
// dumped as a side-effect of validating the configuration if it gets
// processed.
try
{
if (!wasConfigurationDirty)
{
if (cfgbuf.getVar(ICompilerSettingsConstants.DUMP_CONFIG_VAR) != null)
{
// The file may have already been dumped as a side-effect of
// applyToProject() so only dump if it does not exist.
String dumpConfigPath = configuration.getDumpConfig();
if (dumpConfigPath != null && !(new File(dumpConfigPath).exists()))
configuration.validateDumpConfig(cfgbuf);
}
}
if (mainDefinition != null)
{
configuration.setMainDefinition(mainDefinition);
}
else if ((configuration.getMainDefinition() == null) && (targetType == TargetType.SWF))
{
String computedQName = computeQNameForTargetFile();
if (computedQName != null)
configuration.setMainDefinition(computedQName);
}
if (targetType == TargetType.SWC)
validateSWCConfiguration();
else
Configuration.validateNoCompcOnlyOptions(cfgbuf);
}
catch (ConfigurationException e)
{
reportConfigurationException(e);
return null;
}
return instantiateTargetSettings();
}
protected ITargetSettings instantiateTargetSettings()
{
return new TargetSettings(configuration, project);
}
@Override
public ICompilerProblemSettings getCompilerProblemSettings()
{
processConfiguration();
return new CompilerProblemSettings(configuration);
}
@Override
public Collection validateConfiguration(String[] args, TargetType targetType)
{
if (args == null)
throw new NullPointerException("args may not be null");
List problems = new ArrayList();
ConfigurationBuffer configurationBuffer = createConfigurationBuffer(configurationClass);
try
{
CommandLineConfigurator.parse(configurationBuffer, null, args);
// verify SWC-only args are not used to for a SWF target.
if (targetType == TargetType.SWF)
Configuration.validateNoCompcOnlyOptions(configurationBuffer);
}
catch (ConfigurationException e)
{
final ICompilerProblem problem = new ConfigurationProblem(e);
problems.add(problem);
}
return problems;
}
@Override
public Collection getConfigurationProblems()
{
assert configuration != null :
"Get the configuration problems after calling applyToProject() or getTargetSettings()";
List problems = new ArrayList(configurationProblems.size() +
configuration.getConfigurationProblems().size());
problems.addAll(configurationProblems);
problems.addAll(configuration.getConfigurationProblems());
return problems;
}
@Override
public void setConfigurationPathResolver(IPathResolver pathResolver)
{
if (pathResolver == null)
throw new NullPointerException("pathResolver may not be null");
this.configurationPathResolver = pathResolver;
}
// Needed by MXMLC for now.
public Configuration getConfiguration()
{
return configuration;
}
// Needed by MXMLC for now.
public ConfigurationBuffer getConfigurationBuffer()
{
return cfgbuf;
}
/**
* Create a new configuration instance. The Configurator will need to
* create a new configuration for each new configuration. For example,
* creating a new Configurator and getting the target settings will create
* a new configuration. If later on, the configuration is modified by calling
* any of the setter methods on the Configurator, then a new configuration
* will be created the next time applyToProject() or getTargetSettings() is called.
*
* The method may be overriden to allow for greater control when creating a
* custom configuration that extends the built-in configuration.
*
* @return a new configuration instance. If the custom configuration class
* cannot be created, the default configuration class will be created instead.
*/
protected Configuration createConfiguration()
{
try
{
return configurationClass.getConstructor().newInstance();
}
catch (Exception e)
{
// If there is a problem initializing the configuration, then
// throw a ConfigurationException.
reportConfigurationException(new ConfigurationException.CouldNotInstantiate(configurationClass.getName()));
// Create the default configuration so we can report configuration
// problems.
try
{
return Configuration.class.getConstructor().newInstance();
}
catch (Exception e2)
{
// this should never fail
assert(false);
return null;
}
}
}
/**
* Initialize the configuration and the configuration buffer.
*/
protected void initializeConfiguration()
{
// Create a clean configuration and configuration buffer
configuration = createConfiguration();
cfgbuf = createConfigurationBuffer(configuration.getClass());
assert configurationPathResolver != null : "No configuration path resolver was set.";
configuration.setPathResolver(configurationPathResolver);
configuration.setReportMissingCompilerLibraries(reportMissingLibraries);
configuration.setWarnOnRoyaleOnlyOptionUsage(warnOnRoyaleOnlyOptionUsage);
}
/**
* Create a configuration buffer.
* @param configurationClass The Configuration object
* @return the configuration buffer to use
*/
protected ConfigurationBuffer createConfigurationBuffer(
Class extends Configuration> configurationClass)
{
return new ConfigurationBuffer(
configurationClass, Configuration.getAliases());
}
/**
* Apply the follow source-path rules:
*
* 1. If source-path is empty, the target file's directory will be added to
* source-path.
* 2. If source-path is not empty and if the target file's directory is a
* sub-directory of one of the directories in source-path, source-path
* remains unchanged.
* 3. If source-path is not empty and if the target file's directory is not
* a sub-directory of any one of the directories in source-path, the target
* file's directory is prepended to source-path.
*
* @param sourcePath the source path to apply the rules to.
*/
protected void applySourcePathRules(List sourcePath)
{
String targetFileDirectory = configuration.getTargetFileDirectory();
List configuredSourcePath = configuration.getCompilerSourcePath();
if (targetFileDirectory != null)
{
// This method is called with an empty sourcePath so any additions will
// have the effect of prepending to the sourcePath.
if (configuredSourcePath.isEmpty() ||
(!configuredSourcePath.contains(targetFileDirectory) &&
!isSubdirectoryOf(targetFileDirectory, configuredSourcePath)))
{
sourcePath.add(targetFileDirectory);
}
}
// The configuration system provides additional source paths.
sourcePath.addAll(configuredSourcePath);
}
/**
* Check whether the provided path is a subdirectory of the list of
* directories and vice versa.
*
* @param path - absolute path name of directory to test.
* @param directories - {@link Iterable} of directories to test.
* @return true if path is a subdirectory, false otherwise
*/
private static boolean isSubdirectoryOf(String path, Iterable directories)
{
final File pathFile = FileUtils.canonicalFile(new File(path));
for (String directoryName : directories)
{
final File dirFile = FileUtils.canonicalFile(new File(directoryName));
final long dirFilenameLength = dirFile.getAbsolutePath().length();
File parentFile = pathFile.getParentFile();
while (parentFile != null)
{
if (dirFile.equals(parentFile))
return true;
// if the dirFilenameLength is greater than the parentFilename length
// then break out and try the next path, rather than going all the
// way up to the root, as it can't be a sub directory.
if (dirFilenameLength > parentFile.getAbsolutePath().length())
break;
parentFile = parentFile.getParentFile();
}
}
return false;
}
public static List getRSLSettingsFromConfiguration(Configuration configuration)
{
List infoList = configuration.getRslPathInfo();
if (infoList == null || infoList.size() == 0)
{
return Collections.emptyList();
}
boolean verifyDigests = configuration.getVerifyDigests();
List rslSettingsList = new ArrayList(infoList.size());
for (RuntimeSharedLibraryPathInfo info : infoList)
{
// For each loop, convert an RSL and its failovers into
// the RSLSettings class.
RSLSettings rslSettings = new RSLSettings(info.getSWCFile());
List rslURLs = info.getRSLURLs();
List policyFileURLs = info.getPolicyFileURLs();
int n = info.getRSLURLs().size();
for (int i = 0; i < n; i++)
{
rslSettings.addRSLURLAndPolicyFileURL(rslURLs.get(i), policyFileURLs.get(i));
}
rslSettings.setVerifyDigest(verifyDigests);
String swcPath = info.getSWCFile().getPath();
rslSettings.setApplicationDomain(configuration.getApplicationDomain(swcPath));
rslSettings.setForceLoad(configuration.getForceRsls().contains(swcPath));
// Add an RSL to the list of RSL settings.
rslSettingsList.add(rslSettings);
}
return rslSettingsList;
}
/**
* Wrapper around the real processConfiguration.
*
* @return true if success, false otherwise.
*/
protected boolean processConfiguration()
{
boolean success = true;
if (isConfigurationDirty)
{
configurationProblems.clear();
try
{
success = processConfiguration(getOptions(args, more, processExtras(extras)));
}
catch (ConfigurationException e)
{
reportConfigurationException(e);
success = false;
}
catch (Exception e)
{
e.printStackTrace();
}
}
else
{
success = configurationSuccess;
}
isConfigurationDirty = false;
configurationSuccess = success;
return success;
}
/**
* Does all the work to set the command line arguments info the
* configuration object.
*
* @param argsArray - command line arguments
*
* @return true if successful, false otherwise.
*/
protected boolean processConfiguration(String[] argsArray)
{
initializeConfiguration();
boolean success = true;
try
{
loadDefaults(cfgbuf);
// TODO This is needed until we can defer
// the default style loading in loadDefaults().
byPassConfigurationsRequiringFlexSDK();
SystemPropertyConfigurator.load(cfgbuf, "royale");
// Parse the command line a first time, to peak at stuff like
// "royalelib" and "load-config". The first parse is thrown
// away after that and we intentionally parse a second time
// below. See note below.
CommandLineConfigurator.parse(cfgbuf, configurationDefaultVariable, argsArray);
overrideDefaults();
// Return if "-version" is present so the command line can print the
// version.
if (cfgbuf.getVar("version") != null)
return false;
// Return so the command line can print help if "-help" is present.
final List helpVar = cfgbuf.getVar("help");
if (helpVar != null)
return false;
// Load configurations from files.
if (!loadConfig())
success = false;
if (!loadProjectConfig())
success = false;
// The command line needs to take precedence over all defaults and config files.
// By simply re-merging the command line back on top,
// we will get the behavior we want.
cfgbuf.clearSourceVars(CommandLineConfigurator.source);
CommandLineConfigurator.parse(cfgbuf, configurationDefaultVariable, argsArray);
// commit() reports problems instead of throwing an exception. This
// allows us to process all the options in a configuration that
// are correct in the hopes that it will be enough to configure a
// project.
if (!cfgbuf.commit(configuration, configurationProblems))
success = false;
configuration.validate(cfgbuf);
}
catch (ConfigurationException e)
{
reportConfigurationException(e);
success = false;
}
return success;
}
/**
* Load the default values into the passed in config buffer
* @param cfgbuf the config buffer to set the default values in
* @throws ConfigurationException
*/
protected void loadDefaults (ConfigurationBuffer cfgbuf) throws ConfigurationException
{
DefaultsConfigurator.loadDefaults(cfgbuf);
}
/**
* Do the validatation that the old COMPCConfiguration used to do.
*/
protected void validateSWCConfiguration() throws ConfigurationException
{
validateSWCInputs();
// verify that if -include-inheritance-dependencies is set that
// -include-classes is not null
if (configuration.getIncludeInheritanceDependenciesOnly() &&
configuration.getIncludeClasses().size() == 0)
{
throw new ConfigurationException.MissingIncludeClasses();
}
}
/**
* Basic validation of compc options. This code used to be
* in the old compiler's CompcConfiguration.
*
* @throws ConfigurationException
*/
protected void validateSWCInputs() throws ConfigurationException
{
if (configuration.getIncludeSources().isEmpty() &&
configuration.getIncludeClasses().isEmpty() &&
configuration.getIncludeNamespaces().isEmpty() &&
((configuration.getCompilerIncludeLibraries() == null) ||
(configuration.getCompilerIncludeLibraries().size() == 0)) &&
configuration.getIncludeFiles().isEmpty() &&
configuration.getIncludeResourceBundles().isEmpty())
{
throw new ConfigurationException.NoSwcInputs( null, null, -1 );
}
}
/**
* By-pass the configurations that requires Flex SDK.
*/
protected void byPassConfigurationsRequiringFlexSDK() throws ConfigurationException
{
if (System.getProperty("royalelib") == null &&
System.getProperty("application.home") == null)
{
cfgbuf.clearVar("load-config", null, -1);
cfgbuf.clearVar("compiler.theme", null, -1);
}
}
/**
* Override default values.
*/
protected void overrideDefaults() throws ConfigurationException
{
String royalelib = cfgbuf.getToken("royalelib");
if (royalelib == null)
{
final String appHome = System.getProperty("application.home");
if (appHome == null)
cfgbuf.setToken("royalelib", ".");
else
cfgbuf.setToken("royalelib", appHome + File.separator + "frameworks");
}
// Framework Type: halo, gumbo, interop...
String framework = cfgbuf.getToken("framework");
if (framework == null)
cfgbuf.setToken("framework", "halo");
String configname = cfgbuf.getToken("configname");
if (configname == null)
cfgbuf.setToken("configname", "royale");
String buildNumber = cfgbuf.getToken("build.number");
if (buildNumber == null)
{
if ("".equals(VersionInfo.getBuild()))
buildNumber = "workspace";
else
buildNumber = VersionInfo.getBuild();
cfgbuf.setToken("build.number", buildNumber);
}
}
/**
* Load configuration XML file specified in {@code -load-config} option on
* command-line.
*
* @return true if successful, false otherwise.
*/
protected boolean loadConfig()
{
boolean success = true;
List configs;
try
{
configs = cfgbuf.peekConfigurationVar("load-config");
if (configs != null)
{
for (ConfigurationValue cv : configs)
{
for (String path : cv.getArgs())
{
File configFile = configurationPathResolver.resolve(path);
if (!configFile.exists() && path.contains("royale-config"))
{
File configFile2 = configurationPathResolver.resolve(path.replace("royale-config", "flex-config"));
if (configFile2.exists())
configFile = configFile2;
}
if (!configFile.exists())
{
success = false;
if (missingConfigFiles == null)
missingConfigFiles = new ArrayList();
missingConfigFiles.add(path);
}
else
{
if (!loadConfigFromFile(
cfgbuf,
configFile,
new File(configFile.getPath()).getParent(),
"royale-config",
false))
{
success = false;
}
}
}
}
}
}
catch (ConfigurationException e)
{
reportConfigurationException(e);
success = false;
}
return success;
}
/**
* Load a configuration from file. {@code FileConfigurator.load()} is
* wrapped in this method because we want to print a message after loading
* using MXMLC#println(String).
*
* @return true if successful, false otherwise.
*/
protected final boolean loadConfigFromFile(final ConfigurationBuffer buffer,
final File fileSpec,
final String context,
final String rootElement,
final boolean ignoreUnknownItems)
{
boolean success = true;
try
{
FileConfigurator.load(buffer,
new FileSpecification(fileSpec.getAbsolutePath()),
context, rootElement, ignoreUnknownItems);
}
catch (ConfigurationException e)
{
// record exception
reportConfigurationException(e);
success = false;
}
if (loadedConfigFiles == null)
loadedConfigFiles = new ArrayList();
loadedConfigFiles.add(fileSpec.getPath());
return success;
}
/**
* Convert conifguration exceptions to problems and collect them for
* reporting.
*
* @param e
*/
protected void reportConfigurationException(ConfigurationException e)
{
final ICompilerProblem problem = new ConfigurationProblem(e);
configurationProblems.add(problem);
}
/**
* Load project specific configuration. The configuration XML file is at the
* project root with naming convention of [project name]-config.xml.
*
* @return true if successful, false otherwise.
*/
protected boolean loadProjectConfig()
{
boolean success = true;
// Load project file, if any...
List fileValues = cfgbuf.getVar(ICompilerSettingsConstants.FILE_SPECS_VAR);
if ((fileValues != null) && (fileValues.size() > 0))
{
ConfigurationValue cv = fileValues.get(fileValues.size() - 1);
if (cv.getArgs().size() > 0)
{
String val = cv.getArgs().get(cv.getArgs().size() - 1);
int index = val.lastIndexOf('.');
if (index != -1)
{
String project = val.substring(0, index) + "-config.xml";
File projectFile = configurationPathResolver.resolve(project);
if (projectFile.exists())
{
if (!loadConfigFromFile(
cfgbuf,
projectFile,
new File(project).getParent(),
"royale-config",
false))
{
success = false;
}
}
}
}
}
return success;
}
//
// Configuration related methods
//
protected String[] getOptions(Map args, Map more,
String[] extras)
{
ArrayList buffer = new ArrayList();
for (Map.Entry tokenEntry : tokens.entrySet())
{
buffer.add(PLUS_STRING + tokenEntry.getKey() + EQUALS_STRING + tokenEntry.getValue());
}
for (Map.Entry arg : args.entrySet())
{
String key = arg.getKey();
Object value = arg.getValue();
if (value instanceof Boolean)
{
buffer.add(key + EQUALS_STRING + value);
}
else if (value instanceof Number)
{
buffer.add(key);
buffer.add(value.toString());
}
else if (COMPILER_CONTEXT_ROOT.equals(key) && value instanceof String)
{
buffer.add(key);
buffer.add((String)value);
}
else if (value instanceof String)
{
if (!"".equals(value))
{
buffer.add(key);
buffer.add((String)value);
}
else
{
buffer.add(key + EQUALS_STRING);
}
}
else if (value instanceof File)
{
String p = ((File) value).getPath();
if (!"".equals(p))
{
buffer.add(key);
buffer.add(p);
}
else
{
buffer.add(key + EQUALS_STRING);
}
}
else if (value instanceof java.util.Date)
{
buffer.add(key);
buffer.add(value.toString());
}
else if (value instanceof MXMLNamespaceMappingList)
{
addNamespaceMappingsToBuffer(buffer, (MXMLNamespaceMappingList)value, false);
}
else if (value instanceof RSLSettingsList)
{
addRSLSettingsToBuffer(buffer, (RSLSettingsList)value, false);
}
else if (value instanceof CompilerDefinitionMap)
{
final CompilerDefinitionMap defs = (CompilerDefinitionMap)value;
for (Map.Entry entry : defs.entrySet())
{
// String.valueOf will help turn null into "null"
String name = entry.getKey();
String val = entry.getValue();
// handle empty-string values
// technically, name should not ever be empty length (value can be),
// but we don't want to do error handling, CompilerConfiguration.cfgDefine()
// will do it for us later
if (name.length() == 0)
{
name = "\"\"";
}
if (val.length() == 0)
{
val = "\"\"";
}
/* note '+=': defines from all royale-config.xmls will be collected (just '=' would
* always ignore all but the most recent definitions), hopefully in a meaningful
* order (royale-config, user-config, commandline) since we now allow re-definitions.
*/
buffer.add(COMPILER_DEFINE + PLUS_EQUALS_STRING + name + COMMA_STRING + val);
}
}
else if (value instanceof Map)
{
@SuppressWarnings("unchecked")
Map m = (Map) value;
for (Map.Entryentry : m.entrySet())
{
String k = entry.getKey();
Object v = entry.getValue();
if (v instanceof String)
{
buffer.add(key);
buffer.add(k);
buffer.add((String)v);
}
else if (v instanceof File)
{
buffer.add(key);
buffer.add(k);
buffer.add(((File) v).getPath());
}
else if (v instanceof Collection)
{
buffer.add(key);
buffer.add(k);
Collection> list = (Collection>)v;
for (Object next : list)
{
if (next != null)
buffer.add(next.toString());
}
}
else if (v != null)
{
assert false;
}
}
}
else if (value instanceof int[])
{
int[] a = (int[]) value;
buffer.add(key);
buffer.add(String.valueOf(a[0]));
buffer.add(String.valueOf(a[1]));
}
else if (value instanceof Collection)
{
Collection
© 2015 - 2025 Weber Informatics LLC | Privacy Policy