1/*
2 * Copyright (c) 2013, 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.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24package toolbox;
25
26import java.util.ArrayList;
27import java.util.Arrays;
28import java.util.HashMap;
29import java.util.List;
30import java.util.Map;
31
32/**
33 * A task to configure and run the disassembler tool, javap.
34 */
35public class JavapTask extends AbstractTask<JavapTask> {
36    private String classpath;
37    private List<String> options;
38    private List<String> classes;
39
40    /**
41     * Create a task to execute {@code javap} using {@code CMDLINE} mode.
42     * @param toolBox the {@code ToolBox} to use
43     */
44    public JavapTask(ToolBox toolBox) {
45        super(toolBox, Task.Mode.CMDLINE);
46    }
47
48    /**
49     * Sets the classpath.
50     * @param classpath the classpath
51     * @return this task object
52     */
53    public JavapTask classpath(String classpath) {
54        this.classpath = classpath;
55        return this;
56    }
57
58    /**
59     * Sets the options.
60     * @param options the options
61     * @return this task object
62     */
63    public JavapTask options(String... options) {
64        this.options = Arrays.asList(options);
65        return this;
66    }
67
68    /**
69     * Sets the classes to be analyzed.
70     * @param classes the classes
71     * @return this task object
72     */
73    public JavapTask classes(String... classes) {
74        this.classes = Arrays.asList(classes);
75        return this;
76    }
77
78    /**
79     * {@inheritDoc}
80     * @return the name "javap"
81     */
82    @Override
83    public String name() {
84        return "javap";
85    }
86
87    /**
88     * Calls the javap tool with the arguments as currently configured.
89     * @return a Result object indicating the outcome of the task
90     * and the content of any output written to stdout, stderr, or the
91     * main stream.
92     * @throws TaskError if the outcome of the task is not as expected.
93     */
94    @Override
95    public Task.Result run() {
96        List<String> args = new ArrayList<>();
97        if (options != null)
98            args.addAll(options);
99        if (classpath != null) {
100            args.add("-classpath");
101            args.add(classpath);
102        }
103        if (classes != null)
104            args.addAll(classes);
105
106        AbstractTask.WriterOutput direct = new AbstractTask.WriterOutput();
107        // These are to catch output to System.out and System.err,
108        // in case these are used instead of the primary streams
109        AbstractTask.StreamOutput sysOut = new AbstractTask.StreamOutput(System.out, System::setOut);
110        AbstractTask.StreamOutput sysErr = new AbstractTask.StreamOutput(System.err, System::setErr);
111
112        int rc;
113        Map<Task.OutputKind, String> outputMap = new HashMap<>();
114        try {
115            rc = com.sun.tools.javap.Main.run(args.toArray(new String[args.size()]), direct.pw);
116        } finally {
117            outputMap.put(Task.OutputKind.STDOUT, sysOut.close());
118            outputMap.put(Task.OutputKind.STDERR, sysErr.close());
119            outputMap.put(Task.OutputKind.DIRECT, direct.close());
120        }
121        return checkExit(new Task.Result(toolBox, this, rc, outputMap));
122    }
123}
124