blob: b77dd8f1a87ace184cd0e65c2a8d44d4aa1b9f63 [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 flex2.compiler.Logger;
import flex2.compiler.config.ConfigurationException;
import flex2.compiler.util.CompilerMessage;
import flex2.compiler.util.CompilerMessage.CompilerError;
import flex2.compiler.util.ThreadLocalToolkit;
import flex2.tools.oem.Message;
import org.apache.flex.compiler.clients.COMPC;
import org.apache.flex.compiler.clients.MXMLC;
import org.apache.flex.compiler.clients.MXMLJSC.JSOutputType;
import org.apache.flex.compiler.clients.problems.ProblemQuery;
import org.apache.flex.compiler.clients.problems.ProblemQueryProvider;
import org.apache.flex.compiler.config.Configuration;
import org.apache.flex.compiler.config.ConfigurationBuffer;
import org.apache.flex.compiler.config.ConfigurationValue;
import org.apache.flex.compiler.filespecs.FileSpecification;
import org.apache.flex.compiler.internal.config.FileConfigurator;
import org.apache.flex.compiler.problems.CompilerProblemSeverity;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.problems.annotations.DefaultSeverity;
import org.apache.flex.utils.ArgumentUtil;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import static org.apache.flex.compiler.clients.MXMLJSC.JSOutputType.FLEXJS_DUAL;
/**
* Common base class for most flex tools.
*/
public class Tool {
protected static Class<? extends MXMLC> COMPILER;
protected static Class<? extends MxmlJSC> JS_COMPILER;
protected static int compile(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
int exitCode;
final JSOutputType jsOutputType = JSOutputType.fromString(ArgumentUtil.getValue(args, "-js-output-type"));
if (jsOutputType != null) {
ArgumentBag bag = preparePhase1(new ArgumentBag(args));
MxmlJSC mxmlJSC = JS_COMPILER.newInstance();
exitCode = mxmlJSC.execute(bag.args);
if (!mxmlJSC.getProblemQuery().hasErrors()) {
if (jsOutputType.equals(FLEXJS_DUAL)) {
preparePhase2(bag);
exitCode = flexCompile(bag.args);
}
} else {
processProblemReport(mxmlJSC);
}
} else {
exitCode = flexCompile(args);
}
return exitCode;
}
protected static ArgumentBag preparePhase1(ArgumentBag bag) {
bag.isCommandLineOutput = true;
bag.oldOutputPath = ArgumentUtil.getValue(bag.args, "-output");
if (bag.oldOutputPath == null) {
bag.isCommandLineOutput = false;
ConfigurationBuffer flexConfig = null;
try {
flexConfig = loadConfig(bag.args);
} catch (org.apache.flex.compiler.exceptions.ConfigurationException ignored) {
}
final List<ConfigurationValue> output = flexConfig != null ? flexConfig.getVar("output") : null;
final ConfigurationValue configurationValue = output != null ? output.get(0) : null;
bag.oldOutputPath = configurationValue != null ? configurationValue.getArgs().get(0) : null;
}
if (bag.oldOutputPath != null) {
final int lastIndexOf = Math.max(bag.oldOutputPath.lastIndexOf("/"), bag.oldOutputPath.lastIndexOf("\\"));
if (lastIndexOf > -1) {
bag.newOutputPath = bag.oldOutputPath.substring(0, lastIndexOf) + File.separator + "js" + File.separator + "out";
if (bag.isCommandLineOutput) {
ArgumentUtil.setValue(bag.args, "-output", bag.newOutputPath);
} else {
bag.args = ArgumentUtil.addValueAt(bag.args, "-output", bag.newOutputPath, bag.args.length - 1);
}
}
}
return bag;
}
protected static ArgumentBag preparePhase2(ArgumentBag bag) {
bag.args = ArgumentUtil.removeElement(bag.args, "-js-output-type");
if (bag.oldOutputPath != null) {
if (bag.isCommandLineOutput) {
ArgumentUtil.setValue(bag.args, "-output", bag.oldOutputPath);
} else {
bag.args = ArgumentUtil.removeElement(bag.args, "-output");
}
}
if (COMPILER.getName().equals(COMPC.class.getName())) {
bag.args = ArgumentUtil.addValueAt(bag.args, "-include-file", "js" + File.separator + "out" + File.separator + "*," + bag.newOutputPath, bag.args.length - 1);
}
return bag;
}
private static ConfigurationBuffer loadConfig(String[] args) throws org.apache.flex.compiler.exceptions.ConfigurationException {
final String configFilePath = ArgumentUtil.getValue(args, "-load-config");
final File configFile = new File(configFilePath);
final FileSpecification fileSpecification = new FileSpecification(configFile.getAbsolutePath());
final ConfigurationBuffer cfgbuf = createConfigurationBuffer(Configuration.class);
FileConfigurator.load(
cfgbuf,
fileSpecification,
new File(configFile.getPath()).getParent(),
"flex-config",
false);
return cfgbuf;
}
private static ConfigurationBuffer createConfigurationBuffer(
Class<? extends Configuration> configurationClass) {
return new ConfigurationBuffer(
configurationClass, Configuration.getAliases());
}
protected static int flexCompile(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
int exitCode;
MXMLC mxmlc = COMPILER.newInstance();
exitCode = mxmlc.execute(args);
processProblemReport(new CompilerRequestableProblems(mxmlc));
return exitCode;
}
public static Map<String, String> getLicenseMapFromFile(String fileName) throws ConfigurationException {
Map<String, String> result = null;
FileInputStream in = null;
try {
in = new FileInputStream(fileName);
Properties properties = new Properties();
properties.load(in);
Enumeration enumeration = properties.propertyNames();
if (enumeration.hasMoreElements()) {
result = new HashMap<String, String>();
while (enumeration.hasMoreElements()) {
String propertyName = (String) enumeration.nextElement();
result.put(propertyName, properties.getProperty(propertyName));
}
}
} catch (IOException ioException) {
LocalizationManager l10n = ThreadLocalToolkit.getLocalizationManager();
throw new ConfigurationException(l10n.getLocalizedTextString(new FailedToLoadLicenseFile(fileName)));
} finally {
if (in != null) {
try {
in.close();
} catch (IOException ioe) {
}
}
}
return result;
}
public static class FailedToLoadLicenseFile extends CompilerError {
private static final long serialVersionUID = -2980033917773108328L;
public String fileName;
public FailedToLoadLicenseFile(String fileName) {
super();
this.fileName = fileName;
}
}
public static void processProblemReport(ProblemQueryProvider requestableProblems) {
for (ICompilerProblem problem : requestableProblems.getProblemQuery().getProblems()) {
Class aClass = problem.getClass();
Annotation[] annotations = aClass.getAnnotations();
for (Annotation annotation : annotations) {
if (annotation instanceof DefaultSeverity) {
DefaultSeverity myAnnotation = (DefaultSeverity) annotation;
CompilerProblemSeverity cps = myAnnotation.value();
String level;
if (cps.equals(CompilerProblemSeverity.ERROR))
level = Message.ERROR;
else if (cps.equals(CompilerProblemSeverity.WARNING))
level = Message.WARNING;
else
break; // skip if IGNORE?
CompilerMessage msg = new CompilerMessage(level,
problem.getSourcePath(),
problem.getLine() + 1,
problem.getColumn());
try {
String errText = (String) aClass.getField("DESCRIPTION").get(aClass);
while (errText.contains("${")) {
int start = errText.indexOf("${");
int end = errText.indexOf("}", start);
String token = errText.substring(start + 2, end);
String value = (String) aClass.getField(token).get(problem);
token = "${" + token + "}";
errText = errText.replace(token, value);
}
msg.setMessage(errText);
logMessage(msg);
} catch (IllegalArgumentException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SecurityException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalAccessException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchFieldException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}
private static void logMessage(CompilerMessage msg) {
final Logger logger = ThreadLocalToolkit.getLogger();
if (logger != null) {
if (msg.getLevel().equals(Message.INFO)) {
logger.logInfo(msg.getPath(), msg.getLine(), msg.getColumn(), msg.getMessage());
} else if (msg.getLevel().equals(Message.WARNING)) {
logger.logWarning(msg.getPath(), msg.getLine(), msg.getColumn(), msg.getMessage());
} else if (msg.getLevel().equals(Message.ERROR)) {
logger.logError(msg.getPath(), msg.getLine(), msg.getColumn(), msg.getMessage());
}
}
}
public static class NoUpdateMessage extends CompilerMessage.CompilerInfo {
private static final long serialVersionUID = 6943388392279226490L;
public String name;
public NoUpdateMessage(String name) {
this.name = name;
}
}
static class CompilerRequestableProblems implements ProblemQueryProvider {
private MXMLC mxmlc;
public CompilerRequestableProblems(MXMLC mxmlc) {
this.mxmlc = mxmlc;
}
@Override
public ProblemQuery getProblemQuery() {
return mxmlc.getProblems();
}
}
protected static class ArgumentBag {
public String[] args;
public String oldOutputPath;
public String newOutputPath;
public boolean isCommandLineOutput;
public ArgumentBag(String[] args) {
this.args = args;
}
}
}