Log window category and show lines
This commit is contained in:
@@ -286,11 +286,11 @@ open class DefaultLauncher(repository: GameRepository, versionId: String, accoun
|
||||
|
||||
private fun startMonitors(javaProcess: JavaProcess, processListener: ProcessListener, isDaemon: Boolean = true) {
|
||||
processListener.setProcess(javaProcess)
|
||||
val logHandler = Log4jHandler { line, level -> processListener.onLog(line, level); javaProcess.stdOutLines += line }.apply { start() }
|
||||
val logHandler = Log4jHandler { line, level -> processListener.onLog(line, level); javaProcess.lines += line }.apply { start() }
|
||||
javaProcess.relatedThreads += logHandler
|
||||
val stdout = thread(name = "stdout-pump", isDaemon = isDaemon, block = StreamPump(javaProcess.process.inputStream, { logHandler.newLine(it) } )::run)
|
||||
javaProcess.relatedThreads += stdout
|
||||
val stderr = thread(name = "stderr-pump", isDaemon = isDaemon, block = StreamPump(javaProcess.process.errorStream, { processListener.onLog(it + OS.LINE_SEPARATOR, Log4jLevel.ERROR); javaProcess.stdErrLines += it })::run)
|
||||
val stderr = thread(name = "stderr-pump", isDaemon = isDaemon, block = StreamPump(javaProcess.process.errorStream, { processListener.onLog(it + OS.LINE_SEPARATOR, Log4jLevel.ERROR); javaProcess.lines += it })::run)
|
||||
javaProcess.relatedThreads += stderr
|
||||
javaProcess.relatedThreads += thread(name = "exit-waiter", isDaemon = isDaemon, block = ExitWaiter(javaProcess, listOf(stdout, stderr), { exitCode, exitType -> logHandler.onStopped(); processListener.onExit(exitCode, exitType) })::run)
|
||||
}
|
||||
|
||||
@@ -15,13 +15,15 @@
|
||||
* 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 org.jackhuang.hmcl.util
|
||||
package org.jackhuang.hmcl.launch
|
||||
|
||||
import org.jackhuang.hmcl.event.EVENT_BUS
|
||||
import org.jackhuang.hmcl.event.JVMLaunchFailedEvent
|
||||
import org.jackhuang.hmcl.event.JavaProcessExitedAbnormallyEvent
|
||||
import org.jackhuang.hmcl.event.JavaProcessStoppedEvent
|
||||
import org.jackhuang.hmcl.launch.ProcessListener
|
||||
import org.jackhuang.hmcl.util.JavaProcess
|
||||
import org.jackhuang.hmcl.util.containsOne
|
||||
import org.jackhuang.hmcl.util.guessLogLineError
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@@ -36,10 +38,7 @@ internal class ExitWaiter(val process: JavaProcess, val joins: Collection<Thread
|
||||
joins.forEach { it.join() }
|
||||
|
||||
val exitCode = process.exitCode
|
||||
val lines = LinkedList<String>()
|
||||
lines.addAll(process.stdErrLines)
|
||||
lines.addAll(process.stdOutLines)
|
||||
val errorLines = lines.filter(::guessLogLineError)
|
||||
val errorLines = process.lines.filter(::guessLogLineError)
|
||||
val exitType: ProcessListener.ExitType
|
||||
// LaunchWrapper will catch the exception logged and will exit normally.
|
||||
if (exitCode != 0 || errorLines.containsOne("Unable to launch")) {
|
||||
@@ -24,10 +24,12 @@ import org.xml.sax.Attributes
|
||||
import org.xml.sax.InputSource
|
||||
import org.xml.sax.helpers.DefaultHandler
|
||||
import org.xml.sax.helpers.XMLReaderFactory
|
||||
import java.io.InterruptedIOException
|
||||
import java.io.PipedInputStream
|
||||
import java.io.PipedOutputStream
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
import java.util.concurrent.atomic.AtomicBoolean
|
||||
|
||||
/**
|
||||
* This class is to parse log4j classic XML layout logging, since only vanilla Minecraft will enable this layout.
|
||||
@@ -38,18 +40,28 @@ internal class Log4jHandler(val callback: (String, Log4jLevel) -> Unit) : Thread
|
||||
}
|
||||
private val outputStream = PipedOutputStream()
|
||||
private val inputStream = PipedInputStream(outputStream)
|
||||
private val interrupted = AtomicBoolean(false)
|
||||
|
||||
override fun run() {
|
||||
name = "log4j-handler"
|
||||
newLine("<output>")
|
||||
reader.parse(InputSource(inputStream))
|
||||
try {
|
||||
reader.parse(InputSource(inputStream))
|
||||
} catch (e: InterruptedIOException) {
|
||||
// Game has been interrupted.
|
||||
interrupted.set(true)
|
||||
}
|
||||
}
|
||||
|
||||
fun onStopped() {
|
||||
if (interrupted.get())
|
||||
return
|
||||
Scheduler.NEW_THREAD.schedule {
|
||||
newLine("</output>")?.get()
|
||||
outputStream.close()
|
||||
join()
|
||||
if (!interrupted.get()) {
|
||||
newLine("</output>")?.get()
|
||||
outputStream.close()
|
||||
join()
|
||||
}
|
||||
}!!.get()
|
||||
}
|
||||
|
||||
|
||||
@@ -28,7 +28,9 @@ interface ProcessListener {
|
||||
fun setProcess(process: JavaProcess) {}
|
||||
|
||||
/**
|
||||
* Called when receiving a log from stdout
|
||||
* Called when receiving a log from stdout/stderr.
|
||||
*
|
||||
* Does not guarantee that this method is thread safe.
|
||||
*
|
||||
* @param log the log
|
||||
*/
|
||||
|
||||
@@ -15,8 +15,10 @@
|
||||
* 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 org.jackhuang.hmcl.util
|
||||
package org.jackhuang.hmcl.launch
|
||||
|
||||
import org.jackhuang.hmcl.util.LOG
|
||||
import org.jackhuang.hmcl.util.SYSTEM_CHARSET
|
||||
import java.io.IOException
|
||||
import java.io.InputStream
|
||||
import java.util.logging.Level
|
||||
@@ -17,6 +17,7 @@
|
||||
*/
|
||||
package org.jackhuang.hmcl.util
|
||||
|
||||
import java.util.*
|
||||
import java.util.concurrent.ConcurrentLinkedQueue
|
||||
|
||||
class JavaProcess(
|
||||
@@ -24,8 +25,7 @@ class JavaProcess(
|
||||
val commands: List<String>
|
||||
) {
|
||||
val properties = mutableMapOf<String, Any>()
|
||||
val stdOutLines: MutableCollection<String> = ConcurrentLinkedQueue<String>()
|
||||
val stdErrLines: MutableCollection<String> = ConcurrentLinkedQueue<String>()
|
||||
val lines: Queue<String> = ConcurrentLinkedQueue<String>()
|
||||
val relatedThreads = mutableListOf<Thread>()
|
||||
val isRunning: Boolean = try {
|
||||
process.exitValue()
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
package org.jackhuang.hmcl.util
|
||||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
import javafx.scene.input.Clipboard
|
||||
import javafx.scene.input.ClipboardContent
|
||||
import java.io.File
|
||||
import java.lang.management.ManagementFactory
|
||||
import java.nio.charset.Charset
|
||||
@@ -65,5 +67,12 @@ enum class OS {
|
||||
|
||||
val SYSTEM_VERSION: String by lazy { System.getProperty("os.version") }
|
||||
val SYSTEM_ARCH: String by lazy { System.getProperty("os.arch") }
|
||||
|
||||
fun setClipboard(string: String) {
|
||||
val clipboard = Clipboard.getSystemClipboard()
|
||||
clipboard.setContent(ClipboardContent().apply {
|
||||
putString(string)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user