fix: SFTP add transport NPE

This commit is contained in:
hstyi
2025-03-29 14:29:13 +08:00
committed by hstyi
parent 09b3655c4e
commit 1516d6d81e
2 changed files with 68 additions and 64 deletions

View File

@@ -680,7 +680,7 @@ class FileSystemViewTable(
coroutineScope.launch { coroutineScope.launch {
try { try {
doTransfer(arrayOf(attr), fromLocalSystem, targetWorkdir) doTransfer(attr, fromLocalSystem, targetWorkdir)
} catch (e: Exception) { } catch (e: Exception) {
if (log.isErrorEnabled) { if (log.isErrorEnabled) {
log.error(e.message, e) log.error(e.message, e)
@@ -829,78 +829,69 @@ class FileSystemViewTable(
* 开始查找所有子,查找到之后立即添加任务,如果添加失败(任意一个)那么立即终止 * 开始查找所有子,查找到之后立即添加任务,如果添加失败(任意一个)那么立即终止
*/ */
private fun doTransfer( private fun doTransfer(
attrs: Array<FileSystemViewTableModel.Attr>, attr: FileSystemViewTableModel.Attr,
fromLocalSystem: Boolean, fromLocalSystem: Boolean,
targetWorkdir: Path? targetWorkdir: Path?
) { ) {
if (attrs.isEmpty()) return
val sftpPanel = this.sftpPanel val sftpPanel = this.sftpPanel
val target = sftpPanel.getTarget(table) ?: return val target = sftpPanel.getTarget(table) ?: return
var isTerminate = false
/**
* 定义一个添加器,它可以自动的判断导入/拖拽行为
*/
val adder = object {
fun add(transport: Transport): Boolean {
return addTransport(
sftpPanel,
if (fromLocalSystem) attr.path.parent else null,
target,
targetWorkdir,
transport
)
}
}
if (attr.isFile) {
if (!adder.add(createTransport(attr.path, false, 0).apply { scanned() })) {
return
}
}
val queue = ArrayDeque<Transport>() val queue = ArrayDeque<Transport>()
var isTerminate = false
for (attr in attrs) { try {
walk(attr.path, object : FileVisitor<Path> {
/** override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult {
* 定义一个添加器,它可以自动的判断导入/拖拽行为 val transport = createTransport(dir, true, queue.lastOrNull()?.id ?: 0L)
*/ .apply { queue.addLast(this) }
val adder = object { if (adder.add(transport)) return FileVisitResult.CONTINUE
fun add(transport: Transport): Boolean { return FileVisitResult.TERMINATE.apply { isTerminate = true }
return addTransport(
sftpPanel,
if (fromLocalSystem) attr.path.parent else null,
target,
targetWorkdir,
transport
)
} }
}
if (attr.isFile) { override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
if (!adder.add(createTransport(attr.path, false, 0).apply { scanned() })) { if (queue.isEmpty()) return FileVisitResult.SKIP_SIBLINGS
isTerminate = true val transport = createTransport(file, false, queue.last().id).apply { scanned() }
break if (adder.add(transport)) return FileVisitResult.CONTINUE
return FileVisitResult.TERMINATE.apply { isTerminate = true }
} }
continue
}
queue.clear() override fun visitFileFailed(file: Path, exc: IOException): FileVisitResult {
return FileVisitResult.CONTINUE
try {
walk(attr.path, object : FileVisitor<Path> {
override fun preVisitDirectory(dir: Path, attrs: BasicFileAttributes): FileVisitResult {
val transport = createTransport(dir, true, queue.lastOrNull()?.id ?: 0L)
.apply { queue.addLast(this) }
if (adder.add(transport)) return FileVisitResult.CONTINUE
return FileVisitResult.TERMINATE.apply { isTerminate = true }
}
override fun visitFile(file: Path, attrs: BasicFileAttributes): FileVisitResult {
if (queue.isEmpty()) return FileVisitResult.SKIP_SIBLINGS
val transport = createTransport(file, false, queue.last().id).apply { scanned() }
if (adder.add(transport)) return FileVisitResult.CONTINUE
return FileVisitResult.TERMINATE.apply { isTerminate = true }
}
override fun visitFileFailed(file: Path, exc: IOException): FileVisitResult {
return FileVisitResult.CONTINUE
}
override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
// 标记为扫描完毕
queue.removeLast().scanned()
return FileVisitResult.CONTINUE
}
})
} catch (e: Exception) {
if (log.isErrorEnabled) {
log.error(e.message, e)
} }
isTerminate = true
}
if (isTerminate) break override fun postVisitDirectory(dir: Path, exc: IOException?): FileVisitResult {
// 标记为扫描完毕
queue.removeLast().scanned()
return FileVisitResult.CONTINUE
}
})
} catch (e: Exception) {
if (log.isErrorEnabled) {
log.error(e.message, e)
}
isTerminate = true
} }
if (isTerminate) { if (isTerminate) {
@@ -960,7 +951,11 @@ class FileSystemViewTable(
targetWorkdir: Path?, targetWorkdir: Path?,
transport: Transport transport: Transport
): Boolean { ): Boolean {
return sftpPanel.addTransport(table, sourceWorkdir, target, targetWorkdir, transport) return try {
sftpPanel.addTransport(table, sourceWorkdir, target, targetWorkdir, transport)
} catch (e: Exception) {
false
}
} }
private fun createTransport(source: Path, isDirectory: Boolean, parentId: Long): Transport { private fun createTransport(source: Path, isDirectory: Boolean, parentId: Long): Transport {

View File

@@ -12,8 +12,10 @@ import org.jdesktop.swingx.treetable.DefaultMutableTreeTableNode
import org.jdesktop.swingx.treetable.DefaultTreeTableModel import org.jdesktop.swingx.treetable.DefaultTreeTableModel
import org.jdesktop.swingx.treetable.MutableTreeTableNode import org.jdesktop.swingx.treetable.MutableTreeTableNode
import org.slf4j.LoggerFactory import org.slf4j.LoggerFactory
import java.util.*
import java.util.concurrent.locks.ReentrantLock import java.util.concurrent.locks.ReentrantLock
import javax.swing.SwingUtilities import javax.swing.SwingUtilities
import kotlin.collections.ArrayDeque
import kotlin.io.path.name import kotlin.io.path.name
import kotlin.math.abs import kotlin.math.abs
import kotlin.math.max import kotlin.math.max
@@ -27,7 +29,7 @@ class TransportTableModel(private val coroutineScope: CoroutineScope) :
val lock = ReentrantLock() val lock = ReentrantLock()
private val transports = linkedMapOf<Long, TransportTreeTableNode>() private val transports = Collections.synchronizedMap(linkedMapOf<Long, TransportTreeTableNode>())
private val reporter = SpeedReporter(coroutineScope) private val reporter = SpeedReporter(coroutineScope)
private var listeners = emptyArray<TransportListener>() private var listeners = emptyArray<TransportListener>()
private val activeTransports = linkedMapOf<Long, Job>() private val activeTransports = linkedMapOf<Long, Job>()
@@ -104,8 +106,15 @@ class TransportTableModel(private val coroutineScope: CoroutineScope) :
transports[transport.id] = newNode transports[transport.id] = newNode
if ((transports.containsKey(parentId) || p == root) && transports.containsKey(transport.id)) { if ((transports.containsKey(parentId) || p == root) && transports.containsKey(transport.id)) {
// 同步加入节点 // 主线程加入节点
SwingUtilities.invokeLater { insertNodeInto(newNode, p, p.childCount) } SwingUtilities.invokeLater {
// 因为是异步的,父节点此时可能已经被移除了
if (p == root || transports.containsKey(parentId)) {
insertNodeInto(newNode, p, p.childCount)
} else {
removeTransport(transport.id)
}
}
} }
return@withLock true return@withLock true