Skip to content
This repository was archived by the owner on May 12, 2024. It is now read-only.

Commit 44c123c

Browse files
committed
Merge remote-tracking branch 'origin/main'
2 parents 21cbc11 + 13e2979 commit 44c123c

6 files changed

Lines changed: 326 additions & 13 deletions

File tree

standalone/build.gradle

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ repositories {
2020
dependencies {
2121
include project(":")
2222

23-
include "net.lenni0451.classtransform:core:1.9.1"
23+
include "net.lenni0451.classtransform:core:1.10.1"
2424

2525
include "net.sf.jopt-simple:jopt-simple:5.0.4"
2626

@@ -30,6 +30,8 @@ dependencies {
3030
compileOnly "org.jetbrains:annotations:24.0.1"
3131

3232
include "me.tongfei:progressbar:0.9.5"
33+
34+
include("org.jline:jline-terminal-jansi:3.23.0")
3335
}
3436

3537
application {

standalone/src/main/java/net/raphimc/javadowngrader/standalone/Main.java

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
package net.raphimc.javadowngrader.standalone;
1919

2020
import joptsimple.*;
21-
import me.tongfei.progressbar.ProgressBar;
2221
import me.tongfei.progressbar.ProgressBarBuilder;
2322
import me.tongfei.progressbar.ProgressBarStyle;
2423
import net.lenni0451.classtransform.TransformerManager;
2524
import net.lenni0451.classtransform.utils.tree.BasicClassProvider;
25+
import net.raphimc.javadowngrader.standalone.progress.MultiThreadedProgressBar;
2626
import net.raphimc.javadowngrader.standalone.transform.JavaDowngraderTransformer;
2727
import net.raphimc.javadowngrader.standalone.transform.LazyFileClassProvider;
2828
import net.raphimc.javadowngrader.standalone.transform.PathClassProvider;
@@ -75,6 +75,10 @@ public static void main(String[] args) throws Throwable {
7575
final OptionSpec<List<File>> libraryPath = parser.acceptsAll(asList("library_path", "library", "l"), "Additional libraries to add to the classpath (required for stack frames)")
7676
.withRequiredArg()
7777
.withValuesConvertedBy(new PathConverter());
78+
final OptionSpec<Integer> threadCount = parser.acceptsAll(asList("thread_count", "threads", "t"), "The number of threads to use for the downgrading")
79+
.withRequiredArg()
80+
.ofType(Integer.class)
81+
.defaultsTo(Math.min(Runtime.getRuntime().availableProcessors(), 255));
7882

7983
final OptionSet options;
8084
try {
@@ -112,7 +116,12 @@ public static void main(String[] args) throws Throwable {
112116

113117
try {
114118
final long start = System.nanoTime();
115-
doConversion(inputFile, outputFile, options.valueOf(version), GeneralUtil.flatten(options.valuesOf(libraryPath)));
119+
doConversion(
120+
inputFile, outputFile,
121+
options.valueOf(version),
122+
GeneralUtil.flatten(options.valuesOf(libraryPath)),
123+
Math.min(options.valueOf(threadCount), 255)
124+
);
116125
final long end = System.nanoTime();
117126
LOGGER.info(
118127
"Done in {}.",
@@ -132,7 +141,8 @@ private static void doConversion(
132141
final File inputFile,
133142
final File outputFile,
134143
final JavaVersion targetVersion,
135-
List<File> libraryPath
144+
List<File> libraryPath,
145+
int threadCount
136146
) throws Throwable {
137147
LOGGER.info("Downgrading {} to Java {}", inputFile, targetVersion.getName());
138148
if (outputFile.isFile() && !outputFile.canWrite()) {
@@ -196,14 +206,14 @@ private static void doConversion(
196206
});
197207
}
198208
}
199-
final int threadCount = Runtime.getRuntime().availableProcessors();
200-
LOGGER.info("Downgrading classes with {} threads", threadCount);
209+
LOGGER.info("Downgrading classes with {} thread(s)", threadCount);
201210
final ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
202211
final List<Callable<Void>> tasks;
203-
final ProgressBar[] pb = new ProgressBar[1];
212+
final MultiThreadedProgressBar[] pb = new MultiThreadedProgressBar[1];
204213
try (Stream<Path> stream = Files.walk(inRoot)) {
205214
tasks = stream.map(path -> (Callable<Void>) () -> {
206215
final String relative = GeneralUtil.slashName(inRoot.relativize(path));
216+
pb[0].setThreadTask(relative);
207217
final Path inOther = outRoot.resolve(relative);
208218
if (Files.isDirectory(path)) {
209219
Files.createDirectories(inOther);
@@ -234,12 +244,13 @@ private static void doConversion(
234244
}).collect(Collectors.toList());
235245
}
236246
try {
237-
pb[0] = new ProgressBarBuilder()
238-
.setTaskName("Downgrading")
239-
.setStyle(ProgressBarStyle.ASCII)
240-
.setInitialMax(tasks.size())
241-
.setUpdateIntervalMillis(100)
242-
.build();
247+
pb[0] = MultiThreadedProgressBar.create(
248+
new ProgressBarBuilder()
249+
.setTaskName("Downgrading")
250+
.setStyle(ProgressBarStyle.ASCII)
251+
.setInitialMax(tasks.size())
252+
.setUpdateIntervalMillis(100)
253+
);
243254
threadPool.invokeAll(tasks);
244255
} finally {
245256
if (pb[0] != null) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* This file is part of JavaDowngrader - https://github.com/RaphiMC/JavaDowngrader
3+
* Copyright (C) 2023 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.javadowngrader.standalone.progress;
19+
20+
import me.tongfei.progressbar.ProgressBarBuilder;
21+
22+
public interface MultiThreadedProgressBar extends AutoCloseable {
23+
void step();
24+
25+
void setThreadTask(String task);
26+
27+
@Override
28+
void close();
29+
30+
static MultiThreadedProgressBar create(ProgressBarBuilder bar) {
31+
return TerminalUtils.hasCursorMovementSupport()
32+
? new ThreadedLineProgressBar(bar)
33+
: new SimpleProgressBar(bar.build());
34+
}
35+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* This file is part of JavaDowngrader - https://github.com/RaphiMC/JavaDowngrader
3+
* Copyright (C) 2023 RK_01/RaphiMC and contributors
4+
*
5+
* This program is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 3 of the License, or (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU General Public License
16+
* along with this program. If not, see <http://www.gnu.org/licenses/>.
17+
*/
18+
package net.raphimc.javadowngrader.standalone.progress;
19+
20+
import me.tongfei.progressbar.ProgressBar;
21+
22+
class SimpleProgressBar implements MultiThreadedProgressBar {
23+
protected final ProgressBar bar;
24+
25+
public SimpleProgressBar(ProgressBar bar) {
26+
this.bar = bar;
27+
}
28+
29+
@Override
30+
public void step() {
31+
bar.step();
32+
}
33+
34+
@Override
35+
public void setThreadTask(String task) {
36+
}
37+
38+
@Override
39+
public void close() {
40+
bar.close();
41+
}
42+
}
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* The MIT License (MIT)
3+
*
4+
* Copyright (c) 2015--2020 Tongfei Chen and contributors
5+
*
6+
* Permission is hereby granted, free of charge, to any person obtaining a copy
7+
* of this software and associated documentation files (the "Software"), to deal
8+
* in the Software without restriction, including without limitation the rights
9+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10+
* copies of the Software, and to permit persons to whom the Software is
11+
* furnished to do so, subject to the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included in all
14+
* copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22+
* SOFTWARE.
23+
*/
24+
package net.raphimc.javadowngrader.standalone.progress;
25+
26+
import me.tongfei.progressbar.ProgressBarConsumer;
27+
import org.jline.terminal.Terminal;
28+
import org.jline.terminal.TerminalBuilder;
29+
import org.jline.utils.InfoCmp;
30+
31+
import java.io.IOException;
32+
import java.util.Queue;
33+
import java.util.concurrent.ConcurrentLinkedQueue;
34+
import java.util.stream.Stream;
35+
36+
/**
37+
* @author Martin Vehovsky
38+
* @since 0.9.0
39+
*/
40+
class TerminalUtils {
41+
42+
static final char CARRIAGE_RETURN = '\r';
43+
static final char ESCAPE_CHAR = '\u001b';
44+
static final int DEFAULT_TERMINAL_WIDTH = 80;
45+
46+
private static Terminal terminal = null;
47+
private static boolean cursorMovementSupported = false;
48+
49+
static Queue<ProgressBarConsumer> activeConsumers = new ConcurrentLinkedQueue<>();
50+
51+
synchronized static int getTerminalWidth() {
52+
Terminal terminal = getTerminal();
53+
int width = terminal.getWidth();
54+
55+
// Workaround for issue #23 under IntelliJ
56+
return (width >= 10) ? width : DEFAULT_TERMINAL_WIDTH;
57+
}
58+
59+
static boolean hasCursorMovementSupport() {
60+
if (terminal == null)
61+
terminal = getTerminal();
62+
return cursorMovementSupported;
63+
}
64+
65+
synchronized static void closeTerminal() {
66+
try {
67+
if (terminal != null) {
68+
terminal.close();
69+
terminal = null;
70+
}
71+
} catch (IOException ignored) { /* noop */ }
72+
}
73+
74+
static <T extends ProgressBarConsumer> Stream<T> filterActiveConsumers(Class<T> clazz) {
75+
return activeConsumers.stream()
76+
.filter(clazz::isInstance)
77+
.map(clazz::cast);
78+
}
79+
80+
static String moveCursorUp(int count) {
81+
return ESCAPE_CHAR + "[" + count + "A" + CARRIAGE_RETURN;
82+
}
83+
84+
static String moveCursorDown(int count) {
85+
return ESCAPE_CHAR + "[" + count + "B" + CARRIAGE_RETURN;
86+
}
87+
88+
/**
89+
* <ul>
90+
* <li>Creating terminal is relatively expensive, usually takes between 5-10ms.
91+
* <ul>
92+
* <li>If updateInterval is set under 10ms creating new terminal for on every re-render of progress bar could be a problem.</li>
93+
* <li>Especially when multiple progress bars are running in parallel.</li>
94+
* </ul>
95+
* </li>
96+
* <li>Another problem with {@link Terminal} is that once created you can create another instance (say from different thread), but this instance will be
97+
* "dumb". Until previously created terminal will be closed.
98+
* </li>
99+
* </ul>
100+
*/
101+
static Terminal getTerminal() {
102+
if (terminal == null) {
103+
try {
104+
// Issue #42
105+
// Defaulting to a dumb terminal when a supported terminal can not be correctly created
106+
// see https://github.com/jline/jline3/issues/291
107+
terminal = TerminalBuilder.builder().dumb(true).build();
108+
cursorMovementSupported = (
109+
terminal.getStringCapability(InfoCmp.Capability.cursor_up) != null &&
110+
terminal.getStringCapability(InfoCmp.Capability.cursor_down) != null
111+
);
112+
} catch (IOException e) {
113+
throw new RuntimeException("This should never happen! Dumb terminal should have been created.");
114+
}
115+
}
116+
return terminal;
117+
}
118+
119+
}

0 commit comments

Comments
 (0)