/*******************************************************************************
* Copyright (c) 1998, 2015 Oracle and/or its affiliates. All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Oracle - initial API and implementation from Oracle TopLink
******************************************************************************/
package org.eclipse.persistence.tools.workbench.framework.help;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Locale;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.prefs.Preferences;
import org.eclipse.persistence.tools.workbench.framework.action.FrameworkAction;
import org.eclipse.persistence.tools.workbench.framework.app.PreferencesNode;
import org.eclipse.persistence.tools.workbench.framework.context.PreferencesContext;
import org.eclipse.persistence.tools.workbench.framework.context.WorkbenchContext;
import org.eclipse.persistence.tools.workbench.utility.string.StringTools;
/**
* Wrap up the OHJ stuff.
*/
public final class HelpFacade {
// ********** constants **********
/**
* The name of the "help" preferences node used to store
* preferences used by the help facade.
*/
private static final String HELP_PREFERENCES_NODE = "help";
/**
* The name of the application's OHJ help set file.
* By default, this file should be found IN the tlmwhelp.jar;
* and tlmwhelp.jar should be on the classpath.
*/
private static final String HELP_SET_FILE_NAME = "/tlmwhelp.hs";
private static final String HELP_JAR_NAME = "/tlmwhelp.jar";
private static final String BASE_HELP_JAR_NAME = "/tlmwhelp";
/**
* This should specify the file containing
* the *complete* Help content.
*/
static final String LOCAL_FILE_PREFERENCE = "local file";
static final String LOCAL_FILE_PREFERENCE_DEFAULT = "";
/** If true, the Help Welcome screen will be opened at start-up. */
static final String DISPLAY_WELCOME_PREFERENCE = "display welcome";
static final boolean DISPLAY_WELCOME_PREFERENCE_DEFAULT = true;
/** flag to indicate that the local helpset selected in preferences by the user failed to load */
// private static boolean localFailed = false;
// ********** methods **********
/**
* Build and return the appropriate help manager.
*/
public static HelpManager buildHelpManager(HelpManagerConfig config) {
Preferences helpPreferences = config.getPreferences().node(HELP_PREFERENCES_NODE);
return new DefaultHelpManager(config.getResourceRepository(), helpPreferences);
}
private static URL buildLocalizedHelpUrl(Logger logger) {
//try with country first
URL helpUrl = HelpFacade.class.getResource(localizedHelpResourceJarName(true));
if (helpUrl == null) {
//try now without country code
helpUrl = HelpFacade.class.getResource(localizedHelpResourceJarName(false));
}
if (helpUrl != null) {
try {
helpUrl = new URL("jar:" + helpUrl.toString() + "!/");
} catch (MalformedURLException ex) {
log(logger, "LOCALIZED_FILE_NOT_FOUND", helpUrl, ex);
}
URL[] urls = {helpUrl};
URLClassLoader cl = new URLClassLoader(urls);
helpUrl = cl.findResource(HELP_SET_FILE_NAME);
}
return helpUrl;
}
/**
* Returns the appropriate help Jar name for the default locale
*/
private static String localizedHelpResourceJarName(boolean includeCountryCode) {
Locale locale = Locale.getDefault();
StringBuffer sb = new StringBuffer();
sb.append(BASE_HELP_JAR_NAME);
sb.append("_");
sb.append(locale.getLanguage());
if (includeCountryCode && !StringTools.stringIsEmpty(locale.getCountry())) {
sb.append("_");
sb.append(locale.getCountry());
}
sb.append(".jar");
return sb.toString();
}
/**
* Start a thread that will wait until the application has finished launching.
* This will allow us to return the Help Manager as soon as it is built.
* (It also prevents some deadlocks - see bug 3831450.)
*/
private static void startPostLaunchThread(InternalHelpManager helpManager, HelpManagerConfig config) {
new Thread(buildPostLaunchRunnable(helpManager, config), "Display Welcome").start();
}
/**
* Build a Runnable that will wait until the application is finished launching;
* then it will display any error messages concerning Help set-up and display
* the stupid Help Welcome Screen, if appropriate.
*/
private static Runnable buildPostLaunchRunnable(final InternalHelpManager helpManager, final HelpManagerConfig config) {
return new Runnable() {
public void run() {
try {
config.getLaunchCompleteFlag().waitUntilTrue();
} catch (InterruptedException ex) {
// no need to display anything, just let the thread die
return;
}
Preferences helpPreferences = config.getPreferences().node(HELP_PREFERENCES_NODE);
if (config.forceStupidWelcomeScreen() ||
helpPreferences.getBoolean(DISPLAY_WELCOME_PREFERENCE, DISPLAY_WELCOME_PREFERENCE_DEFAULT)) {
helpManager.showTopic("welcome");
}
helpManager.launchComplete();
}
};
}
/**
* We need to do all this because Logger#log(LogRecord) does not pass through
* Logger#doLog(LogRecord) like all the other Logger#log(...) methods.
*/
private static void log(Logger logger, String message, Object parm, Throwable exception) {
LogRecord logRecord = new LogRecord(Level.WARNING, message);
logRecord.setParameters(new Object[] {parm});
logRecord.setThrown(exception);
logRecord.setLoggerName(logger.getName());
logRecord.setResourceBundle(logger.getResourceBundle());
logger.log(logRecord);
}
/**
* Build and return an action for opening the development-time
* only Help Topic ID Window.
*/
public static FrameworkAction buildHelpTopicIDWindowAction(WorkbenchContext context) {
return new HelpTopicIDWindowAction(context);
}
/**
* Build and return a preferences node for the preferences dialog.
*/
public static PreferencesNode buildHelpPreferencesNode(PreferencesContext context) {
PreferencesContext helpContext = (PreferencesContext) context.buildRedirectedPreferencesContext(HELP_PREFERENCES_NODE);
return new HelpPreferencesNode(helpContext);
}
/**
* Suppress default constructor, ensuring non-instantiability.
*/
private HelpFacade() {
super();
throw new UnsupportedOperationException();
}
// ********** internal exceptions **********
/** throw when we have problems with building a "local" help book */
private static class LocalHelpBookWarning extends RuntimeException {
LocalHelpBookWarning() {
super();
}
}
}