protected void refreshChildren(TaskMonitor monitor)
			throws CancelledException {
		GFile f = getGFile();
		if (f == null || !isLoaded() || isLeaf()) {
			return;
		}
		Map<FSRL, GFile> currentFiles = getListing(f);

		int changeCount = 0;
		boolean cryptoCausesFullRefresh = true;
		boolean flagFSBRootNodeWithCryptoUpdate = false;

		List<GTreeNode> newNodes = new ArrayList<>();
		List<GTreeNode> currentChildren = new ArrayList<>(children());
		for (GTreeNode oldNode : currentChildren) {
			monitor.increment();
			if (oldNode instanceof FSBNode fsbNode) {
				GFile currentFile = currentFiles.get(fsbNode.getFSRL());
				if (fileMatchesNode(currentFile, fsbNode)) {
					boolean checkPwUpdate = cryptoCausesFullRefresh &&
						fsbNode instanceof FSBFileNode fileNode && fileNode.hasMissingPassword();

					fsbNode.refreshNode(monitor);

					flagFSBRootNodeWithCryptoUpdate |= checkPwUpdate &&
						fsbNode instanceof FSBFileNode fileNode && !fileNode.hasMissingPassword();

					newNodes.add(fsbNode); // port old node over to new list
					currentFiles.remove(fsbNode.getFSRL());
				}
				else {
					// by not adding to newNodes, the old node will disappear
					changeCount++;
				}
			}
		}

		// add any remaining GFiles as new nodes
		changeCount += currentFiles.size();
		currentFiles.values()
				.stream()
				.map(f1 -> createNodeFromFile(f1, monitor))
				.forEach(newNodes::add);

		Collections.sort(newNodes, FSBNODE_NAME_TYPE_COMPARATOR);

		FSBRootNode fsbRootNode;
		if (flagFSBRootNodeWithCryptoUpdate && (fsbRootNode = getFSBRootNode()) != null) {
			fsbRootNode.setCryptoStatusUpdated(true);
		}

		if (changeCount > 0) {
			setChildren(newNodes);
		}
	}
Returns the extension of this node's name, or "" if none

@return extension of this node's name, or "" if none
Ghidra/Features/Base/src/main/java/ghidra/plugins/fsbrowser/FSBNode.java