src/java.base/share/classes/java/util/spi/ToolProvider.java
changeset 47216 71c04702a3d5
parent 41484 834b7539ada3
child 53927 03924ad3f4d0
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     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 java.util.spi;
       
    27 
       
    28 import java.io.PrintStream;
       
    29 import java.io.PrintWriter;
       
    30 import java.security.AccessController;
       
    31 import java.security.PrivilegedAction;
       
    32 import java.util.Objects;
       
    33 import java.util.Optional;
       
    34 import java.util.ServiceLoader;
       
    35 import java.util.stream.StreamSupport;
       
    36 
       
    37 /**
       
    38  * An interface for command-line tools to provide a way to
       
    39  * be invoked without necessarily starting a new VM.
       
    40  *
       
    41  * <p>Tool providers are normally located using the service-provider
       
    42  * loading facility defined by {@link ServiceLoader}.
       
    43  * Each provider must provide a name, and a method to run
       
    44  * an instance of the corresponding tool. When a tool is run,
       
    45  * it will be provided with an array of string arguments, and a
       
    46  * pair of streams: one for normal (or expected) output and the other
       
    47  * for reporting any errors that may occur.
       
    48  * The interpretation of the string arguments will normally be defined by
       
    49  * each individual tool provider, but will generally correspond to the
       
    50  * arguments that could be provided to the tool when invoking the tool
       
    51  * from the command line.
       
    52  *
       
    53  * @since 9
       
    54  */
       
    55 public interface ToolProvider {
       
    56     /**
       
    57      * Returns the name of this tool provider.
       
    58      *
       
    59      * @apiNote It is recommended that the name be the same as would be
       
    60      * used on the command line: for example, "javac", "jar", "jlink".
       
    61      *
       
    62      * @return the name of this tool provider
       
    63      */
       
    64     String name();
       
    65 
       
    66     /**
       
    67      * Runs an instance of the tool, returning zero for a successful run.
       
    68      * Any non-zero return value indicates a tool-specific error during the
       
    69      * execution.
       
    70      *
       
    71      * Two streams should be provided, for "expected" output, and for any
       
    72      * error messages. If it is not necessary to distinguish the output,
       
    73      * the same stream may be used for both.
       
    74      *
       
    75      * @apiNote The interpretation of the arguments will be specific to
       
    76      * each tool.
       
    77      *
       
    78      * @param out a stream to which "expected" output should be written
       
    79      *
       
    80      * @param err a stream to which any error messages should be written
       
    81      *
       
    82      * @param args the command-line arguments for the tool
       
    83      *
       
    84      * @return the result of executing the tool.
       
    85      *         A return value of 0 means the tool did not encounter any errors;
       
    86      *         any other value indicates that at least one error occurred
       
    87      *         during execution.
       
    88      *
       
    89      * @throws NullPointerException if any of the arguments are {@code null},
       
    90      *         or if there are any {@code null} values in the {@code args}
       
    91      *         array
       
    92      */
       
    93     int run(PrintWriter out, PrintWriter err, String... args);
       
    94 
       
    95     /**
       
    96      * Runs an instance of the tool, returning zero for a successful run.
       
    97      * Any non-zero return value indicates a tool-specific error during the
       
    98      * execution.
       
    99      *
       
   100      * Two streams should be provided, for "expected" output, and for any
       
   101      * error messages. If it is not necessary to distinguish the output,
       
   102      * the same stream may be used for both.
       
   103      *
       
   104      * @apiNote The interpretation of the arguments will be specific to
       
   105      * each tool.
       
   106      *
       
   107      * @implNote This implementation wraps the {@code out} and {@code err}
       
   108      * streams within {@link PrintWriter}s, and then calls
       
   109      * {@link #run(PrintWriter, PrintWriter, String[])}.
       
   110      *
       
   111      * @param out a stream to which "expected" output should be written
       
   112      *
       
   113      * @param err a stream to which any error messages should be written
       
   114      *
       
   115      * @param args the command-line arguments for the tool
       
   116      *
       
   117      * @return the result of executing the tool.
       
   118      *         A return value of 0 means the tool did not encounter any errors;
       
   119      *         any other value indicates that at least one error occurred
       
   120      *         during execution.
       
   121      *
       
   122      * @throws NullPointerException if any of the arguments are {@code null},
       
   123      *         or if there are any {@code null} values in the {@code args}
       
   124      *         array
       
   125      */
       
   126     default int run(PrintStream out, PrintStream err, String... args) {
       
   127         Objects.requireNonNull(out);
       
   128         Objects.requireNonNull(err);
       
   129         for (String arg : args) {
       
   130             Objects.requireNonNull(args);
       
   131         }
       
   132 
       
   133         PrintWriter outWriter = new PrintWriter(out);
       
   134         PrintWriter errWriter = new PrintWriter(err);
       
   135         try {
       
   136             try {
       
   137                 return run(outWriter, errWriter, args);
       
   138             } finally {
       
   139                 outWriter.flush();
       
   140             }
       
   141         } finally {
       
   142             errWriter.flush();
       
   143         }
       
   144     }
       
   145 
       
   146     /**
       
   147      * Returns the first instance of a {@code ToolProvider} with the given name,
       
   148      * as loaded by {@link ServiceLoader} using the system class loader.
       
   149      *
       
   150      * @param name the name of the desired tool provider
       
   151      *
       
   152      * @return an {@code Optional<ToolProvider>} of the first instance found
       
   153      *
       
   154      * @throws NullPointerException if {@code name} is {@code null}
       
   155      */
       
   156     static Optional<ToolProvider> findFirst(String name) {
       
   157         Objects.requireNonNull(name);
       
   158         ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
       
   159         return AccessController.doPrivileged(
       
   160             (PrivilegedAction<Optional<ToolProvider>>) () -> {
       
   161                 ServiceLoader<ToolProvider> sl =
       
   162                     ServiceLoader.load(ToolProvider.class, systemClassLoader);
       
   163                 return StreamSupport.stream(sl.spliterator(), false)
       
   164                     .filter(p -> p.name().equals(name))
       
   165                     .findFirst();
       
   166             });
       
   167     }
       
   168 }
       
   169