All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.xtend.maven.AbstractXtendInstallDebugInfoMojo Maven / Gradle / Ivy

The newest version!
package org.eclipse.xtend.maven;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.xtext.generator.trace.AbstractTraceRegion;
import org.eclipse.xtext.generator.trace.ITraceToBytecodeInstaller;
import org.eclipse.xtext.generator.trace.TraceAsPrimarySourceInstaller;
import org.eclipse.xtext.generator.trace.TraceAsSmapInstaller;
import org.eclipse.xtext.generator.trace.TraceFileNameProvider;
import org.eclipse.xtext.generator.trace.TraceRegionSerializer;
import org.eclipse.xtext.util.Strings;

import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.io.Files;
import com.google.inject.Inject;
import com.google.inject.Provider;

/**
 * @author Moritz Eysholdt - Initial contribution and API
 */
public abstract class AbstractXtendInstallDebugInfoMojo extends AbstractXtendMojo {

	@Inject
	protected ClassFileDebugSourceExtractor classFileDebugSourceExtractor;

	/**
	 * Set this to false to show synthetic variables in the debugger. This only has an effect if
	 * {@link #traceAsPrimarySourceInstallerProvider} is set to true. Synthetic variables are variables which are
	 * created by the Xtend compiler. Therefore they only exist in the compiled Java code but not in the Xtend code.
	 * 
	 * @parameter default-value="true" expression="${hideSyntheticVariables}"
	 */
	protected boolean hideSyntheticVariables;

	@Inject
	private Provider traceAsPrimarySourceInstallerProvider;

	@Inject
	private Provider traceAsSmapInstaller;

	@Inject
	private TraceFileNameProvider traceFileNameProvider;

	@Inject
	protected TraceRegionSerializer traceRegionSerializer;

	/**
	 * Set this to true to use the Xtend sources as the primary debugging sources. This will completely hide the Java
	 * sources in the debugger. You'll need to enable it if your JVM doesn't support JSR-045.
	 * 
	 * @parameter default-value="false" expression="${xtendAsPrimaryDebugSource}"
	 */
	protected boolean xtendAsPrimaryDebugSource;

	protected void collectJavaSourceFile2traceFile(String root, String subdir,
			Map javaSourceFile2traceFile) {
		File file = new File(root + "/" + subdir);
		File[] listFiles = file.listFiles();
		if (listFiles == null) {
			getLog().warn("Directory "+ file.getPath() +" is empty. Can't process.");
			return;
		}
		for (File child : listFiles) {
			String name = child.getName();
			if (child.isDirectory())
				collectJavaSourceFile2traceFile(root, subdir + "/" + name, javaSourceFile2traceFile);
			else if (name.endsWith(TraceFileNameProvider.TRACE_FILE_EXTENSION)) {
				String javaSourceFile = subdir + "/" + traceFileNameProvider.getJavaFromTrace(name);
				javaSourceFile2traceFile.put(javaSourceFile, child);
			}
		}
	}

	protected ITraceToBytecodeInstaller createTraceToBytecodeInstaller() {
		if (xtendAsPrimaryDebugSource) {
			TraceAsPrimarySourceInstaller installer = traceAsPrimarySourceInstallerProvider.get();
			installer.setHideSyntheticVariables(hideSyntheticVariables);
			return installer;
		} else {
			TraceAsSmapInstaller installer = traceAsSmapInstaller.get();
			return installer;
		}
	}

	protected Multimap createTraceToClassFileMap(List sourceFolders, String outputFolder) {
		Map javaSourceFile2traceFile = Maps.newLinkedHashMap();

		for (String sourceRoot : sourceFolders)
			collectJavaSourceFile2traceFile(sourceRoot, "", javaSourceFile2traceFile);

		Set packageDirs = Sets.newLinkedHashSet();
		for (String javaSourceFile : javaSourceFile2traceFile.keySet())
			packageDirs.add(Strings.skipLastToken(javaSourceFile, "/"));

		Multimap trace2class = LinkedHashMultimap.create();

		for (String packageDirName : packageDirs) {
			File packageDir = new File(outputFolder + "/" + packageDirName);
			if (packageDir.isDirectory()) {
				for (File classFile : packageDir.listFiles())
					if (classFile.getName().endsWith(".class"))
						try {
							String sourceFileName = classFileDebugSourceExtractor.getDebugSourceFileName(classFile);
							if (Strings.isEmpty(sourceFileName))
								continue;
							if (!sourceFileName.toLowerCase().endsWith(".java"))
								continue;
							File traceFile = javaSourceFile2traceFile.get(packageDirName + "/" + sourceFileName);
							if (traceFile != null)
								trace2class.put(traceFile, classFile);
						} catch (IOException e) {
							getLog().error("Error reading " + classFile, e);
						}
			}
		}
		return trace2class;
	}

	protected void installTrace(File traceFile, Collection classFiles) throws FileNotFoundException, IOException {
		ITraceToBytecodeInstaller traceToBytecodeInstaller = createTraceToBytecodeInstaller();
		InputStream in = new FileInputStream(traceFile);
		try {
			AbstractTraceRegion traceRegion = traceRegionSerializer.readTraceRegionFrom(in);
			traceToBytecodeInstaller.setTrace(traceFileNameProvider.getJavaFromTrace(traceFile.getName()), traceRegion);
			if (getLog().isDebugEnabled())
				getLog().debug("Installing trace " + traceFile + " into:");
			for (File classFile : classFiles) {
				if (getLog().isDebugEnabled())
					getLog().debug("  " + classFile);
				Files.write(traceToBytecodeInstaller.installTrace(Files.toByteArray(classFile)), classFile);
			}
		} finally {
			in.close();
		}
	}

	protected void installTraces(Multimap trace2class) {
		for (Map.Entry> e : trace2class.asMap().entrySet()) {
			try {
				installTrace(e.getKey(), e.getValue());
			} catch (Exception e1) {
				getLog().error(e1);
			}
		}
	}

	protected void logStatus(String folder, Multimap trace2class) {
		String p = xtendAsPrimaryDebugSource ? "primary" : "secondary (via SMAP)";
		int n = trace2class.size();
		getLog().info("Installing Xtend files into " + n + " class files as " + p + " debug sources in: " + folder);
		getLog().debug("xtendAsPrimaryDebugSource=" + xtendAsPrimaryDebugSource);
		getLog().debug("hideSyntheticVariables=" + hideSyntheticVariables);
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy