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

Commit

Permalink
Merge remote-tracking branch 'origin/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
RaphiMC committed Sep 2, 2023
2 parents 21cbc11 + 13e2979 commit 44c123c
Show file tree
Hide file tree
Showing 6 changed files with 326 additions and 13 deletions.
4 changes: 3 additions & 1 deletion standalone/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ repositories {
dependencies {
include project(":")

include "net.lenni0451.classtransform:core:1.9.1"
include "net.lenni0451.classtransform:core:1.10.1"

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

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

include "me.tongfei:progressbar:0.9.5"

include("org.jline:jline-terminal-jansi:3.23.0")
}

application {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@
package net.raphimc.javadowngrader.standalone;

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

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

try {
final long start = System.nanoTime();
doConversion(inputFile, outputFile, options.valueOf(version), GeneralUtil.flatten(options.valuesOf(libraryPath)));
doConversion(
inputFile, outputFile,
options.valueOf(version),
GeneralUtil.flatten(options.valuesOf(libraryPath)),
Math.min(options.valueOf(threadCount), 255)
);
final long end = System.nanoTime();
LOGGER.info(
"Done in {}.",
Expand All @@ -132,7 +141,8 @@ private static void doConversion(
final File inputFile,
final File outputFile,
final JavaVersion targetVersion,
List<File> libraryPath
List<File> libraryPath,
int threadCount
) throws Throwable {
LOGGER.info("Downgrading {} to Java {}", inputFile, targetVersion.getName());
if (outputFile.isFile() && !outputFile.canWrite()) {
Expand Down Expand Up @@ -196,14 +206,14 @@ private static void doConversion(
});
}
}
final int threadCount = Runtime.getRuntime().availableProcessors();
LOGGER.info("Downgrading classes with {} threads", threadCount);
LOGGER.info("Downgrading classes with {} thread(s)", threadCount);
final ExecutorService threadPool = Executors.newFixedThreadPool(threadCount);
final List<Callable<Void>> tasks;
final ProgressBar[] pb = new ProgressBar[1];
final MultiThreadedProgressBar[] pb = new MultiThreadedProgressBar[1];
try (Stream<Path> stream = Files.walk(inRoot)) {
tasks = stream.map(path -> (Callable<Void>) () -> {
final String relative = GeneralUtil.slashName(inRoot.relativize(path));
pb[0].setThreadTask(relative);
final Path inOther = outRoot.resolve(relative);
if (Files.isDirectory(path)) {
Files.createDirectories(inOther);
Expand Down Expand Up @@ -234,12 +244,13 @@ private static void doConversion(
}).collect(Collectors.toList());
}
try {
pb[0] = new ProgressBarBuilder()
.setTaskName("Downgrading")
.setStyle(ProgressBarStyle.ASCII)
.setInitialMax(tasks.size())
.setUpdateIntervalMillis(100)
.build();
pb[0] = MultiThreadedProgressBar.create(
new ProgressBarBuilder()
.setTaskName("Downgrading")
.setStyle(ProgressBarStyle.ASCII)
.setInitialMax(tasks.size())
.setUpdateIntervalMillis(100)
);
threadPool.invokeAll(tasks);
} finally {
if (pb[0] != null) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/*
* This file is part of JavaDowngrader - https://github.com/RaphiMC/JavaDowngrader
* Copyright (C) 2023 RK_01/RaphiMC and contributors
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.raphimc.javadowngrader.standalone.progress;

import me.tongfei.progressbar.ProgressBarBuilder;

public interface MultiThreadedProgressBar extends AutoCloseable {
void step();

void setThreadTask(String task);

@Override
void close();

static MultiThreadedProgressBar create(ProgressBarBuilder bar) {
return TerminalUtils.hasCursorMovementSupport()
? new ThreadedLineProgressBar(bar)
: new SimpleProgressBar(bar.build());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* This file is part of JavaDowngrader - https://github.com/RaphiMC/JavaDowngrader
* Copyright (C) 2023 RK_01/RaphiMC and contributors
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package net.raphimc.javadowngrader.standalone.progress;

import me.tongfei.progressbar.ProgressBar;

class SimpleProgressBar implements MultiThreadedProgressBar {
protected final ProgressBar bar;

public SimpleProgressBar(ProgressBar bar) {
this.bar = bar;
}

@Override
public void step() {
bar.step();
}

@Override
public void setThreadTask(String task) {
}

@Override
public void close() {
bar.close();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
/*
* The MIT License (MIT)
*
* Copyright (c) 2015--2020 Tongfei Chen and contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package net.raphimc.javadowngrader.standalone.progress;

import me.tongfei.progressbar.ProgressBarConsumer;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.jline.utils.InfoCmp;

import java.io.IOException;
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.stream.Stream;

/**
* @author Martin Vehovsky
* @since 0.9.0
*/
class TerminalUtils {

static final char CARRIAGE_RETURN = '\r';
static final char ESCAPE_CHAR = '\u001b';
static final int DEFAULT_TERMINAL_WIDTH = 80;

private static Terminal terminal = null;
private static boolean cursorMovementSupported = false;

static Queue<ProgressBarConsumer> activeConsumers = new ConcurrentLinkedQueue<>();

synchronized static int getTerminalWidth() {
Terminal terminal = getTerminal();
int width = terminal.getWidth();

// Workaround for issue #23 under IntelliJ
return (width >= 10) ? width : DEFAULT_TERMINAL_WIDTH;
}

static boolean hasCursorMovementSupport() {
if (terminal == null)
terminal = getTerminal();
return cursorMovementSupported;
}

synchronized static void closeTerminal() {
try {
if (terminal != null) {
terminal.close();
terminal = null;
}
} catch (IOException ignored) { /* noop */ }
}

static <T extends ProgressBarConsumer> Stream<T> filterActiveConsumers(Class<T> clazz) {
return activeConsumers.stream()
.filter(clazz::isInstance)
.map(clazz::cast);
}

static String moveCursorUp(int count) {
return ESCAPE_CHAR + "[" + count + "A" + CARRIAGE_RETURN;
}

static String moveCursorDown(int count) {
return ESCAPE_CHAR + "[" + count + "B" + CARRIAGE_RETURN;
}

/**
* <ul>
* <li>Creating terminal is relatively expensive, usually takes between 5-10ms.
* <ul>
* <li>If updateInterval is set under 10ms creating new terminal for on every re-render of progress bar could be a problem.</li>
* <li>Especially when multiple progress bars are running in parallel.</li>
* </ul>
* </li>
* <li>Another problem with {@link Terminal} is that once created you can create another instance (say from different thread), but this instance will be
* "dumb". Until previously created terminal will be closed.
* </li>
* </ul>
*/
static Terminal getTerminal() {
if (terminal == null) {
try {
// Issue #42
// Defaulting to a dumb terminal when a supported terminal can not be correctly created
// see https://github.com/jline/jline3/issues/291
terminal = TerminalBuilder.builder().dumb(true).build();
cursorMovementSupported = (
terminal.getStringCapability(InfoCmp.Capability.cursor_up) != null &&
terminal.getStringCapability(InfoCmp.Capability.cursor_down) != null
);
} catch (IOException e) {
throw new RuntimeException("This should never happen! Dumb terminal should have been created.");
}
}
return terminal;
}

}
Loading

0 comments on commit 44c123c

Please sign in to comment.