Package flex2.compiler.css

Source Code of flex2.compiler.css.CssCompiler

/*
*
*  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.compiler.css;

import flash.css.StyleSheet;
import flash.fonts.FontManager;
import flash.util.Trace;
import flex2.compiler.AbstractDelegatingSubCompiler;
import flex2.compiler.CompilationUnit;
import flex2.compiler.CompilerBenchmarkHelper;
import flex2.compiler.CompilerContext;
import flex2.compiler.Logger;
import flex2.compiler.Source;
import flex2.compiler.SymbolTable;
import flex2.compiler.Transcoder;
import flex2.compiler.as3.As3Compiler;
import flex2.compiler.as3.EmbedExtension;
import flex2.compiler.common.CompilerConfiguration;
import flex2.compiler.io.FileUtil;
import flex2.compiler.io.LocalFile;
import flex2.compiler.io.TextFile;
import flex2.compiler.io.VirtualFile;
import flex2.compiler.mxml.MxmlLogAdapter;
import flex2.compiler.mxml.SourceCodeBuffer;
import flex2.compiler.mxml.gen.VelocityUtil;
import flex2.compiler.mxml.lang.StandardDefs;
import flex2.compiler.mxml.lang.TextParser;
import flex2.compiler.mxml.rep.AtEmbed;
import flex2.compiler.util.CompilerMessage.CompilerError;
import flex2.compiler.util.DualModeLineNumberMap;
import flex2.compiler.util.LineNumberMap;
import flex2.compiler.util.MimeMappings;
import flex2.compiler.util.NameMappings;
import flex2.compiler.util.ThreadLocalToolkit;
import flex2.compiler.util.VelocityException.GenerateException;
import flex2.compiler.util.VelocityException.TemplateNotFound;
import flex2.compiler.util.VelocityException.UnableToWriteGeneratedFile;
import flex2.compiler.util.VelocityManager;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;

/**
* This subcompiler is used to translate a CSS file into an AS3
* representation, so it can be compiled by the AS3 delegate compiler
* into bytecode.  When the resulting SWF is loaded at runtime as a
* CSS module, the StyleManager will be populated with the styles
* defined in the CSS file.
*
* @author Paul Reilly
*/
public class CssCompiler extends AbstractDelegatingSubCompiler
{
    private static final String TEMPLATE_PATH = "flex2/compiler/css/";
    private static final String STYLE_MODULE_KEY = "styleModule";
    private static final String COMPILER_NAME = "css";

    private String[] mimeTypes;
    private CompilerConfiguration configuration;
    private NameMappings nameMappings;

    public CssCompiler(CompilerConfiguration configuration, Transcoder[] transcoders, NameMappings mappings)
    {
        this.configuration = configuration;
        mimeTypes = new String[]{MimeMappings.CSS};
        nameMappings = mappings;
        String gendir = (configuration.keepGeneratedActionScript()? configuration.getGeneratedDirectory() : null);

        // Create an As3Compiler as our delegate sub-compiler.
        As3Compiler asc = new As3Compiler(configuration);
        asc.addCompilerExtension(new EmbedExtension(transcoders, gendir, configuration.showDeprecationWarnings()));
        delegateSubCompiler = asc;
    }

    /**
     * The name of this compiler as a simple String identifier.
     *
     * @return This Compiler's name.
     */
    public String getName()
    {
        return COMPILER_NAME;
    }

    /**
     * If this compiler can process the specified file, return true.
     */
    public boolean isSupported(String mimeType)
    {
        return mimeTypes[0].equals(mimeType);
    }

    private String generateStyleName(Source source)
    {
        String result = source.getName();

        int lastSeparator = result.lastIndexOf(File.separator);

        if (lastSeparator != -1)
        {
            result = result.substring(lastSeparator + 1);

            int extension = result.indexOf(".css");

            if (extension != -1)
            {
                result = result.substring(0, extension);
            }
        }

        return result;
    }

    /**
     * Return supported mime types.
     */
    public String[] getSupportedMimeTypes()
    {
        return mimeTypes;
    }

    /**
     * Pre-process source file.
     */
    public Source preprocess(Source source)
    {
        if (benchmarkHelper != null)
        {
            benchmarkHelper.startPhase(CompilerBenchmarkHelper.PREPROCESS, source.getNameForReporting());
        }

        // The defs (mx.core:FlexModuleFactory, mx.core:mx_internal,
        // mx.core:IFlexModule, and mx.core:IFlexModuleFactory) are
        // used in frame 1, so they can't be externed.  ModuleBase is
        // used by the generated source, so it can't be externed
        // either.  The generated source depends on the rest of these
        // defs, but they should already be included in the loading
        // SWF, so we explicitly extern them.  The list was created by
        // examining a link report from a simple CSS compilation.
        // Although, this process is manual, it was alot easier than
        // writing a custom linker.  One alternative was to extern all
        // of framework.swc, but this prevents customers from using
        // skin assets from framework.swc in their runtime CSS
        // modules.
      if (!configuration.archiveClassesAndAssets())
      {
          StandardDefs standardDefs = ThreadLocalToolkit.getStandardDefs();
         
            configuration.addExtern(standardDefs.CLASS_CSSSTYLEDECLARATION);
            configuration.addExtern(standardDefs.CLASS_DOWNLOADPROGRESSBAR);
            configuration.addExtern(standardDefs.CLASS_FLEXEVENT);
            configuration.addExtern(standardDefs.CLASS_FLEXSPRITE);
            configuration.addExtern(standardDefs.CLASS_LOADERCONFIG);
            configuration.addExtern(standardDefs.CLASS_MODULEEVENT);
            configuration.addExtern(standardDefs.CLASS_MODULEMANAGER);
            configuration.addExtern(standardDefs.CLASS_PRELOADER);
            configuration.addExtern(standardDefs.CLASS_STYLEEVENT);
        // Don't extern StyleManager.  It is needed in case the module
        // is loaded in a bootstrap topology
            // configuration.addExtern(StandardDefs.CLASS_STYLEMANAGER);
            configuration.addExtern(standardDefs.CLASS_SYSTEMCHILDRENLIST);
            configuration.addExtern(standardDefs.CLASS_SYSTEMMANAGER);
            configuration.addExtern(standardDefs.CLASS_SYSTEMRAWCHILDRENLIST);
            configuration.addExtern(standardDefs.INTERFACE_ICHILDLIST);
            configuration.addExtern(standardDefs.INTERFACE_IFLEXDISPLAYOBJECT);
            configuration.addExtern(standardDefs.INTERFACE_IFOCUSMANAGERCONTAINER);
            configuration.addExtern(standardDefs.INTERFACE_IINVALIDATING);
            configuration.addExtern(standardDefs.INTERFACE_ILAYOUTMANAGERCLIENT);
            configuration.addExtern(standardDefs.INTERFACE_IMODULEINFO);
            configuration.addExtern(standardDefs.INTERFACE_IRAWCHILDRENCONTAINER);
            configuration.addExtern(standardDefs.INTERFACE_ISIMPLESTYLECLIENT);
            configuration.addExtern(standardDefs.INTERFACE_ISTYLECLIENT);
            configuration.addExtern(standardDefs.INTERFACE_ISYSTEMMANAGER);
            configuration.addExtern(standardDefs.INTERFACE_IUICOMPONENT);
      }
     
        String componentName = source.getShortName();
        if (!TextParser.isValidIdentifier(componentName))
        {
            InvalidComponentName invalidComponentName = new InvalidComponentName(componentName);
            invalidComponentName.setPath(source.getNameForReporting());
            ThreadLocalToolkit.log(invalidComponentName);
        }

        if (benchmarkHelper != null)
        {
            benchmarkHelper.endPhase(CompilerBenchmarkHelper.PREPROCESS);
        }

        return source;
    }

    /**
     * Parse... The implementation must:
     *
     * 1. create a compilation unit
     * 2. put the Source object and the syntax tree in the compilation unit
     * 3. register unit.includes, unit.dependencies, unit.topLevelDefinitions and unit.metadata
     */
    public CompilationUnit parse1(Source source, SymbolTable symbolTable)
    {
        if (benchmarkHelper != null)
        {
            benchmarkHelper.startPhase(CompilerBenchmarkHelper.PARSE1, source.getNameForReporting());
        }

        CompilationUnit unit = source.getCompilationUnit();

        if (unit != null && unit.hasTypeInfo)
        {
            return unit;
        }
       
        // System.out.println("parse1: " + source.getNameForReporting());
        FontManager fontManager = configuration.getFontsConfiguration().getTopLevelManager();

        StyleSheet styleSheet = new StyleSheet();
        styleSheet.checkDeprecation(configuration.showDeprecationWarnings());

        InputStream in = null;
        try
        {
            in = source.getInputStream();
            styleSheet.parse(source.getName(),
                             in,
                             ThreadLocalToolkit.getLogger(),
                             fontManager);
        }
        catch (Exception exception)
        {
            if (Trace.error)
            {
                exception.printStackTrace();
            }

            ParseError parseError = new ParseError(exception.getLocalizedMessage());
            parseError.setPath(source.getName());
            ThreadLocalToolkit.log(parseError);
            return null;
        }
        finally
        {
            if (in != null)
            {
                try
                {
                    in.close();
                }
                catch (IOException ex)
                {

                }
            }
        }       

        if (styleSheet.errorsExist())
        {
            // Error
            ThreadLocalToolkit.getLogger().log(new StyleSheetParseError(source.getName()));
        }

        StyleModule styleModule = new StyleModule(source, symbolTable.perCompileData);

        // Flex3 and earlier didn't support qualified types or advanced css.
        if (configuration.getCompatibilityVersion() <= flex2.compiler.common.MxmlConfiguration.VERSION_3_0)
        {
            styleModule.setAdvanced(false);
            styleModule.setQualifiedTypeSelectors(false);
        }
        else
        {
            styleModule.setQualifiedTypeSelectors(configuration.getQualifiedTypeSelectors());
        }

        styleModule.setNameMappings(nameMappings);
        String styleName = generateStyleName(source);
        styleModule.setName(styleName);
        styleModule.extractStyles(styleSheet, false);

        CompilerContext context = new CompilerContext();

        CompilationUnit cssCompilationUnit = source.newCompilationUnit(null, context);

        VirtualFile generatedFile = generateSourceCodeFile(cssCompilationUnit, styleModule);

        Source generatedSource = new Source(generatedFile, source);

        // when building a SWC, we want to locate all the asset sources and ask compc to put them in the SWC.
        Collection<AtEmbed> atEmbeds = styleModule.getAtEmbeds();
        if (atEmbeds != null && configuration.archiveClassesAndAssets())
        {
          Map<String, LocalFile> archiveFiles = new HashMap<String, LocalFile>();
          for (Iterator<AtEmbed>  i = atEmbeds.iterator(); i.hasNext(); )
          {
            AtEmbed e = (AtEmbed) i.next();
            String src = (String) e.getAttributes().get(Transcoder.SOURCE);
            String original = (String) e.getAttributes().get(Transcoder.ORIGINAL);
            if (src != null)
            {
              archiveFiles.put(original, new LocalFile(new File(src)));
            }
          }
          if (archiveFiles.size() > 0)
          {
            context.setAttribute(CompilerContext.CSS_ARCHIVE_FILES, archiveFiles);
          }
        }
       
        // Use MxmlLogAdapter to do filtering, e.g. -generated.as -> .css, as line -> css
        // line, etc...
        Logger original = ThreadLocalToolkit.getLogger();
        LineNumberMap lineNumberMap = styleModule.getLineNumberMap();
        Logger adapter = new MxmlLogAdapter(original, lineNumberMap);
        ThreadLocalToolkit.setLogger(adapter);

        CompilationUnit ascCompilationUnit = delegateSubCompiler.parse1(generatedSource, symbolTable);

        if (ascCompilationUnit != null)
        {
            // transfer includes from the ASC unit to the CSS unit
            cssCompilationUnit.getSource().addFileIncludes(ascCompilationUnit.getSource());
            context.setAttribute(DELEGATE_UNIT, ascCompilationUnit);
            context.setAttribute(LINE_NUMBER_MAP, lineNumberMap);
            Source.transferMetaData(ascCompilationUnit, cssCompilationUnit);
            Source.transferGeneratedSources(ascCompilationUnit, cssCompilationUnit);
            Source.transferDefinitions(ascCompilationUnit, cssCompilationUnit);
            Source.transferInheritance(ascCompilationUnit, cssCompilationUnit);
        }
        else
        {
            cssCompilationUnit = null;
        }

        if (benchmarkHelper != null)
        {
            benchmarkHelper.endPhase(CompilerBenchmarkHelper.PARSE1);
        }

        return cssCompilationUnit;
    }

    public void parse2(CompilationUnit unit, SymbolTable symbolTable)
    {
        if (benchmarkHelper != null)
            benchmarkHelper.startPhase(CompilerBenchmarkHelper.PARSE2, unit.getSource().getNameForReporting());

        if (unit != null && unit.hasTypeInfo)
        {
            return;
        }

        super.parse2(unit, symbolTable);

        if (benchmarkHelper != null)
            benchmarkHelper.endPhase(CompilerBenchmarkHelper.PARSE2);
    }

    public void analyze1(CompilationUnit unit, SymbolTable symbolTable)
    {
        if (benchmarkHelper != null)
            benchmarkHelper.startPhase(CompilerBenchmarkHelper.ANALYZE1, unit.getSource().getNameForReporting());

        if (unit != null && unit.hasTypeInfo)
        {
            return;
        }

        super.analyze1(unit, symbolTable);

        if (benchmarkHelper != null)
            benchmarkHelper.endPhase(CompilerBenchmarkHelper.ANALYZE1);
    }

    public void analyze2(CompilationUnit unit, SymbolTable symbolTable)
    {
        if (benchmarkHelper != null)
            benchmarkHelper.startPhase(CompilerBenchmarkHelper.ANALYZE2, unit.getSource().getNameForReporting());

        if (unit != null && unit.hasTypeInfo)
        {
            return;
        }

        super.analyze2(unit, symbolTable);

        if (benchmarkHelper != null)
            benchmarkHelper.endPhase(CompilerBenchmarkHelper.ANALYZE2);
    }

    public void analyze3(CompilationUnit unit, SymbolTable symbolTable)
    {
        if (benchmarkHelper != null)
            benchmarkHelper.startPhase(CompilerBenchmarkHelper.ANALYZE3, unit.getSource().getNameForReporting());

        if (unit != null && unit.hasTypeInfo)
        {
            return;
        }

        super.analyze3(unit, symbolTable);

        if (benchmarkHelper != null)
            benchmarkHelper.endPhase(CompilerBenchmarkHelper.ANALYZE3);
    }

    public void analyze4(CompilationUnit unit, SymbolTable symbolTable)
    {
        if (benchmarkHelper != null)
            benchmarkHelper.startPhase(CompilerBenchmarkHelper.ANALYZE4, unit.getSource().getNameForReporting());

        super.analyze4(unit, symbolTable);

        if (benchmarkHelper != null)
            benchmarkHelper.endPhase(CompilerBenchmarkHelper.ANALYZE4);
    }

    public void generate(CompilationUnit unit, SymbolTable symbolTable)
    {
        if (benchmarkHelper != null)
            benchmarkHelper.startPhase(CompilerBenchmarkHelper.GENERATE,unit.getSource().getNameForReporting());

        if (unit != null && unit.hasTypeInfo)
        {
            return;
        }

        super.generate(unit, symbolTable);

        if (benchmarkHelper != null)
            benchmarkHelper.endPhase(CompilerBenchmarkHelper.GENERATE);
    }

    public void postprocess(CompilationUnit unit, SymbolTable symbolTable)
    {
        if (benchmarkHelper != null)
            benchmarkHelper.startPhase(CompilerBenchmarkHelper.POSTPROCESS, unit.getSource().getNameForReporting());

        if (unit != null && unit.hasTypeInfo)
        {
            return;
        }

        super.postprocess(unit, symbolTable);

        if (benchmarkHelper != null)
            benchmarkHelper.endPhase(CompilerBenchmarkHelper.POSTPROCESS);
    }

    private VirtualFile generateSourceCodeFile(CompilationUnit compilationUnit, StyleModule styleModule)
    {
        Template template;
        StandardDefs standardDefs = compilationUnit.getStandardDefs();
        String templateName = TEMPLATE_PATH + (!configuration.archiveClassesAndAssets() ? standardDefs.getStyleModuleTemplate() : standardDefs.getStyleLibraryTemplate());

        try
        {
            template = VelocityManager.getTemplate(templateName);
        }
        catch (Exception exception)
        {
            ThreadLocalToolkit.log(new TemplateNotFound(templateName));
            return null;
        }

        SourceCodeBuffer sourceCodeBuffer = new SourceCodeBuffer();

        String genFileName = (configuration.getGeneratedDirectory() +
                              File.separatorChar +
                              styleModule.getName() +
                              "-generated.as");

        Source source = compilationUnit.getSource();

        DualModeLineNumberMap lineNumberMap = new DualModeLineNumberMap(source.getNameForReporting(), genFileName);
        styleModule.setLineNumberMap(lineNumberMap);

        try
        {
            VelocityUtil velocityUtil = new VelocityUtil(TEMPLATE_PATH, configuration.debug(),
                                                         sourceCodeBuffer, lineNumberMap);
            VelocityContext velocityContext = VelocityManager.getCodeGenContext(velocityUtil);
            velocityContext.put(STYLE_MODULE_KEY, styleModule);
            template.merge(velocityContext, sourceCodeBuffer);
        }
        catch (Exception e)
        {
            ThreadLocalToolkit.log(new GenerateException(styleModule.getName(), e.getLocalizedMessage()));
            return null;
        }

        String sourceCode = sourceCodeBuffer.toString();

        if (configuration.keepGeneratedActionScript())
        {
            try
            {
                FileUtil.writeFile(genFileName, sourceCode);
            }
            catch (IOException e)
            {
                ThreadLocalToolkit.log(new UnableToWriteGeneratedFile(genFileName, e.getLocalizedMessage()));
            }
        }

        return new TextFile(sourceCode, genFileName, null, MimeMappings.AS, Long.MAX_VALUE);
    }

    public static class InvalidComponentName extends CompilerError
    {
        private static final long serialVersionUID = -6052613984350060542L;
        public final String name;

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

    public static class StyleSheetParseError extends CompilerError
    {
        private static final long serialVersionUID = -2795572334523977344L;
        public final String stylePath;

        public StyleSheetParseError(String stylePath)
        {
            this.stylePath = stylePath;
        }
    }
}
TOP

Related Classes of flex2.compiler.css.CssCompiler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.