src/jdk.jshell/share/classes/jdk/jshell/spi/ExecutionControl.java

Print this page




   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.jshell.spi;
  27 
  28 import java.util.Collection;
  29 import jdk.jshell.JShellException;
  30 
  31 /**
  32  * This interface specifies the functionality that must provided to implement
  33  * a pluggable JShell execution engine.
  34  * <p>
  35  * The audience for this Service Provider Interface is engineers
  36  * wishing to implement their own version of the execution engine in support
  37  * of the JShell API.  This is NOT a part of the JShell API.
  38  * <p>
  39  * A Snippet is compiled into code wrapped in a 'wrapper class'.  The execution
  40  * engine is used by the core JShell implementation to load and, for
  41  * executable Snippets, execute the Snippet.
  42  * <p>
  43  * Methods defined in this interface should only be called by the core JShell
  44  * implementation.
  45  * <p>
  46  * To install an instance of ExecutionControl, it is passed to
  47  * {@link jdk.jshell.JShell.Builder#executionEngine(jdk.jshell.spi.ExecutionControl) }.
  48  */
  49 public interface ExecutionControl {
  50 
  51     /**
  52      * Represents the current status of a class in the execution engine.
  53      */
  54     public enum ClassStatus {
  55         /**
  56          * Class is not known to the execution engine (not loaded).
  57          */
  58         UNKNOWN,
  59 
  60         /**
  61          * Class is loaded, but the loaded/redefined bytes do not match those
  62          * returned by {@link ExecutionEnv#getClassBytes(java.lang.String) }.





  63          */
  64         NOT_CURRENT,

  65 
  66         /**
  67          * Class is loaded and loaded/redefined bytes match those
  68          * returned by {@link ExecutionEnv#getClassBytes(java.lang.String) }.





  69          */
  70         CURRENT
  71     };
  72 
  73     /**
  74      * Initializes the instance. No methods in this interface can be called
  75      * before this.
  76      *
  77      * @param env the execution environment information provided by JShell
  78      * @throws Exception if the instance is unable to initialize








  79      */
  80     void start(ExecutionEnv env) throws Exception;

  81 
  82     /**
  83      * Shuts down this execution engine. Implementation should free all
  84      * resources held by this execution engine.
  85      * <p>
  86      * No calls to methods on this interface should be made after close.








  87      */
  88     void close();

  89 
  90     /**
  91      * Adds the path to the execution class path.
  92      *
  93      * @param path the path to add
  94      * @return true if successful

  95      */
  96     boolean addToClasspath(String path);

  97 
  98     /**
  99      * Invokes an executable Snippet by calling a method on the specified
 100      * wrapper class. The method must have no arguments and return String.
 101      *
 102      * @param classname the class whose method should be invoked
 103      * @param methodname the name of method to invoke
 104      * @return the result of the execution or null if no result
 105      * @throws JShellException if a user exception if thrown,
 106      * {@link jdk.jshell.EvalException EvalException} will be thrown; if an
 107      * unresolved reference is encountered,
 108      * {@link jdk.jshell.UnresolvedReferenceException UnresolvedReferenceException}
 109      * will be thrown
 110      */
 111     String invoke(String classname, String methodname) throws JShellException;

 112 
 113     /**
 114      * Attempts to load new classes. Class bytes are retrieved from
 115      * {@link ExecutionEnv#getClassBytes(java.lang.String) }
 116      *
 117      * @param classes list of class names to load
 118      * @return true if load succeeded
 119      */
 120     boolean load(Collection<String> classes);

 121 
 122     /**
 123      * Attempts to redefine previously loaded classes. Class bytes are retrieved
 124      * from {@link ExecutionEnv#getClassBytes(java.lang.String) }
 125      *
 126      * @param classes list of class names to redefine
 127      * @return true if redefine succeeded









 128      */
 129     boolean redefine(Collection<String> classes);

 130 
 131     /**
 132      * Queries if the class is loaded and the class bytes are current.
 133      *
 134      * @param classname name of the wrapper class to query
 135      * @return {@code UNKNOWN} if the class is not loaded; {@code CURRENT} if
 136      * the loaded/redefined bytes are equal to the most recent bytes for this
 137      * wrapper class; otherwise {@code NOT_CURRENT}
 138      */
 139     ClassStatus getClassStatus(String classname);



























































































 140 
 141     /**
 142      * Interrupt a running invoke.








 143      */
 144     void stop();




 145 
 146     /**
 147      * Returns the value of a variable.
 148      *
 149      * @param classname the name of the wrapper class of the variable
 150      * @param varname the name of the variable
 151      * @return the value of the variable
 152      */
 153     String varValue(String classname, String varname);












 154 }


   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */

  25 package jdk.jshell.spi;
  26 
  27 import java.io.Serializable;

  28 
  29 /**
  30  * This interface specifies the functionality that must provided to implement a
  31  * pluggable JShell execution engine.
  32  * <p>
  33  * The audience for this Service Provider Interface is engineers wishing to
  34  * implement their own version of the execution engine in support of the JShell
  35  * API.
  36  * <p>
  37  * A Snippet is compiled into code wrapped in a 'wrapper class'. The execution
  38  * engine is used by the core JShell implementation to load and, for executable
  39  * Snippets, execute the Snippet.
  40  * <p>
  41  * Methods defined in this interface should only be called by the core JShell
  42  * implementation.
  43  * <p>
  44  * To install an {@code ExecutionControl}, it's {@code Generator} is passed to
  45  * {@link jdk.jshell.JShell.Builder#executionEngine(ExecutionControl.Generator)  }.
  46  */
  47 public interface ExecutionControl {
  48     
  49     public interface Generator {
  50         ExecutionControl generate(ExecutionEnv env) throws Throwable;
  51     }





  52 
  53     /**
  54      * Attempts to load new classes.
  55      *
  56      * @param cbcs the class name and bytecodes to load
  57      * @throws ClassInstallException exception occurred loading the classes,
  58      * some or all were not loaded
  59      * @throws NotImplementedException if not implemented
  60      * @throws EngineTerminationException the execution engine has terminated
  61      */
  62     void load(ClassBytecodes[] cbcs)
  63             throws ClassInstallException, NotImplementedException, EngineTerminationException;
  64 
  65     /**
  66      * Attempts to redefine previously loaded classes.
  67      *
  68      * @param cbcs the class name and bytecodes to redefine
  69      * @throws ClassInstallException exception occurred redefining the classes,
  70      * some or all were not redefined
  71      * @throws NotImplementedException if not implemented
  72      * @throws EngineTerminationException the execution engine has terminated
  73      */
  74     void redefine(ClassBytecodes[] cbcs)
  75             throws ClassInstallException, NotImplementedException, EngineTerminationException;
  76 
  77     /**
  78      * Invokes an executable Snippet by calling a method on the specified
  79      * wrapper class. The method must have no arguments and return String.
  80      *
  81      * @param className the class whose method should be invoked
  82      * @param methodName the name of method to invoke
  83      * @return the result of the execution or null if no result
  84      * @throws UserException the invoke raised a user exception
  85      * @throws ResolutionException the invoke attempted to directly or
  86      * indirectly invoke an unresolved snippet
  87      * @throws StoppedException if the {@code invoke()} was canceled by
  88      * {@link ExecutionControl#stop}
  89      * @throws EngineTerminationException the execution engine has terminated
  90      * @throws InternalException an internal problem occurred
  91      */
  92     String invoke(String className, String methodName)
  93             throws RunException, EngineTerminationException, InternalException;
  94 
  95     /**
  96      * Returns the value of a variable.
  97      *
  98      * @param className the name of the wrapper class of the variable
  99      * @param varName the name of the variable
 100      * @return the value of the variable
 101      * @throws UserException formatting the value raised a user exception
 102      * @throws ResolutionException formatting the value attempted to directly or
 103      * indirectly invoke an unresolved snippet
 104      * @throws StoppedException if the formatting the value was canceled by
 105      * {@link ExecutionControl#stop}
 106      * @throws EngineTerminationException the execution engine has terminated
 107      * @throws InternalException an internal problem occurred
 108      */
 109     String varValue(String className, String varName)
 110             throws RunException, EngineTerminationException, InternalException;
 111 
 112     /**
 113      * Adds the path to the execution class path.
 114      *
 115      * @param path the path to add
 116      * @throws EngineTerminationException the execution engine has terminated
 117      * @throws InternalException an internal problem occurred
 118      */
 119     void addToClasspath(String path)
 120             throws EngineTerminationException, InternalException;
 121 
 122     /**
 123      * Sets the execution class path to the specified path.

 124      *
 125      * @param path the path to add
 126      * @throws EngineTerminationException the execution engine has terminated
 127      * @throws InternalException an internal problem occurred





 128      */
 129     void setClasspath(String path)
 130             throws EngineTerminationException, InternalException;
 131 
 132     /**
 133      * Interrupts a running invoke.

 134      *
 135      * @throws EngineTerminationException the execution engine has terminated
 136      * @throws InternalException an internal problem occurred
 137      */
 138     void stop()
 139             throws EngineTerminationException, InternalException;
 140 
 141     /**
 142      * Run a non-standard command (or a standard command from a newer version).

 143      *
 144      * @param command the non-standard command
 145      * @param arg the commands argument
 146      * @return the commands return value
 147      * @throws UserException the command raised a user exception
 148      * @throws ResolutionException the command attempted to directly or
 149      * indirectly invoke an unresolved snippet
 150      * @throws StoppedException if the command was canceled by
 151      * {@link ExecutionControl#stop}
 152      * @throws EngineTerminationException the execution engine has terminated
 153      * @throws NotImplementedException if not implemented
 154      * @throws InternalException an internal problem occurred
 155      */
 156     Object extensionCommand(String command, Object arg)
 157             throws RunException, EngineTerminationException, InternalException;
 158 
 159     /**
 160      * Shuts down this execution engine. Implementation should free all
 161      * resources held by this execution engine.
 162      * <p>
 163      * No calls to methods on this interface should be made after close.


 164      */
 165     void close();
 166 
 167     public static final class ClassBytecodes implements Serializable {
 168 
 169         private static final long serialVersionUID = 1L;
 170 
 171         public ClassBytecodes(String name, byte[] bytecodes) {
 172             this.name = name;
 173             this.bytecodes = bytecodes;
 174         }
 175         public final String name;
 176         public final byte[] bytecodes;
 177     }
 178 
 179     @SuppressWarnings("serial")
 180     public static abstract class ExecutionControlException extends Exception {
 181 
 182         public ExecutionControlException(String message) {
 183             super(message);
 184         }
 185     }
 186 
 187     /**
 188      * Unbidden execution engine termination has occurred.
 189      */
 190     @SuppressWarnings("serial")
 191     public static class EngineTerminationException extends ExecutionControlException {
 192 
 193         public EngineTerminationException(String message) {
 194             super(message);
 195         }
 196     }
 197 
 198     @SuppressWarnings("serial")
 199     public static class NotImplementedException extends InternalException {
 200 
 201         public NotImplementedException(String message) {
 202             super(message);
 203         }
 204     }
 205 
 206     @SuppressWarnings("serial")
 207     public static class InternalException extends ExecutionControlException {
 208 
 209         public InternalException(String message) {
 210             super(message);
 211         }
 212     }
 213 
 214     @SuppressWarnings("serial")
 215     public static class ClassInstallException extends ExecutionControlException {
 216 
 217         private final boolean[] installed;
 218 
 219         public ClassInstallException(String message, boolean[] installed) {
 220             super(message);
 221             this.installed = installed;
 222         }
 223 
 224         public boolean[] installed() {
 225             return installed;
 226         }
 227     }
 228 
 229     @SuppressWarnings("serial")             // serialVersionUID intentionally omitted
 230     public static abstract class RunException extends ExecutionControlException {
 231 
 232         private RunException(String message) {
 233             super(message);
 234         }
 235     }
 236 
 237     @SuppressWarnings("serial")             // serialVersionUID intentionally omitted
 238     public static class UserException extends RunException {
 239 
 240         private final String causeExceptionClass;
 241 
 242         public UserException(String message, String causeExceptionClass, StackTraceElement[] stackElements) {
 243             super(message);
 244             this.causeExceptionClass = causeExceptionClass;
 245             this.setStackTrace(stackElements);
 246         }
 247 
 248         public String causeExceptionClass() {
 249             return causeExceptionClass;
 250         }
 251     }
 252 
 253     @SuppressWarnings("serial")             // serialVersionUID intentionally omitted
 254     public static class ResolutionException extends RunException {
 255 
 256         private final int id;
 257 
 258         /**
 259          * Constructs an exception indicating that a
 260          * {@code DeclarationSnippet} with unresolved references has been
 261          * encountered. The throw of this exception is generated into the body
 262          * of a
 263          * {@link jdk.jshell.Snippet.Status#RECOVERABLE_DEFINED RECOVERABLE_DEFINED}
 264          * method.
 265          *
 266          * @param id An internal identifier of the specific method
 267          * @param stackElements the stack trace
 268          */
 269         public ResolutionException(int id, StackTraceElement[] stackElements) {
 270             super("resolution exception: " + id);
 271             this.id = id;
 272             this.setStackTrace(stackElements);
 273         }
 274 
 275         /**
 276          * Retrieves the internal identifier of the unresolved identifier.
 277          *
 278          * @return the internal identifier


 279          */
 280         public int id() {
 281             return id;
 282         }
 283     }
 284 
 285     @SuppressWarnings("serial")             // serialVersionUID intentionally omitted
 286     public static class StoppedException extends RunException {
 287 
 288         public StoppedException() {
 289             super("stopped by stop()");
 290         }
 291     }
 292 
 293 }