/******************************************************************************* * Copyright (c) 2011-2014 Fernando Petrola * * This file is part of Dragome SDK. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the GNU Public License v3.0 * which accompanies this distribution, and is available at * http://www.gnu.org/licenses/gpl.html ******************************************************************************/ package com.dragome.web.helpers.serverside; import java.io.File; import java.io.FileOutputStream; import java.net.URI; import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.jar.JarOutputStream; import java.util.logging.Logger; import org.apache.commons.io.FileUtils; import com.dragome.commons.DragomeConfigurator; import com.dragome.commons.compiler.BytecodeToJavascriptCompiler; import com.dragome.commons.compiler.BytecodeToJavascriptCompilerConfiguration; import com.dragome.commons.compiler.BytecodeTransformer; import com.dragome.commons.compiler.annotations.CompilerType; import com.dragome.commons.compiler.classpath.Classpath; import com.dragome.commons.compiler.classpath.ClasspathEntry; import com.dragome.commons.compiler.classpath.ClasspathFile; import com.dragome.commons.compiler.classpath.ClasspathFileFilter; import com.dragome.commons.compiler.classpath.serverside.JarClasspathEntry; import com.dragome.services.ServiceLocator; import com.dragome.services.WebServiceLocator; import com.dragome.view.VisualActivity; import com.dragome.web.helpers.DefaultClasspathFileFilter; import proguard.Configuration; import proguard.ConfigurationParser; import proguard.ProGuard; public class DragomeCompilerLauncher { private static Logger LOGGER= Logger.getLogger(DragomeCompilerLauncher.class.getName()); public static void compileWithMainClass(Classpath classPath, String target) { ServiceLocator serviceLocator= ServiceLocator.getInstance(); DragomeConfigurator configurator= serviceLocator.getConfigurator(); String mainClassName= VisualActivity.class.getName(); CompilerType defaultCompilerType= configurator.getDefaultCompilerType(); BytecodeTransformer bytecodeTransformer= configurator.getBytecodeTransformer(); ClasspathFileFilter classpathFilter= configurator.getClasspathFilter(); if (classpathFilter == null) classpathFilter= new DefaultClasspathFileFilter(); BytecodeToJavascriptCompiler bytecodeToJavascriptCompiler= WebServiceLocator.getInstance().getBytecodeToJavascriptCompiler(); configurator.sortClassPath(classPath); classPath= process(classPath, configurator); List<ClasspathEntry> extraClasspath= configurator.getExtraClasspath(classPath); classPath.addEntries(extraClasspath); BytecodeToJavascriptCompilerConfiguration compilerConfiguration= new BytecodeToJavascriptCompilerConfiguration(classPath, target, mainClassName, defaultCompilerType, bytecodeTransformer, classpathFilter, configurator.isCheckingCast(), configurator.isCaching()); bytecodeToJavascriptCompiler.configure(compilerConfiguration); bytecodeToJavascriptCompiler.compile(); } private static Classpath process(Classpath classPath, DragomeConfigurator configurator) { try { String path= null; String tempDir= System.getProperty("java.io.tmpdir"); File tmpDir= new File(tempDir + File.separatorChar + "dragomeTemp"); Path tmpPath= tmpDir.toPath(); FileUtils.deleteDirectory(tmpDir); Files.createDirectories(tmpPath); File file= Files.createTempFile(tmpPath, "dragome-merged-", ".jar").toFile(); file.deleteOnExit(); path= file.getAbsolutePath(); try (JarOutputStream jos= new JarOutputStream(new FileOutputStream(file))) { List<ClasspathEntry> entries= classPath.getEntries(); for (ClasspathEntry classpathEntry : entries) classpathEntry.copyFilesToJar(jos, new DefaultClasspathFileFilter() { private ArrayList<String> keepClass= new ArrayList<>(); public boolean accept(ClasspathFile classpathFile) { boolean result= super.accept(classpathFile); String entryName= classpathFile.getPath(); if (!keepClass.contains(entryName)) { keepClass.add(entryName); if (entryName.endsWith(".js") || entryName.endsWith(".class") || entryName.contains("MANIFEST") || entryName.contains(".html") || entryName.contains(".css")) result&= true; } return result; } }); } if (configurator.isRemoveUnusedCode()) { return runProguard(file, configurator); } else return new Classpath(JarClasspathEntry.createFromPath(path)); } catch (Exception e) { throw new RuntimeException(e); } } private static Classpath runProguard(File file, DragomeConfigurator configurator) throws Exception { URI uri= DragomeCompilerLauncher.class.getResource("/proguard.conf").toURI(); Properties properties= System.getProperties(); properties.put("in-jar-filename", file.getAbsolutePath()); String outFilename= file.getAbsolutePath().replace(".jar", "-proguard.jar"); new File(outFilename).deleteOnExit(); properties.put("out-jar-filename", outFilename); ConfigurationParser parser= new ConfigurationParser(uri.toURL(), properties); URL additionalCodeKeepConfigFile= configurator.getAdditionalCodeKeepConfigFile(); Configuration configuration= new Configuration(); parser.parse(configuration); if (additionalCodeKeepConfigFile != null) { ConfigurationParser parserForAdditionalKeepCodeConfigFile= new ConfigurationParser(additionalCodeKeepConfigFile, properties); parserForAdditionalKeepCodeConfigFile.parse(configuration); } new ProGuard(configuration).execute(); return new Classpath(JarClasspathEntry.createFromPath(outFilename)); } }