| /* |
| * |
| * 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 flex2.tools; |
| |
| import flash.localization.LocalizationManager; |
| import flex2.compiler.common.Configuration; |
| import flex2.compiler.common.ConfigurationPathResolver; |
| import flex2.compiler.common.PathResolver; |
| import flex2.compiler.config.*; |
| import flex2.compiler.io.VirtualFile; |
| import flex2.compiler.util.CompilerMessage; |
| import flex2.compiler.util.ThreadLocalToolkit; |
| import org.apache.flex.compiler.clients.MXMLC; |
| |
| import java.io.BufferedInputStream; |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.lang.reflect.InvocationTargetException; |
| import java.util.*; |
| import java.util.Map.Entry; |
| |
| /** |
| * A command line tool for compiling Flex applications. Despite the |
| * name, in addition to .mxml files, this tool can be used to compile |
| * other file formats, like .as and .css. |
| */ |
| public final class Mxmlc extends Tool { |
| static private String l10nConfigPrefix = "flex2.configuration"; |
| |
| public static final String FILE_SPECS = "file-specs"; |
| |
| /** |
| * The entry-point for Mxmlc. |
| * Note that if you change anything in this method, make sure to check Compc, Shell, and |
| * the server's CompileFilter to see if the same change needs to be made there. You |
| * should also inform the Zorn team of the change. |
| * |
| * @param args |
| */ |
| public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException { |
| System.exit(mxmlcNoExit(args)); |
| } |
| |
| public static int mxmlcNoExit(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { |
| |
| COMPILER = MXMLC.class; |
| JS_COMPILER = MxmlJSC.class; |
| |
| return compile(args); |
| } |
| |
| public static void mxmlc(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException { |
| |
| COMPILER = MXMLC.class; |
| JS_COMPILER = MxmlJSC.class; |
| |
| compile(args); |
| } |
| |
| public static Configuration processConfiguration(LocalizationManager lmgr, String program, String[] args, |
| ConfigurationBuffer cfgbuf, Class<? extends Configuration> cls, String defaultVar) |
| throws ConfigurationException, IOException { |
| return processConfiguration(lmgr, program, args, cfgbuf, cls, defaultVar, true); |
| } |
| |
| public static Configuration processConfiguration(LocalizationManager lmgr, String program, String[] args, |
| ConfigurationBuffer cfgbuf, Class<? extends Configuration> cls, String defaultVar, |
| boolean ignoreUnknownItems) |
| throws IOException { |
| ToolsConfiguration toolsConfiguration = null; |
| try { |
| SystemPropertyConfigurator.load(cfgbuf, "flex"); |
| |
| // Parse the command line a first time, to peak at stuff like |
| // "flexlib" 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, defaultVar, args); |
| |
| String flexlib = cfgbuf.getToken("flexlib"); |
| if (flexlib == null) { |
| String appHome = System.getProperty("application.home"); |
| |
| if (appHome == null) { |
| appHome = "."; |
| } else { |
| appHome += File.separator + "frameworks"; // FIXME - need to eliminate this from the compiler |
| } |
| cfgbuf.setToken("flexlib", appHome); |
| } |
| |
| // 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", "flex"); |
| } |
| |
| String buildNumber = cfgbuf.getToken("build.number"); |
| if (buildNumber == null) { |
| if ("".equals(VersionInfo.getBuild())) { |
| buildNumber = "workspace"; |
| } else { |
| buildNumber = VersionInfo.getBuild(); |
| } |
| cfgbuf.setToken("build.number", buildNumber); |
| } |
| |
| |
| // We need to intercept "help" options because we want to try to correctly |
| // interpret them even when the rest of the configuration is totally screwed up. |
| |
| if (cfgbuf.getVar("version") != null) { |
| System.out.println(VersionInfo.buildMessage()); |
| System.exit(0); |
| } |
| |
| processHelp(cfgbuf, program, defaultVar, lmgr, args); |
| |
| // at this point, we should have enough to know both |
| // flexlib and the config file. |
| |
| ConfigurationPathResolver configResolver = new ConfigurationPathResolver(); |
| |
| List<ConfigurationValue> configs = cfgbuf.peekConfigurationVar("load-config"); |
| |
| if (configs != null) { |
| for (ConfigurationValue cv : configs) { |
| for (String path : cv.getArgs()) { |
| VirtualFile configFile = ConfigurationPathResolver.getVirtualFile(path, configResolver, cv); |
| cfgbuf.calculateChecksum(configFile); |
| InputStream in = configFile.getInputStream(); |
| if (in != null) { |
| FileConfigurator.load(cfgbuf, new BufferedInputStream(in), configFile.getName(), |
| configFile.getParent(), "flex-config", ignoreUnknownItems); |
| } else { |
| throw new ConfigurationException.ConfigurationIOError(path, cv.getVar(), cv.getSource(), cv.getLine()); |
| } |
| } |
| } |
| } |
| |
| PathResolver resolver = ThreadLocalToolkit.getPathResolver(); |
| // Load project file, if any... |
| List fileValues = cfgbuf.getVar(FILE_SPECS); |
| if ((fileValues != null) && (fileValues.size() > 0)) { |
| ConfigurationValue cv = (ConfigurationValue) 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"; |
| VirtualFile projectFile = resolver.resolve(configResolver, project); |
| if (projectFile != null) { |
| cfgbuf.calculateChecksum(projectFile); |
| InputStream in = projectFile.getInputStream(); |
| if (in != null) { |
| FileConfigurator.load(cfgbuf, new BufferedInputStream(in), |
| projectFile.getName(), projectFile.getParent(), "flex-config", |
| ignoreUnknownItems); |
| } |
| } |
| } |
| } |
| } |
| |
| // The command line needs to take precedence over all defaults and config files. |
| // This is a bit gross, but by simply re-merging the command line back on top, |
| // we will get the behavior we want. |
| cfgbuf.clearSourceVars(CommandLineConfigurator.source); |
| CommandLineConfigurator.parse(cfgbuf, defaultVar, args); |
| |
| toolsConfiguration = null; |
| try { |
| toolsConfiguration = (ToolsConfiguration) cls.newInstance(); |
| toolsConfiguration.setConfigPathResolver(configResolver); |
| } catch (Exception e) { |
| LocalizationManager l10n = ThreadLocalToolkit.getLocalizationManager(); |
| throw new ConfigurationException(l10n.getLocalizedTextString(new CouldNotInstantiate(toolsConfiguration))); |
| } |
| cfgbuf.commit(toolsConfiguration); |
| |
| // enterprise service config file has other config file dependencies. add them here... |
| calculateServicesChecksum(toolsConfiguration, cfgbuf); |
| |
| toolsConfiguration.validate(cfgbuf); |
| |
| // consolidate license keys... |
| VirtualFile licenseFile = toolsConfiguration.getLicenseFile(); |
| if (licenseFile != null) { |
| Map<String, String> fileLicenses = Tool.getLicenseMapFromFile(licenseFile.getName()); |
| Map<String, String> cmdLicenses = toolsConfiguration.getLicensesConfiguration().getLicenseMap(); |
| if (cmdLicenses == null) { |
| toolsConfiguration.getLicensesConfiguration().setLicenseMap(fileLicenses); |
| } else if (fileLicenses != null) { |
| fileLicenses.putAll(cmdLicenses); |
| toolsConfiguration.getLicensesConfiguration().setLicenseMap(fileLicenses); |
| } |
| } |
| } catch (ConfigurationException e) { |
| e.printStackTrace(); |
| } |
| |
| return toolsConfiguration; |
| } |
| |
| static void processHelp(ConfigurationBuffer cfgbuf, String program, String defaultVar, LocalizationManager lmgr, String[] args) { |
| if (cfgbuf.getVar("help") != null) { |
| Set<String> keywords = new HashSet<String>(); |
| List vals = cfgbuf.getVar("help"); |
| for (Iterator it = vals.iterator(); it.hasNext(); ) { |
| ConfigurationValue val = (ConfigurationValue) it.next(); |
| for (Object element : val.getArgs()) { |
| String keyword = (String) element; |
| while (keyword.startsWith("-")) |
| keyword = keyword.substring(1); |
| keywords.add(keyword); |
| } |
| } |
| if (keywords.size() == 0) { |
| keywords.add("help"); |
| } |
| |
| ThreadLocalToolkit.logInfo(getStartMessage(program)); |
| System.out.println(); |
| System.out.println(CommandLineConfigurator.usage(program, defaultVar, cfgbuf, keywords, lmgr, l10nConfigPrefix)); |
| System.exit(0); |
| } |
| |
| if (args.length == 0 && ("mxmlc".equals(program) || "compc".equals(program))) { |
| ThreadLocalToolkit.logInfo(getStartMessage(program)); |
| System.err.println(CommandLineConfigurator.brief(program, defaultVar, lmgr, l10nConfigPrefix)); |
| System.exit(1); |
| } |
| } |
| |
| private static void calculateServicesChecksum(Configuration config, ConfigurationBuffer cfgbuf) { |
| Map<String, Long> services = null; |
| if (config.getCompilerConfiguration().getServicesDependencies() != null) { |
| services = config.getCompilerConfiguration().getServicesDependencies().getConfigPaths(); |
| } |
| |
| if (services != null) { |
| for (Entry<String, Long> entry : services.entrySet()) { |
| cfgbuf.calculateChecksum(entry.getKey(), entry.getValue()); |
| } |
| } |
| } |
| |
| public static void processConfigurationException(ConfigurationException ex, String program) { |
| ThreadLocalToolkit.log(ex); |
| |
| if (ex.source == null || ex.source.equals("command line")) { |
| Map<String, String> p = new HashMap<String, String>(); |
| p.put("program", program); |
| String help = ThreadLocalToolkit.getLocalizationManager().getLocalizedTextString("flex2.compiler.CommandLineHelp", p); |
| if (help != null) { |
| // "Use '" + program + " -help' for information about using the command line."); |
| System.err.println(help); |
| } |
| } |
| } |
| |
| private static String getStartMessage(String program) { |
| LocalizationManager l10n = ThreadLocalToolkit.getLocalizationManager(); |
| |
| return l10n.getLocalizedTextString(new StartMessage(program, VersionInfo.buildMessage())); |
| } |
| |
| public static class CouldNotInstantiate extends CompilerMessage.CompilerInfo { |
| private static final long serialVersionUID = -8970190710117830662L; |
| |
| public CouldNotInstantiate(Configuration config) { |
| super(); |
| this.config = config; |
| } |
| |
| public final Configuration config; |
| } |
| |
| public static class StartMessage extends CompilerMessage.CompilerInfo { |
| private static final long serialVersionUID = 4807822711658875257L; |
| |
| public StartMessage(String program, String buildMessage) { |
| super(); |
| this.program = program; |
| this.buildMessage = buildMessage; |
| } |
| |
| public final String program, buildMessage; |
| } |
| |
| public static class OutputMessage extends CompilerMessage.CompilerInfo { |
| private static final long serialVersionUID = -4859993585489031839L; |
| |
| public String name; |
| public String length; |
| |
| public OutputMessage(String name, String length) { |
| this.name = name; |
| this.length = length; |
| } |
| } |
| } |
| |