You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@netbeans.apache.org by ge...@apache.org on 2019/04/30 11:49:24 UTC

[netbeans] branch master updated: Integration of JEP-330 (#1171)

This is an automated email from the ASF dual-hosted git repository.

geertjan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/netbeans.git


The following commit(s) were added to refs/heads/master by this push:
     new 8836aad  Integration of JEP-330 (#1171)
8836aad is described below

commit 8836aad99151ac1e57ff440c15de90c67251fce7
Author: Sarvesh Kesharwani <32...@users.noreply.github.com>
AuthorDate: Tue Apr 30 17:19:17 2019 +0530

    Integration of JEP-330 (#1171)
    
    * adding support to run single java files outside projects (JEP-330)
    
    * adding SingleJavaSourceRunActionProvider.java to global lookup
    
    * adding content to SingleJavaSourceRunActionProvider.java
    
    * removing unused methods and variables
    
    * restricting JEP-330 to jdk-11 and above
    
    * fixing check for jdk-11 and execution in linux
    
    * removing unnecessary dependencies in projectui
    
    * fixing the public packages in java.source
    
    * removing extecxecution dependency in java.source; using dataObjects' attributes to add arguments and vm options
    
    * adding test case for JEP-330 run
    
    * using tests to check functionality of SingleJavaSourceRunActionProvider
    
    * removing unused code
    
    * removing unused imports
    
    * testing java.api.common with jdk11
    
    * adding check for jdk11 in test file
    
    * adding quiet option to travis build
    
    * changing RunProcess to package protected; changing TestJavaFile to JavaFileTest
    
    * restoring .travis.yml
    
    * adding test for isActionEnabled; fixing bug in isActionEnabled
---
 .../modules/java/api/common/RunProcess.java        |  86 +++++++++++++++++
 .../common/SingleJavaSourceRunActionProvider.java  | 107 +++++++++++++++++++++
 .../test/unit/data/files/TestSingleJavaFile.java   |   7 ++
 .../modules/java/api/common/JavaFileTest.java      |  73 ++++++++++++++
 .../org/netbeans/modules/java/Bundle.properties    |   1 +
 .../src/org/netbeans/modules/java/JavaNode.java    |  63 ++++++++++++
 6 files changed, 337 insertions(+)

diff --git a/java/java.api.common/src/org/netbeans/modules/java/api/common/RunProcess.java b/java/java.api.common/src/org/netbeans/modules/java/api/common/RunProcess.java
new file mode 100644
index 0000000..cc7d44d
--- /dev/null
+++ b/java/java.api.common/src/org/netbeans/modules/java/api/common/RunProcess.java
@@ -0,0 +1,86 @@
+/*
+ * 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.java.api.common;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/**
+ *
+ * @author Sarvesh Kesharwani
+ */
+class RunProcess implements Callable<Process> {
+    
+    private static final Logger LOG = Logger.getLogger(RunProcess.class.getName());
+
+    private final String dirPath;
+    private final List<String> commandsList;
+    private InputStream is;
+    private Process p;
+
+    public RunProcess(String command, String dirPath) {
+        this.dirPath = dirPath;
+        commandsList = new ArrayList<>();
+        commandsList.add(command);
+        setupProcess();
+    }
+
+    public RunProcess(String command) {
+        commandsList = new ArrayList<>();
+        commandsList.add(command);
+        this.dirPath = System.getProperty("user.home");
+        setupProcess();
+    }
+
+    public RunProcess(List<String> commandsList) {
+        this.commandsList = commandsList;
+        this.dirPath = System.getProperty("user.home");
+        setupProcess();
+    }
+
+    public void setupProcess() {
+        try {
+            ProcessBuilder runFileProcessBuilder = new ProcessBuilder(commandsList);
+            runFileProcessBuilder.directory(new File(dirPath));
+            runFileProcessBuilder.redirectErrorStream(true);
+            p = runFileProcessBuilder.start();
+            is = p.getInputStream();
+        } catch (IOException ex) {
+            LOG.log(
+                    Level.WARNING,
+                    "Could not get InputStream of Run Process"); //NOI18N
+        }
+    }
+
+    public InputStream getInputStream() {
+        return is;
+    }
+
+    @Override
+    public Process call() throws Exception {
+        return p;
+    }
+    
+}
diff --git a/java/java.api.common/src/org/netbeans/modules/java/api/common/SingleJavaSourceRunActionProvider.java b/java/java.api.common/src/org/netbeans/modules/java/api/common/SingleJavaSourceRunActionProvider.java
new file mode 100644
index 0000000..662d454
--- /dev/null
+++ b/java/java.api.common/src/org/netbeans/modules/java/api/common/SingleJavaSourceRunActionProvider.java
@@ -0,0 +1,107 @@
+/*
+ * 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.java.api.common;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.Future;
+import org.netbeans.api.extexecution.ExecutionDescriptor;
+import org.netbeans.api.extexecution.ExecutionService;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
+import org.netbeans.spi.project.ActionProvider;
+import org.openide.filesystems.FileObject;
+import org.openide.loaders.DataObject;
+import org.openide.util.Lookup;
+import org.openide.util.Utilities;
+import org.openide.util.lookup.ServiceProvider;
+
+/**
+ * This class provides support to run a single Java file without a parent
+ * project (JEP-330).
+ *
+ * @author Sarvesh Kesharwani
+ */
+@ServiceProvider(service = ActionProvider.class)
+public class SingleJavaSourceRunActionProvider implements ActionProvider {
+    
+    private static final String FILE_ARGUMENTS = "single_file_run_arguments"; //NOI18N
+    private static final String FILE_VM_OPTIONS = "single_file_vm_options"; //NOI18N
+
+    @Override
+    public String[] getSupportedActions() {
+        return new String[]{ActionProvider.COMMAND_RUN_SINGLE};
+    }
+
+    @Override
+    public void invokeAction(String command, Lookup context) throws IllegalArgumentException {
+        FileObject fileObject = getJavaFileWithoutProjectFromLookup(context);
+        if (fileObject == null) 
+            return;
+        ExecutionDescriptor descriptor = new ExecutionDescriptor().controllable(true).frontWindow(true).
+                    preExecution(null).postExecution(null);
+        RunProcess process = invokeActionHelper(command, fileObject);
+        ExecutionService exeService = ExecutionService.newService(
+                    process,
+                    descriptor, "Running Single Java File");
+        Future<Integer> exitCode = exeService.run();
+    }
+
+    @Override
+    public boolean isActionEnabled(String command, Lookup context) throws IllegalArgumentException {
+        // JEP-330 is supported only on JDK-11 and above.
+        String javaVersion = System.getProperty("java.specification.version");
+        if (javaVersion.startsWith("1.")) {
+            javaVersion = javaVersion.substring(2);
+        }
+        int version = Integer.parseInt(javaVersion);
+        FileObject fileObject = getJavaFileWithoutProjectFromLookup(context);
+        return version >= 11 && fileObject != null;
+    }
+    
+    public RunProcess invokeActionHelper (String command, FileObject fileObject) {
+        String filePath = fileObject.getPath();
+        Object argumentsObject = fileObject.getAttribute(FILE_ARGUMENTS);
+        String arguments = argumentsObject != null ? (String) argumentsObject : "";
+        Object vmOptionsObject = fileObject.getAttribute(FILE_VM_OPTIONS);
+        String vmOptions = vmOptionsObject != null ? (String) vmOptionsObject : "";
+        List<String> commandsList = new ArrayList<>();
+        if (Utilities.isUnix()) {
+            commandsList.add("bash");
+            commandsList.add("-c");
+        }
+        File javaPathFile = new File(new File(new File(System.getProperty("java.home")), "bin"), "java");
+        String javaPath = "\"" + javaPathFile.getAbsolutePath() + "\"";
+        commandsList.add(javaPath + " " + vmOptions + " " + filePath + " " + arguments);
+        return new RunProcess(commandsList);
+    }
+
+    private FileObject getJavaFileWithoutProjectFromLookup(Lookup lookup) {
+        for (DataObject dObj : lookup.lookupAll(DataObject.class)) {
+            FileObject fObj = dObj.getPrimaryFile();
+            Project p = FileOwnerQuery.getOwner(fObj);
+            if (p == null && fObj.getExt().equalsIgnoreCase("java")) {
+                return fObj;
+            }
+        }
+        return null;
+    }
+        
+}
diff --git a/java/java.api.common/test/unit/data/files/TestSingleJavaFile.java b/java/java.api.common/test/unit/data/files/TestSingleJavaFile.java
new file mode 100644
index 0000000..b6390a6
--- /dev/null
+++ b/java/java.api.common/test/unit/data/files/TestSingleJavaFile.java
@@ -0,0 +1,7 @@
+public class TestSingleJavaFile {
+    
+    public static void main (String args[]) {
+        System.out.print("hello world");
+    }
+    
+}
diff --git a/java/java.api.common/test/unit/src/org/netbeans/modules/java/api/common/JavaFileTest.java b/java/java.api.common/test/unit/src/org/netbeans/modules/java/api/common/JavaFileTest.java
new file mode 100644
index 0000000..13c76d1
--- /dev/null
+++ b/java/java.api.common/test/unit/src/org/netbeans/modules/java/api/common/JavaFileTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.java.api.common;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.logging.Logger;
+import static junit.framework.TestCase.assertEquals;
+import org.netbeans.junit.NbTestCase;
+import org.openide.filesystems.FileObject;
+import org.openide.filesystems.FileUtil;
+import org.openide.util.Lookup;
+
+/**
+ *
+ * @author Sarvesh Kesharwani
+ */
+public class JavaFileTest extends NbTestCase {
+    
+    private static final Logger LOG = Logger.getLogger(JavaFileTest.class.getName());
+    
+    public JavaFileTest(String name) {
+        super(name);
+    }
+    
+    public void testSingleJavaSourceRun() throws IOException {
+        File f1 = new File(new File(new File(getDataDir().getAbsolutePath()), "files"), "TestSingleJavaFile.java");
+        FileObject javaFO = FileUtil.toFileObject(f1);
+        SingleJavaSourceRunActionProvider runActionProvider = new SingleJavaSourceRunActionProvider();
+        if (!isJDK11OrNewer()) {
+            assertFalse("The action is only enabled on JDK11 and newer", runActionProvider.isActionEnabled("run.single", Lookup.EMPTY));
+            return;
+        }
+        RunProcess process = runActionProvider.invokeActionHelper("run.single", javaFO);
+        BufferedReader reader
+                = new BufferedReader(new InputStreamReader(process.getInputStream()));
+        StringBuilder builder = new StringBuilder();
+        String line = null;
+        while ((line = reader.readLine()) != null) {
+            builder.append(line);
+        }
+        String result = builder.toString();
+        assertEquals("hello world", result);
+    }
+    
+    private boolean isJDK11OrNewer() {
+        String javaVersion = System.getProperty("java.specification.version");
+        if (javaVersion.startsWith("1.")) {
+            javaVersion = javaVersion.substring(2);
+        }
+        int version = Integer.parseInt(javaVersion);
+        return version >= 11;
+    }
+    
+}
diff --git a/java/java.source/src/org/netbeans/modules/java/Bundle.properties b/java/java.source/src/org/netbeans/modules/java/Bundle.properties
index f640478..c87723c 100644
--- a/java/java.source/src/org/netbeans/modules/java/Bundle.properties
+++ b/java/java.source/src/org/netbeans/modules/java/Bundle.properties
@@ -36,6 +36,7 @@ HINT_JavaNode_execute_classpath=What classes are expected to be available to thi
 PROP_JavaNode_boot_classpath=Boot Classpath
 HINT_JavaNode_boot_classpath=What Java platform (JRE) classes this class is expected to be compiled and run against.
 LBL_JavaNode_classpath_unknown=<unknown>
+LBL_JavaNode_without_project_run=Run Single File
 
 #JavaNode badges:
 TP_NeedsCompileBadge=Needs to be compiled.
diff --git a/java/java.source/src/org/netbeans/modules/java/JavaNode.java b/java/java.source/src/org/netbeans/modules/java/JavaNode.java
index 4cb93f9..3abe857 100644
--- a/java/java.source/src/org/netbeans/modules/java/JavaNode.java
+++ b/java/java.source/src/org/netbeans/modules/java/JavaNode.java
@@ -52,6 +52,8 @@ import org.netbeans.api.java.classpath.ClassPath;
 import org.netbeans.api.java.source.CompilationController;
 import org.netbeans.api.java.source.JavaSource;
 import org.netbeans.api.java.source.Task;
+import org.netbeans.api.project.FileOwnerQuery;
+import org.netbeans.api.project.Project;
 import org.netbeans.api.queries.FileBuiltQuery;
 import org.netbeans.api.queries.FileBuiltQuery.Status;
 import org.netbeans.modules.classfile.Access;
@@ -75,6 +77,7 @@ import static org.openide.util.ImageUtilities.loadImage;
 import org.openide.util.Lookup;
 
 import static org.openide.util.NbBundle.getMessage;
+import org.openide.util.NbPreferences;
 
 import org.openide.util.RequestProcessor;
 import org.openide.util.Utilities;
@@ -97,6 +100,8 @@ public final class JavaNode extends DataNode implements ChangeListener {
     private static final String ANNOTATION_ICON_BASE = "org/netbeans/modules/java/resources/annotation_file.png";   //NOI18N
     private static final String EXECUTABLE_BADGE_URL = "org/netbeans/modules/java/resources/executable-badge.png";  //NOI18N
     private static final String NEEDS_COMPILE_BADGE_URL = "org/netbeans/modules/java/resources/needs-compile.png";  //NOI18N
+    private static final String FILE_ARGUMENTS = "single_file_run_arguments"; //NOI18N
+    private static final String FILE_VM_OPTIONS = "single_file_vm_options"; //NOI18N
 
     private static final Map<String,Image> IMAGE_CACHE = new ConcurrentHashMap<>();
     private static final boolean ALWAYS_PREFFER_COMPUTED_ICON = Boolean.getBoolean("JavaNode.prefferComputedIcon"); //NOI18N
@@ -213,6 +218,64 @@ public final class JavaNode extends DataNode implements ChangeListener {
         });
         sheet.put(ps);
         
+        Project parentProject = FileOwnerQuery.getOwner(super.getDataObject().getPrimaryFile());
+        DataObject dObj = super.getDataObject();
+        // If any of the parent folders is a project, user won't have the option to specify these attributes to the java files.
+        if (parentProject == null) {
+            Node.Property arguments = new org.openide.nodes.PropertySupport.ReadWrite<String> (
+                    "runFileArguments", // NOI18N
+                    String.class,
+                    "Arguments",
+                    "Arguments passed to the main method while running the file."
+                ) {
+                    public String getValue () {
+                        Object arguments = dObj.getPrimaryFile().getAttribute(FILE_ARGUMENTS);
+                        return arguments != null ? (String) arguments : "";
+                    }
+
+                    public void setValue (String o) {
+                        try {
+                            dObj.getPrimaryFile().setAttribute(FILE_ARGUMENTS, o);
+                        } catch (IOException ex) {
+                            LOG.log(
+                                    Level.WARNING,
+                                    "Java File does not exist : {0}", //NOI18N
+                                    dObj.getPrimaryFile().getName());
+                        }
+                    }
+                };
+            Node.Property vmOptions = new org.openide.nodes.PropertySupport.ReadWrite<String> (
+                    "runFileVMOptions", // NOI18N
+                    String.class,
+                    "VM Options",
+                    "VM Options to be considered while running the file."
+                ) {
+                    public String getValue () {
+                        Object vmOptions = dObj.getPrimaryFile().getAttribute(FILE_VM_OPTIONS);
+                        return vmOptions != null ? (String) vmOptions : "";
+                    }
+
+                    public void setValue (String o) {
+                        try {
+                            dObj.getPrimaryFile().setAttribute(FILE_VM_OPTIONS, o);
+                        } catch (IOException ex) {
+                            LOG.log(
+                                    Level.WARNING,
+                                    "Java File does not exist : {0}", //NOI18N
+                                    dObj.getPrimaryFile().getName());
+                        }
+                    }
+                };
+            Sheet.Set ss = new Sheet.Set();
+            ss.setName("runFileArguments"); // NOI18N
+            ss.setDisplayName(getMessage(JavaNode.class, "LBL_JavaNode_without_project_run"));
+            ss.setShortDescription("Run the file's source code.");
+            ss.put (arguments);
+            ss.put (vmOptions);
+            sheet.put(ss);
+        }
+        
+        
         @SuppressWarnings("LocalVariableHidesMemberVariable")
         PropertySet[] propertySets = sheet.toArray();
         


---------------------------------------------------------------------
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