/*
 *
 *  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 flash.localization.ResourceBundleLocalizer;
import flash.localization.XLRLocalizer;
import flash.swf.Movie;
import flash.util.Trace;
import flex2.compiler.*;
import flex2.compiler.common.*;
import flex2.compiler.config.*;
import flex2.compiler.extensions.ExtensionManager;
import flex2.compiler.extensions.IMxmlcExtension;
import flex2.compiler.i18n.I18nUtils;
import flex2.compiler.io.FileUtil;
import flex2.compiler.io.VirtualFile;
import flex2.compiler.swc.SwcCache;
import flex2.compiler.swc.SwcException;
import flex2.compiler.util.Benchmark;
import flex2.compiler.util.CompilerMessage;
import flex2.compiler.util.NameMappings;
import flex2.compiler.util.ThreadLocalToolkit;
import flex2.linker.ConsoleApplication;
import flex2.linker.LinkerAPI;
import flex2.linker.LinkerException;
import org.apache.flex.tools.FlexTool;

import java.io.*;
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.
 *
 * @author Clement Wong
 */
public final class Mxmlc extends Tool implements FlexTool
{
    public static final String FILE_SPECS = "file-specs";

    @Override
    public String getName() {
        return FLEX_TOOL_MXMLC;
    }

    @Override
    public int execute(String[] args) {
        mxmlc(args);
        return ThreadLocalToolkit.errorCount();
    }

    /**
     * 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)
    {
        mxmlc(args);
        System.exit(ThreadLocalToolkit.errorCount());
    }

    public static void mxmlc(String[] args)
    {
        Transcoder[] transcoders = null;
        Benchmark benchmark = null;

        try
        {
            CompilerAPI.useAS3();

            // setup the path resolver
            CompilerAPI.usePathResolver();

            // set up for localizing messages
            LocalizationManager l10n = new LocalizationManager();
            l10n.addLocalizer( new XLRLocalizer() );
            l10n.addLocalizer( new ResourceBundleLocalizer() );
            ThreadLocalToolkit.setLocalizationManager(l10n);

            // setup the console logger. the configuration parser needs a logger.
            CompilerAPI.useConsoleLogger();

            // process configuration
            ConfigurationBuffer cfgbuf = new ConfigurationBuffer(CommandLineConfiguration.class, Configuration.getAliases());

            // Do not set this.  The file-specs should be included in the configuration buffer
            // checksum so changes to the class list can be detected during incremental builds.
            //cfgbuf.setDefaultVar(FILE_SPECS);
            DefaultsConfigurator.loadDefaults( cfgbuf );
            CommandLineConfiguration configuration = (CommandLineConfiguration) processConfiguration(
                l10n, "mxmlc", args, cfgbuf, CommandLineConfiguration.class, FILE_SPECS);

            // well, setup the logger again now that we know configuration.getWarnings()???
            CompilerAPI.useConsoleLogger(true, true, configuration.getWarnings(), true);
            CompilerAPI.setupHeadless(configuration);

            if (configuration.benchmark())
            {
                benchmark = CompilerAPI.runBenchmark();
                benchmark.startTime(Benchmark.PRECOMPILE);
            }
            else
            {
                CompilerAPI.disableBenchmark();
            }

            // make sure targetFile abstract pathname is an absolute path...
            VirtualFile targetFile = CompilerAPI.getVirtualFile(configuration.getTargetFile());
            WebTierAPI.checkSupportedTargetMimeType(targetFile);

            // mxmlc only wants to take one file.
            List<String> fileList = configuration.getFileList();
            if (fileList == null || fileList.size() != 1)
            {
                throw new ConfigurationException.OnlyOneSource( "filespec", null, -1);
            }

            List<VirtualFile> virtualFileList = CompilerAPI.getVirtualFileList(fileList);

            CompilerConfiguration compilerConfig = configuration.getCompilerConfiguration();
            NameMappings mappings = CompilerAPI.getNameMappings(configuration);

            // create a FileSpec... can reuse based on targetFile, debug settings, etc...
            FileSpec fileSpec = new FileSpec(Collections.<VirtualFile>emptyList(), WebTierAPI.getFileSpecMimeTypes());

            // create a SourcePath...
            VirtualFile[] asClasspath = compilerConfig.getSourcePath();
            SourceList sourceList = new SourceList(virtualFileList,
                                                   asClasspath,
                                                   targetFile,
                                                   WebTierAPI.getSourcePathMimeTypes());
            SourcePath sourcePath = new SourcePath(asClasspath,
                                                   targetFile,
                                                   WebTierAPI.getSourcePathMimeTypes(),
                                                   compilerConfig.allowSourcePathOverlap());

            ResourceContainer resources = new ResourceContainer();
            ResourceBundlePath bundlePath = new ResourceBundlePath(configuration.getCompilerConfiguration(), targetFile);

            ArrayList<Source> sources = new ArrayList<Source>();
            List<CompilationUnit> units = new ArrayList<CompilationUnit>();

            if (benchmark != null)
            {
                benchmark.benchmark(l10n.getLocalizedTextString(new InitialSetup()));
            }

            // load SWCs
            CompilerSwcContext swcContext = new CompilerSwcContext();
            SwcCache cache = new SwcCache();
            
            // lazy read should only be set by mxmlc/compc
            cache.setLazyRead(true);

            swcContext.load( compilerConfig.getLibraryPath(),
                             Configuration.getAllExcludedLibraries(compilerConfig, configuration),
                             compilerConfig.getThemeFiles(),
                             compilerConfig.getIncludeLibraries(),
                             mappings,
                             I18nUtils.getTranslationFormat(compilerConfig),
                             cache );
            configuration.addExterns( swcContext.getExterns() );
            configuration.addIncludes( swcContext.getIncludes() );
            configuration.getCompilerConfiguration().addThemeCssFiles( swcContext.getThemeStyleSheets() );

            // Figure out the name of the output file.
            File outputFile = getOutputFile(configuration, targetFile);

            // Checksums to figure out if incremental compile can be done.
            String incrementalFileName = null;
            SwcChecksums swcChecksums = null;

            // Should we attempt to build incrementally using the incremental file?
            boolean recompile = true;

            // If incremental compilation is enabled and the output file exists,
            // use the persisted store to figure out if a compile/link is necessary.
            // link without a compile is not supported without changes to the
            // persistantStore since units for Sources of type isSwcScriptOwner()
            // aren't stored/restored properly. units contains null entries for those
            // type of Source.  To force a rebuild, with -incremental specified, delete the
            // incremental file.
            if (configuration.getCompilerConfiguration().getIncremental())
            {
                swcChecksums = new SwcChecksums(swcContext, cfgbuf, configuration);

                // If incremental compilation is enabled, read the cached
                // compilation units...  Do not include the checksum in the file name so that
                // cache files don't pile up as the configuration changes.  There needs
                // to be a 1-to-1 mapping between the swc file and the cache file.
                incrementalFileName = outputFile.getPath() + ".cache";

                // If the output file doesn't exist don't bother loading the
                // cache since a recompile is needed.
                if (outputFile.exists())
                {
                    RandomAccessFile incrementalFile = null;
                    try
                    {
                        incrementalFile = new RandomAccessFile(incrementalFileName, "r");

                        // For loadCompilationUnits, loadedChecksums[1] must match
                        // the cached value else IOException is thrown.
                        int[] loadedChecksums = swcChecksums.copy();

                        CompilerAPI.loadCompilationUnits(configuration, fileSpec, sourceList, sourcePath, resources, bundlePath, null, /* sources */
                        null, /*units */
                        loadedChecksums, swcChecksums.getSwcDefSignatureChecksums(), swcChecksums.getSwcFileChecksums(), null, /* archiveFiles */
                        incrementalFile, incrementalFileName, null /* font manager */);

                        if (!(swcChecksums.isRecompilationNeeded(loadedChecksums) && !swcChecksums.isRelinkNeeded(loadedChecksums)))
                        {
                            recompile = false;
                        }
                    }
                    catch (FileNotFoundException ex)
                    {
                            // the incremental file doesn't exist
                            ThreadLocalToolkit.logDebug(ex.getLocalizedMessage());
                    }
                    catch (IOException ex)
                    {
                        // error loading the incremental file - most likely checksum
                        // mismatch or format mismatch
                        ThreadLocalToolkit.logInfo(ex.getLocalizedMessage());
                    }
                    finally
                    {
                        if (incrementalFile != null)
                        {
                            try
                            {
                                incrementalFile.close();
                            }
                            catch (IOException ex)
                            {
                            }
                            // If the load failed, or recompilation is needed, reset
                            // all the variables to their original state.
                            if (recompile)
                            {
                                fileSpec = new FileSpec(Collections.<VirtualFile>emptyList(), WebTierAPI.getFileSpecMimeTypes());
                                sourceList = new SourceList(virtualFileList,
                                                            asClasspath,
                                                            targetFile,
                                                            WebTierAPI.getSourcePathMimeTypes());
                                sourcePath = new SourcePath(asClasspath,
                                                            targetFile,
                                                            WebTierAPI.getSourcePathMimeTypes(),
                                                            compilerConfig.allowSourcePathOverlap());
                                resources = new ResourceContainer();
                                bundlePath = new ResourceBundlePath(configuration.getCompilerConfiguration(), targetFile);
                            }
                        }
                    }
                }
            }

            VirtualFile projector = configuration.getProjector();
            boolean createProjector = (projector != null && projector.getName().endsWith("avmplus.exe"));

            // Validate CompilationUnits in FileSpec and SourcePath.  If
            // count > 0 something changed.
            int count = CompilerAPI.validateCompilationUnits(
                    fileSpec, sourceList, sourcePath, bundlePath, resources,
                    swcContext,
                    null    /* perCompileData */,
                    configuration);
            recompile = recompile || (count > 0);

            if (recompile)
            {
                // Get standard bundle of compilers, transcoders.
                transcoders = WebTierAPI.getTranscoders( configuration );
                SubCompiler[] compilers = WebTierAPI.getCompilers(compilerConfig, mappings, transcoders);

                if (benchmark != null)
                {
                    benchmark.stopTime(Benchmark.PRECOMPILE, false);
                }

                units = CompilerAPI.compile(fileSpec, sourceList,
                                            null, /* classes */
                                            sourcePath, resources, bundlePath, swcContext,
                                            mappings, configuration, compilers,
                                            createProjector ? null : new PreLink(),
                                            configuration.getLicensesConfiguration().getLicenseMap(),
                                            sources);

                if (benchmark != null)
                {
                    benchmark.startTime(Benchmark.POSTCOMPILE);
                }

                OutputStream swfOut = new BufferedOutputStream(new FileOutputStream(outputFile));
                PostLink postLink = null;

                if (configuration.optimize() && !configuration.debug())
                {
                    postLink = new PostLink(configuration);
                }

                // link
                if (createProjector)
                {
                    ConsoleApplication app = LinkerAPI.linkConsole(units, postLink, configuration);
                    
                    createProjector(configuration, projector, app, swfOut);
                }
                else
                {
                    Movie movie = LinkerAPI.link(units, postLink, configuration);
                    
                    if (projector != null)
                    {
                        createProjector(configuration, projector, movie, swfOut);
                    }
                    else
                    {
                        CompilerAPI.encode(configuration, movie, swfOut);
                    }
                }

                swfOut.flush();
                swfOut.close();

                // If incremental compilation is enabled, save the compilation units.
                if (configuration.getCompilerConfiguration().getIncremental())
                {
                    // Make sure the checksums are all current.
                    swcChecksums.saveChecksums(units);

                    RandomAccessFile incrementalFile = null;
                    try
                    {
                        incrementalFile = new RandomAccessFile(incrementalFileName, "rw");

                        // In case we're reusing the file, clear it.
                        incrementalFile.setLength(0);

                        CompilerAPI.persistCompilationUnits(
                                configuration, fileSpec, sourceList, sourcePath,
                                resources, bundlePath,
                                sources,   /* sources */
                                units,   /* units */
                                swcChecksums.getChecksums(),
                                swcChecksums.getSwcDefSignatureChecksums(),
                                swcChecksums.getSwcFileChecksums(),
                                null,   /* archiveFiles */
                                "", incrementalFile);
                    }
                    catch (IOException ex)
                    {
                        ThreadLocalToolkit.logInfo(ex.getLocalizedMessage());

                        // Get rid of the cache file since the write failed.
                        new File(incrementalFileName).deleteOnExit();
                    }
                    finally
                    {
                        if (incrementalFile != null)
                        {
                            try
                            {
                                incrementalFile.close();
                            }
                            catch (IOException ex)
                            {
                            }
                        }
                    }
                }

                ThreadLocalToolkit.log(new OutputMessage(FileUtil.getCanonicalPath(outputFile),
                        Long.toString(outputFile.length())));
            }
            else
            {
                if (benchmark != null)
                {
                    benchmark.stopTime(Benchmark.PRECOMPILE, false);
                    benchmark.startTime(Benchmark.POSTCOMPILE);
                }

                // swf is already up-to-date so no need to compile/link or rewrite file
                ThreadLocalToolkit.log(new NoUpdateMessage(FileUtil.getCanonicalPath(outputFile)));
            }
            
            Set<IMxmlcExtension> extensions = ExtensionManager.getMxmlcExtensions( configuration.getCompilerConfiguration().getExtensionsConfiguration().getExtensionMappings() );
            for ( IMxmlcExtension extension : extensions )
            {
                if(ThreadLocalToolkit.errorCount() == 0) {
                    extension.run( args );
                }
            }        
        
        }
        catch (ConfigurationException ex)
        {
        	ThreadLocalToolkit.logInfo( getStartMessage( "mxmlc" ) );
            processConfigurationException(ex, "mxmlc");
        }
        catch (CompilerException ex)
        {
            assert ThreadLocalToolkit.errorCount() > 0;
        }
        catch (LinkerException ex)
        {
            assert ThreadLocalToolkit.errorCount() > 0;
        }
        catch (SwcException ex)
        {
            assert ThreadLocalToolkit.errorCount() > 0;
        }
        catch (Throwable t) // IOException, Throwable
        {
            ThreadLocalToolkit.logError(t.getLocalizedMessage());

            if (Trace.error)
            {
                t.printStackTrace();
            }
        }
        finally
        {
            if (benchmark != null)
            {
                if ((ThreadLocalToolkit.errorCount() == 0) &&
                    benchmark.hasStarted(Benchmark.POSTCOMPILE))
                {
                    benchmark.stopTime(Benchmark.POSTCOMPILE, false);
                }
                benchmark.totalTime();
                benchmark.peakMemoryUsage(true);
            }

            if (transcoders != null)
            {
                for (Transcoder element : transcoders)
                {
                    element.clear();
                }
            }

            CompilerAPI.removePathResolver();
        }
    }

    private static File getOutputFile(CommandLineConfiguration configuration, VirtualFile targetFile)
    {
        String name;
        VirtualFile projector = configuration.getProjector();
        boolean createProjector = (projector != null && projector.getName().endsWith("avmplus.exe"));

        if (createProjector)
        {
            // output .exe
            name = configuration.getOutput();
            if (name == null)
            {
                name = targetFile.getName();
                name = name.substring(0, name.lastIndexOf('.')) + ".exe";
            }
        }
        else
        {
            // output SWF
            name = configuration.getOutput();
            if (name == null)
            {
                name = targetFile.getName();
                if (projector != null)
                {
                    name = name.substring(0, name.lastIndexOf('.')) + ".exe";
                }
                else
                {
                    name = name.substring(0, name.lastIndexOf('.')) + ".swf";
                }
            }
        }

        return FileUtil.openFile(name, true);
    }

    public static void createProjector(Configuration config, VirtualFile projector, ConsoleApplication app, OutputStream out)
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try
        {
            CompilerAPI.encode(app, baos);
            createProjector(config, projector, baos, out);
        }
        catch (IOException ex)
        {
        }
    }

    public static void createProjector(Configuration config, VirtualFile projector, Movie movie, OutputStream out)
    {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try
        {
            CompilerAPI.encode(config, movie, baos);
            createProjector(config, projector, baos, out);
        }
        catch (IOException ex)
        {
        }
        finally
        {
        }
    }

    public static long createProjector(Configuration config, VirtualFile projector, ByteArrayOutputStream baos, OutputStream out)
    {
        long size = 0;
        BufferedInputStream in = null;
        try
        {
            in = new BufferedInputStream(projector.getInputStream());
            FileUtil.streamOutput(in, out);
            byte header[] = new byte[8];
            header[0] = 0x56;
            header[1] = 0x34;
            header[2] = 0x12;
            header[3] = (byte) 0xFA;
            header[4] = (byte) (baos.size() & 0xFF);
            header[5] = (byte) ((baos.size() >> 8) & 0xFF);
            header[6] = (byte) ((baos.size() >> 16) & 0xFF);
            header[7] = (byte) ((baos.size() >> 24) & 0xFF);
            out.write(baos.toByteArray());
            out.write(header);
            out.flush();
            size = projector.size() + baos.size() + 8;
        }
        catch (IOException ex)
        {
            size = 0;
        }
        finally
        {
            if (in != null) { try { in.close(); } catch (IOException ex) {} }
        }

        return size;
    }

    static private String l10nConfigPrefix = "flex2.configuration";

    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, false);
    }

    public static Configuration processConfiguration( LocalizationManager lmgr, String program, String[] args,
                                               ConfigurationBuffer cfgbuf, Class<? extends Configuration> cls, String defaultVar,
                                               boolean ignoreUnknownItems)
        throws ConfigurationException, IOException
    {
        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 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);
            }
        }

        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()));
    }

    // error messages

    public static class InitialSetup extends CompilerMessage.CompilerInfo
    {
        private static final long serialVersionUID = 1333039844101599298L;

        public InitialSetup()
        {
            super();
        }
    }

    public static class DumpConfig extends CompilerMessage.CompilerInfo
    {
        private static final long serialVersionUID = 953067728556782737L;

        public DumpConfig(String filename)
        {
            this.filename = filename;
        }
        public final String filename;
    }

    public static class LoadedSWCs extends CompilerMessage.CompilerInfo
    {
        private static final long serialVersionUID = 5287457959220324715L;

        public LoadedSWCs(int num)
        {
            super();
            this.num = num;
        }

        public final int num;
    }

    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;
        }
    }

    public static class NoUpdateMessage extends CompilerMessage.CompilerInfo
    {
        private static final long serialVersionUID = 6943388392279226490L;
        public String name;

        public NoUpdateMessage(String name)
        {
            this.name = name;
        }
    }

}

