package org.netbeans.gradle.project.query; import java.io.File; import java.net.URL; import javax.swing.event.ChangeListener; import org.netbeans.api.java.queries.BinaryForSourceQuery.Result; import org.netbeans.gradle.project.util.GradleFileUtils; import org.netbeans.gradle.project.util.LazyChangeSupport; import org.netbeans.gradle.project.util.NbFileUtils; import org.netbeans.spi.java.queries.BinaryForSourceQueryImplementation; import org.openide.filesystems.FileObject; import org.openide.filesystems.FileUtil; import org.openide.util.lookup.ServiceProvider; import org.openide.util.lookup.ServiceProviders; @ServiceProviders({@ServiceProvider(service = BinaryForSourceQueryImplementation.class)}) public final class GradleCacheBinaryForSourceQuery extends AbstractBinaryForSourceQuery { private static final URL[] NO_ROOTS = new URL[0]; private static final LazyChangeSupport CHANGES; static { CHANGES = LazyChangeSupport.createSwing(new EventSource()); GradleFileUtils.GRADLE_USER_HOME.addChangeListener(new Runnable() { @Override public void run() { notifyCacheChange(); } }); } public GradleCacheBinaryForSourceQuery() { } public static void notifyCacheChange() { CHANGES.fireChange(); } @Override protected Result tryFindBinaryRoots(File sourceRoot) { File gradleUserHome = GradleFileUtils.GRADLE_USER_HOME.getValue(); if (gradleUserHome == null) { return null; } final FileObject sourceRootObj = FileUtil.toFileObject(sourceRoot); if (sourceRootObj == null) { return null; } FileObject gradleUserHomeObj = FileUtil.toFileObject(gradleUserHome); if (gradleUserHomeObj == null || !FileUtil.isParentOf(gradleUserHomeObj, sourceRootObj)) { return null; } FileObject hashDir = sourceRootObj.getParent(); if (hashDir == null) { return null; } FileObject srcDir = hashDir.getParent(); if (srcDir == null) { return null; } final String binFileName = GradleFileUtils.sourceToBinaryName(sourceRootObj); if (binFileName == null) { return null; } if (GradleFileUtils.SOURCE_DIR_NAME.equals(srcDir.getNameExt())) { final FileObject artifactRoot = srcDir.getParent(); if (artifactRoot == null) { return null; } return new OldFormatCacheResult(artifactRoot, binFileName); } return GradleFileUtils.isSourceFile(sourceRootObj) ? new NewFormatCacheResult(srcDir, binFileName) : null; } private static final class EventSource implements 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); } } private static class NewFormatCacheResult implements Result { private final FileObject artifactRoot; private final String binFileName; public NewFormatCacheResult(FileObject artifactRoot, String binFileName) { this.artifactRoot = artifactRoot; this.binFileName = binFileName; } @Override public URL[] getRoots() { // The cache directory of Gradle looks like this: // // ...... \\HASH_OF_SOURCE\\binary-sources.XXX // ...... \\HASH_OF_BINARY\\binary.XXX FileObject binFile = NbFileUtils.getFileFromASubDir(artifactRoot, binFileName); return binFile != null ? new URL[]{binFile.toURL()} : NO_ROOTS; } @Override public void addChangeListener(ChangeListener l) { CHANGES.addChangeListener(l); } @Override public void removeChangeListener(ChangeListener l) { CHANGES.removeChangeListener(l); } } private static class OldFormatCacheResult implements Result { private final FileObject artifactRoot; private final String binFileName; public OldFormatCacheResult(FileObject artifactRoot, String binFileName) { this.artifactRoot = artifactRoot; this.binFileName = binFileName; } @Override public URL[] getRoots() { // The cache directory of Gradle looks like this: // // ...... \\source\\HASH_OF_SOURCE\\binary-sources.jar // ...... \\packaging type\\HASH_OF_BINARY\\binary.jar for (String binDirName: GradleFileUtils.BINARY_DIR_NAMES) { FileObject binDir = artifactRoot.getFileObject(binDirName); if (binDir == null) { continue; } FileObject binFile = NbFileUtils.getFileFromASubDir(binDir, binFileName); if (binFile != null) { return new URL[]{binFile.toURL()}; } } return NO_ROOTS; } @Override public void addChangeListener(ChangeListener l) { CHANGES.addChangeListener(l); } @Override public void removeChangeListener(ChangeListener l) { CHANGES.removeChangeListener(l); } } }