GP-3081 - Fixed help build for external plugins

This commit is contained in:
dragonmacher 2023-02-13 18:49:23 -05:00
parent 1de4b32e51
commit f4a60244b3
6 changed files with 61 additions and 41 deletions

View file

@ -22,11 +22,12 @@ import java.util.Map.Entry;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import org.apache.commons.lang3.StringUtils;
import generic.jar.ResourceFile; import generic.jar.ResourceFile;
import ghidra.framework.ApplicationProperties; import ghidra.framework.ApplicationProperties;
import ghidra.framework.GModule; import ghidra.framework.GModule;
import ghidra.util.SystemUtilities; import ghidra.util.SystemUtilities;
import util.CollectionUtils;
import utility.application.ApplicationLayout; import utility.application.ApplicationLayout;
import utility.application.ApplicationUtilities; import utility.application.ApplicationUtilities;
import utility.module.ClasspathFilter; import utility.module.ClasspathFilter;
@ -39,6 +40,14 @@ import utility.module.ModuleUtilities;
*/ */
public class GenericApplicationLayout extends ApplicationLayout { public class GenericApplicationLayout extends ApplicationLayout {
/**
* System property that allows specification of additional application root dirs. This is used
* for clients that build plugins external to an installation. The property will be parsed
* using {@link File#pathSeparator}, allowing for multiple values.
*/
private static final String ADDITIONAL_APPLICATION_ROOT_DIRS =
"ADDITIONAL_APPLICATION_ROOT_DIRS";
private static final String NO_RELEASE_NAME = "NO_RELEASE"; private static final String NO_RELEASE_NAME = "NO_RELEASE";
/** Dev mode main source bin dir pattern */ /** Dev mode main source bin dir pattern */
@ -92,19 +101,10 @@ public class GenericApplicationLayout extends ApplicationLayout {
} }
// Modules // Modules
if (SystemUtilities.isInDevelopmentMode()) { Collection<ResourceFile> moduleRoots =
ModuleUtilities.findModuleRootDirectories(applicationRootDirs);
// In development mode we rely on the IDE's classpath to determine which modules to modules =
// include, as opposed to scanning the filesystem. This prevents unrelated modules ModuleUtilities.findModules(applicationRootDirs, moduleRoots, new ClasspathFilter());
// from being used.
modules = ModuleUtilities.findModules(applicationRootDirs,
ModuleUtilities.findModuleRootDirectories(applicationRootDirs),
new ClasspathFilter());
}
else {
modules = ModuleUtilities.findModules(applicationRootDirs, applicationRootDirs);
}
// User directories // User directories
userTempDir = ApplicationUtilities.getDefaultUserTempDir(applicationProperties); userTempDir = ApplicationUtilities.getDefaultUserTempDir(applicationProperties);
@ -160,17 +160,33 @@ public class GenericApplicationLayout extends ApplicationLayout {
} }
/** /**
* Get the default list of Application directories. In repo-based * Get the default list of Application directories. In repo-based development mode this
* development mode this includes the root Ghidra directory within each repo. * includes the root Ghidra directory within each repo. When not in development mode, the
* When not in development mode, the requirement is that the current working * requirement is that the current working directory correspond to the installation root. The
* directory correspond to the installation root. The first entry will be * first entry will be the primary root in both cases.
* the primary root in both cases.
* @return root directories * @return root directories
*/ */
public static Collection<ResourceFile> getDefaultApplicationRootDirs() { public static Collection<ResourceFile> getDefaultApplicationRootDirs() {
Set<ResourceFile> results = new HashSet<>();
String additionalRootsProperty = System.getProperty(ADDITIONAL_APPLICATION_ROOT_DIRS);
if (!StringUtils.isBlank(additionalRootsProperty)) {
String[] paths = additionalRootsProperty.split(File.pathSeparator);
for (String path : paths) {
ResourceFile file = new ResourceFile(path);
results.add(file);
}
}
if (SystemUtilities.isInDevelopmentMode()) { if (SystemUtilities.isInDevelopmentMode()) {
return ApplicationUtilities.findDefaultApplicationRootDirs(); Collection<ResourceFile> defaultRoots =
ApplicationUtilities.findDefaultApplicationRootDirs();
results.addAll(defaultRoots);
} }
return CollectionUtils.asList(new ResourceFile(System.getProperty("user.dir"))); else {
results.add(new ResourceFile(System.getProperty("user.dir")));
}
return results;
} }
} }

View file

@ -488,7 +488,7 @@ public class HelpBuildUtils {
debug("Exception loading filesystem for uri: " + uri + "\n\t" + e1.getMessage()); debug("Exception loading filesystem for uri: " + uri + "\n\t" + e1.getMessage());
} }
} }
return Paths.get(uri); return null;
} }
/** /**

View file

@ -17,11 +17,10 @@ package help.validator;
import java.io.IOException; import java.io.IOException;
import java.net.URISyntaxException; import java.net.URISyntaxException;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*; import java.util.*;
import ghidra.util.exception.AssertException;
import help.HelpBuildUtils; import help.HelpBuildUtils;
import help.validator.location.HelpModuleLocation; import help.validator.location.HelpModuleLocation;
import help.validator.model.HREF; import help.validator.model.HREF;
@ -30,7 +29,8 @@ import help.validator.model.IMG;
public class ReferenceTagProcessor extends TagProcessor { public class ReferenceTagProcessor extends TagProcessor {
private static final String EOL = System.getProperty("line.separator"); private static final String EOL = System.getProperty("line.separator");
private static final String STYLESHEET_FILENAME = "DefaultStyle.css"; private static final String SHARED_STYLESHEET_NAME = "help/shared/DefaultStyle.css";
private static final Path SHARED_STYLESHEET_PATH = Paths.get(SHARED_STYLESHEET_NAME);
private Path htmlFile; private Path htmlFile;
private Set<Path> styleSheets = new HashSet<>(); private Set<Path> styleSheets = new HashSet<>();
@ -38,7 +38,6 @@ public class ReferenceTagProcessor extends TagProcessor {
private boolean readingTitle = false; private boolean readingTitle = false;
private final StringBuffer errors = new StringBuffer(); private final StringBuffer errors = new StringBuffer();
private final Path defaultStyleSheet;
private final AnchorManager anchorManager; private final AnchorManager anchorManager;
private final HelpModuleLocation help; private final HelpModuleLocation help;
private int errorCount; private int errorCount;
@ -46,13 +45,6 @@ public class ReferenceTagProcessor extends TagProcessor {
public ReferenceTagProcessor(HelpModuleLocation help, AnchorManager anchorManager) { public ReferenceTagProcessor(HelpModuleLocation help, AnchorManager anchorManager) {
this.help = help; this.help = help;
this.anchorManager = anchorManager; this.anchorManager = anchorManager;
Path sharedHelpDir = HelpBuildUtils.getSharedHelpDirectory();
defaultStyleSheet = sharedHelpDir.resolve(Path.of(STYLESHEET_FILENAME));
if (Files.notExists(defaultStyleSheet)) {
throw new AssertException("Cannot find expected stylesheet: " + defaultStyleSheet);
}
} }
@Override @Override
@ -122,10 +114,17 @@ public class ReferenceTagProcessor extends TagProcessor {
String href = tagAttributes.get("href"); String href = tagAttributes.get("href");
if (href != null) { if (href != null) {
// The user has linked to the system stylesheet; no need to resolve
if (SHARED_STYLESHEET_NAME.equals(href)) {
styleSheets.add(SHARED_STYLESHEET_PATH);
}
else {
Path css = HelpBuildUtils.getFile(htmlFile, href); Path css = HelpBuildUtils.getFile(htmlFile, href);
css = css.normalize(); css = css.normalize();
styleSheets.add(css); // validated later styleSheets.add(css); // validated later
} }
}
// } // }
} }
} }
@ -175,7 +174,7 @@ public class ReferenceTagProcessor extends TagProcessor {
boolean hasDefaultStyleSheet = false; boolean hasDefaultStyleSheet = false;
for (Path ss : styleSheets) { for (Path ss : styleSheets) {
if (defaultStyleSheet.equals(ss)) { if (SHARED_STYLESHEET_PATH.equals(ss)) {
hasDefaultStyleSheet = true; hasDefaultStyleSheet = true;
break; break;
} }
@ -183,7 +182,7 @@ public class ReferenceTagProcessor extends TagProcessor {
if (!hasDefaultStyleSheet) { if (!hasDefaultStyleSheet) {
errorCount++; errorCount++;
errors.append("Incorrect stylesheet defined - none match " + defaultStyleSheet + errors.append("Incorrect stylesheet defined - none match " + SHARED_STYLESHEET_NAME +
" in file " + htmlFile + EOL + "\tDiscovered stylesheets: " + styleSheets + EOL); " in file " + htmlFile + EOL + "\tDiscovered stylesheets: " + styleSheets + EOL);
} }

View file

@ -253,6 +253,11 @@ task buildHelp(type: JavaExec, dependsOn: indexHelp) {
args '-o', "${outputDir.absolutePath}" // set the output directory arg args '-o', "${outputDir.absolutePath}" // set the output directory arg
// register the Ghidra installation as an application root so the help system can find modules
systemProperties = [
"ADDITIONAL_APPLICATION_ROOT_DIRS": "${ghidraInstallDir}/Ghidra"
]
doFirst { doFirst {
configurations.helpPath.each { configurations.helpPath.each {
args "-hp" args "-hp"

View file

@ -14,9 +14,9 @@
* limitations under the License. * limitations under the License.
*/ */
apply from: "$rootProject.projectDir/gradle/javaProject.gradle" apply from: "$rootProject.projectDir/gradle/javaProject.gradle"
apply from: "$rootProject.projectDir/gradle/helpProject.gradle"
apply plugin: 'eclipse' apply plugin: 'eclipse'
eclipse.project.name = '_Skeleton' eclipse.project.name = '_Skeleton'
dependencies { dependencies {

View file

@ -10,7 +10,7 @@
<META name="ProgId" content="FrontPage.Editor.Document"> <META name="ProgId" content="FrontPage.Editor.Document">
<TITLE>Skeleton Help File for a Module</TITLE> <TITLE>Skeleton Help File for a Module</TITLE>
<LINK rel="stylesheet" type="text/css" href="help/shared/Frontpage.css"> <LINK rel="stylesheet" type="text/css" href="help/shared/DefaultStyle.css">
</HEAD> </HEAD>
<BODY> <BODY>