Skip to content

Commit

Permalink
fix frontendproperties readFile() to work with classpath and update d…
Browse files Browse the repository at this point in the history
…ownload_custom_buttons_json reference (#10946)

* app.properties: add new download_custom_buttons_json to enum and confic_service property list

* FrontendProperty enum: fix ordering so list ends on correct line

* app.properties example for download_custom_buttons_json fixed

- changed example to use absolute path based on default docker config, since classpath: isn't supported
- updated documentation
- added TODO on readFile() method

* merge in docs updates from master

* download_custom_buttons: doc tweak

* application.properties example updated to match reference

* FrontEndProperties: update readFile() to support relative and classpath by leveraging spring ResourceUtils

* download_custom_buttons_json: update examples back to "classpath:"

* Application.properties example: updated classpath relative path

* Frontend Properties readFile: changed classpath to use ClassLoader.getResourceAsStream() instead of ResourceUtils.getFile()

- check both the file system and the classpath

* readfile: logging, fix style

* readFile: split out file/resource search code to new method locateFile()

- modified logging to use the verb "Found"

---------

Co-authored-by: Denis Papp <[email protected]>
Co-authored-by: Denis Papp <[email protected]>
  • Loading branch information
3 people authored Aug 22, 2024
1 parent b3ae689 commit ff85ba4
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 17 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -800,9 +800,9 @@ enable_study_tags=true|false
```

# Add Custom Buttons to data tables
Custom Buttons can be defined which will conditionally appear in all group comparison data tables (with CopyDownloadControls) to launch a custom URL. This can be used, for example, to launch a software application (that is installed on the user's system) with the data. This configuration can also customize new elements on the Visualize page. It points to a JSON file on the classpath. (See [download_custom_buttons reference](download_custom_buttons-Reference.md)).
Custom Buttons can be defined which will conditionally appear in all group comparison data tables (with CopyDownloadControls) to launch a custom URL. This can be used, for example, to launch a software application (that is installed on the user's system) with the data. This configuration can also customize new elements on the Visualize page. It points to a JSON file. (See [download_custom_buttons reference](download_custom_buttons-Reference.md)).


```
download_custom_buttons_json=classpath:/custom_buttons/download_custom_button_avm.json
download_custom_buttons_json=classpath:custom_buttons/download_custom_button_avm.json
```
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ Custom Buttons can be defined which will conditionally appear in all group compa

## Configuration File

The Custom Buttons are defined in a JSON file in the classpath. Set `download_custom_buttons_json` to refer to the file in the
`application.properties` (See [application.properties reference](application.properties-Reference.md#add-custom-buttons-to-data-tables)).
The Custom Buttons are defined in a JSON file on the classpath. Set `download_custom_buttons_json` to refer to the file (see [application.properties reference](application.properties-Reference.md#add-custom-buttons-to-data-tables)).

## JSON format

Expand Down Expand Up @@ -67,6 +66,4 @@ To modify software to leverage this:

- Modify your software to read data from clipboard.
- Modify your software or installer to register a URL protocol to launch.
- Modify your software or installer to install a custom font.


- Modify your software or installer to install a custom font.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@
import org.springframework.stereotype.Service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
Expand Down Expand Up @@ -291,18 +296,66 @@ private Map<String,String> cloneProperties() {
);
}

private String readFile(String fileName) {
if (fileName != null && !fileName.isEmpty()) {
try (BufferedReader br = Files.newBufferedReader(Paths.get(fileName))) {
return br.lines().map(String::trim).collect(Collectors.joining(""));
} catch (Exception e) {
log.error("Error reading frontend config file: {}", e.getMessage());
return null;
/**
* Find the file, either on the file system or in a .jar, and return as an InputStream.
* @propertiesFileName: the file path
* @return: a valid InputStream (not null), otherwise throws FileNotFoundException
* TECH: file system locations have precedence over classpath
* REF: based on getResourceStream() in WebServletContextListener.java
*/
private InputStream locateFile(String filePath) throws FileNotFoundException {
// try absolute or relative to working directory
File file = new File(filePath);
if (file.exists()) {
// throws if is a directory or cannot be opened
log.info("Found frontend config file: {}", file.getAbsolutePath());
return new FileInputStream(file);
}

// try relative to PORTAL_HOME
String home = System.getenv("PORTAL_HOME");
if (home != null) {
file = new File(Paths.get(home, filePath).toString());
if (file.exists()) {
log.info("Found frontend config file: {}", file.getAbsolutePath());
return new FileInputStream(file);
}
}

// try resource (e.g. app.jar)
InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filePath);
if (inputStream != null) {
log.info("Found frontend config resource: {}", filePath);
return inputStream;
} else {
throw new FileNotFoundException("File not found in system or classpath: " + filePath);
}
return null;
}


/**
* Read the file, either on the file system or in a .jar, and return the content as a single-line string.
* @propertiesFileName: the file path
*/
private String readFile(String propertiesFileName) {
if (propertiesFileName == null || propertiesFileName.isEmpty()) {
return null;
}

// strip off classpath prefix and always check all locations (ClassLoader and file system)
String filePath = propertiesFileName.startsWith("classpath:")
? propertiesFileName.substring("classpath:".length())
: propertiesFileName;

try {
InputStream inputStream = locateFile(filePath);
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
return br.lines().map(String::trim).collect(Collectors.joining(""));
} catch (Exception e) {
log.error("Error reading frontend config file: {}", e.getMessage());
return null;
}
}

public String getFrontendUrl(String propertyValue) {
String frontendUrlRuntime = env.getProperty("frontend.url.runtime", "");
if (frontendUrlRuntime.length() > 0) {
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/application.properties.EXAMPLE
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,7 @@ spring.devtools.restart.enabled=false
#enable_study_tags=true|false

## Custom Buttons
# download_custom_buttons_json=classpath:/custom_buttons/download_custom_button_avm.json
# download_custom_buttons_json=classpath:custom_buttons/download_custom_button_avm.json

# EOL - Do not delete the following lines

0 comments on commit ff85ba4

Please sign in to comment.