package org.eclipse.vjet.eclipse.javatojs.core; import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Properties; import org.eclipse.vjet.core.codegen.bootstrap.CodeGenInputEntity; import org.eclipse.vjet.core.codegen.bootstrap.CodeGenOutputEntity; import org.eclipse.vjet.core.codegen.bootstrap.CodeGenOutputType; import org.eclipse.vjet.core.codegen.bootstrap.CodeGenStatus; import org.eclipse.vjet.core.codegen.bootstrap.CodeGeneratorMarker; import org.eclipse.vjet.core.codegen.bootstrap.ICodeGenTool; import org.eclipse.vjet.core.codegen.bootstrap.ICodeGeneratorMarker; import org.eclipse.vjet.core.codegen.bootstrap.IJava2JsCodeGenInput; import org.eclipse.vjet.core.codegen.bootstrap.IJava2JsCodeGenOutput; import org.eclipse.vjet.core.codegen.bootstrap.IJava2JsCodeGenTool; import org.eclipse.vjet.core.codegen.bootstrap.IToolMonitor; import org.eclipse.vjet.core.codegen.bootstrap.Java2JsCodeGenInput; import org.eclipse.vjet.core.codegen.bootstrap.Java2JsCodeGenOutput; import org.eclipse.vjet.core.codegen.bootstrap.ResourceValidationException; import org.eclipse.vjet.core.codegen.bootstrap.StatusCode; import org.eclipse.vjet.dsf.javatojs.control.ICodeGenPathResolver; import org.eclipse.vjet.dsf.javatojs.trace.TranslateError; import org.eclipse.vjet.dsf.javatojs.translate.config.CodeGenConfig; import org.eclipse.vjet.dsf.javatojs.util.VjoFiler; import org.eclipse.vjet.dsf.jsgen.shared.generate.CodeStyle; import org.eclipse.vjet.dsf.jst.declaration.JstType; import org.eclipse.vjet.dsf.logger.LogLevel; import org.eclipse.vjet.dsf.util.JavaSourceLocator; public class JavaToJsCodeGenTool implements IJava2JsCodeGenTool, ICodeGenTool { private static final String VJO_FILE_EXT = ".js"; private static final String JSR_FILE_EXT = "Jsr.java"; private static final String JAVA_FILE_EXT = ".java"; /** * must be set as an environmental variable */ public static final String JAVA_SOURCE_PATH = "java.source.path"; public List<CodeGenStatus> validate(CodeGenInputEntity arg0) { CodeGenStatus status = null; try { // TODO validate status = new CodeGenStatus(StatusCode.Success); } catch (ResourceValidationException e) { status = new CodeGenStatus(StatusCode.Error); status.setThrowable(e); status.setMessage(e.getMessage()); } List<CodeGenStatus> statusCollection = new ArrayList<CodeGenStatus>(); statusCollection.add(status); return statusCollection; } public List<CodeGenStatus> generate(CodeGenInputEntity inputEntity, List<CodeGenOutputEntity> outputCollection) { List<CodeGenStatus> statusCollection = new ArrayList<CodeGenStatus>( outputCollection.size()); try { URL inputURL = (URL)inputEntity.getData(); if (inputURL == null) { throw new RuntimeException("inputEntity.getData() is null"); } //TODO: PluginCodeGenConfig should be created using // the plugin configuration from UI CodeGenConfig config = new CodeGenConfig(); PluginCodeGenHelper helper = new PluginCodeGenHelper(config); List<JstType> jstTypes = helper.toJst(inputURL); if (!helper.getAllErrors().isEmpty()) { List<TranslateError> errors = helper.getAllErrors(); CodeGenStatus status = null; for (TranslateError error : errors) { if (error.getLevel().equals(LogLevel.ERROR)) { status = new CodeGenStatus(StatusCode.Error); } else if (error.getLevel().equals(LogLevel.WARN)) { status = new CodeGenStatus(StatusCode.Warning); } else if (error.getLevel().equals(LogLevel.FATAL)) { status = new CodeGenStatus(StatusCode.FatalError); } else { continue; } status.setMessage(error.getMsg()); status.setLineNumber((int) error.getSrcLineNo()); statusCollection.add(status); } } for (CodeGenOutputEntity output : outputCollection) { try { if (output.getType() == CodeGenOutputType.Vjo){ output.getOutputStream().write(helper.toVjo(jstTypes.get(0), CodeStyle.PRETTY)); } else if (output.getType() == CodeGenOutputType.Jsr && config.shouldGenJsr()){ output.getOutputStream().write(helper.toJsr(jstTypes.get(0), CodeStyle.PRETTY, true)); } else { output.getOutputStream().write("Invalid codegen type:" + output.getType()); } output.getOutputStream().flush(); output.getOutputStream().close(); CodeGenStatus status = new CodeGenStatus(StatusCode.Success); status.setLineNumber(1); status.setMessage("Successfully generated: "+ output.getName()); statusCollection.add(status); } catch (Exception e) { e.printStackTrace(); //KEEPME CodeGenStatus status = new CodeGenStatus(StatusCode.Error); status.setMessage(e.getMessage()); status.setLineNumber(1); status.setThrowable(e); statusCollection.add(status); } } } catch(Exception e){ e.printStackTrace(); //KEEPME CodeGenStatus status = new CodeGenStatus(StatusCode.Error); status.setMessage(e.getMessage()); status.setLineNumber(1); status.setThrowable(e); statusCollection.add(status); } return statusCollection; } public List<CodeGenOutputEntity> getOutputEntities(CodeGenInputEntity inputEntity) { List<CodeGenOutputEntity> outputEntities = new ArrayList<CodeGenOutputEntity>(); String inFileName = inputEntity.getName(); if (!isValidInputFile(inFileName)) { throw new IllegalArgumentException("Unknown input file type: " + inFileName); } CodeGenOutputEntity vjoOut = new CodeGenOutputEntity(); String vjoFileName = formatGeneratedName(inFileName, VJO_FILE_EXT); vjoOut.setName(vjoFileName); vjoOut.setType(CodeGenOutputType.Vjo); outputEntities.add(vjoOut); CodeGenOutputEntity jsrOut = new CodeGenOutputEntity(); String jsrFileName = formatGeneratedName(inFileName, JSR_FILE_EXT); jsrOut.setName(jsrFileName); jsrOut.setType(CodeGenOutputType.Jsr); outputEntities.add(jsrOut); return outputEntities; } // // Private // private static boolean isValidInputFile(String fileName){ return fileName.endsWith(".java"); } private static String formatGeneratedName(final String name, final String ext) { String s = name; int index = s.indexOf("."); if (index > 0) { // take name in front of file extension. s = s.substring(0, index); } if (s.length() > 0 && !Character.isUpperCase(s.charAt(0))) { char c = Character.toUpperCase(s.charAt(0)); if (s.length() > 1) { s = c + s.substring(1); } else { s = String.valueOf(c); } } return s + ext; } public List<IJava2JsCodeGenOutput> generate( List<IJava2JsCodeGenInput> input, IToolMonitor monitor) { monitor.beginTask("Java to JS code generation", input.size()); List<IJava2JsCodeGenOutput> output = new ArrayList<IJava2JsCodeGenOutput>(); for (IJava2JsCodeGenInput codeGenInput : input) { try { generate(codeGenInput, monitor, output); } catch (MalformedURLException e) { throw new RuntimeException( e); } } monitor.done(); return output; } private void generate(IJava2JsCodeGenInput input, IToolMonitor monitor, List<IJava2JsCodeGenOutput> output) throws MalformedURLException { /* * Must set the system property java.source.path for each call to the generator. * @author Ricker */ if (input != null && input.getJavaSourcePath() != null) { System.setProperty(JAVA_SOURCE_PATH, input.getJavaSourcePath()); JavaSourceLocator.getInstance().reset(); // reset java source locator } URL inputURL = input.getUrl(); if (inputURL == null) { throw new RuntimeException("IJava2JsCodeGenInput.getUrl() is null"); } // URL configURL = input.getJava2JsConfig(); // if (inputURL == null) { // throw new RuntimeException("IJava2JsCodeGenInput.getJava2JsConfig() is null"); // } // skip *Jsr.java files if (inputURL.toExternalForm().endsWith(JSR_FILE_EXT)) { return; } Properties configProp = input.getJava2JsProperties(); if (configProp == null) { throw new RuntimeException("IJava2JsCodeGenInput.getJava2JsProperties() is null"); } CodeGenConfig config = new CodeGenConfig(configProp); PluginCodeGenHelper helper = new PluginCodeGenHelper(config, monitor); List<JstType> jstTypes = helper.toJst(inputURL); List<IJava2JsCodeGenInput> inputs = write(jstTypes, helper, output); if (!helper.getAllErrors().isEmpty()) { output.addAll(processErrors(inputs, helper.getAllErrors())); } return; } private List<IJava2JsCodeGenOutput> processErrors( List<IJava2JsCodeGenInput> inputs, List<TranslateError> allErrors) { List<IJava2JsCodeGenOutput> outputs = new ArrayList<IJava2JsCodeGenOutput>(); for (TranslateError error : allErrors) { if (error.getSrcName() != null) { IJava2JsCodeGenInput input = findInput(error, inputs); if (input != null) { // Create a Java2JsCodeGenOutput for the error // markers and set the input file since errors belong to // the input file. Java2JsCodeGenOutput out = new Java2JsCodeGenOutput(); out.setInput(input); out.setUrl(input.getUrl()); setMarkers(out.getMarkers(), error); outputs.add(out); } } } return outputs; } private IJava2JsCodeGenInput findInput(TranslateError error, List<IJava2JsCodeGenInput> inputs) { for (IJava2JsCodeGenInput input : inputs) { String source = error.getSrcName().replace('.', '/')+JAVA_FILE_EXT; String url = input.getUrl().toExternalForm(); if (url.endsWith(source)) { return input; } } return null; } private List<IJava2JsCodeGenInput> write(List<JstType> jstTypes, PluginCodeGenHelper helper, List<IJava2JsCodeGenOutput> output) throws MalformedURLException { List<IJava2JsCodeGenInput> inputs = new ArrayList<IJava2JsCodeGenInput>(); for (JstType jst : jstTypes) { URL inputUrl = ICodeGenPathResolver.DEFAULT.getJavaFilePath(jst); Java2JsCodeGenInput input = new Java2JsCodeGenInput(); input.setUrl(inputUrl); inputs.add(input); URL vjoFilePath = ICodeGenPathResolver.DEFAULT.getVjoFilePath(jst); VjoFiler.writeToFile(vjoFilePath, helper.toVjo(jst, CodeStyle.PRETTY)); Java2JsCodeGenOutput out = new Java2JsCodeGenOutput(); out.setUrl(vjoFilePath); out.setInput(input); output.add(out); if (helper.getConfig().shouldGenJsr()) { URL jsrFilePath = ICodeGenPathResolver.DEFAULT.getJsrFilePath(jst); VjoFiler.writeToFile(jsrFilePath, helper.toJsr(jst, CodeStyle.PRETTY, true)); out = new Java2JsCodeGenOutput(); out.setUrl(jsrFilePath); out.setInput(input); output.add(out); } } return inputs; } private void setMarkers(List<ICodeGeneratorMarker> markers, TranslateError error) { CodeGeneratorMarker status = new CodeGeneratorMarker(); if (error.getLevel().equals(LogLevel.ERROR)) { status.setStatus(StatusCode.Error); } else if (error.getLevel().equals(LogLevel.WARN)) { status.setStatus(StatusCode.Warning); } else if (error.getLevel().equals(LogLevel.FATAL)) { status.setStatus(StatusCode.FatalError); } else { return; } status.setMessage(error.getMsg()); int line = (int) (error.getSrcLineNo() == 0 ? 1 : error.getSrcLineNo()); status.setLineNumber(line); markers.add(status); } }