Log window category and show lines

This commit is contained in:
huangyuhui
2017-08-21 20:59:32 +08:00
parent be202a6e1a
commit a67bfabea4
13 changed files with 304 additions and 44 deletions

View File

@@ -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)
}

View File

@@ -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")) {

View File

@@ -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()
}

View File

@@ -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
*/

View File

@@ -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

View File

@@ -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()

View File

@@ -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)
})
}
}
}