You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by lk...@apache.org on 2020/06/29 16:09:58 UTC
[netbeans] branch release120 updated: Allow Gradle projects to be
opened instantly
This is an automated email from the ASF dual-hosted git repository.
lkishalmi pushed a commit to branch release120
in repository https://gitbox.apache.org/repos/asf/netbeans.git
The following commit(s) were added to refs/heads/release120 by this push:
new 7067d25 Allow Gradle projects to be opened instantly
7067d25 is described below
commit 7067d25a99ad231bb9d19932ce92033494ddbda3
Author: Laszlo Kishalmi <la...@gmail.com>
AuthorDate: Mon Jun 29 09:02:56 2020 -0700
Allow Gradle projects to be opened instantly
---
groovy/gradle/apichanges.xml | 39 ++++
groovy/gradle/licenseinfo.xml | 1 +
groovy/gradle/manifest.mf | 2 +-
.../modules/gradle/ActionProviderImpl.java | 5 +
.../modules/gradle/GradleProjectCache.java | 35 ++--
.../gradle/GradleProjectProblemProvider.java | 29 ++-
.../modules/gradle/NbGradleProjectImpl.java | 28 ++-
.../org/netbeans/modules/gradle/ProjectTrust.java | 230 +++++++++++++++++++++
.../org/netbeans/modules/gradle/ReloadAction.java | 8 +-
.../modules/gradle/api/execute/RunUtils.java | 34 +++
.../gradle/customizer/BuildActionsCustomizer.java | 9 +-
.../modules/gradle/customizer/Bundle.properties | 2 +
.../customizer/GradleCustomizerProvider.java | 60 ++++--
.../gradle/customizer/GradleExecutionPanel.form | 95 +++++++++
.../gradle/customizer/GradleExecutionPanel.java | 127 ++++++++++++
.../modules/gradle/execute/Bundle.properties | 1 +
.../modules/gradle/execute/TrustProjectPanel.form | 79 +++++++
.../modules/gradle/execute/TrustProjectPanel.java | 109 ++++++++++
.../modules/gradle/options/Bundle.properties | 1 +
.../modules/gradle/options/SettingsPanel.form | 25 ++-
.../modules/gradle/options/SettingsPanel.java | 26 ++-
.../org/netbeans/modules/gradle/resources/info.png | Bin 0 -> 766 bytes
.../modules/gradle/spi/GradleSettings.java | 56 ++++-
.../customizer/support/FilterPanelProvider.java | 7 +-
.../gradle/spi/newproject/TemplateOperation.java | 5 +-
.../gradle/AbstractGradleProjectTestCase.java | 3 +-
.../modules/gradle/NbGradleProjectFactoryTest.java | 9 -
.../netbeans/modules/gradle/ProjectTrustTest.java | 88 ++++++++
.../modules/gradle/api/execute/RunUtilsTest.java | 5 +
29 files changed, 1024 insertions(+), 94 deletions(-)
diff --git a/groovy/gradle/apichanges.xml b/groovy/gradle/apichanges.xml
index 65a70c0..b0a3bbe 100644
--- a/groovy/gradle/apichanges.xml
+++ b/groovy/gradle/apichanges.xml
@@ -83,6 +83,45 @@ is the proper place.
<!-- ACTUAL CHANGES BEGIN HERE: -->
<changes>
+ <change id="gradle-project-trust">
+ <api name="general"/>
+ <summary>Introduce Trust relationship with Gradle Projects to prevent unintentional Gradle invocation.</summary>
+ <version major="2" minor="2"/>
+ <date year="2020" month="6" day="24"/>
+ <author login="lkishalmi"/>
+ <compatibility binary="compatible" source="compatible"/>
+ <description>
+ <p>
+ Gradle projects are maintaining a trust attribute from now.
+ This trust is based on the NetBeans user directory and the
+ a secret placed in the Gradle Root project directory.
+ </p>
+ <p>
+ Trusting any project of a multi-project Gradle build means
+ trust all project in that multi-project project, as the
+ trust is placed on the root project.
+ </p>
+ <p>
+ This change is backported to version 2.0.1 as well.
+ </p>
+ <p>
+ Added <code>RunUtils.isProjectTrusted(Project,boolean)</code>
+ where plugin can check if a project is trusted or request
+ one time trust with interactive mode.
+ </p>
+ <p>
+ There is no API/SPI to mark a project trusted/untrusted.
+ Projects are not trusted by default, but become trusted once
+ a priming build is requested or a Gradle task is invoked as
+ a result of an user action.
+ </p>
+ <p>
+ Added <code>org.netbeans.modules.gradle.spi.GradleSettings.GradleExecutionRule</code>
+ with setter ad getter in <code>org.netbeans.modules.gradle.spi.GradleSettings</code>
+ as a global option to how to treat automatic Gradle Execution globally.
+ </p>
+ </description>
+ </change>
<change id="gradle-tooling-api-split">
<api name="general"/>
<summary>Move Gradle Tooling API to a separate module.</summary>
diff --git a/groovy/gradle/licenseinfo.xml b/groovy/gradle/licenseinfo.xml
index 93818e5..e08b8e5 100644
--- a/groovy/gradle/licenseinfo.xml
+++ b/groovy/gradle/licenseinfo.xml
@@ -25,6 +25,7 @@
<file>src/org/netbeans/modules/gradle/resources/defaultFolder.gif</file>
<file>src/org/netbeans/modules/gradle/resources/defaultFolderOpen.gif</file>
<file>src/org/netbeans/modules/gradle/resources/empty.png</file>
+ <file>src/org/netbeans/modules/gradle/resources/info.png</file>
<file>src/org/netbeans/modules/gradle/resources/javadoc-badge.png</file>
<file>src/org/netbeans/modules/gradle/resources/libraries-badge.png</file>
<file>src/org/netbeans/modules/gradle/resources/libraries.png</file>
diff --git a/groovy/gradle/manifest.mf b/groovy/gradle/manifest.mf
index 4f49bfb..b4ef608 100644
--- a/groovy/gradle/manifest.mf
+++ b/groovy/gradle/manifest.mf
@@ -3,5 +3,5 @@ AutoUpdate-Show-In-Client: false
OpenIDE-Module: org.netbeans.modules.gradle/2
OpenIDE-Module-Layer: org/netbeans/modules/gradle/layer.xml
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/gradle/Bundle.properties
-OpenIDE-Module-Specification-Version: 2.0
+OpenIDE-Module-Specification-Version: 2.0.1
OpenIDE-Module-Requires: cnb.org.netbeans.modules.groovy.kit
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/ActionProviderImpl.java b/groovy/gradle/src/org/netbeans/modules/gradle/ActionProviderImpl.java
index fc0e9ce..b3da4a6 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/ActionProviderImpl.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/ActionProviderImpl.java
@@ -232,7 +232,12 @@ public class ActionProviderImpl implements ActionProvider {
}
}
+
boolean reloadOnly = !showUI && (args.length == 0);
+ if (!reloadOnly) {
+ //Trust project only if it does execute a real action
+ ProjectTrust.getDefault().trustProject(project);
+ }
final boolean needReload;
final Quality maxQualily = (cfg.getCommandLine().hasFlag(GradleCommandLine.Flag.OFFLINE))
&& (mapping.getReloadRule() != ActionMapping.ReloadRule.ALWAYS_ONLINE)
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java b/groovy/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java
index 22860c7..e8f76d8 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/GradleProjectCache.java
@@ -16,7 +16,6 @@
* specific language governing permissions and limitations
* under the License.
*/
-
package org.netbeans.modules.gradle;
import org.netbeans.modules.gradle.spi.GradleFiles;
@@ -99,26 +98,31 @@ public final class GradleProjectCache {
// Increase this number if new info is gathered from the projects.
private static final int COMPATIBLE_CACHE_VERSION = 12;
+ private GradleProjectCache() {
+ }
+
/**
- * Loads a physical GradleProject either from Gradle or Cache. As project retrieval can be time consuming using
- * Gradle sometimes it's just enough to shoot for FALLBACK information. Aiming for FALLBACK quality either retrieves
- * the GradleProject form cache if it's valid or returns the fallback Project implementation.
+ * Loads a physical GradleProject either from Gradle or Cache. As project
+ * retrieval can be time consuming using Gradle sometimes it's just enough
+ * to shoot for FALLBACK information. Aiming for FALLBACK quality either
+ * retrieves the GradleProject form cache if it's valid or returns the
+ * fallback Project implementation.
*
* @param files The project to load.
* @param requestedQuality The project information quality to aim for.
* @return The retrievable GradleProject
*/
- public static GradleProject loadProject(final NbGradleProjectImpl project, Quality aim, boolean ignoreCache, String... args) {
+ public static GradleProject loadProject(final NbGradleProjectImpl project, Quality aim, boolean ignoreCache, boolean interactive, String... args) {
final GradleFiles files = project.getGradleFiles();
if (aim == FALLBACK) {
return fallbackProject(files);
}
- GradleProject prev = project.project;
+ GradleProject prev = project.project != null ? project.project : fallbackProject(files);
// Try to turn to the cache
if (!(ignoreCache || GradleSettings.getDefault().isCacheDisabled())
- && (prev.getQuality() == FALLBACK)) {
+ && (prev.getQuality() == FALLBACK)) {
ProjectCacheEntry cacheEntry = loadCachedProject(files);
if (cacheEntry != null) {
if (cacheEntry.isCompatible()) {
@@ -130,18 +134,18 @@ public final class GradleProjectCache {
}
}
}
- if (prev == null) {
- // Could this happen?
- prev = fallbackProject(project.getGradleFiles());
- }
final ReloadContext ctx = new ReloadContext(project, prev, aim);
ctx.args = args;
GradleProject ret;
try {
- ret = GRADLE_LOADER_RP.submit(new ProjectLoaderTask(ctx)).get();
- updateSubDirectoryCache(ret);
+ if (RunUtils.isProjectTrusted(project, interactive)) {
+ ret = GRADLE_LOADER_RP.submit(new ProjectLoaderTask(ctx)).get();
+ updateSubDirectoryCache(ret);
+ } else {
+ ret = prev.invalidate();
+ }
} catch (InterruptedException | ExecutionException ex) {
ret = fallbackProject(files);
}
@@ -182,7 +186,6 @@ public final class GradleProjectCache {
cmd.addSystemProperty(GradleDaemon.PROP_TOOLING_JAR, TOOLING_JAR);
cmd.addProjectProperty("nbSerializeCheck", "true");
-
GoOnline goOnline;
if (GradleSettings.getDefault().isOffline()) {
goOnline = GoOnline.NEVER;
@@ -476,9 +479,6 @@ public final class GradleProjectCache {
return createFallbackProject(FALLBACK, files, Collections.<String>emptyList());
}
- private static GradleProject evaluatedProject(GradleFiles files, Collection<String> probs) {
- return createFallbackProject(EVALUATED, files, probs);
- }
private static GradleProject createFallbackProject(Quality quality, GradleFiles files, Collection<String> probs) {
Collection<? extends ProjectInfoExtractor> extractors = Lookup.getDefault().lookupAll(ProjectInfoExtractor.class);
@@ -513,6 +513,7 @@ public final class GradleProjectCache {
}
static final class ReloadContext {
+
final NbGradleProjectImpl project;
final GradleProject previous;
final Quality aim;
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/GradleProjectProblemProvider.java b/groovy/gradle/src/org/netbeans/modules/gradle/GradleProjectProblemProvider.java
index 648e96a..083da69 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/GradleProjectProblemProvider.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/GradleProjectProblemProvider.java
@@ -68,24 +68,31 @@ public class GradleProjectProblemProvider implements ProjectProblemsProvider {
}
@Override
- @NbBundle.Messages("LBL_BrokenPlatform=Broken Platform.")
+ @NbBundle.Messages({
+ "LBL_BrokenPlatform=Broken Platform.",
+ "LBL_PrimingRequired=Priming Build Required.",
+ "TXT_PrimingRequired=In order to be able to read this project, "
+ + "NetBeans needs to execute its Gradle scripts as priming build."
+ + "\n\n"
+ + "Executing Gradle scripts allows arbitrary code execution, "
+ + "as current user, on this system."
+ })
public Collection<? extends ProjectProblem> getProblems() {
List<ProjectProblem> ret = new ArrayList<>();
synchronized (this) {
if (listener == null) {
- listener = new PropertyChangeListener() {
-
- @Override
- public void propertyChange(PropertyChangeEvent evt) {
- if (NbGradleProject.PROP_PROJECT_INFO.equals(evt.getPropertyName())) {
- support.firePropertyChange(PROP_PROBLEMS, null, null);
- }
- }
- };
+ listener = (PropertyChangeEvent evt) -> {
+ if (NbGradleProject.PROP_PROJECT_INFO.equals(evt.getPropertyName())) {
+ support.firePropertyChange(PROP_PROBLEMS, null, null);
+ }
+ };
NbGradleProject.addPropertyChangeListener(project, listener);
}
}
GradleProject gp = project.getLookup().lookup(NbGradleProjectImpl.class).getGradleProject();
+ if (gp.getQuality().notBetterThan(EVALUATED)) {
+ ret.add(ProjectProblem.createError(Bundle.LBL_PrimingRequired(), Bundle.TXT_PrimingRequired(), resolver));
+ }
for (String problem : gp.getProblems()) {
String[] lines = problem.split("\\n"); //NOI18N
ret.add(ProjectProblem.createWarning(lines[0], problem.replaceAll("\\n", "<br/>"), resolver)); //NOI18N
@@ -107,7 +114,7 @@ public class GradleProjectProblemProvider implements ProjectProblemsProvider {
@Override
public Result call() throws Exception {
NbGradleProjectImpl impl = project.getLookup().lookup(NbGradleProjectImpl.class);
- GradleProject gradleProject = GradleProjectCache.loadProject(impl, FULL_ONLINE, true);
+ GradleProject gradleProject = GradleProjectCache.loadProject(impl, FULL_ONLINE, true, true);
impl.fireProjectReload(false);
Quality q = gradleProject.getQuality();
Status st = q.worseThan(SIMPLE) ? Status.UNRESOLVED :
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/NbGradleProjectImpl.java b/groovy/gradle/src/org/netbeans/modules/gradle/NbGradleProjectImpl.java
index 2d8bc5a..0dcd6d0 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/NbGradleProjectImpl.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/NbGradleProjectImpl.java
@@ -53,6 +53,7 @@ import static java.util.logging.Level.*;
import java.util.logging.Logger;
import org.netbeans.api.annotations.common.NonNull;
import org.netbeans.api.annotations.common.SuppressWarnings;
+import org.netbeans.api.project.ui.ProjectProblems;
import org.netbeans.modules.gradle.api.GradleBaseProject;
import org.netbeans.spi.project.CacheDirectoryProvider;
import org.netbeans.spi.project.support.LookupProviderSupport;
@@ -84,8 +85,7 @@ public final class NbGradleProjectImpl implements Project {
private final Lookup completeLookup;
private Updater openedProjectUpdater;
private Quality aimedQuality = FALLBACK;
- private final @NonNull
- NbGradleProject watcher;
+ private final @NonNull NbGradleProject watcher;
@SuppressWarnings("MS_SHOULD_BE_FINAL")
public static WatcherAccessor ACCESSOR = null;
@@ -97,7 +97,7 @@ public final class NbGradleProjectImpl implements Project {
Class<?> c = NbGradleProject.class;
try {
Class.forName(c.getName(), true, c.getClassLoader());
- } catch (Exception ex) {
+ } catch (ClassNotFoundException ex) {
LOG.log(SEVERE, "very wrong, very wrong, yes indeed", ex);
}
}
@@ -249,18 +249,14 @@ public final class NbGradleProjectImpl implements Project {
}
private GradleProject loadProject(boolean ignoreCache, Quality aim, String... args) {
- GradleProject prj = GradleProjectCache.loadProject(this, aim, ignoreCache, args);
+ GradleProject prj = GradleProjectCache.loadProject(this, aim, ignoreCache, false, args);
return prj;
}
void reloadProject(final boolean ignoreCache, final Quality aim, final String... args) {
- RELOAD_RP.post(new Runnable() {
-
- @Override
- public void run() {
- project = loadProject(ignoreCache, aim, args);
- ACCESSOR.doFireReload(watcher);
- }
+ RELOAD_RP.post(() -> {
+ project = loadProject(ignoreCache, aim, args);
+ ACCESSOR.doFireReload(watcher);
});
}
@@ -293,11 +289,11 @@ public final class NbGradleProjectImpl implements Project {
@Override
protected void projectOpened() {
- Runnable open = new Runnable() {
- @Override
- public void run() {
- setAimedQuality(FULL);
- attachAllUpdater();
+ Runnable open = () -> {
+ setAimedQuality(FULL);
+ attachAllUpdater();
+ if (ProjectProblems.isBroken(NbGradleProjectImpl.this)) {
+ ProjectProblems.showAlert(NbGradleProjectImpl.this);
}
};
if (GradleSettings.getDefault().isOpenLazy()) {
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/ProjectTrust.java b/groovy/gradle/src/org/netbeans/modules/gradle/ProjectTrust.java
new file mode 100644
index 0000000..adec605
--- /dev/null
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/ProjectTrust.java
@@ -0,0 +1,230 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.gradle;
+
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.NoSuchAlgorithmException;
+import java.util.Collections;
+import java.util.List;
+import java.util.Random;
+import java.util.prefs.Preferences;
+import javax.crypto.Mac;
+import javax.crypto.spec.SecretKeySpec;
+import org.netbeans.api.project.Project;
+import org.openide.util.NbPreferences;
+
+/**
+ * This class allows Projects to store and check the trust property of a project.
+ * The trust is a unique identifier which is calculated on the project trusted
+ * directory and the current NetBeans user home.
+ *
+ * @author lkishalmi
+ */
+public class ProjectTrust {
+ private static final String KEY_SALT = "secret"; //NOI18N
+ private static final String NODE_PROJECT = "projects"; //NOI18N
+ private static final String NODE_TRUST = "trust"; //NOI18N
+
+ private static final String HMAC_SHA256 = "HmacSHA256"; //NOI18N
+
+ private static ProjectTrust instance;
+
+ private final Key key;
+ final Preferences projectTrust;
+ final byte[] salt;
+
+ ProjectTrust(Preferences prefs) {
+ byte[] buf = prefs.getByteArray(KEY_SALT, null);
+ if (buf == null) {
+ buf = new byte[16];
+ new Random().nextBytes(buf);
+ prefs.putByteArray(KEY_SALT, buf);
+ }
+ salt = buf;
+ projectTrust = prefs.node(NODE_PROJECT);
+ key = new SecretKeySpec(salt, HMAC_SHA256);
+ }
+
+ /**
+ * Returns true if the specified project is trusted.
+ *
+ * @param project of the trust check.
+ * @return true if the given project is trusted.
+ */
+ public boolean isTrusted(Project project) {
+ String pathId = getPathId(project);
+ String projectId = projectTrust.get(pathId, null);
+ if (projectId == null) {
+ return false;
+ }
+ boolean ret = false;
+ Path trustFile = getProjectTrustFile(project);
+ try {
+ List<String> trust = Files.readAllLines(trustFile);
+ String hash = hmacSha256(fromHex(projectId));
+ ret = trust.size() == 1 && trust.iterator().next().equals(hash);
+ } catch (IOException ex) {
+ }
+ return ret;
+ }
+
+ /**
+ * Marks the given project trusted, if it was not trusted before.
+ * @param project the project to trust.
+ */
+ public void trustProject(Project project) {
+ if (!isTrusted(project)) {
+ String pathId = getPathId(project);
+ Path trustFile = getProjectTrustFile(project);
+ byte[] rnd = new byte[16];
+ new Random().nextBytes(rnd);
+ String projectId = toHex(rnd);
+ projectTrust.put(pathId, projectId);
+ try {
+ Files.createDirectories(trustFile.getParent());
+ Files.write(trustFile, Collections.singletonList(hmacSha256(rnd)));
+ } catch (IOException ex) {}
+ }
+ }
+
+ /**
+ * Marks the given project not trusted.
+ * @param project the project to remove trust from.
+ */
+ public void distrustProject(Project project) {
+ String pathId = getPathId(project);
+ projectTrust.remove(pathId);
+ Path trustFile = getProjectTrustFile(project);
+ if (trustFile != null) {
+ try {
+ Files.delete(trustFile);
+ } catch (IOException ex) {
+ }
+ }
+
+ }
+
+ public static ProjectTrust getDefault() {
+ if (instance == null) {
+ Preferences p = NbPreferences.forModule(ProjectTrust.class).node(NODE_TRUST);
+ instance = new ProjectTrust(p);
+ }
+ return instance;
+ }
+
+ /**
+ * The path which shall be considered as a source of trust for the given
+ * project. For Gradle projects it is the root project directory.
+ *
+ * @param project the project to calculate the source of trust from.
+ * @return the Path to the trusted directory of the project
+ */
+ protected Path getProjectTrustPath(Project project) {
+ if (project instanceof NbGradleProjectImpl) {
+ return ((NbGradleProjectImpl) project).getGradleFiles().getRootDir().toPath();
+ }
+ throw new IllegalArgumentException("Project shall be an NbGradleProjectImpl instance."); //NOI18N
+ }
+
+ /**
+ * The directory where to store the project trust files. It is preferred to
+ * return a directory which is most likely end up on the ignore list of the
+ * used version control system.
+ *
+ * @param project the project to return the trust file path for.
+ * @return the Path of the directory to place the trust files in.
+ */
+ protected Path getProjectTrustFilePath(Project project) {
+ if (project instanceof NbGradleProjectImpl) {
+ Path root = getProjectTrustPath(project);
+ return root == null ? null : root.resolve(".gradle/nb-cache/trust"); //NOI18N
+ }
+ throw new IllegalArgumentException("Project shall be an NbGradleProjectImpl instance."); //NOI18N
+ }
+
+ /**
+ * Returns the name of the file where the project trust shall be stored. It
+ * is the {@code <trust file path>/<unique path id>}. It ensures that different
+ * NetBeans installations won't clash on a same file.
+ *
+ * @param project the project to calculate the trust file for.
+ * @return the Path to the trust file.
+ */
+ Path getProjectTrustFile(Project project) {
+ String pathId = getPathId(project);
+ Path trustFilePath = getProjectTrustFilePath(project);
+ return trustFilePath.resolve(pathId);
+ }
+
+ /**
+ * Generate a unique id of the Project trusted path. The returned id is
+ * unique as of the given project and the NetBeans user home, so the same
+ * project with different NetBeans installation would result a different id.
+ *
+ * @param project the project to get the trusted path from.
+ * @return the unique ID of the project trust path.
+ */
+ String getPathId(Project project) {
+ Path path = getProjectTrustPath(project);
+ path = path.normalize().toAbsolutePath();
+ return hmacSha256(path.toString().getBytes(StandardCharsets.UTF_8));
+ }
+
+ String hmacSha256(byte[] buf) {
+ byte[] out;
+ try {
+ Mac hmac = Mac.getInstance(HMAC_SHA256);
+ hmac.init(key);
+ out = hmac.doFinal(buf);
+ return toHex(out);
+ } catch (NoSuchAlgorithmException | InvalidKeyException ex) {
+ // Shall not happen on JVM-s fulfilling the specs.
+ // This throw line is not expected to be called, but let hmac be final
+ throw new IllegalArgumentException("JDK has issues with HMAC_SHA256: " + ex.getMessage());
+ }
+ }
+
+ static byte[] fromHex(String hex) {
+ int len = hex.length();
+ byte[] ret = new byte[len / 2];
+ for (int i = 0; i < len; i += 2) {
+ ret[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
+ + Character.digit(hex.charAt(i + 1), 16));
+
+ }
+ return ret;
+ }
+
+ private static final byte[] HEX_ARRAY = "0123456789ABCDEF".getBytes(StandardCharsets.UTF_8); //NOI18N
+ static String toHex(byte[] b) {
+ byte[] hexChars = new byte[b.length * 2];
+ for (int j = 0; j < b.length; j++) {
+ int v = b[j] & 0xFF;
+ hexChars[j * 2] = HEX_ARRAY[v >>> 4];
+ hexChars[j * 2 + 1] = HEX_ARRAY[v & 0x0F];
+ }
+ return new String(hexChars, StandardCharsets.UTF_8);
+ }
+
+}
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/ReloadAction.java b/groovy/gradle/src/org/netbeans/modules/gradle/ReloadAction.java
index 71bf3d2..db743c1 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/ReloadAction.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/ReloadAction.java
@@ -35,6 +35,7 @@ import org.openide.util.NbBundle;
import org.netbeans.modules.gradle.api.GradleProjects;
import static org.netbeans.modules.gradle.Bundle.*;
+import static org.netbeans.modules.gradle.api.NbGradleProject.Quality.FULL_ONLINE;
/**
*
@@ -73,7 +74,12 @@ public class ReloadAction extends AbstractAction implements ContextAwareAction
for (Project project : reload) {
if (project instanceof NbGradleProjectImpl) {
NbGradleProjectImpl impl = (NbGradleProjectImpl) project;
- impl.reloadProject(true, impl.getAimedQuality());
+ NbGradleProjectImpl.RELOAD_RP.submit(() -> {
+ // A bit low level calls, just to allow UI interaction to
+ // Trust the project.
+ impl.project = GradleProjectCache.loadProject(impl, FULL_ONLINE, true, true);
+ NbGradleProjectImpl.ACCESSOR.doFireReload(NbGradleProject.get(impl));
+ });
}
}
}
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/api/execute/RunUtils.java b/groovy/gradle/src/org/netbeans/modules/gradle/api/execute/RunUtils.java
index 8da09b7..37ca71d 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/api/execute/RunUtils.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/api/execute/RunUtils.java
@@ -56,12 +56,17 @@ import org.netbeans.api.java.platform.Specification;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.modules.gradle.GradleDistributionManager;
+import org.netbeans.modules.gradle.ProjectTrust;
import org.netbeans.modules.gradle.api.execute.RunConfig.ExecFlag;
+import org.netbeans.modules.gradle.execute.TrustProjectPanel;
import org.netbeans.modules.gradle.spi.GradleSettings;
import org.netbeans.spi.project.SingleMethod;
+import org.openide.DialogDescriptor;
+import org.openide.DialogDisplayer;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.loaders.DataObject;
+import org.openide.util.NbBundle.Messages;
import org.openide.util.Pair;
/**
@@ -130,6 +135,7 @@ public final class RunUtils {
* @param project The Gradle project
* @param action The name of the IDE action that's going to be executed
* @param displayName The display name of the output tab
+ * @param flags Execution flags.
* @param args Gradle command line arguments
* @return the Gradle execution configuration.
* @since 1.5
@@ -230,6 +236,34 @@ public final class RunUtils {
return isOptionEnabled(project, PROP_INCLUDE_OPEN_PROJECTS, false);
}
+ /**
+ * Check if the given project is trusted for execution. If the project is not
+ * trusted invoking this method can ask for temporal trust for one execution
+ * only by displaying a dialog.
+ *
+ * @param project the project to be checked
+ * @param interactive ask for permission from UI.
+ * @return if the execution is trusted.
+ */
+ @Messages({
+ "ProjectTrustDlg.TITLE=Not a Trusted Project"
+ })
+ public static boolean isProjectTrusted(Project project, boolean interactive) {
+ boolean ret = GradleSettings.getDefault().getGradleExecutionRule() == GradleSettings.GradleExecutionRule.ALWAYS
+ || ProjectTrust.getDefault().isTrusted(project);
+ if (ret == false && interactive) {
+ TrustProjectPanel trust = new TrustProjectPanel(project);
+ DialogDescriptor dsc = new DialogDescriptor(trust, Bundle.ProjectTrustDlg_TITLE(), true, null);
+ if (DialogDisplayer.getDefault().notify(dsc) == DialogDescriptor.OK_OPTION) {
+ if (trust.getTrustInFuture()) {
+ ProjectTrust.getDefault().trustProject(project);
+ }
+ ret = true;
+ }
+ }
+ return ret;
+ }
+
public static GradleCommandLine getDefaultCommandLine(Project project) {
String args = NbGradleProject.getPreferences(project, true).get(PROP_DEFAULT_CLI, null);
return args != null ? new GradleCommandLine(args) : null;
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/customizer/BuildActionsCustomizer.java b/groovy/gradle/src/org/netbeans/modules/gradle/customizer/BuildActionsCustomizer.java
index bff7868..9e520b0 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/customizer/BuildActionsCustomizer.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/customizer/BuildActionsCustomizer.java
@@ -60,9 +60,6 @@ public class BuildActionsCustomizer extends javax.swing.JPanel {
final DefaultListModel<CustomActionMapping> customActionsModel = new DefaultListModel<>();
final DefaultComboBoxModel<String> availableActionsModel = new DefaultComboBoxModel<>();
final CustomActionRegistrationSupport actionRegistry;
- final ActionListener saveListener = (ActionEvent e) -> {
- save();
- };
final DocumentListener applyListener = new DocumentListener() {
@Override
@@ -402,16 +399,12 @@ public class BuildActionsCustomizer extends javax.swing.JPanel {
cbAdd.setSelectedIndex(0);
}//GEN-LAST:event_cbAddActionPerformed
- public ActionListener getSaveListener() {
- return saveListener;
- }
-
private CustomActionMapping getSelectedMapping() {
int index = lsActions.getSelectedIndex();
return index >= 0 ? customActionsModel.elementAt(index) : null;
}
- private void save() {
+ void save() {
actionRegistry.save();
}
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/customizer/Bundle.properties b/groovy/gradle/src/org/netbeans/modules/gradle/customizer/Bundle.properties
index be85fc4..ea2fda4 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/customizer/Bundle.properties
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/customizer/Bundle.properties
@@ -44,3 +44,5 @@ BuildActionsCustomizer.jLabel1.text=Configure Action:
ProjectInfoPanel.jLabel6.text=Included Builds:
BuildActionsCustomizer.cbRepeatable.toolTipText=Is this action allowed to be rerun from the output tab?
BuildActionsCustomizer.lbReloadHints.text=<html>Reload Project after this action:\n<ul>\n<li><b>NEVER:</b> Do not reload.</li>\n<li><b>DEFAULT:</b> Reload only if the project had some problems.</li>\n<li><b>ALWAYS:</b> Always reload the project.</li>\n<li><b>ALWAYS_ONLINE:</b> Always reload the project, allowing Gradle to go online.</li>\n</ul>
+GradleExecutionPanel.cbTrustProject.text=Trust Gradle execution on this project
+GradleExecutionPanel.lbReadOnly.text=Can be changed on the root project only.
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/customizer/GradleCustomizerProvider.java b/groovy/gradle/src/org/netbeans/modules/gradle/customizer/GradleCustomizerProvider.java
index 5fdc5b6..ed728cf 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/customizer/GradleCustomizerProvider.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/customizer/GradleCustomizerProvider.java
@@ -36,6 +36,7 @@ import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JComponent;
import org.netbeans.api.project.ProjectUtils;
+import org.netbeans.modules.gradle.spi.customizer.support.FilterPanelProvider;
import org.openide.util.HelpCtx;
import org.openide.util.Lookup;
import org.openide.util.Mutex;
@@ -75,25 +76,18 @@ public class GradleCustomizerProvider implements CustomizerProvider2 {
}
}
// try {
- Mutex.EVENT.readAccess(new Runnable() {
-
- @Override
- public void run() {
- assert EventQueue.isDispatchThread();
- Lookup context = Lookups.singleton(project);
- Dialog dialog = ProjectCustomizer.createCustomizerDialog("Projects/" + NbGradleProject.GRADLE_PROJECT_TYPE + "/Customizer", //NOI18N
- context,
- preselectedCategory,
- new ActionListener() {
- @Override
- public void actionPerformed(ActionEvent ae) {
- //noop
- }
- }, null, HELP_CTX);
- dialog.setTitle(TIT_Project_Properties(ProjectUtils.getInformation(project).getDisplayName()));
- dialog.setModal(true);
- dialog.setVisible(true);
- }
+ Mutex.EVENT.readAccess(() -> {
+ assert EventQueue.isDispatchThread();
+ Lookup context = Lookups.singleton(project);
+ Dialog dialog = ProjectCustomizer.createCustomizerDialog("Projects/" + NbGradleProject.GRADLE_PROJECT_TYPE + "/Customizer", //NOI18N
+ context,
+ preselectedCategory,
+ (ActionEvent ae) -> {/*noop*/},
+ null,
+ HELP_CTX);
+ dialog.setTitle(TIT_Project_Properties(ProjectUtils.getInformation(project).getDisplayName()));
+ dialog.setModal(true);
+ dialog.setVisible(true);
});
// } catch (Exception ex) {
// Logger.getLogger(GradleCustomizerProvider.class.getName()).log(Level.SEVERE, "Cannot show project customizer", ex);
@@ -126,6 +120,31 @@ public class GradleCustomizerProvider implements CustomizerProvider2 {
};
}
+ @NbBundle.Messages("category.Execution=Gradle Execution")
+ @ProjectCustomizer.CompositeCategoryProvider.Registration(
+ projectType = NbGradleProject.GRADLE_PROJECT_TYPE,
+ category = "build/execute",
+ categoryLabel ="#category.Execution",
+ position = 305)
+ public static ProjectCustomizer.CompositeCategoryProvider buildCompileCustomizerProvider() {
+ ProjectCustomizer.CompositeCategoryProvider provider = new ProjectCustomizer.CompositeCategoryProvider() {
+ @Override
+ public ProjectCustomizer.Category createCategory(Lookup context) {
+ return null;
+ }
+
+ @Override
+ public JComponent createComponent(ProjectCustomizer.Category category, Lookup context) {
+ Project project = context.lookup(Project.class);
+
+ GradleExecutionPanel customizer = new GradleExecutionPanel(project);
+ category.setStoreListener((ActionEvent e) -> customizer.save());
+ return customizer;
+ }
+ };
+ return new FilterPanelProvider(provider, FilterPanelProvider.ROOT_PROJECT);
+ }
+
@NbBundle.Messages("category.BuildActions=Build Actions")
@ProjectCustomizer.CompositeCategoryProvider.Registration(
projectType=NbGradleProject.GRADLE_PROJECT_TYPE,
@@ -143,9 +162,10 @@ public class GradleCustomizerProvider implements CustomizerProvider2 {
public JComponent createComponent(ProjectCustomizer.Category category, Lookup context) {
Project project = context.lookup(Project.class);
BuildActionsCustomizer customizer = new BuildActionsCustomizer(project);
- category.setStoreListener(customizer.getSaveListener());
+ category.setStoreListener((ActionEvent e) -> customizer.save());
return customizer;
}
};
}
+
}
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/customizer/GradleExecutionPanel.form b/groovy/gradle/src/org/netbeans/modules/gradle/customizer/GradleExecutionPanel.form
new file mode 100644
index 0000000..723895d
--- /dev/null
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/customizer/GradleExecutionPanel.form
@@ -0,0 +1,95 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+ <AuxValues>
+ <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+ <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+ <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+ </AuxValues>
+
+ <Layout>
+ <DimensionLayout dim="0">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" alignment="0" attributes="0">
+ <EmptySpace min="-2" max="-2" attributes="0"/>
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" attributes="0">
+ <Component id="lbReadOnly" min="-2" max="-2" attributes="0"/>
+ <EmptySpace min="0" pref="0" max="32767" attributes="0"/>
+ </Group>
+ <Component id="cbTrustProject" max="32767" attributes="0"/>
+ <Group type="102" attributes="0">
+ <EmptySpace min="21" pref="21" max="-2" attributes="0"/>
+ <Component id="lbTrustTerms" max="32767" attributes="0"/>
+ </Group>
+ </Group>
+ <EmptySpace max="-2" attributes="0"/>
+ </Group>
+ </Group>
+ </DimensionLayout>
+ <DimensionLayout dim="1">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" alignment="0" attributes="0">
+ <EmptySpace max="-2" attributes="0"/>
+ <Component id="cbTrustProject" min="-2" max="-2" attributes="0"/>
+ <EmptySpace max="-2" attributes="0"/>
+ <Component id="lbTrustTerms" min="-2" pref="234" max="-2" attributes="0"/>
+ <EmptySpace pref="8" max="32767" attributes="0"/>
+ <Component id="lbReadOnly" min="-2" max="-2" attributes="0"/>
+ <EmptySpace max="-2" attributes="0"/>
+ </Group>
+ </Group>
+ </DimensionLayout>
+ </Layout>
+ <SubComponents>
+ <Component class="javax.swing.JCheckBox" name="cbTrustProject">
+ <Properties>
+ <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString bundle="org/netbeans/modules/gradle/customizer/Bundle.properties" key="GradleExecutionPanel.cbTrustProject.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
+ </Property>
+ </Properties>
+ </Component>
+ <Component class="javax.swing.JLabel" name="lbTrustTerms">
+ <Properties>
+ <Property name="verticalAlignment" type="int" value="1"/>
+ </Properties>
+ </Component>
+ <Component class="javax.swing.JLabel" name="lbReadOnly">
+ <Properties>
+ <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor">
+ <Image iconType="3" name="/org/netbeans/modules/gradle/resources/info.png"/>
+ </Property>
+ <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString bundle="org/netbeans/modules/gradle/customizer/Bundle.properties" key="GradleExecutionPanel.lbReadOnly.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
+ </Property>
+ </Properties>
+ </Component>
+ </SubComponents>
+</Form>
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/customizer/GradleExecutionPanel.java b/groovy/gradle/src/org/netbeans/modules/gradle/customizer/GradleExecutionPanel.java
new file mode 100644
index 0000000..e03a029
--- /dev/null
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/customizer/GradleExecutionPanel.java
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.gradle.customizer;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.modules.gradle.ProjectTrust;
+import org.netbeans.modules.gradle.api.GradleBaseProject;
+import org.openide.util.NbBundle.Messages;
+
+/**
+ *
+ * @author lkishalmi
+ */
+@Messages({
+ "GRADLE_TRUST_MSG=<html><p>Executing Gradle can be potentially un-safe as it "
+ + "allows arbitrary code execution.</p><p></p>"
+ + "<p>By trusting this project, and with that all its subprojects, "
+ + "you entitle NetBeans to invoke Gradle to load project details "
+ + "without further confirmation.</p><p></p>"
+ + "<p>Invoking any build related actions, would mark this project "
+ + "automatically trusted.</p>",
+})
+public class GradleExecutionPanel extends javax.swing.JPanel {
+
+ Project project;
+
+ /**
+ * Creates new form GradleExecutionPanel
+ */
+ public GradleExecutionPanel() {
+ initComponents();
+ lbTrustTerms.setText(Bundle.GRADLE_TRUST_MSG());
+ }
+
+ public GradleExecutionPanel(Project project) {
+ this();
+ this.project = project;
+ GradleBaseProject gbp = GradleBaseProject.get(project);
+ if (gbp != null) {
+ lbReadOnly.setVisible(!gbp.isRoot());
+ cbTrustProject.setEnabled(gbp.isRoot());
+ lbTrustTerms.setEnabled(gbp.isRoot());
+ cbTrustProject.setSelected(ProjectTrust.getDefault().isTrusted(project));
+ }
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ cbTrustProject = new javax.swing.JCheckBox();
+ lbTrustTerms = new javax.swing.JLabel();
+ lbReadOnly = new javax.swing.JLabel();
+
+ org.openide.awt.Mnemonics.setLocalizedText(cbTrustProject, org.openide.util.NbBundle.getMessage(GradleExecutionPanel.class, "GradleExecutionPanel.cbTrustProject.text")); // NOI18N
+
+ lbTrustTerms.setVerticalAlignment(javax.swing.SwingConstants.TOP);
+
+ lbReadOnly.setIcon(new javax.swing.ImageIcon(getClass().getResource("/org/netbeans/modules/gradle/resources/info.png"))); // NOI18N
+ org.openide.awt.Mnemonics.setLocalizedText(lbReadOnly, org.openide.util.NbBundle.getMessage(GradleExecutionPanel.class, "GradleExecutionPanel.lbReadOnly.text")); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addComponent(lbReadOnly)
+ .addGap(0, 0, Short.MAX_VALUE))
+ .addComponent(cbTrustProject, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(layout.createSequentialGroup()
+ .addGap(21, 21, 21)
+ .addComponent(lbTrustTerms, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(cbTrustProject)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(lbTrustTerms, javax.swing.GroupLayout.PREFERRED_SIZE, 234, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, 8, Short.MAX_VALUE)
+ .addComponent(lbReadOnly)
+ .addContainerGap())
+ );
+ }// </editor-fold>//GEN-END:initComponents
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JCheckBox cbTrustProject;
+ private javax.swing.JLabel lbReadOnly;
+ private javax.swing.JLabel lbTrustTerms;
+ // End of variables declaration//GEN-END:variables
+
+ void save() {
+ if (project != null) {
+ if (cbTrustProject.isSelected()) {
+ ProjectTrust.getDefault().trustProject(project);
+ } else {
+ ProjectTrust.getDefault().distrustProject(project);
+ }
+ }
+ }
+}
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/execute/Bundle.properties b/groovy/gradle/src/org/netbeans/modules/gradle/execute/Bundle.properties
index 7666da7..9ecf071 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/execute/Bundle.properties
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/execute/Bundle.properties
@@ -28,3 +28,4 @@ ExecutionOptionsPanel.cbConfigureOnDemand.text=Configure on Demand
ExecutionOptionsPanel.jLabel1.text=Log Level:
ExecutionOptionsPanel.jLabel2.text=Stack Trace:
GradleExecutorOptionsPanel.lbRememberAs.text=Remember &as:
+TrustProjectPanel.cbTrustProject.text=Trust this project in the future
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/execute/TrustProjectPanel.form b/groovy/gradle/src/org/netbeans/modules/gradle/execute/TrustProjectPanel.form
new file mode 100644
index 0000000..6ab56ae
--- /dev/null
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/execute/TrustProjectPanel.form
@@ -0,0 +1,79 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements. See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership. The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied. See the License for the
+ specific language governing permissions and limitations
+ under the License.
+
+-->
+
+<Form version="1.5" maxVersion="1.9" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
+ <AuxValues>
+ <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
+ <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
+ <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/>
+ <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
+ <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
+ <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
+ </AuxValues>
+
+ <Layout>
+ <DimensionLayout dim="0">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" attributes="0">
+ <EmptySpace max="-2" attributes="0"/>
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" alignment="1" attributes="0">
+ <EmptySpace min="0" pref="157" max="32767" attributes="0"/>
+ <Component id="cbTrustProject" min="-2" max="-2" attributes="0"/>
+ </Group>
+ <Component id="lbTrustMessage" alignment="0" max="32767" attributes="0"/>
+ </Group>
+ <EmptySpace max="-2" attributes="0"/>
+ </Group>
+ </Group>
+ </DimensionLayout>
+ <DimensionLayout dim="1">
+ <Group type="103" groupAlignment="0" attributes="0">
+ <Group type="102" alignment="0" attributes="0">
+ <EmptySpace max="-2" attributes="0"/>
+ <Component id="lbTrustMessage" pref="248" max="32767" attributes="0"/>
+ <EmptySpace type="separate" max="-2" attributes="0"/>
+ <Component id="cbTrustProject" min="-2" max="-2" attributes="0"/>
+ <EmptySpace max="-2" attributes="0"/>
+ </Group>
+ </Group>
+ </DimensionLayout>
+ </Layout>
+ <SubComponents>
+ <Component class="javax.swing.JLabel" name="lbTrustMessage">
+ <Properties>
+ <Property name="verticalAlignment" type="int" value="1"/>
+ </Properties>
+ </Component>
+ <Component class="javax.swing.JCheckBox" name="cbTrustProject">
+ <Properties>
+ <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString bundle="org/netbeans/modules/gradle/execute/Bundle.properties" key="TrustProjectPanel.cbTrustProject.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
+ </Property>
+ </Properties>
+ </Component>
+ </SubComponents>
+</Form>
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/execute/TrustProjectPanel.java b/groovy/gradle/src/org/netbeans/modules/gradle/execute/TrustProjectPanel.java
new file mode 100644
index 0000000..e4bbfcf
--- /dev/null
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/execute/TrustProjectPanel.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.gradle.execute;
+
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectInformation;
+import org.openide.util.NbBundle.Messages;
+
+/**
+ *
+ * @author lkishalmi
+ */
+public class TrustProjectPanel extends javax.swing.JPanel {
+
+ /**
+ * Creates new form TrustProjectPanel
+ */
+ public TrustProjectPanel() {
+ this(null);
+ }
+
+ @Messages({
+ "# {0} = Project name",
+ "TrustProjectPanel.INFO=<html><p>NetBeans is about to invoke a Gradle build process of the project: <b>{0}</b>.</p>"
+ + " <p>Executing Gradle can be potentially un-safe as it"
+ + " allows arbitrary code execution.</p>",
+ "TrustProjectPanel.INFO_UNKNOWN=<html><p>NetBeans is about to invoke a Gradle build process.</p>"
+ + " <p>Executing Gradle can be potentially un-safe as it"
+ + " allows arbitrary code execution.</p>"
+ })
+ public TrustProjectPanel(Project project) {
+ initComponents();
+ ProjectInformation info = project != null ? project.getLookup().lookup(ProjectInformation.class) : null;
+ if (project == null) {
+ cbTrustProject.setEnabled(false);
+ cbTrustProject.setVisible(false);
+ }
+ if (info == null) {
+ lbTrustMessage.setText(Bundle.TrustProjectPanel_INFO_UNKNOWN());
+ } else {
+ lbTrustMessage.setText(Bundle.TrustProjectPanel_INFO(info.getDisplayName()));
+ }
+ }
+
+ /**
+ * This method is called from within the constructor to initialize the form.
+ * WARNING: Do NOT modify this code. The content of this method is always
+ * regenerated by the Form Editor.
+ */
+ @SuppressWarnings("unchecked")
+ // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
+ private void initComponents() {
+
+ lbTrustMessage = new javax.swing.JLabel();
+ cbTrustProject = new javax.swing.JCheckBox();
+
+ lbTrustMessage.setVerticalAlignment(javax.swing.SwingConstants.TOP);
+
+ org.openide.awt.Mnemonics.setLocalizedText(cbTrustProject, org.openide.util.NbBundle.getMessage(TrustProjectPanel.class, "TrustProjectPanel.cbTrustProject.text")); // NOI18N
+
+ javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
+ this.setLayout(layout);
+ layout.setHorizontalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, layout.createSequentialGroup()
+ .addGap(0, 157, Short.MAX_VALUE)
+ .addComponent(cbTrustProject))
+ .addComponent(lbTrustMessage, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addContainerGap())
+ );
+ layout.setVerticalGroup(
+ layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
+ .addGroup(layout.createSequentialGroup()
+ .addContainerGap()
+ .addComponent(lbTrustMessage, javax.swing.GroupLayout.DEFAULT_SIZE, 248, Short.MAX_VALUE)
+ .addGap(18, 18, 18)
+ .addComponent(cbTrustProject)
+ .addContainerGap())
+ );
+ }// </editor-fold>//GEN-END:initComponents
+
+ public boolean getTrustInFuture() {
+ return cbTrustProject.isSelected();
+ }
+
+ // Variables declaration - do not modify//GEN-BEGIN:variables
+ private javax.swing.JCheckBox cbTrustProject;
+ private javax.swing.JLabel lbTrustMessage;
+ // End of variables declaration//GEN-END:variables
+}
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/options/Bundle.properties b/groovy/gradle/src/org/netbeans/modules/gradle/options/Bundle.properties
index 5fbc83f..428b1a8 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/options/Bundle.properties
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/options/Bundle.properties
@@ -53,3 +53,4 @@ SettingsPanel.cbDownloadJavadoc.toolTipText=Not implemented yet.
SettingsPanel.cbDownloadSources.toolTipText=Not implemented yet.
SettingsPanel.cbSilentInstall.text=Install Gradle Runtime Silently
SettingsPanel.btDefaultHome.text=Default
+SettingsPanel.lbAllowExecution.text=Allow Gradle Execution:
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/options/SettingsPanel.form b/groovy/gradle/src/org/netbeans/modules/gradle/options/SettingsPanel.form
index 075ee76..8e8a9d0 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/options/SettingsPanel.form
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/options/SettingsPanel.form
@@ -145,6 +145,11 @@
<EmptySpace min="0" pref="346" max="32767" attributes="0"/>
</Group>
<Component id="jPanel2" alignment="0" max="32767" attributes="0"/>
+ <Group type="102" alignment="1" attributes="0">
+ <Component id="lbAllowExecution" max="32767" attributes="0"/>
+ <EmptySpace max="-2" attributes="0"/>
+ <Component id="cbAllowExecution" min="-2" pref="280" max="-2" attributes="0"/>
+ </Group>
</Group>
<EmptySpace max="-2" attributes="0"/>
</Group>
@@ -156,7 +161,12 @@
<Component id="jPanel1" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
<Component id="jPanel2" min="-2" pref="124" max="-2" attributes="0"/>
- <EmptySpace min="-2" pref="41" max="-2" attributes="0"/>
+ <EmptySpace max="-2" attributes="0"/>
+ <Group type="103" groupAlignment="3" attributes="0">
+ <Component id="cbAllowExecution" alignment="3" min="-2" max="-2" attributes="0"/>
+ <Component id="lbAllowExecution" alignment="3" min="-2" max="-2" attributes="0"/>
+ </Group>
+ <EmptySpace min="-2" pref="11" max="-2" attributes="0"/>
<Component id="cbPreferMaven" min="-2" max="-2" attributes="0"/>
<EmptySpace max="-2" attributes="0"/>
</Group>
@@ -506,6 +516,19 @@
</Component>
</SubComponents>
</Container>
+ <Component class="javax.swing.JLabel" name="lbAllowExecution">
+ <Properties>
+ <Property name="horizontalAlignment" type="int" value="11"/>
+ <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
+ <ResourceString bundle="org/netbeans/modules/gradle/options/Bundle.properties" key="SettingsPanel.lbAllowExecution.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, "{key}")"/>
+ </Property>
+ </Properties>
+ </Component>
+ <Component class="javax.swing.JComboBox" name="cbAllowExecution">
+ <AuxValues>
+ <AuxValue name="JavaCodeGenerator_TypeParameters" type="java.lang.String" value="<GradleSettings.GradleExecutionRule>"/>
+ </AuxValues>
+ </Component>
<Component class="javax.swing.JCheckBox" name="cbPreferMaven">
<Properties>
<Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/options/SettingsPanel.java b/groovy/gradle/src/org/netbeans/modules/gradle/options/SettingsPanel.java
index 3bdcff5..4536fc8 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/options/SettingsPanel.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/options/SettingsPanel.java
@@ -73,6 +73,7 @@ public class SettingsPanel extends javax.swing.JPanel {
cbDownloadLibs.setModel(new DefaultComboBoxModel<>(GradleSettings.DownloadLibsRule.values()));
cbDownloadSources.setModel(new DefaultComboBoxModel<>(GradleSettings.DownloadMiscRule.values()));
cbDownloadJavadoc.setModel(new DefaultComboBoxModel<>(GradleSettings.DownloadMiscRule.values()));
+ cbAllowExecution.setModel(new DefaultComboBoxModel<>(GradleSettings.GradleExecutionRule.values()));
}
/**
@@ -112,6 +113,8 @@ public class SettingsPanel extends javax.swing.JPanel {
cbSkipCheck = new javax.swing.JCheckBox();
cbNoRebuild = new javax.swing.JCheckBox();
cbConfigureOnDemand = new javax.swing.JCheckBox();
+ lbAllowExecution = new javax.swing.JLabel();
+ cbAllowExecution = new javax.swing.JComboBox<>();
cbPreferMaven = new javax.swing.JCheckBox();
pnlAppearance = new javax.swing.JPanel();
jPanel4 = new javax.swing.JPanel();
@@ -379,6 +382,9 @@ public class SettingsPanel extends javax.swing.JPanel {
.addGap(72, 72, 72))
);
+ lbAllowExecution.setHorizontalAlignment(javax.swing.SwingConstants.TRAILING);
+ org.openide.awt.Mnemonics.setLocalizedText(lbAllowExecution, org.openide.util.NbBundle.getMessage(SettingsPanel.class, "SettingsPanel.lbAllowExecution.text")); // NOI18N
+
org.openide.awt.Mnemonics.setLocalizedText(cbPreferMaven, org.openide.util.NbBundle.getMessage(SettingsPanel.class, "SettingsPanel.cbPreferMaven.text")); // NOI18N
javax.swing.GroupLayout pnlExecutionLayout = new javax.swing.GroupLayout(pnlExecution);
@@ -392,7 +398,11 @@ public class SettingsPanel extends javax.swing.JPanel {
.addGroup(pnlExecutionLayout.createSequentialGroup()
.addComponent(cbPreferMaven)
.addGap(0, 346, Short.MAX_VALUE))
- .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
+ .addComponent(jPanel2, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, pnlExecutionLayout.createSequentialGroup()
+ .addComponent(lbAllowExecution, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addComponent(cbAllowExecution, javax.swing.GroupLayout.PREFERRED_SIZE, 280, javax.swing.GroupLayout.PREFERRED_SIZE)))
.addContainerGap())
);
pnlExecutionLayout.setVerticalGroup(
@@ -401,7 +411,11 @@ public class SettingsPanel extends javax.swing.JPanel {
.addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(jPanel2, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addGap(41, 41, 41)
+ .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
+ .addGroup(pnlExecutionLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
+ .addComponent(cbAllowExecution, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
+ .addComponent(lbAllowExecution))
+ .addGap(11, 11, 11)
.addComponent(cbPreferMaven)
.addContainerGap())
);
@@ -712,6 +726,8 @@ public class SettingsPanel extends javax.swing.JPanel {
cbDownloadSources.setSelectedItem(settings.getDownloadSources());
cbDownloadJavadoc.setSelectedItem(settings.getDownloadJavadoc());
+ cbAllowExecution.setSelectedItem(settings.getGradleExecutionRule());
+
new SwingWorker<List<NbGradleVersion>, Void>() {
@Override
@@ -773,6 +789,8 @@ public class SettingsPanel extends javax.swing.JPanel {
settings.setDownloadSources((GradleSettings.DownloadMiscRule) cbDownloadSources.getSelectedItem());
settings.setDownloadJavadoc((GradleSettings.DownloadMiscRule) cbDownloadJavadoc.getSelectedItem());
+ settings.setGradleExecutionRule((GradleSettings.GradleExecutionRule) cbAllowExecution.getSelectedItem());
+
if (settings.isPreferMaven() != cbPreferMaven.isSelected()) {
settings.setPreferMaven(cbPreferMaven.isSelected());
NotificationDisplayer.getDefault().notify(Bundle.TIT_RestartIDE(),
@@ -818,6 +836,8 @@ public class SettingsPanel extends javax.swing.JPanel {
isChanged |= settings.getDownloadSources() != cbDownloadSources.getSelectedItem();
isChanged |= settings.getDownloadJavadoc() != cbDownloadJavadoc.getSelectedItem();
+ isChanged |= settings.getGradleExecutionRule() != cbAllowExecution.getSelectedItem();
+
return isChanged;
}
@@ -871,6 +891,7 @@ public class SettingsPanel extends javax.swing.JPanel {
private javax.swing.JButton btDefaultHome;
private javax.swing.JButton btGradleUserHome;
private javax.swing.JButton btUseCustomGradle;
+ private javax.swing.JComboBox<GradleSettings.GradleExecutionRule> cbAllowExecution;
private javax.swing.JCheckBox cbAlwaysShowOutput;
private javax.swing.JCheckBox cbConfigureOnDemand;
private javax.swing.JCheckBox cbDisplayDescription;
@@ -898,6 +919,7 @@ public class SettingsPanel extends javax.swing.JPanel {
private javax.swing.JPanel jPanel4;
private javax.swing.JPanel jPanel5;
private javax.swing.JPanel jPanel6;
+ private javax.swing.JLabel lbAllowExecution;
private javax.swing.JLabel lbDownloadJavadoc;
private javax.swing.JLabel lbDownloadLibs;
private javax.swing.JLabel lbDownloadSources;
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/resources/info.png b/groovy/gradle/src/org/netbeans/modules/gradle/resources/info.png
new file mode 100644
index 0000000..6213c0c
Binary files /dev/null and b/groovy/gradle/src/org/netbeans/modules/gradle/resources/info.png differ
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/spi/GradleSettings.java b/groovy/gradle/src/org/netbeans/modules/gradle/spi/GradleSettings.java
index 6a0102d..d4cb7ee 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/spi/GradleSettings.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/spi/GradleSettings.java
@@ -68,6 +68,29 @@ public final class GradleSettings {
}
}
+ /**
+ * Rule, that determines when to allow automatic Gradle execution.
+ * @since 2.2
+ */
+ @Messages({
+ "GE_TRUSTED_PROJECTS=Trusted Projects Only",
+ "GE_ALWAYS=Always"
+ })
+ public enum GradleExecutionRule {
+ TRUSTED_PROJECTS,
+ ALWAYS;
+
+ @Override
+ public String toString() {
+ switch (this) {
+ case TRUSTED_PROJECTS: return Bundle.GE_TRUSTED_PROJECTS();
+ case ALWAYS: return Bundle.GE_ALWAYS();
+ }
+ return name();
+ }
+
+ }
+
public static final String PROP_GRADLE_DISTRIBUTION = "gradleHome";
public static final String PROP_PREFER_WRAPPER = "preferWrapper";
@@ -102,10 +125,24 @@ public final class GradleSettings {
public static final String PROP_DOWNLOAD_SOURCES = "downloadSources";
public static final String PROP_DOWNLOAD_JAVADOC = "downloadJavaDoc";
- private static final GradleSettings INSTANCE = new GradleSettings();
+ public static final String PROP_GRADLE_EXEC_RULE = "gradleExecutionRule";
+
+ private static final GradleSettings INSTANCE = new GradleSettings(NbPreferences.forModule(GradleSettings.class));
+
+ private final Preferences preferences;
+
+ @Deprecated
+ public GradleSettings() {
+ this(NbPreferences.forModule(GradleSettings.class));
+ }
+
+ GradleSettings(Preferences preferences) {
+ this.preferences = preferences;
+ }
+
public Preferences getPreferences() {
- return NbPreferences.forModule(GradleSettings.class);
+ return preferences;
}
public static GradleSettings getDefault() {
@@ -321,4 +358,19 @@ public final class GradleSettings {
String ruleName = getPreferences().get(PROP_DOWNLOAD_JAVADOC, DownloadMiscRule.NEVER.name());
return DownloadMiscRule.valueOf(ruleName);
}
+
+ /**
+ * @since 2.2
+ */
+ public void setGradleExecutionRule(GradleExecutionRule rule) {
+ getPreferences().put(PROP_GRADLE_EXEC_RULE, rule.name());
+ }
+
+ /**
+ * @since 2.2
+ */
+ public GradleExecutionRule getGradleExecutionRule() {
+ String ruleName = getPreferences().get(PROP_GRADLE_EXEC_RULE, GradleExecutionRule.TRUSTED_PROJECTS.name());
+ return GradleExecutionRule.valueOf(ruleName);
+ }
}
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/spi/customizer/support/FilterPanelProvider.java b/groovy/gradle/src/org/netbeans/modules/gradle/spi/customizer/support/FilterPanelProvider.java
index 11a56cb..570714c 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/spi/customizer/support/FilterPanelProvider.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/spi/customizer/support/FilterPanelProvider.java
@@ -34,6 +34,8 @@ import org.openide.util.Lookup;
*/
public final class FilterPanelProvider implements ProjectCustomizer.CompositeCategoryProvider {
+ public static final String ROOT_PROJECT = "ROOT-PROJECT";
+
final ProjectCustomizer.CompositeCategoryProvider original;
final String plugin;
@@ -47,10 +49,7 @@ public final class FilterPanelProvider implements ProjectCustomizer.CompositeCat
Project project = context.lookup(Project.class);
assert project != null;
GradleBaseProject gbp = GradleBaseProject.get(project);
- if (!gbp.getPlugins().contains(plugin)) {
- return null;
- }
- return original.createCategory(context);
+ return gbp.getPlugins().contains(plugin) || ROOT_PROJECT.equals(plugin) ? original.createCategory(context) : null;
}
@Override
diff --git a/groovy/gradle/src/org/netbeans/modules/gradle/spi/newproject/TemplateOperation.java b/groovy/gradle/src/org/netbeans/modules/gradle/spi/newproject/TemplateOperation.java
index c4afee4..ef8d621 100644
--- a/groovy/gradle/src/org/netbeans/modules/gradle/spi/newproject/TemplateOperation.java
+++ b/groovy/gradle/src/org/netbeans/modules/gradle/spi/newproject/TemplateOperation.java
@@ -52,6 +52,7 @@ import java.util.LinkedHashSet;
import java.util.Set;
import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
+import org.netbeans.modules.gradle.ProjectTrust;
import org.netbeans.modules.gradle.api.GradleProjects;
import org.netbeans.modules.gradle.api.NbGradleProject.Quality;
import org.openide.loaders.DataFolder;
@@ -257,10 +258,12 @@ public final class TemplateOperation implements Runnable {
}
project = ProjectManager.getDefault().findProject(projectDir);
if (project != null) {
+ //Let's trust the generate project
+ ProjectTrust.getDefault().trustProject(project);
NbGradleProjectImpl nbProject = project.getLookup().lookup(NbGradleProjectImpl.class);
if (nbProject != null) {
//Just load the project into the cache.
- GradleProjectCache.loadProject(nbProject, Quality.FULL_ONLINE, true);
+ GradleProjectCache.loadProject(nbProject, Quality.FULL_ONLINE, true, false);
}
return Collections.singleton(projectDir);
}
diff --git a/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/AbstractGradleProjectTestCase.java b/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/AbstractGradleProjectTestCase.java
index c0c8810..85fde0f 100644
--- a/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/AbstractGradleProjectTestCase.java
+++ b/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/AbstractGradleProjectTestCase.java
@@ -65,6 +65,7 @@ public class AbstractGradleProjectTestCase extends NbTestCase {
protected Project openProject(FileObject projectDir) throws IOException {
Project prj = ProjectManager.getDefault().findProject(projectDir);
assertNotNull(prj);
+ ProjectTrust.getDefault().trustProject(prj);
ProjectOpenedTrampoline.DEFAULT.projectOpened(prj.getLookup().lookup(ProjectOpenedHook.class));
return prj;
}
@@ -73,7 +74,7 @@ public class AbstractGradleProjectTestCase extends NbTestCase {
FileObject ret = FileUtil.toFileObject(getWorkDir());
if (path != null) {
for (String p : path.split("/")) {
- ret = ret.createFolder(p);
+ ret = ret.getFileObject(p) != null ? ret.getFileObject(p): ret.createFolder(p);
}
}
TestFileUtils.writeFile(ret, "build.gradle", buildScript);
diff --git a/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/NbGradleProjectFactoryTest.java b/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/NbGradleProjectFactoryTest.java
index 607dc7a..af92113 100644
--- a/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/NbGradleProjectFactoryTest.java
+++ b/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/NbGradleProjectFactoryTest.java
@@ -18,16 +18,7 @@
*/
package org.netbeans.modules.gradle;
-import org.junit.After;
-import org.junit.AfterClass;
-import org.junit.Before;
-import org.junit.BeforeClass;
-import org.junit.Test;
-import static org.junit.Assert.*;
-import org.netbeans.api.project.Project;
-import org.netbeans.api.project.ProjectManager;
import org.netbeans.junit.NbTestCase;
-import org.netbeans.spi.project.ProjectState;
import org.openide.filesystems.FileObject;
import org.openide.filesystems.FileUtil;
import org.openide.filesystems.LocalFileSystem;
diff --git a/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/ProjectTrustTest.java b/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/ProjectTrustTest.java
new file mode 100644
index 0000000..dde52eb
--- /dev/null
+++ b/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/ProjectTrustTest.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.netbeans.modules.gradle;
+
+import java.io.IOException;
+import java.util.Random;
+import org.netbeans.api.project.Project;
+import org.netbeans.api.project.ProjectManager;
+import org.openide.filesystems.FileObject;
+import org.openide.util.NbPreferences;
+
+/**
+ *
+ * @author lkishalmi
+ */
+public class ProjectTrustTest extends AbstractGradleProjectTestCase {
+
+
+ public ProjectTrustTest(String name) {
+ super(name);
+ }
+
+ public void testIsTrusted4Untrusted() throws IOException {
+ int rnd = new Random().nextInt(1000000);
+ FileObject a = createGradleProject("projectA-" + rnd,
+ "apply plugin: 'java'\n", "");
+ Project prjA = ProjectManager.getDefault().findProject(a);
+ ProjectTrust trust = new ProjectTrust(NbPreferences.root().node("org/netbeans/modules/gradle/trust"));
+ assertFalse(trust.isTrusted(prjA));
+ }
+
+ public void testIsTrusted4Trusted() throws IOException {
+ int rnd = new Random().nextInt(1000000);
+ FileObject a = createGradleProject("projectA-" + rnd,
+ "apply plugin: 'java'\n", "");
+ Project prjA = ProjectManager.getDefault().findProject(a);
+ ProjectTrust trust = new ProjectTrust(NbPreferences.root().node("org/netbeans/modules/gradle/trust"));
+ trust.trustProject(prjA);
+ assertTrue(trust.isTrusted(prjA));
+ }
+
+ public void testIsTrusted4TrustedSub() throws IOException {
+ int rnd = new Random().nextInt(1000000);
+ FileObject a = createGradleProject("projectA-" + rnd,
+ "apply plugin: 'java'\n", "include 'projectB'\n");
+ FileObject b = createGradleProject("projectA-" + rnd + "/projectB",
+ "apply plugin: 'java'\n", null);
+ Project prjA = ProjectManager.getDefault().findProject(a);
+ Project prjB = ProjectManager.getDefault().findProject(b);
+ ProjectTrust trust = new ProjectTrust(NbPreferences.root().node("org/netbeans/modules/gradle/trust"));
+ trust.trustProject(prjA);
+ assertTrue(trust.isTrusted(prjA));
+ assertTrue(trust.isTrusted(prjB));
+ }
+
+ public void testIsTrusted4UnTrustedSub() throws IOException {
+ int rnd = new Random().nextInt(1000000);
+ FileObject a = createGradleProject("projectA-" + rnd,
+ "apply plugin: 'java'\n", "include 'projectB'\n");
+ FileObject b = createGradleProject("projectA-" + rnd + "/projectB",
+ "apply plugin: 'java'\n", null);
+ Project prjA = ProjectManager.getDefault().findProject(a);
+ Project prjB = ProjectManager.getDefault().findProject(b);
+ ProjectTrust trust = new ProjectTrust(NbPreferences.root().node("org/netbeans/modules/gradle/trust"));
+ trust.trustProject(prjA);
+ assertTrue(trust.isTrusted(prjA));
+ assertTrue(trust.isTrusted(prjB));
+ trust.distrustProject(prjB);
+ assertFalse(trust.isTrusted(prjA));
+ assertFalse(trust.isTrusted(prjB));
+ }
+}
diff --git a/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/api/execute/RunUtilsTest.java b/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/api/execute/RunUtilsTest.java
index 39648b9..07a9b9a 100644
--- a/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/api/execute/RunUtilsTest.java
+++ b/groovy/gradle/test/unit/src/org/netbeans/modules/gradle/api/execute/RunUtilsTest.java
@@ -25,6 +25,7 @@ import org.netbeans.api.project.Project;
import org.netbeans.api.project.ProjectManager;
import org.netbeans.api.project.ui.OpenProjects;
import org.netbeans.modules.gradle.AbstractGradleProjectTestCase;
+import org.netbeans.modules.gradle.ProjectTrust;
import org.openide.filesystems.FileObject;
/**
@@ -43,7 +44,9 @@ public class RunUtilsTest extends AbstractGradleProjectTestCase {
FileObject b = createGradleProject("projectB",
"apply plugin: 'java'\n", "");
Project prjA = ProjectManager.getDefault().findProject(a);
+ ProjectTrust.getDefault().trustProject(prjA);
Project prjB = ProjectManager.getDefault().findProject(b);
+ ProjectTrust.getDefault().trustProject(prjB);
OpenProjects.getDefault().open(new Project[] {prjA, prjB}, false);
GradleCommandLine cmd = RunUtils.getIncludedOpenProjects(prjB);
Collection<String> params = cmd.getParameters(GradleCommandLine.Parameter.INCLUDE_BUILD);
@@ -58,7 +61,9 @@ public class RunUtilsTest extends AbstractGradleProjectTestCase {
FileObject b = createGradleProject("projectB",
"apply plugin: 'java'\n", "includeBuild '../projectA'\n");
Project prjA = ProjectManager.getDefault().findProject(a);
+ ProjectTrust.getDefault().trustProject(prjA);
Project prjB = ProjectManager.getDefault().findProject(b);
+ ProjectTrust.getDefault().trustProject(prjB);
OpenProjects.getDefault().open(new Project[] {prjA, prjB}, false);
GradleCommandLine cmd = RunUtils.getIncludedOpenProjects(prjB);
Collection<String> params = cmd.getParameters(GradleCommandLine.Parameter.INCLUDE_BUILD);
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@netbeans.apache.org
For additional commands, e-mail: commits-help@netbeans.apache.org
For further information about the NetBeans mailing lists, visit:
https://cwiki.apache.org/confluence/display/NETBEANS/Mailing+lists