未验证 提交 63a57130 编写于 作者: S Skylot

refactor: load resource table nodes in one change (#1648)

上级 bc4db61e
......@@ -52,7 +52,7 @@ public class ResourceSearchProvider implements ISearchProvider {
if (cancelable.isCanceled()) {
return null;
}
JResource resNode = getNextNode();
JResource resNode = getNextResFile(cancelable);
if (resNode == null) {
return null;
}
......@@ -62,7 +62,7 @@ public class ResourceSearchProvider implements ISearchProvider {
}
pos = 0;
resQueue.removeLast();
addChildren(resQueue, resNode);
addChildren(resNode);
if (resQueue.isEmpty()) {
return null;
}
......@@ -90,39 +90,37 @@ public class ResourceSearchProvider implements ISearchProvider {
return new JResSearchNode(resNode, line.trim(), newPos);
}
private @Nullable JResource getNextNode() {
JResource node = resQueue.peekLast();
if (node == null) {
return null;
}
try {
node.loadNode();
} catch (Exception e) {
LOG.error("Error load resource node: {}", node, e);
resQueue.removeLast();
return getNextNode();
}
if (node.getType() == JResource.JResType.FILE) {
if (shouldProcess(node)) {
return node;
private @Nullable JResource getNextResFile(Cancelable cancelable) {
while (true) {
JResource node = resQueue.peekLast();
if (node == null) {
return null;
}
try {
node.loadNode();
} catch (Exception e) {
LOG.error("Error load resource node: {}", node, e);
resQueue.removeLast();
continue;
}
if (cancelable.isCanceled()) {
return null;
}
if (node.getType() == JResource.JResType.FILE) {
if (shouldProcess(node)) {
return node;
}
resQueue.removeLast();
} else {
// dir
resQueue.removeLast();
addChildren(node);
}
resQueue.removeLast();
return getNextNode();
}
// dit or root
resQueue.removeLast();
addChildren(resQueue, node);
return getNextNode();
}
private void addChildren(Deque<JResource> deque, JResource resNode) {
Enumeration<TreeNode> children = resNode.children();
while (children.hasMoreElements()) {
TreeNode node = children.nextElement();
if (node instanceof JResource) {
deque.add((JResource) node);
}
}
private void addChildren(JResource resNode) {
resQueue.addAll(resNode.getSubNodes());
}
private static Deque<JResource> initResQueue(MainWindow mw) {
......@@ -155,16 +153,15 @@ public class ResourceSearchProvider implements ISearchProvider {
}
private boolean shouldProcess(JResource resNode) {
ResourceFile resFile = resNode.getResFile();
if (resFile.getType() == ResourceType.ARSC) {
// don't check size of generated resource table, it will also skip all sub files
return anyExt || extSet.contains("xml");
}
if (!anyExt) {
String fileExt;
ResourceFile resFile = resNode.getResFile();
if (resFile.getType() == ResourceType.ARSC) {
fileExt = "xml";
} else {
fileExt = CommonFileUtils.getFileExtension(resFile.getOriginalName());
if (fileExt == null) {
return false;
}
String fileExt = CommonFileUtils.getFileExtension(resFile.getOriginalName());
if (fileExt == null) {
return false;
}
if (!extSet.contains(fileExt)) {
return false;
......
package jadx.gui.treemodel;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
......@@ -14,10 +14,10 @@ import org.jetbrains.annotations.Nullable;
import jadx.api.ICodeInfo;
import jadx.api.ICodeWriter;
import jadx.api.ResourceFile;
import jadx.api.ResourceFileContent;
import jadx.api.ResourceType;
import jadx.api.ResourcesLoader;
import jadx.api.impl.SimpleCodeInfo;
import jadx.core.utils.ListUtils;
import jadx.core.utils.Utils;
import jadx.core.xmlgen.ResContainer;
import jadx.gui.ui.TabbedPane;
......@@ -26,6 +26,7 @@ import jadx.gui.ui.panel.ContentPanel;
import jadx.gui.ui.panel.ImagePanel;
import jadx.gui.utils.NLS;
import jadx.gui.utils.UiUtils;
import jadx.gui.utils.res.ResTableHelper;
public class JResource extends JLoadableNode {
private static final long serialVersionUID = -201018424302612434L;
......@@ -41,6 +42,10 @@ public class JResource extends JLoadableNode {
private static final ImageIcon JAVA_ICON = UiUtils.openSvgIcon("nodes/java");
private static final ImageIcon UNKNOWN_ICON = UiUtils.openSvgIcon("nodes/unknown");
public static final Comparator<JResource> RESOURCES_COMPARATOR =
Comparator.<JResource>comparingInt(r -> r.type.ordinal())
.thenComparing(JResource::getName, String.CASE_INSENSITIVE_ORDER);
public enum JResType {
ROOT,
DIR,
......@@ -49,11 +54,11 @@ public class JResource extends JLoadableNode {
private final transient String name;
private final transient String shortName;
private final transient List<JResource> files = new ArrayList<>(1);
private final transient JResType type;
private final transient ResourceFile resFile;
private transient boolean loaded;
private transient volatile boolean loaded;
private transient List<JResource> subNodes = Collections.emptyList();
private transient ICodeInfo content;
public JResource(ResourceFile resFile, String name, JResType type) {
......@@ -69,7 +74,8 @@ public class JResource extends JLoadableNode {
}
public final void update() {
if (files.isEmpty()) {
removeAllChildren();
if (Utils.isEmpty(subNodes)) {
if (type == JResType.DIR || type == JResType.ROOT
|| resFile.getType() == ResourceType.ARSC) {
// fake leaf to force show expand button
......@@ -77,14 +83,7 @@ public class JResource extends JLoadableNode {
add(new TextNode(NLS.str("tree.loading")));
}
} else {
removeAllChildren();
Comparator<JResource> typeComparator = Comparator.comparingInt(r -> r.type.ordinal());
Comparator<JResource> nameComparator = Comparator.comparing(JResource::getName, String.CASE_INSENSITIVE_ORDER);
files.sort(typeComparator.thenComparing(nameComparator));
for (JResource res : files) {
for (JResource res : subNodes) {
res.update();
add(res);
}
......@@ -106,8 +105,23 @@ public class JResource extends JLoadableNode {
return type;
}
public List<JResource> getFiles() {
return files;
public List<JResource> getSubNodes() {
return subNodes;
}
public void addSubNode(JResource node) {
subNodes = ListUtils.safeAdd(subNodes, node);
}
public void sortSubNodes() {
sortResNodes(subNodes);
}
private static void sortResNodes(List<JResource> nodes) {
if (Utils.notEmpty(nodes)) {
nodes.forEach(JResource::sortSubNodes);
nodes.sort(RESOURCES_COMPARATOR);
}
}
@Override
......@@ -145,9 +159,9 @@ public class JResource extends JLoadableNode {
}
if (rc.getDataType() == ResContainer.DataType.RES_TABLE) {
ICodeInfo codeInfo = loadCurrentSingleRes(rc);
for (ResContainer subFile : rc.getSubFiles()) {
loadSubNodes(this, subFile, 1);
}
List<JResource> nodes = ResTableHelper.buildTree(rc);
sortResNodes(nodes);
subNodes = nodes;
return codeInfo;
}
// single node
......@@ -178,47 +192,6 @@ public class JResource extends JLoadableNode {
}
}
private void loadSubNodes(JResource root, ResContainer rc, int depth) {
String resName = rc.getName();
String[] path = resName.split("/");
String resShortName = path.length == 0 ? resName : path[path.length - 1];
ICodeInfo code = rc.getText();
ResourceFileContent fileContent = new ResourceFileContent(resShortName, ResourceType.XML, code);
addPath(path, root, new JResource(fileContent, resName, resShortName, JResType.FILE));
for (ResContainer subFile : rc.getSubFiles()) {
loadSubNodes(root, subFile, depth + 1);
}
}
private static void addPath(String[] path, JResource root, JResource jResource) {
if (path.length == 1) {
root.getFiles().add(jResource);
return;
}
JResource currentRoot = root;
int last = path.length - 1;
for (int i = 0; i <= last; i++) {
String f = path[i];
if (i == last) {
currentRoot.getFiles().add(jResource);
} else {
currentRoot = getResDir(currentRoot, f);
}
}
}
private static JResource getResDir(JResource root, String dirName) {
for (JResource file : root.getFiles()) {
if (file.getName().equals(dirName)) {
return file;
}
}
JResource resDir = new JResource(null, dirName, JResType.DIR);
root.getFiles().add(resDir);
return resDir;
}
@Override
public String getSyntaxName() {
if (resFile == null) {
......
......@@ -68,17 +68,18 @@ public class JRoot extends JNode {
} else {
subRF = new JResource(rf, rf.getDeobfName(), name, JResType.FILE);
}
curRf.getFiles().add(subRF);
curRf.addSubNode(subRF);
}
curRf = subRF;
}
}
root.sortSubNodes();
root.update();
return root;
}
private JResource getResourceByName(JResource rf, String name) {
for (JResource sub : rf.getFiles()) {
for (JResource sub : rf.getSubNodes()) {
if (sub.getName().equals(name)) {
return sub;
}
......
......@@ -375,7 +375,7 @@ public class UiUtils {
try {
SwingUtilities.invokeAndWait(runnable);
} catch (InterruptedException e) {
LOG.warn("UI thread interrupted", e);
LOG.warn("UI thread interrupted, runnable: {}", runnable, e);
} catch (Exception e) {
throw new RuntimeException(e);
}
......
package jadx.gui.utils.res;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.jetbrains.annotations.Nullable;
import jadx.api.ICodeInfo;
import jadx.api.ResourceFileContent;
import jadx.api.ResourceType;
import jadx.core.xmlgen.ResContainer;
import jadx.gui.treemodel.JResource;
public class ResTableHelper {
/**
* Build UI tree for resource table container.
*
* @return root nodes
*/
public static List<JResource> buildTree(ResContainer resTable) {
ResTableHelper resTableHelper = new ResTableHelper();
resTableHelper.process(resTable);
return resTableHelper.roots;
}
private final List<JResource> roots = new ArrayList<>();
private final Map<String, JResource> dirs = new HashMap<>();
private ResTableHelper() {
}
private void process(ResContainer resTable) {
for (ResContainer subFile : resTable.getSubFiles()) {
loadSubNodes(subFile);
}
}
private void loadSubNodes(ResContainer rc) {
String resName = rc.getName();
int split = resName.lastIndexOf('/');
String dir;
String name;
if (split == -1) {
dir = null;
name = resName;
} else {
dir = resName.substring(0, split);
name = resName.substring(split + 1);
}
ICodeInfo code = rc.getText();
ResourceFileContent fileContent = new ResourceFileContent(name, ResourceType.XML, code);
JResource resFile = new JResource(fileContent, resName, name, JResource.JResType.FILE);
addResFile(dir, resFile);
for (ResContainer subFile : rc.getSubFiles()) {
loadSubNodes(subFile);
}
}
private void addResFile(@Nullable String dir, JResource resFile) {
if (dir == null) {
roots.add(resFile);
return;
}
JResource dirRes = dirs.get(dir);
if (dirRes != null) {
dirRes.addSubNode(resFile);
return;
}
JResource parentDir = null;
int splitPos = -1;
while (true) {
int prevStart = splitPos + 1;
splitPos = dir.indexOf('/', prevStart);
boolean last = splitPos == -1;
String path = last ? dir : dir.substring(0, splitPos);
JResource curDir = dirs.get(path);
if (curDir == null) {
String dirName = last ? dir.substring(prevStart) : dir.substring(prevStart, splitPos);
curDir = new JResource(null, dirName, JResource.JResType.DIR);
dirs.put(path, curDir);
if (parentDir == null) {
roots.add(curDir);
} else {
parentDir.addSubNode(curDir);
}
}
if (last) {
curDir.addSubNode(resFile);
return;
}
parentDir = curDir;
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册