package org.netbeans.gradle.project.java.query; import java.io.File; import java.net.MalformedURLException; import java.net.URL; import java.util.Arrays; import java.util.Objects; import java.util.logging.Level; import java.util.logging.Logger; import javax.swing.event.ChangeListener; import org.jtrim.utils.ExceptionHelper; import org.netbeans.api.java.queries.BinaryForSourceQuery; import org.netbeans.gradle.model.java.JavaSourceGroup; import org.netbeans.gradle.model.java.JavaSourceSet; import org.netbeans.gradle.project.java.JavaExtension; import org.netbeans.gradle.project.java.JavaModelChangeListener; import org.netbeans.gradle.project.java.model.NbJavaModule; import org.netbeans.gradle.project.query.AbstractBinaryForSourceQuery; import org.netbeans.gradle.project.util.LazyChangeSupport; import org.netbeans.gradle.project.util.NbFileUtils; import org.netbeans.gradle.project.util.NbSupplier; import org.openide.util.Utilities; public final class GradleBinaryForSourceQuery extends AbstractBinaryForSourceQuery implements JavaModelChangeListener { private static final Logger LOGGER = Logger.getLogger(GradleSourceForBinaryQuery.class.getName()); private static final URL[] NO_ROOTS = new URL[0]; private final NbSupplier<? extends NbJavaModule> moduleProvider; private final LazyChangeSupport changes; public GradleBinaryForSourceQuery(final JavaExtension javaExt) { this(new NbSupplier<NbJavaModule>() { @Override public NbJavaModule get() { return javaExt.getCurrentModel().getMainModule(); } }); ExceptionHelper.checkNotNullArgument(javaExt, "javaExt"); } public GradleBinaryForSourceQuery(NbSupplier<? extends NbJavaModule> moduleProvider) { ExceptionHelper.checkNotNullArgument(moduleProvider, "moduleProvider"); this.moduleProvider = moduleProvider; this.changes = LazyChangeSupport.createSwing(new EventSource()); } private static File tryGetOutputDir( NbJavaModule module, File root) { for (JavaSourceSet sourceSet: module.getSources()) { for (JavaSourceGroup sourceGroup: sourceSet.getSourceGroups()) { for (File sourceRoot: sourceGroup.getSourceRoots()) { if (Objects.equals(sourceRoot, root)) { return sourceSet.getOutputDirs().getClassesDir(); } } } } return null; } private static URL[] getRootsAsURLs( NbJavaModule module, File root) { File outputDir = tryGetOutputDir(module, root); if (outputDir == null) { return NO_ROOTS; } try { URL url = Utilities.toURI(outputDir).toURL(); return new URL[]{url}; } catch (MalformedURLException ex) { LOGGER.log(Level.INFO, "Cannot convert to URL: " + outputDir, ex); return NO_ROOTS; } } @Override public void onModelChange() { changes.fireChange(); } @Override protected File normalizeSourcePath(File sourcePath) { NbJavaModule module = moduleProvider.get(); for (JavaSourceSet sourceSet: module.getSources()) { for (JavaSourceGroup sourceGroup: sourceSet.getSourceGroups()) { for (File sourceRoot: sourceGroup.getSourceRoots()) { if (NbFileUtils.isParentOrSame(sourceRoot, sourcePath)) { return sourceRoot; } } } } return null; } @Override protected BinaryForSourceQuery.Result tryFindBinaryRoots(final File sourceRoot) { // If source path normalization succeeds, it is a source root we own. return new BinaryForSourceQuery.Result() { @Override public URL[] getRoots() { NbJavaModule mainModule = moduleProvider.get(); return getRootsAsURLs(mainModule, sourceRoot); } @Override public void addChangeListener(ChangeListener listener) { changes.addChangeListener(listener); } @Override public void removeChangeListener(ChangeListener listener) { changes.removeChangeListener(listener); } @Override public String toString() { return Arrays.toString(getRoots()); } }; } private static final class EventSource implements BinaryForSourceQuery.Result, LazyChangeSupport.Source { private volatile LazyChangeSupport changes; @Override public void init(LazyChangeSupport changes) { assert changes != null; this.changes = changes; } @Override public URL[] getRoots() { return NO_ROOTS; } @Override public void addChangeListener(ChangeListener l) { changes.addChangeListener(l); } @Override public void removeChangeListener(ChangeListener l) { changes.removeChangeListener(l); } } }