mirror of
https://github.com/NationalSecurityAgency/ghidra.git
synced 2025-10-06 03:50:02 +02:00
Merge remote-tracking branch 'origin/GP-4017_dev747368_pdb_symbolserver_fsrl'
This commit is contained in:
commit
7fa03c9719
8 changed files with 350 additions and 19 deletions
|
@ -19,6 +19,8 @@ import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import ghidra.plugin.importer.ProgramMappingService;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.SystemUtilities;
|
import ghidra.util.SystemUtilities;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -63,6 +65,27 @@ import ghidra.util.SystemUtilities;
|
||||||
public class FSRL {
|
public class FSRL {
|
||||||
public static final String PARAM_MD5 = "MD5";
|
public static final String PARAM_MD5 = "MD5";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link FSRL} stored in a {@link Program}'s properties, or null if not present
|
||||||
|
* or malformed.
|
||||||
|
*
|
||||||
|
* @param program {@link Program}
|
||||||
|
* @return {@link FSRL} from program's properties, or null if not present or invalid
|
||||||
|
*/
|
||||||
|
public static FSRL fromProgram(Program program) {
|
||||||
|
String fsrlStr = program.getOptions(Program.PROGRAM_INFO)
|
||||||
|
.getString(ProgramMappingService.PROGRAM_SOURCE_FSRL, null);
|
||||||
|
if (fsrlStr != null) {
|
||||||
|
try {
|
||||||
|
return FSRL.fromString(fsrlStr);
|
||||||
|
}
|
||||||
|
catch (MalformedURLException e) {
|
||||||
|
// fall thru, return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a {@link FSRL} from a raw string. The parent portions of the FSRL
|
* Creates a {@link FSRL} from a raw string. The parent portions of the FSRL
|
||||||
* are not intern()'d so will not be shared with other FSRL instances.
|
* are not intern()'d so will not be shared with other FSRL instances.
|
||||||
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package ghidra.formats.gfilesystem;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An {@link InputStream} wrapper that keeps a {@link FileSystemRef} pinned.
|
||||||
|
*/
|
||||||
|
public class RefdInputStream extends InputStream {
|
||||||
|
|
||||||
|
private FileSystemRef fsRef;
|
||||||
|
private InputStream delegate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link RefdInputStream}.
|
||||||
|
*
|
||||||
|
* @param fsRef {@link FileSystemRef}
|
||||||
|
* @param delegate the wrapped {@link InputStream}
|
||||||
|
*/
|
||||||
|
public RefdInputStream(FileSystemRef fsRef, InputStream delegate) {
|
||||||
|
this.fsRef = fsRef;
|
||||||
|
this.delegate = delegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void close() throws IOException {
|
||||||
|
if (fsRef != null) {
|
||||||
|
fsRef.close();
|
||||||
|
fsRef = null;
|
||||||
|
}
|
||||||
|
delegate.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int available() throws IOException {
|
||||||
|
return delegate.available();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read() throws IOException {
|
||||||
|
return delegate.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b) throws IOException {
|
||||||
|
return delegate.read(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int read(byte[] b, int off, int len) throws IOException {
|
||||||
|
return delegate.read(b, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] readAllBytes() throws IOException {
|
||||||
|
return delegate.readAllBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int readNBytes(byte[] b, int off, int len) throws IOException {
|
||||||
|
return delegate.readNBytes(b, off, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public byte[] readNBytes(int len) throws IOException {
|
||||||
|
return delegate.readNBytes(len);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void mark(int readlimit) {
|
||||||
|
delegate.mark(readlimit);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean markSupported() {
|
||||||
|
return delegate.markSupported();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long skip(long n) throws IOException {
|
||||||
|
return delegate.skip(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized void reset() throws IOException {
|
||||||
|
delegate.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long transferTo(OutputStream out) throws IOException {
|
||||||
|
return delegate.transferTo(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void skipNBytes(long n) throws IOException {
|
||||||
|
delegate.skipNBytes(n);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,161 @@
|
||||||
|
/* ###
|
||||||
|
* IP: GHIDRA
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
package pdb.symbolserver;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.nio.file.Files;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
|
import ghidra.app.util.bin.ByteProvider;
|
||||||
|
import ghidra.formats.gfilesystem.*;
|
||||||
|
import ghidra.util.exception.CancelledException;
|
||||||
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Companion to the {@link SameDirSymbolStore}, handles the case where the imported binary
|
||||||
|
* was located in a container file (eg. zip file).
|
||||||
|
* <p>
|
||||||
|
* Instances of this class are conditionally created by the
|
||||||
|
* {@link SameDirSymbolStore#createInstance(String, SymbolServerInstanceCreatorContext) registry factory method}
|
||||||
|
* when it detects that the imported binary's {@link FSRL} isn't a simple local file.
|
||||||
|
*/
|
||||||
|
public class ContainerFileSymbolServer implements SymbolServer {
|
||||||
|
|
||||||
|
private final FileSystemService fsService;
|
||||||
|
private final FSRLRoot fsFSRL;
|
||||||
|
private final String subdir;
|
||||||
|
|
||||||
|
public ContainerFileSymbolServer(FSRL programFSRL) {
|
||||||
|
this.fsFSRL = programFSRL.getFS();
|
||||||
|
this.subdir = FilenameUtils.getFullPath(programFSRL.getPath());
|
||||||
|
this.fsService = FileSystemService.getInstance();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return ".";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescriptiveName() {
|
||||||
|
return SameDirSymbolStore.PROGRAMS_IMPORT_LOCATION_DESCRIPTION_STR + " - " +
|
||||||
|
fsFSRL.toPrettyFullpathString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(TaskMonitor monitor) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean exists(String filename, TaskMonitor monitor) {
|
||||||
|
try (RefdFile file = getFile(filename, monitor)) {
|
||||||
|
return file != null;
|
||||||
|
}
|
||||||
|
catch (IOException e1) {
|
||||||
|
// fall thru
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private RefdFile getFile(String filename, TaskMonitor monitor) {
|
||||||
|
try (FileSystemRef fsRef = fsService.getFilesystem(fsFSRL, monitor)) {
|
||||||
|
if (fsRef != null) {
|
||||||
|
GFileSystem fs = fsRef.getFilesystem();
|
||||||
|
String path = FSUtilities.appendPath(subdir, filename);
|
||||||
|
GFile file = fs.lookup(path);
|
||||||
|
if (file != null && !file.isDirectory()) {
|
||||||
|
return new RefdFile(fsRef.dup(), file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException | CancelledException e) {
|
||||||
|
// fall thru
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<SymbolFileLocation> find(SymbolFileInfo fileInfo, Set<FindOption> findOptions,
|
||||||
|
TaskMonitor monitor) {
|
||||||
|
|
||||||
|
try (RefdFile fref = getFile(fileInfo.getName(), monitor)) {
|
||||||
|
// TODO: need to be able to read info from candidate pdb file using some type of stream
|
||||||
|
if (fref != null) {
|
||||||
|
GFile file = fref.file;
|
||||||
|
GFileSystem fs = file.getFilesystem();
|
||||||
|
try (ByteProvider bp = fs.getByteProvider(file, monitor)) {
|
||||||
|
File tmpPdbFile = fsService.createPlaintextTempFile(bp, "temp_pdb", monitor);
|
||||||
|
File tmpPdbDir =
|
||||||
|
Files.createTempDirectory(tmpPdbFile.getParentFile().toPath(), "temp_pdb")
|
||||||
|
.toFile();
|
||||||
|
File destPdbFile = new File(tmpPdbDir, file.getName()).getCanonicalFile();
|
||||||
|
if (!destPdbFile.getParentFile().equals(tmpPdbDir)) {
|
||||||
|
throw new IOException("Bad filename: " + destPdbFile);
|
||||||
|
}
|
||||||
|
if (!tmpPdbFile.renameTo(destPdbFile)) {
|
||||||
|
throw new IOException(
|
||||||
|
"Unable to move file: " + tmpPdbFile + " to " + destPdbFile);
|
||||||
|
}
|
||||||
|
SymbolFileInfo foundInfo = SymbolFileInfo.fromFile(destPdbFile, monitor);
|
||||||
|
destPdbFile.delete();
|
||||||
|
tmpPdbDir.delete();
|
||||||
|
return List.of(new SymbolFileLocation(file.getName(), this, foundInfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (IOException | CancelledException e) {
|
||||||
|
// fall thru
|
||||||
|
}
|
||||||
|
return List.of();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public SymbolServerInputStream getFileStream(String filename, TaskMonitor monitor)
|
||||||
|
throws IOException {
|
||||||
|
try (RefdFile fref = getFile(filename, monitor)) {
|
||||||
|
if (fref != null) {
|
||||||
|
GFile file = fref.file;
|
||||||
|
InputStream is = file.getFilesystem().getInputStream(file, monitor);
|
||||||
|
is = new RefdInputStream(fref.fsRef.dup(), is);
|
||||||
|
return new SymbolServerInputStream(is, file.getLength());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (CancelledException e) {
|
||||||
|
// fall thru
|
||||||
|
}
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFileLocation(String filename) {
|
||||||
|
return fsFSRL.withPath(filename).toPrettyFullpathString();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isLocal() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ContainerFileSymbolServer: [ fsrl: %s ]".formatted(fsFSRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -18,6 +18,7 @@ package pdb.symbolserver;
|
||||||
import java.io.*;
|
import java.io.*;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
import ghidra.formats.gfilesystem.FSRL;
|
||||||
import ghidra.util.task.TaskMonitor;
|
import ghidra.util.task.TaskMonitor;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,6 +62,23 @@ public class SameDirSymbolStore implements SymbolStore {
|
||||||
return symbolFileLocation;
|
return symbolFileLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@link SymbolServer} for the "Program's Import Location" item. May return either
|
||||||
|
* a {@link SameDirSymbolStore} instance, or a {@link ContainerFileSymbolServer}.
|
||||||
|
*
|
||||||
|
* @param locationString will be "."
|
||||||
|
* @param context {@link SymbolServerInstanceCreatorContext}
|
||||||
|
* @return new {@link SymbolServer}
|
||||||
|
*/
|
||||||
|
public static SymbolServer createInstance(String locationString,
|
||||||
|
SymbolServerInstanceCreatorContext context) {
|
||||||
|
FSRL programFSRL = context.getProgramFSRL();
|
||||||
|
if (programFSRL != null && programFSRL.getNestingDepth() != 1) {
|
||||||
|
return new ContainerFileSymbolServer(programFSRL);
|
||||||
|
}
|
||||||
|
return new SameDirSymbolStore(context.getRootDir());
|
||||||
|
}
|
||||||
|
|
||||||
private final File rootDir;
|
private final File rootDir;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -17,6 +17,11 @@ package pdb.symbolserver;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
|
import org.apache.commons.io.FilenameUtils;
|
||||||
|
|
||||||
|
import ghidra.formats.gfilesystem.FSRL;
|
||||||
|
import ghidra.program.model.listing.Program;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Context for the {@link SymbolServerInstanceCreatorRegistry} when creating new
|
* Context for the {@link SymbolServerInstanceCreatorRegistry} when creating new
|
||||||
* {@link SymbolServer} instances.
|
* {@link SymbolServer} instances.
|
||||||
|
@ -30,6 +35,7 @@ import java.io.File;
|
||||||
*/
|
*/
|
||||||
public class SymbolServerInstanceCreatorContext {
|
public class SymbolServerInstanceCreatorContext {
|
||||||
private final File rootDir;
|
private final File rootDir;
|
||||||
|
private final FSRL programFSRL;
|
||||||
private final SymbolServerInstanceCreatorRegistry symbolServerInstanceCreatorRegistry;
|
private final SymbolServerInstanceCreatorRegistry symbolServerInstanceCreatorRegistry;
|
||||||
|
|
||||||
SymbolServerInstanceCreatorContext(
|
SymbolServerInstanceCreatorContext(
|
||||||
|
@ -37,9 +43,16 @@ public class SymbolServerInstanceCreatorContext {
|
||||||
this(null, symbolServerInstanceCreatorRegistry);
|
this(null, symbolServerInstanceCreatorRegistry);
|
||||||
}
|
}
|
||||||
|
|
||||||
SymbolServerInstanceCreatorContext(File rootDir,
|
SymbolServerInstanceCreatorContext(Program program,
|
||||||
SymbolServerInstanceCreatorRegistry symbolServerInstanceCreatorRegistry) {
|
SymbolServerInstanceCreatorRegistry symbolServerInstanceCreatorRegistry) {
|
||||||
this.rootDir = rootDir;
|
if (program != null) {
|
||||||
|
this.programFSRL = FSRL.fromProgram(program);
|
||||||
|
this.rootDir = new File(FilenameUtils.getFullPath(program.getExecutablePath()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.programFSRL = null;
|
||||||
|
this.rootDir = null;
|
||||||
|
}
|
||||||
this.symbolServerInstanceCreatorRegistry = symbolServerInstanceCreatorRegistry;
|
this.symbolServerInstanceCreatorRegistry = symbolServerInstanceCreatorRegistry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,4 +74,13 @@ public class SymbolServerInstanceCreatorContext {
|
||||||
return rootDir;
|
return rootDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the FSRL of imported binary.
|
||||||
|
*
|
||||||
|
* @return {@link FSRL} of the imported binary, or null if not present
|
||||||
|
*/
|
||||||
|
public FSRL getProgramFSRL() {
|
||||||
|
return programFSRL;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,13 +15,10 @@
|
||||||
*/
|
*/
|
||||||
package pdb.symbolserver;
|
package pdb.symbolserver;
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Predicate;
|
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
import java.util.*;
|
||||||
import org.apache.commons.io.FilenameUtils;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
import ghidra.program.model.listing.Program;
|
import ghidra.program.model.listing.Program;
|
||||||
import ghidra.util.Msg;
|
import ghidra.util.Msg;
|
||||||
|
@ -163,8 +160,7 @@ public class SymbolServerInstanceCreatorRegistry {
|
||||||
* @return new {@link SymbolServerInstanceCreatorContext}
|
* @return new {@link SymbolServerInstanceCreatorContext}
|
||||||
*/
|
*/
|
||||||
public SymbolServerInstanceCreatorContext getContext(Program program) {
|
public SymbolServerInstanceCreatorContext getContext(Program program) {
|
||||||
File exeLocation = new File(FilenameUtils.getFullPath(program.getExecutablePath()));
|
return new SymbolServerInstanceCreatorContext(program, this);
|
||||||
return new SymbolServerInstanceCreatorContext(exeLocation, this);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void registerDefaultSymbolServerInstanceCreators() {
|
private void registerDefaultSymbolServerInstanceCreators() {
|
||||||
|
@ -173,7 +169,7 @@ public class SymbolServerInstanceCreatorRegistry {
|
||||||
registerSymbolServerInstanceCreator(100, HttpSymbolServer::isHttpSymbolServerLocation,
|
registerSymbolServerInstanceCreator(100, HttpSymbolServer::isHttpSymbolServerLocation,
|
||||||
(loc, context) -> new HttpSymbolServer(URI.create(loc)));
|
(loc, context) -> new HttpSymbolServer(URI.create(loc)));
|
||||||
registerSymbolServerInstanceCreator(200, SameDirSymbolStore::isSameDirLocation,
|
registerSymbolServerInstanceCreator(200, SameDirSymbolStore::isSameDirLocation,
|
||||||
(loc, context) -> new SameDirSymbolStore(context.getRootDir()));
|
SameDirSymbolStore::createInstance);
|
||||||
registerSymbolServerInstanceCreator(300, LocalSymbolStore::isLocalSymbolStoreLocation,
|
registerSymbolServerInstanceCreator(300, LocalSymbolStore::isLocalSymbolStoreLocation,
|
||||||
(loc, context) -> new LocalSymbolStore(new File(loc)));
|
(loc, context) -> new LocalSymbolStore(new File(loc)));
|
||||||
}
|
}
|
||||||
|
|
|
@ -787,10 +787,9 @@ public class LoadPdbDialog extends DialogComponentProvider {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
SymbolServer symbolServer = symbolFileLocation.getSymbolServer();
|
SymbolServer symbolServer = symbolFileLocation.getSymbolServer();
|
||||||
if (!(symbolServer instanceof SymbolStore)) {
|
if (!(symbolServer instanceof SymbolStore symbolStore)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
SymbolStore symbolStore = (SymbolStore) symbolServer;
|
|
||||||
File file = symbolStore.getFile(symbolFileLocation.getPath());
|
File file = symbolStore.getFile(symbolFileLocation.getPath());
|
||||||
return SymbolStore.isCompressedFilename(file.getName()) ? null : file;
|
return SymbolStore.isCompressedFilename(file.getName()) ? null : file;
|
||||||
}
|
}
|
||||||
|
|
|
@ -91,10 +91,9 @@ class SymbolServerPanel extends JPanel {
|
||||||
|
|
||||||
SymbolServerService temporarySymbolServerService =
|
SymbolServerService temporarySymbolServerService =
|
||||||
PdbPlugin.getSymbolServerService(symbolServerInstanceCreatorContext);
|
PdbPlugin.getSymbolServerService(symbolServerInstanceCreatorContext);
|
||||||
if (temporarySymbolServerService.getSymbolStore() instanceof LocalSymbolStore) {
|
if (temporarySymbolServerService
|
||||||
setSymbolStorageLocation(
|
.getSymbolStore() instanceof LocalSymbolStore tempLocalSymbolStore) {
|
||||||
((LocalSymbolStore) temporarySymbolServerService.getSymbolStore()).getRootDir(),
|
setSymbolStorageLocation(tempLocalSymbolStore.getRootDir(), false);
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
tableModel.addSymbolServers(temporarySymbolServerService.getSymbolServers());
|
tableModel.addSymbolServers(temporarySymbolServerService.getSymbolServers());
|
||||||
setConfigChanged(false);
|
setConfigChanged(false);
|
||||||
|
@ -368,8 +367,8 @@ class SymbolServerPanel extends JPanel {
|
||||||
SymbolServer symbolServer =
|
SymbolServer symbolServer =
|
||||||
symbolServerInstanceCreatorContext.getSymbolServerInstanceCreatorRegistry()
|
symbolServerInstanceCreatorContext.getSymbolServerInstanceCreatorRegistry()
|
||||||
.newSymbolServer(firstSearchPath, symbolServerInstanceCreatorContext);
|
.newSymbolServer(firstSearchPath, symbolServerInstanceCreatorContext);
|
||||||
if (symbolServer instanceof LocalSymbolStore &&
|
if (symbolServer instanceof LocalSymbolStore localSymbolStore &&
|
||||||
((LocalSymbolStore) symbolServer).isValid()) {
|
localSymbolStore.isValid()) {
|
||||||
int choice = OptionDialog.showYesNoCancelDialog(this, "Set Symbol Storage Location",
|
int choice = OptionDialog.showYesNoCancelDialog(this, "Set Symbol Storage Location",
|
||||||
"Set symbol storage location to " + firstSearchPath + "?");
|
"Set symbol storage location to " + firstSearchPath + "?");
|
||||||
if (choice == OptionDialog.CANCEL_OPTION) {
|
if (choice == OptionDialog.CANCEL_OPTION) {
|
||||||
|
@ -378,7 +377,7 @@ class SymbolServerPanel extends JPanel {
|
||||||
if (choice == OptionDialog.YES_OPTION) {
|
if (choice == OptionDialog.YES_OPTION) {
|
||||||
symbolServerPaths.remove(0);
|
symbolServerPaths.remove(0);
|
||||||
configChanged = true;
|
configChanged = true;
|
||||||
setSymbolStorageLocation(((LocalSymbolStore) symbolServer).getRootDir(), true);
|
setSymbolStorageLocation(localSymbolStore.getRootDir(), true);
|
||||||
symbolStorageLocationTextField.setText(symbolServer.getName());
|
symbolStorageLocationTextField.setText(symbolServer.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue