Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,27 @@
*******************************************************************************/
package org.phoebus.framework.preferences;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.prefs.Preferences;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/** Write preferences in property file format
* @author Kay Kasemir
Expand All @@ -36,31 +53,149 @@ public static void save(final OutputStream stream) throws Exception
final OutputStreamWriter out = new OutputStreamWriter(stream);
)
{
out.append("# Preference settings\n");
out.append("# Format:\n");
out.append("# the.package.name/key=value\n");
listSettings(out, Preferences.userRoot());
out.append("# End.\n");
out.append("# Preference settings<br/>\n");
out.append("# Format:<br/>\n");
out.append("# the.package.name/key=value<br/>\n");
out.append("<div style='color: red; font-weight: bold'># key=value in red are incorrect properties</div><br/>\n");
listSettings(getAllPropertyKeys(), out, Preferences.userRoot());
out.append("# End.<br/>\n");
out.flush();
}
}

private static void listSettings(final Writer out, final Preferences node) throws Exception
private static void listSettings(Map<String, String> allKeysWithPackages, final Writer out, final Preferences node) throws Exception
{
for (String key : node.keys())
formatSetting(out, node, key);
formatSetting(allKeysWithPackages, out, node, key);
for (String child : node.childrenNames())
listSettings(out, node.node(child));
listSettings(allKeysWithPackages, out, node.node(child));
}

private static void formatSetting(final Writer out, final Preferences node, final String key) throws Exception
private static void formatSetting(Map<String, String> allKeysWithPackages, final Writer out, final Preferences node, final String key) throws Exception
{
final String path = node.absolutePath();
out.append(path.substring(1).replace('/', '.'))
.append('/')
.append(key)
String fullKey = path.substring(1).replace('/', '.') + '/' + key;
String keyFound = allKeysWithPackages.get(fullKey);
boolean bNotFound = keyFound == null ? true : false;
if (bNotFound) out.append("<div style='color: red; font-weight: bold'>");
out.append(escapeHtml(fullKey))
.append('=')
.append(node.get(key, ""))
.append('\n');
.append(escapeHtml(node.get(key, "")))
.append("<br/>\n");
if (bNotFound) out.append("</div>");
}

private static Map<String, String> getAllPropertyKeys() throws Exception
{
Map<String, String> allKeysWithPackages = new HashMap<>();

String classpath = System.getProperty("java.class.path");
String[] jars = classpath.split(System.getProperty("path.separator"));

if (jars.length == 1) jars = getAllJarFromManifest(jars[0]);

for (String jarEntry : jars) {
File file = new File(jarEntry);

if (jarEntry.endsWith(".jar")) {
try (JarFile jarFile = new JarFile(file)) {
Enumeration<JarEntry> entries = jarFile.entries();

while (entries.hasMoreElements()) {
JarEntry entry = entries.nextElement();
String entryName = entry.getName();

if (entryName.endsWith("preferences.properties")) {
parsePropertiesWithPackage(
jarFile.getInputStream(entry),
entryName,
allKeysWithPackages
);
}
}
} catch (IOException e) {
System.err.println("Error opening JAR : " + jarEntry);
e.printStackTrace();
}
}
}

return allKeysWithPackages;
}

private static String[] getAllJarFromManifest(String jarPath) {
String[] jars = new String[0];
File jarFile = new File(jarPath);

try (JarFile jar = new JarFile(jarFile)) {
Manifest manifest = jar.getManifest();

if (manifest != null) {
String classPath = manifest.getMainAttributes().getValue("Class-Path");

if (classPath != null && !classPath.isEmpty()) {
jars = classPath.split(" ");

for (int iJar = 0; iJar < jars.length; iJar++) {
Path fullPath = Paths.get(jarFile.getParent()).resolve(jars[iJar]);
jars[iJar] = fullPath.toString();
}
} else {
System.err.println("No Class-Path found in MANIFEST.MF.");
}
} else {
System.err.println("MANIFEST.MF not found in the JAR.");
}
} catch (IOException e) {
System.err.println("Error when reading the jar : " + jarPath);
e.printStackTrace();
}

return jars;
}

private static void parsePropertiesWithPackage(InputStream inputStream, String fileName, Map<String, String> allKeysWithPackages) {
Properties props = new Properties();
String packageName = null;

try (BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
StringBuilder content = new StringBuilder();

while ((line = reader.readLine()) != null) {
line = line.trim();
if (line.startsWith("#") && line.contains("Package")) {
// Find package name
Pattern pattern = Pattern.compile("#\\s*Package\\s+([^\\s]+)");
Matcher matcher = pattern.matcher(line);
if (matcher.find()) {
packageName = matcher.group(1);
}
} else if (!line.startsWith("#")) {
content.append(line).append("\n");
}
}

if (content.length() > 0) {
props.load(new ByteArrayInputStream(content.toString().getBytes()));
}

// properties found
for (String key : props.stringPropertyNames()) {
String prefixedKey = (packageName != null) ? packageName + "/" + key : key;
allKeysWithPackages.put(prefixedKey, props.getProperty(key));
}
} catch (IOException e) {
System.err.println("Error when reading file " + fileName);
e.printStackTrace();
}
}

private static String escapeHtml(String input) {
return input.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
.replace("\"", "&quot;")
.replace("'", "&#39;");
}
}
14 changes: 10 additions & 4 deletions core/ui/src/main/java/org/phoebus/ui/help/OpenAbout.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
import javafx.scene.image.Image;
import javafx.scene.layout.Priority;
import javafx.scene.layout.VBox;
import javafx.scene.web.WebView;

/** Menu entry to open 'about'
* @author Kay Kasemir
Expand Down Expand Up @@ -204,12 +205,17 @@ private Node createDetailSection()
logger.log(Level.WARNING, "Cannot list preferences", ex);
}

area = new TextArea(prefs_buf.toString());
area.setEditable(false);
WebView webView = new WebView();
String content = "<html><head><style>" +
"body {font-family: monospace;}" +
"</style></head><body>";
content += prefs_buf.toString();
content += "</body></html>";
webView.getEngine().loadContent(content);

VBox.setVgrow(area, Priority.ALWAYS);
VBox.setVgrow(webView, Priority.ALWAYS);

final Tab prefs = new Tab(Messages.HelpAboutPrefs, area);
final Tab prefs = new Tab(Messages.HelpAboutPrefs, webView);

final TabPane tabs = new TabPane(apps, envs, props, prefs);
return tabs;
Expand Down