blob: c040edf2488c6c1e2ffe3a623e0938d7634e6e7f [file] [log] [blame]
/*
*
* 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.*;
import flex2.compiler.*;
import flex2.compiler.SourceList.UnsupportedFileType;
import flex2.compiler.ResourceBundlePath;
import flex2.compiler.abc.AbcCompiler;
import flex2.compiler.as3.As3Compiler;
import flex2.compiler.as3.EmbedExtension;
import flex2.compiler.as3.SignatureExtension;
import flex2.compiler.as3.StyleExtension;
import flex2.compiler.as3.HostComponentExtension;
import flex2.compiler.as3.binding.BindableExtension;
import flex2.compiler.as3.SkinPartExtension;
import flex2.compiler.as3.managed.ManagedExtension;
import flex2.compiler.common.CompilerConfiguration;
import flex2.compiler.common.Configuration;
import flex2.compiler.css.CssCompiler;
import flex2.compiler.fxg.FXGCompiler;
import flex2.compiler.i18n.I18nCompiler;
import flex2.compiler.i18n.I18nUtils;
import flex2.compiler.io.VirtualFile;
import flex2.compiler.media.*;
import flex2.compiler.mxml.MxmlCompiler;
import flex2.compiler.swc.SwcCache;
import flex2.compiler.util.MimeMappings;
import flex2.compiler.util.NameMappings;
import flex2.compiler.util.ThreadLocalToolkit;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
/**
* This class is used externally by the webtier compiler and
* internally by some of the other flex tools, like fcsh and mxmlc.
*/
public final class WebTierAPI extends Tool
{
/**
* This method is called by flex.webtier.server.j2ee.CompilerFilter.
*/
public static Target compile(VirtualFile targetFile, Configuration configuration, SwcCache swcCache, Map licenseMap)
throws CompilerException
{
Target target = new Target();
try
{
if (configuration.benchmark())
{
flex2.compiler.CompilerAPI.runBenchmark();
}
else
{
flex2.compiler.CompilerAPI.disableBenchmark();
}
target.configuration = configuration;
flex2.compiler.CompilerAPI.useAS3();
flex2.compiler.CompilerAPI.usePathResolver();
flex2.compiler.CompilerAPI.setupHeadless(configuration);
// set up for localizing messages
LocalizationManager l10n = new LocalizationManager();
l10n.addLocalizer( new XLRLocalizer() );
l10n.addLocalizer( new ResourceBundleLocalizer() );
ThreadLocalToolkit.setLocalizationManager( l10n );
checkSupportedTargetMimeType(targetFile);
List<VirtualFile> virtualFileList = new ArrayList<VirtualFile>();
virtualFileList.add(targetFile);
CompilerConfiguration compilerConfig = configuration.getCompilerConfiguration();
NameMappings mappings = flex2.compiler.CompilerAPI.getNameMappings(configuration);
// get standard bundle of compilers, transcoders
flex2.compiler.Transcoder[] transcoders = getTranscoders(configuration);
flex2.compiler.SubCompiler[] compilers = getCompilers(compilerConfig, mappings, transcoders);
// create a FileSpec...
target.fileSpec = new FileSpec(Collections.<VirtualFile>emptyList(), getFileSpecMimeTypes());
VirtualFile[] asClasspath = compilerConfig.getSourcePath();
// create a SourceList...
target.sourceList = new SourceList(virtualFileList,
asClasspath,
targetFile,
getSourcePathMimeTypes());
// create a SourcePath...
target.sourcePath = new SourcePath(asClasspath,
targetFile,
getSourcePathMimeTypes(),
compilerConfig.allowSourcePathOverlap());
// create a ResourceContainer
target.resources = new ResourceContainer();
target.bundlePath = new ResourceBundlePath(configuration.getCompilerConfiguration(), targetFile);
if (ThreadLocalToolkit.getBenchmark() != null)
{
ThreadLocalToolkit.getBenchmark().benchmark(l10n.getLocalizedTextString(new Mxmlc.InitialSetup()));
}
// load SWCs
CompilerSwcContext swcContext = new CompilerSwcContext();
swcContext.load(compilerConfig.getLibraryPath(),
Configuration.getAllExcludedLibraries(compilerConfig, configuration),
compilerConfig.getThemeFiles(),
compilerConfig.getIncludeLibraries(),
mappings,
I18nUtils.getTranslationFormat(compilerConfig),
swcCache);
configuration.addExterns(swcContext.getExterns());
configuration.addIncludes( swcContext.getIncludes() );
configuration.getCompilerConfiguration().addThemeCssFiles(swcContext.getThemeStyleSheets());
// validate CompilationUnits in FileSpec, SourceList and SourcePath
flex2.compiler.CompilerAPI.validateCompilationUnits(target.fileSpec, target.sourceList, target.sourcePath,
target.bundlePath, target.resources, swcContext, null, configuration);
// create a SymbolTable...
final SymbolTable symbolTable = new SymbolTable(configuration);
target.perCompileData = symbolTable.perCompileData;
// compile
target.units = flex2.compiler.CompilerAPI.compile(target.fileSpec, target.sourceList, null, target.sourcePath, target.resources,
target.bundlePath, swcContext, symbolTable, mappings, configuration, compilers,
new PreLink(), licenseMap, new ArrayList<Source>());
return target;
}
catch (CompilerException ex)
{
throw ex;
}
catch (Throwable t)
{
String message = t.getMessage();
if (message == null)
{
message = t.getClass().getName();
}
ThreadLocalToolkit.logError(message);
throw new CompilerException(message);
}
finally
{
flex2.compiler.CompilerAPI.removePathResolver();
}
}
/**
* This method is used by Toolkit.
*
* @see flex2.tools.oem.Toolkit
*/
public static long optimize(InputStream in, OutputStream out, Configuration configuration) throws IOException
{
// decoder
Movie movie = new Movie();
TagDecoder tagDecoder = new TagDecoder(in);
MovieDecoder movieDecoder = new MovieDecoder(movie);
tagDecoder.parse(movieDecoder);
// optimize
optimize(movie, configuration);
//TODO PERFORMANCE: A lot of unnecessary recopying and buffering here
// encode
TagEncoder handler = new TagEncoder();
MovieEncoder encoder = new MovieEncoder(handler);
encoder.export(movie);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
handler.writeTo(baos);
out.write(baos.toByteArray());
return baos.size();
}
/**
* This method is used by Optimizer.
*
* @see flex2.tools.Optimizer
*/
static void optimize(Movie m, Configuration configuration)
{
// don't keep debug opcodes
// abc merge
// peephole optimization
m.enableDebugger = null;
m.uuid = null;
PostLink postLink = (configuration != null) ? new PostLink(configuration) : new PostLink(false, true);
postLink.run(m);
}
/**
* This method is used by Toolkit.
*
* @see flex2.tools.oem.Toolkit
*/
public static long optimize(InputStream in, OutputStream out) throws IOException
{
return optimize(in, out, null);
}
/**
* This method is called by flex.webtier.server.j2ee.IncrementalCompilerFilter.
*/
public static Transcoder[] getTranscoders( Configuration cfg )
{
// create a list of supported transcoders
return new Transcoder[]{new JPEGTranscoder(), new LosslessImageTranscoder(), //new JAITranscoder(),
new SVGTranscoder(cfg.getCompilerConfiguration().showDeprecationWarnings()),
new SoundTranscoder(), new MovieTranscoder(), new FontTranscoder(cfg),
new DataTranscoder(), new XMLTranscoder(),
new SkinTranscoder(), new PBJTranscoder()
};
}
/**
* This method is called by flex.webtier.server.j2ee.IncrementalCompilerFilter.
*/
public static flex2.compiler.SubCompiler[] getCompilers(CompilerConfiguration compilerConfig, NameMappings mappings,
Transcoder[] transcoders)
{
// support .AS3
As3Compiler asc = new As3Compiler(compilerConfig);
// signature generation should occur before other extensions can touch the syntax tree
if (!compilerConfig.getDisableIncrementalOptimizations())
{
SignatureExtension.init(compilerConfig);
asc.addCompilerExtension(SignatureExtension.getInstance());
}
final String gendir = (compilerConfig.keepGeneratedActionScript()
? compilerConfig.getGeneratedDirectory()
: null);
final boolean generateAbstractSyntaxTree = compilerConfig.getGenerateAbstractSyntaxTree();
asc.addCompilerExtension(new EmbedExtension(transcoders, gendir, compilerConfig.showDeprecationWarnings()));
asc.addCompilerExtension(new StyleExtension());
// IMPORTANT!!!! The HostComponentExtension must run before the BindableExtension!!!!
asc.addCompilerExtension(new HostComponentExtension(compilerConfig.reportMissingRequiredSkinPartsAsWarnings()));
asc.addCompilerExtension(new BindableExtension(gendir, generateAbstractSyntaxTree, false));
asc.addCompilerExtension(new ManagedExtension(gendir, generateAbstractSyntaxTree,
compilerConfig.getServicesDependencies(), false));
asc.addCompilerExtension(new SkinPartExtension());
// asc.addCompilerExtension(new flex2.compiler.util.TraceExtension());
// support MXML
MxmlCompiler mxmlc = new MxmlCompiler(compilerConfig, compilerConfig,
mappings, transcoders);
// support ABC
AbcCompiler abc = new AbcCompiler(compilerConfig);
abc.addCompilerExtension(new StyleExtension());
// abc.addCompilerExtension(new flex2.compiler.util.TraceExtension());
// support FXG
FXGCompiler fxg = new FXGCompiler(compilerConfig, mappings);
// support i18n (.properties)
I18nCompiler prop = new I18nCompiler(compilerConfig, transcoders);
// support CSS
CssCompiler css = new CssCompiler(compilerConfig, transcoders, mappings);
return new SubCompiler[]{asc, mxmlc, abc, fxg, prop, css};
}
/**
* This method is used by Mxmlc, Fcsh, and Application.
*
* @see flex2.tools.Mxmlc
* @see flex2.tools.Fcsh
* @see flex2.tools.oem.Application
*/
public static void checkSupportedTargetMimeType(VirtualFile targetFile) throws CompilerException
{
String[] mimeTypes = getTargetMimeTypes();
for (int i = 0, length = mimeTypes.length; i < length; i++)
{
if (mimeTypes[i].equals(targetFile.getMimeType()))
{
return;
}
}
UnsupportedFileType ex = new UnsupportedFileType(targetFile.getName());
ThreadLocalToolkit.log(ex);
throw ex;
}
/**
* This method is called by flex.webtier.server.j2ee.IncrementalCompilerFilter.
*/
public static String[] getFileSpecMimeTypes()
{
return new String[]{MimeMappings.AS, MimeMappings.MXML, MimeMappings.FXG, MimeMappings.CSS, MimeMappings.ABC};
}
/**
* This method is called by flex.webtier.server.j2ee.IncrementalCompilerFilter.
*/
public static String[] getSourceListMimeTypes()
{
return new String[]{MimeMappings.AS, MimeMappings.MXML, MimeMappings.FXG, MimeMappings.CSS};
}
/**
* This method is called by flex.webtier.server.j2ee.IncrementalCompilerFilter.
*/
public static String[] getSourcePathMimeTypes()
{
return new String[]{MimeMappings.AS, MimeMappings.MXML, MimeMappings.FXG};
}
/**
* This method is called by flex.webtier.server.j2ee.IncrementalCompilerFilter.
*
* FXG is not included in the list of target mime types, because
* the compiler doesn't support an FXG based root yet and we don't
* want to allow broken SWF's to be created.
*/
public static String[] getTargetMimeTypes()
{
return new String[]{MimeMappings.AS, MimeMappings.MXML, MimeMappings.CSS};
}
}