Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVlad Klicnik2001-05-14 18:44:34 +0000
committerVlad Klicnik2001-05-14 18:44:34 +0000
commit172bc6c37636db342545a9540675833c93a77a51 (patch)
treedad0687a97079a1e89fabde76e19fed8f9e3d4d0
downloadeclipse.platform.ua-172bc6c37636db342545a9540675833c93a77a51.tar.gz
eclipse.platform.ua-172bc6c37636db342545a9540675833c93a77a51.tar.xz
eclipse.platform.ua-172bc6c37636db342545a9540675833c93a77a51.zip
*** empty log message ***
-rw-r--r--.gitignore11
-rw-r--r--org.eclipse.help/.classpath9
-rw-r--r--org.eclipse.help/.cvsignore1
-rw-r--r--org.eclipse.help/.vcm_meta7
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/IContext.java43
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/IHelp.java86
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/IHelpTopic.java40
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/ContextImpl.java55
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/Help.java131
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/HelpPlugin.java31
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/HelpSystem.java262
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Action.java21
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Context.java21
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Contribution.java44
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/InfoSet.java32
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/InfoView.java19
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Insert.java19
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Topic.java19
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/TopicRef.java16
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Visitor.java24
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpAction.java35
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpContext.java120
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpContribution.java173
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInfoSet.java93
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInfoView.java92
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInsert.java43
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopic.java43
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopicFactory.java61
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopicRef.java38
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ActionContributor.java28
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContextContributor.java32
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContextManager.java50
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContributionManager.java29
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/Contributor.java28
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContributorCreator.java21
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/TopicContributor.java24
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ViewContributor.java25
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributionFactory.java52
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributionParser.java185
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributorFactory.java81
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContextManager.java321
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContributionManager.java134
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContributionManagerProxy.java124
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLActionContributor.java47
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLActionContributorCreator.java30
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContextContributor.java202
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContextContributorCreator.java30
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContributor.java156
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLTopicContributor.java74
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLTopicContributorCreator.java30
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLViewContributor.java65
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLViewContributorCreator.java30
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/HelpNavigationManager.java191
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/InfosetBuilder.java448
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/NavigationModel.java235
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/XMLGenerator.java70
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/XMLNavGenerator.java160
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/Help.java65
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/ServletFacade.java119
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/StandaloneFacade.java40
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/search/ISearchEngine.java43
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/search/XMLSearchContributor.java82
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/AddressTest.java117
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/CSSEmbedProcessor.java68
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpContentManager.java81
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpConnection.java53
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpRequest.java183
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpResponse.java49
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpServer.java204
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpURL.java173
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpURLFactory.java47
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HighlightProcessor.java239
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/OutputProcessor.java16
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/PluginURL.java233
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/SearchURL.java189
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/TempURL.java90
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/BelongsToPluginsFileFilter.java50
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/DocResources.java159
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpException.java25
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpLogListener.java109
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpVisitor.java46
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/Logger.java146
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/PersistentMap.java150
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/PluginVersionInfo.java139
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/Resources.java177
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/RuntimeHelpStatus.java125
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/SearchableDocFileNameFilter.java38
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/SequenceGenerator.java45
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/TString.java323
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/TableOfContentsGenerator.java173
-rw-r--r--org.eclipse.help/Eclipse Help/org/eclipse/help/package.html42
-rw-r--r--org.eclipse.help/build.properties2
-rw-r--r--org.eclipse.help/doc/HelpSample.JPGbin0 -> 122515 bytes
-rw-r--r--org.eclipse.help/doc/org_eclipse_help.html37
-rw-r--r--org.eclipse.help/doc/org_eclipse_help_contexts.html73
-rw-r--r--org.eclipse.help/doc/org_eclipse_help_contributions.html364
-rw-r--r--org.eclipse.help/doc/org_eclipse_help_support.html43
-rw-r--r--org.eclipse.help/dtd/actions.dtd10
-rw-r--r--org.eclipse.help/dtd/contexts.dtd11
-rw-r--r--org.eclipse.help/dtd/infoset.dtd10
-rw-r--r--org.eclipse.help/dtd/topics.dtd8
-rw-r--r--org.eclipse.help/html/default.css1
-rw-r--r--org.eclipse.help/html/default_home.html14
-rw-r--r--org.eclipse.help/html/notopic.html5
-rw-r--r--org.eclipse.help/html/workbench.jpgbin0 -> 31031 bytes
-rw-r--r--org.eclipse.help/plugin.jars1
-rw-r--r--org.eclipse.help/plugin.properties5
-rw-r--r--org.eclipse.help/plugin.xml92
-rw-r--r--org.eclipse.help/remote.ini5
109 files changed, 9010 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 000000000..c550c6af7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,11 @@
+bin/
+*~
+*.rej
+*.bak
+*.patch
+javacore.*
+heapdump.*
+core.*
+Snap.*
+target/
+
diff --git a/org.eclipse.help/.classpath b/org.eclipse.help/.classpath
new file mode 100644
index 000000000..76184155f
--- /dev/null
+++ b/org.eclipse.help/.classpath
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="Eclipse Help"/>
+ <classpathentry kind="lib" path="C:\eclipse\jre\lib\rt.jar"/>
+ <classpathentry kind="lib" path="C:\eclipse\plugins\org.eclipse.core.runtime\runtime.jar"/>
+ <classpathentry kind="lib" path="C:\eclipse\plugins\org.apache.xerces\xerces.jar"/>
+ <classpathentry kind="src" path="\org.eclipse.core.boot"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.help/.cvsignore b/org.eclipse.help/.cvsignore
new file mode 100644
index 000000000..c5e82d745
--- /dev/null
+++ b/org.eclipse.help/.cvsignore
@@ -0,0 +1 @@
+bin \ No newline at end of file
diff --git a/org.eclipse.help/.vcm_meta b/org.eclipse.help/.vcm_meta
new file mode 100644
index 000000000..7655f8db4
--- /dev/null
+++ b/org.eclipse.help/.vcm_meta
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project-description>
+ <comment></comment>
+ <nature id="org.eclipse.jdt.core.javanature"/>
+ <builder name="org.eclipse.jdt.core.javabuilder">
+ </builder>
+</project-description>
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/IContext.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/IContext.java
new file mode 100644
index 000000000..c6cca1980
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/IContext.java
@@ -0,0 +1,43 @@
+package org.eclipse.help;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * A context registered for context-sensitive help.
+ * <p>
+ * This interface models the context-sensitive help that can be associated with
+ * SWT menus, menu items, and controls, and with JFace actions. A help context
+ * provides the text description of the object with which it is associated with,
+ * as well as topic links that contain more related information. This information
+ * would be displayed to the user when context sensitive help (F1) is requested.
+ * </p>
+ * <p>
+ * In the current implementation of the Help system, valid contexts can be
+ * contributed through the <code>contexts</code> element of the
+ * <code>"org.eclipse.help.contexts"</code> extension point. The
+ * <code>IHelp.findContext(String)</code> method is used at runtime to create
+ * or fetch IContext objects using there fully qualified contextIds. If there
+ * is a need to override this behavior, then this IContext interface could be
+ * implemented by a client and registered with the SWT control or JFace action.
+ * </p>
+ */
+public interface IContext {
+ /**
+ * Returns a list of related topics for this help context.
+ *
+ * @return a list of related help topics
+ */
+ public IHelpTopic[] getRelatedTopics();
+ /**
+ * Returns the text description for this context.
+ *
+ * @return the text description
+ */
+ public String getText();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/IHelp.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/IHelp.java
new file mode 100644
index 000000000..bfb72d5dd
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/IHelp.java
@@ -0,0 +1,86 @@
+package org.eclipse.help;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * Interface to the help system UI.
+ * <p>
+ * The Eclipse platform defines an extension point
+ * (<code>"org.eclipse.help.support"</code>) for plugging in a help system UI.
+ * The help system UI is entirely optional.
+ * Clients may provide a UI for presenting help to the user by implementing this
+ * interface and including the name of their class in the
+ * <code>&LT;config&GT;</code> element in an extension to the platform's help
+ * support extension point (<code>"org.eclipse.help.support"</code>).
+ * </p>
+ * <p>
+ * Note that an implementation of the help system UI is provided by the
+ * <code>"org.eclipse.help.ui"</code> plug-in (This plug-in is not
+ * mandatory, and can be removed). Since the platform can only make use of a
+ * single help system UI implementation, make sure that the platform is not
+ * configured with more than one plug-in trying to extend this extension point.
+ * </p>
+ */
+public interface IHelp {
+
+ /**
+ * Displays context-sensitive help for contexts with the given context ids.
+ * <p>
+ * (x,y) coordinates specify the location where the context sensitive
+ * help UI will be presented. These coordinates are screen-relative
+ * (ie: (0,0) is the top left-most screen corner).
+ * The platform is responsible for calling this method and supplying the
+ * appropriate location.
+ * </p>
+ *
+ * @param contextIds a list of help context ids
+ * @param x horizontal position
+ * @param y verifical position
+ * @see #findContext
+ */
+ public void displayHelp(String[] contextIds, int x, int y);
+ /**
+ * Displays context-sensitive help for the given contexts.
+ * <p>
+ * (x,y) coordinates specify the location where the context sensitive
+ * help UI will be presented. These coordinates are screen-relative
+ * (ie: (0,0) is the top left-most screen corner).
+ * The platform is responsible for calling this method and supplying the
+ * appropriate location.
+ * </p>
+ *
+ *
+ * @param contexts a list of help contexts
+ * @param x horizontal position
+ * @param y verifical position
+ */
+ public void displayHelp(IContext[] contexts, int x, int y);
+ /**
+ * Displays help content for the information set with the given id.
+ * <p>
+ * This method is called by the platform to launch the help system UI, displaying
+ * the documentation identified by the <code>infoSet</code> parameter.
+ * </p>
+ * <p>
+ * In the current implementation of the Help system, valid information sets are
+ * contributed through the <code>infoSet</code> element of the
+ * <code>"org.eclipse.help.contributions"</code> extension point.
+ * </p>
+ *
+ * @param infoSet the information set id
+ */
+ public void displayHelp(String infoSet);
+ /**
+ * Computes and returns context information for the given context id.
+ *
+ * @param contextId the context id
+ * @return the context, or <code>null</code> if none
+ */
+ public IContext findContext(String contextId);
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/IHelpTopic.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/IHelpTopic.java
new file mode 100644
index 000000000..417f53acc
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/IHelpTopic.java
@@ -0,0 +1,40 @@
+package org.eclipse.help;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * A help topic.
+ * <p>
+ * This interface models a help topic that can be defined in a help context object.
+ * An array of help topics is typically associated with an IContext object, and would be
+ * displayed to the user when context sensitive help (F1) is requested.
+ * </p>
+ * <p>
+ * In the current implementation of the Help system, valid contexts can be
+ * contributed through the <code>contexts</code> element of the
+ * <code>"org.eclipse.help.contexts"</code> extension point. If there
+ * is a need to override this behavior, then this IHelpTopic interface, and the IContext
+ * interface could be implemented by a client and registered with the SWT control or
+ * JFace action.
+ * </p>
+ */
+public interface IHelpTopic {
+ /**
+ * Returns the string URL associated with this help topic.
+ *
+ * @return the string URL of the topic
+ */
+ public String getHref();
+ /**
+ * Returns the label of this help topic.
+ *
+ * @return the label
+ */
+ public String getLabel();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/ContextImpl.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/ContextImpl.java
new file mode 100644
index 000000000..b9f5b9f8c
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/ContextImpl.java
@@ -0,0 +1,55 @@
+package org.eclipse.help.internal;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.help.*;
+
+/**
+ * IContext Implementation that performs lazy lookup of
+ * context ID and HelpContext instantiation.
+ * when any of the IContext methods are called.
+ */
+public class ContextImpl implements IContext {
+ private String contextID;
+ private IContext context = null;
+ private boolean used = false;
+ /**
+ * ContextImpl constructor.
+ */
+ public ContextImpl(String contextId) {
+ super();
+ this.contextID = contextId;
+ }
+ /**
+ * Returns a list of related topics for this help context.
+ *
+ * @return a list of related help topics
+ */
+ public IHelpTopic[] getRelatedTopics() {
+ if (!used) {
+ context = HelpSystem.getContextManager().getContext(contextID);
+ used = true;
+ }
+ if (context == null)
+ return null;
+ return context.getRelatedTopics();
+ }
+ /**
+ * Returns the text description for this context.
+ *
+ * @return the text description
+ */
+ public String getText() {
+ if (!used) {
+ context = HelpSystem.getContextManager().getContext(contextID);
+ used = true;
+ }
+ if (context == null)
+ return null;
+ return context.getText();
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/Help.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/Help.java
new file mode 100644
index 000000000..c76dd5ac8
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/Help.java
@@ -0,0 +1,131 @@
+package org.eclipse.help.internal;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+
+import org.eclipse.help.*;
+
+/**
+ * For displaying help to the user. The Eclipse platform defines an extension
+ * point (<code>"org.eclipse.help.support"</code>) for the help system UI.
+ * The help system UI is entirely optional (the standard help system UI provided
+ * by the <code>"org.eclipse.help.ui"</code> plug-in is not mandatory).
+ * This class provides static convenience methods for showing help to the user
+ * when possible; the methods do nothing when no help system UI is unavailable.
+ * <p>
+ * This class provides static methods only; it is not intended to be
+ * instantiated or subclassed by clients.
+ * </p>
+ */
+public final class Help {
+ // configuration information
+ private static IConfigurationElement viewerCfig = null;
+
+ // pluggable viewer
+ private static IHelp helpSupport = null;
+
+ // constants
+ private static final String HELP_EXTENSION_POINT = "org.eclipse.help.support";
+ private static final String HELP_CONFIG = "config";
+ private static final String HELP_CLASS = "class";
+
+ static {
+ // initialize the unique help browser.
+ init();
+ }
+
+ /**
+ * Hide default constructor
+ */
+ private Help() {
+ super();
+ }
+ /**
+ * Displays context-sensitive help for contexts with the given context ids.
+ * Does nothing if no help system UI is available.
+ *
+ * @param contextIds a list of help context ids
+ * @param x horizontal position
+ * @param y verifical position
+ * @see #findContext
+ * @see IHelp#displayHelp
+ */
+ public static void displayHelp(String[] contextIds, int x, int y) {
+ // delegate to pluggable viewer
+ if (helpSupport != null)
+ helpSupport.displayHelp(contextIds, x, y);
+ }
+ /**
+ * Displays context-sensitive help for the given contexts.
+ * Does nothing if no help system UI is available.
+ *
+ * @param contexts a list of help contexts
+ * @param x horizontal position
+ * @param y verifical position
+ * @see IHelp#displayHelp
+ */
+ public static void displayHelp(IContext[] contexts, int x, int y) {
+ // delegate to pluggable viewer
+ if (helpSupport != null)
+ helpSupport.displayHelp(contexts, x, y);
+ }
+ /**
+ * Displays help content for the information set with the given id.
+ * Does nothing if no help system UI is available.
+ *
+ * @param infoSet the information set id
+ * @see IHelp#displayHelp(java.lang.String)
+ */
+ public static void displayHelp(String infoSet) {
+ // delegate to pluggable viewer
+ if (helpSupport != null)
+ helpSupport.displayHelp(infoSet);
+ }
+ /**
+ * Computes and returns context information for the given context id.
+ * Does nothing if no help system UI is available.
+ *
+ * @param contextId the context id
+ * @return the context, or <code>null</code> if none or if there is no
+ * help system UI
+ * @see IHelp#findContext
+ */
+ public static IContext findContext(String contextID) {
+ if (helpSupport != null)
+ return helpSupport.findContext(contextID);
+ return null;
+ }
+ private static void init() {
+ // obtain viewer configuration from registry
+ IPluginRegistry registry = Platform.getPluginRegistry();
+ IExtensionPoint xpt = registry.getExtensionPoint(HELP_EXTENSION_POINT);
+ if (xpt == null)
+ return;
+
+ IExtension[] extList = xpt.getExtensions();
+ if (extList.length == 0)
+ return;
+
+ // only one pluggable viewer allowed ... always take first (only)
+ // extension and its first (only) element
+ IConfigurationElement[] cfigList = extList[0].getConfigurationElements();
+ if (cfigList.length == 0)
+ return;
+
+ if (!cfigList[0].getName().equals(HELP_CONFIG))
+ return;
+ viewerCfig = cfigList[0];
+
+ // create executable viewer and cache it
+ try {
+ //this.viewer = (IHelpViewer) viewerCfig.createExecutableExtension(VIEWER_CLASS);
+ helpSupport = (IHelp) viewerCfig.createExecutableExtension(HELP_CLASS);
+ } catch (Exception e) { /* die silently */
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/HelpPlugin.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/HelpPlugin.java
new file mode 100644
index 000000000..0e88b73be
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/HelpPlugin.java
@@ -0,0 +1,31 @@
+package org.eclipse.help.internal;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+
+/**
+ * Simple plugin for a remote help system.
+ */
+public class HelpPlugin extends Plugin {
+ protected static HelpPlugin plugin;
+
+ /**
+ * HelpViewerPlugin constructor. It is called as part of plugin
+ * activation.
+ */
+ public HelpPlugin(IPluginDescriptor descriptor) {
+ super(descriptor);
+ plugin = this;
+ }
+ /**
+ * @return com.ibm.ua.HelpViewerPlugin
+ */
+ public static HelpPlugin getDefault() {
+ return plugin;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/HelpSystem.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/HelpSystem.java
new file mode 100644
index 000000000..8ff6e016e
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/HelpSystem.java
@@ -0,0 +1,262 @@
+package org.eclipse.help.internal;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.net.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.navigation.*;
+import org.eclipse.help.internal.server.HelpServer;
+import org.eclipse.help.internal.contributors.xml.*;
+import org.eclipse.help.internal.search.ISearchEngine;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.help.internal.contributors.*;
+
+/**
+ * The actual implementation of the help system plugin.
+ */
+public final class HelpSystem {
+ protected static final HelpSystem instance = new HelpSystem();
+ protected ContributionManager contributionManager;
+ protected HelpNavigationManager navigationManager;
+ protected ContextManager contextManager;
+ protected ISearchEngine searchManager;
+ protected Plugin plugin;
+
+ int debug_level;
+ private String browserPath;
+
+ // constants
+ private static final String SEARCH_ENGINE_EXTENSION_POINT =
+ "org.eclipse.help.searchEngine";
+ private static final String SEARCH_ENGINE_CONFIG = "config";
+ private static final String SEARCH_ENGINE_CLASS = "class";
+
+ // public constants (preferences)
+ public static final int INSTALL_LOCAL = 0;
+ public static final int INSTALL_CLIENT = 1;
+ public static final int INSTALL_SERVER = 2;
+
+ // Contants indicating level of logging
+ public static final int LOG_ERROR = 0; // log errors
+ public static final int LOG_WARNING = 1; // log errors and warnings
+ public static final int LOG_DEBUG = 2;
+ // log errors, warning, debug messages, and information messages
+
+ // configuration settings
+ int install = INSTALL_LOCAL;
+ private String remoteServerPath;
+ private URL remoteServerURL;
+
+ private String localServerAddress;
+ private String localServerPort;
+
+ /**
+ * HelpSystem constructor comment.
+ */
+ private HelpSystem() {
+ super();
+ }
+ /**
+ * Obtains path to the HTML browser
+ * @return java.lang.String
+ */
+ public static String getBrowserPath() {
+ return getInstance().browserPath;
+ }
+ /**
+ * Used to obtain Print Manager
+ * returns an instance of HelpPrintManager
+ */
+ public static ContextManager getContextManager() {
+ if (getInstance().contextManager == null)
+ getInstance().contextManager = new HelpContextManager();
+ return getInstance().contextManager;
+ }
+ /**
+ * Used to obtain Contribution Manager
+ * @return instance of ContributionManager
+ */
+ public static ContributionManager getContributionManager() {
+ if (getInstance().contributionManager == null) {
+ if (isClient())
+ getInstance().contributionManager = new HelpContributionManagerProxy();
+ else
+ getInstance().contributionManager = new HelpContributionManager();
+ }
+ return getInstance().contributionManager;
+ }
+ /**
+ */
+ public static int getDebugLevel() {
+ return getInstance().debug_level;
+ }
+ public static HelpSystem getInstance() {
+ return instance;
+ }
+ /**
+ * Returns the ip and port, as http://ip:port
+ */
+ public static URL getLocalHelpServerURL() {
+ return HelpServer.getAddress();
+ }
+ /**
+ * Used to obtain Contribution Manager
+ * @return instance of ContributionManager
+ */
+ public static HelpNavigationManager getNavigationManager() {
+ if (getInstance().navigationManager == null) {
+ getInstance().navigationManager = new HelpNavigationManager();
+ // launch the help server to serve documents
+ HelpServer.instance();
+ }
+ return getInstance().navigationManager;
+ }
+ public static Plugin getPlugin() {
+ return getInstance().plugin;
+ }
+ /**
+ * Returns the path to the help server.
+ * This is usually empty, but for remote install it can be
+ * something like /eclipse/servlet/help
+ */
+ public static String getRemoteHelpServerPath() {
+ return getInstance().remoteServerPath;
+ }
+ /**
+ * Returns the ip and port, as http://ip:port
+ */
+ public static URL getRemoteHelpServerURL() {
+ return getInstance().remoteServerURL;
+ }
+ /**
+ * Used to obtain Search Manager
+ * @return instance of SearchManager
+ */
+ public static synchronized ISearchEngine getSearchManager() {
+ if (getInstance().searchManager == null) {
+ // obtain searchengine configuration from registry
+ IPluginRegistry registry = Platform.getPluginRegistry();
+ IExtensionPoint xpt = registry.getExtensionPoint(SEARCH_ENGINE_EXTENSION_POINT);
+ if (xpt == null)
+ return null;
+
+ IExtension[] extList = xpt.getExtensions();
+ if (extList.length == 0)
+ return null;
+
+ // only one pluggable viewer allowed ... always take first (only)
+ // extension and its first (only) element
+ IConfigurationElement[] cfigList = extList[0].getConfigurationElements();
+ if (cfigList.length == 0)
+ return null;
+
+ if (!cfigList[0].getName().equals(SEARCH_ENGINE_CONFIG))
+ return null;
+ IConfigurationElement searchCfig = cfigList[0];
+
+ // create executable engine and cache it
+ try {
+ getInstance().searchManager =
+ (ISearchEngine) searchCfig.createExecutableExtension(SEARCH_ENGINE_CLASS);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+ return getInstance().searchManager;
+ }
+ public static boolean isClient() {
+ return getInstance().install == INSTALL_CLIENT;
+ }
+ public static boolean isLocal() {
+ return getInstance().install == INSTALL_LOCAL;
+ }
+ public static boolean isServer() {
+ return getInstance().install == INSTALL_SERVER;
+ }
+ /**
+ */
+ public HelpSystem newInstance() {
+ return null;
+ }
+ public static void setBrowserPath(String path) {
+ getInstance().browserPath = path;
+ }
+ public static void setDebugLevel(int debug_level) {
+ getInstance().debug_level = debug_level;
+ Logger.setDebugLevel(debug_level);
+ }
+ public static void setInstall(int install) {
+ int oldInstall = getInstance().install;
+ getInstance().install = install;
+ // when the user has new preference we may need
+ // to cleanup the managers
+ if (oldInstall != install) {
+ // contextManager stays the same
+
+ // need new contribution manager
+ if (getInstance().contributionManager != null)
+ getInstance().contributionManager = null;
+
+ // need new navigation manager
+ if (getInstance().navigationManager != null)
+ getInstance().navigationManager = null;
+
+ // need new search manager
+ if (getInstance().searchManager != null)
+ getInstance().searchManager = null;
+ }
+ }
+ public static void setLocalServerInfo(String addr, String port) {
+ getInstance().localServerAddress = addr;
+ getInstance().localServerPort = port;
+ HelpServer.setAddress(addr, port);
+ }
+ public static void setPlugin(Plugin plugin) {
+ getInstance().plugin = plugin;
+ }
+ public static void setRemoteServerInfo(String url) {
+ try {
+ if (url != null) {
+ URL fullURL = new URL(url);
+ getInstance().remoteServerURL =
+ new URL(fullURL.getProtocol(), fullURL.getHost(), fullURL.getPort(), "");
+ getInstance().remoteServerPath = fullURL.getFile();
+ }
+ } catch (MalformedURLException mue) {
+ }
+ }
+ /**
+ * Shuts down the Help System.
+ * @exception CoreException if this method fails to shut down
+ * this plug-in
+ */
+ public static void shutdown() throws CoreException {
+ HelpServer.instance().close();
+ Logger.logInfo(Resources.getString("I003"));
+ Logger.shutdown();
+ }
+ /**
+ * Called by Platform after loading the plugin
+ */
+ public static void startup() {
+ try {
+ if (isServer()) {
+ // This is a server install, so need to generate navigation first
+ getNavigationManager();
+ }
+ Logger.logInfo(Resources.getString("I002"));
+ } catch (Exception e) {
+ getPlugin().getLog().log(
+ new Status(
+ Status.ERROR,
+ getPlugin().getDescriptor().getUniqueIdentifier(),
+ 0,
+ Resources.getString("E005"),
+ e));
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Action.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Action.java
new file mode 100644
index 000000000..edfb3e0da
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Action.java
@@ -0,0 +1,21 @@
+package org.eclipse.help.internal.contributions;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * Action contribution
+ */
+public interface Action extends Contribution {
+ public String getView();
+ /**
+ * Returns true when this actions are meant for a stand-alone component
+ * installation.
+ */
+ public boolean isStandalone();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Context.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Context.java
new file mode 100644
index 000000000..e61f39f5f
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Context.java
@@ -0,0 +1,21 @@
+package org.eclipse.help.internal.contributions;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.help.*;
+
+/**
+ * Context contribution
+ */
+public interface Context extends Contribution {
+ /** Returns a specific nested context */
+ public Context getContext(String id);
+ /** Returns the text description for this context */
+ public String getDescription();
+ /** Returns the related links */
+ public IHelpTopic[] getRelatedTopics();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Contribution.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Contribution.java
new file mode 100644
index 000000000..45409e7f5
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Contribution.java
@@ -0,0 +1,44 @@
+package org.eclipse.help.internal.contributions;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Interface for help contributions (topics, actions,views, etc.)
+ */
+public interface Contribution {
+ // switches indicating how to insert
+ public final static int FIRST = 1;
+ public final static int LAST = -1;
+ public final static int NEXT = 129;
+ public final static int NORMAL = 0;
+ public final static int PREV = 127;
+
+ /**
+ */
+ void accept(Visitor visitor);
+ /**
+ */
+ Iterator getChildren();
+ /**
+ */
+ List getChildrenList();
+ /**
+ */
+ String getID();
+ /**
+ */
+ String getLabel();
+ /**
+ */
+ Contribution getParent();
+ /**
+ */
+ String getRawLabel();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/InfoSet.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/InfoSet.java
new file mode 100644
index 000000000..98be1f42d
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/InfoSet.java
@@ -0,0 +1,32 @@
+package org.eclipse.help.internal.contributions;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * Views contribution
+ */
+public interface InfoSet extends Contribution {
+ /**
+ */
+ String getHref();
+ /**
+ */
+ InfoView getView(String name);
+ /**
+ */
+ String[] getViewNames();
+ /**
+ */
+ InfoView[] getViews();
+ /**
+ * Returns true when this actions are meant for a stand-alone component
+ * installation.
+ */
+ public boolean isStandalone();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/InfoView.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/InfoView.java
new file mode 100644
index 000000000..e7aca03f4
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/InfoView.java
@@ -0,0 +1,19 @@
+package org.eclipse.help.internal.contributions;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * View contribution
+ */
+public interface InfoView extends Contribution {
+
+ /**
+ */
+ Topic getRoot();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Insert.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Insert.java
new file mode 100644
index 000000000..4178b596d
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Insert.java
@@ -0,0 +1,19 @@
+package org.eclipse.help.internal.contributions;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * Insert contribution
+ */
+public interface Insert extends Contribution {
+
+ public String getMode();
+ public String getSource();
+ public String getTarget();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Topic.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Topic.java
new file mode 100644
index 000000000..c6b8d5a67
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Topic.java
@@ -0,0 +1,19 @@
+package org.eclipse.help.internal.contributions;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * Topic contribution
+ */
+public interface Topic extends Contribution {
+
+ /**
+ */
+ String getHref();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/TopicRef.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/TopicRef.java
new file mode 100644
index 000000000..febbdf0a0
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/TopicRef.java
@@ -0,0 +1,16 @@
+package org.eclipse.help.internal.contributions;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * Topic reference contribution
+ */
+public interface TopicRef extends Topic {
+ public Topic getTopic();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Visitor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Visitor.java
new file mode 100644
index 000000000..63c2b349f
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/Visitor.java
@@ -0,0 +1,24 @@
+package org.eclipse.help.internal.contributions;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * Visitor to walk a contribution hierarchy
+ */
+public interface Visitor {
+ /**
+ */
+ void visit(InfoSet infoSet);
+ /**
+ */
+ void visit(InfoView view);
+ /**
+ */
+ void visit(Topic topic);
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpAction.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpAction.java
new file mode 100644
index 000000000..687bec82b
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpAction.java
@@ -0,0 +1,35 @@
+package org.eclipse.help.internal.contributions.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.xml.sax.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+
+/**
+ * Default implementation for an action contribution
+ */
+public class HelpAction extends HelpContribution implements Action {
+ protected String view;
+ protected boolean isStandalone = false;
+ public HelpAction(Attributes attrs) {
+ super(attrs);
+ if (attrs != null) {
+ view = attrs.getValue(ViewContributor.VIEW_ELEM);
+ isStandalone =
+ Boolean
+ .valueOf(attrs.getValue(ActionContributor.ACTIONS_STANDALONE_ATTR))
+ .booleanValue();
+ }
+ }
+ public String getView() {
+ return view;
+ }
+ public boolean isStandalone() {
+ return isStandalone;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpContext.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpContext.java
new file mode 100644
index 000000000..9d8b0266e
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpContext.java
@@ -0,0 +1,120 @@
+package org.eclipse.help.internal.contributions.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.xml.sax.*;
+import org.eclipse.help.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+
+/**
+ * Context object, as defined in the map.xml
+ */
+public class HelpContext
+ extends HelpContribution
+ implements Context, IContext {
+ private String description;
+ /**
+ * Context constructor comment.
+ */
+ public HelpContext(Attributes attrs) {
+ super(attrs);
+ ///merge(contextNode);
+ }
+ /**
+ * Overriden to handle <description>
+ */
+ public Contribution addChild(Contribution child) {
+ /*
+ if (child instanceof Topic)
+ return super.addChild(child);
+ else
+ description = "some description. Change the <description> specs and parsing.";
+ return null;
+ */
+ return super.addChild(child);
+ }
+ public Context getContext(String id) {
+ for (Iterator it = children.iterator(); it.hasNext();) {
+ Context c = (Context) it.next();
+ if (c.getID().equals(id))
+ return c;
+ }
+ return null;
+ }
+ public String getDescription() {
+ // description is already NL enabled when the XML files are parsed.
+ return description;
+ }
+ /** List of topic ids */
+ public IHelpTopic[] getRelatedTopics() {
+ if (children.size() > 0) {
+ IHelpTopic[] related = new IHelpTopic[children.size()];
+ children.toArray(related);
+ return related;
+ } else {
+ // signal empty topics. handled by calling class.
+ return null;
+ }
+ }
+ public String getText() {
+ return getDescription();
+ }
+ /**
+ * Merges the current context with info from an XML
+ * definition of the context.
+ * Contexts are nested and maintained as trees;
+ */
+ void merge(HelpContext context) {
+ /*
+ for (Iterator it=context.getChildren(); it.hasNext(); )
+ {
+ HelpContext child = (Context)it.next();
+ if (child.getNodeType() != Node.ELEMENT_NODE) continue;
+ Element childElement = (Element)child;
+
+ if (childElement.getTagName().equals(ContextContributor.DESC_ELEM))
+ {
+ Node text = childElement.getFirstChild();
+ if (text != null)
+ description = text.getNodeValue();
+
+ continue;
+ }
+
+ if (childElement.getTagName().equals(ContextContributor.RELATED_ELEM))
+ {
+ if (relatedTopics == null) relatedTopics = new Vector();
+ relatedTopics.add(childElement.getAttribute(ContextContributor.RELATED_ATTR));
+ continue;
+ }
+
+ if (!childElement.getTagName().equals(ContextContributor.CONTEXT_ELEM))
+ {
+ System.out.println("error: unexpected " + childElement.getTagName());
+ continue;
+ }
+
+ String id = childElement.getAttribute(ContextContributor.ID_ATTR);
+ HelpContext oldChildContext = (HelpContext)getContext(id);
+ if (oldChildContext == null)
+ {
+ Context newChildContext = new HelpContext(childElement);
+ addChild(newChildContext);
+ }
+ else
+ {
+ oldChildContext.merge(childElement);
+ }
+ }
+ */
+ }
+ public void setDescription(String s) {
+ description = s;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpContribution.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpContribution.java
new file mode 100644
index 000000000..89b9ec320
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpContribution.java
@@ -0,0 +1,173 @@
+package org.eclipse.help.internal.contributions.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.xml.sax.*;
+import org.eclipse.help.internal.contributions.Contribution;
+import org.eclipse.help.internal.contributions.Visitor;
+import org.eclipse.help.internal.util.*;
+
+/**
+ * Common class for contribution data.
+ */
+public class HelpContribution implements Contribution {
+
+ protected HelpContribution parent;
+ protected List children = new ArrayList(/* of HelpContribution */);
+
+ protected String id;
+
+ // counter to track children with FIRST or LAST position preferences
+ protected int firstChildrenNo = 0;
+ protected String label;
+ protected int lastChildrenNo = 0;
+ protected String translatedLabel;
+
+ /**
+ */
+ public HelpContribution(Attributes attrs) {
+ if (attrs == null)
+ return;
+
+ // set the label
+ this.label = attrs.getValue("label");
+ if (this.label == null)
+ this.label = attrs.getValue("id");
+ if (this.label == null)
+ this.label = getClass().toString();
+
+ // set the id
+ id = attrs.getValue("id");
+ }
+ /**
+ * Implements the method for the Visitor pattern
+ * @param visitor com.ibm.itp.contributions.Visitor
+ */
+ public void accept(Visitor visitor) {
+ // this should execute
+ System.out.println(Resources.getString("contribution_accept"));
+ }
+ /**
+ * Adds a child and returns it
+ * @returns com.ibm.itp.contributions.HelpContribution
+ * @param parentNode com.ibm.itp.contributions.HelpContribution
+ */
+ public Contribution addChild(Contribution child) {
+ return insertChild(child, Contribution.NORMAL);
+ }
+ /**
+ */
+ public Iterator getChildren() {
+ return children.iterator();
+ }
+ /**
+ */
+ public List getChildrenList() {
+ return children;
+ }
+ /**
+ */
+ public String getID() {
+ return id;
+ }
+ /**
+ * Returns the translated label
+ */
+ public String getLabel() {
+ if (translatedLabel == null) {
+ translatedLabel = label;
+ if (translatedLabel.indexOf('%') == 0) {
+ int lastPeriod = id.lastIndexOf('.');
+ String pluginID = id.substring(0, lastPeriod);
+ translatedLabel =
+ DocResources.getPluginString(pluginID, translatedLabel.substring(1));
+ }
+ }
+ return translatedLabel;
+ }
+ /**
+ */
+ public Contribution getParent() {
+ return parent;
+ }
+ /**
+ * Returns the label without translation, as it appears in the xml files
+ */
+ public String getRawLabel() {
+ return label;
+ }
+ /**
+ * Adds a child and returns it
+ * @returns com.ibm.itp.contributions.HelpContribution
+ * @param parentNode com.ibm.itp.contributions.HelpContribution
+ */
+ public Contribution insertChild(Contribution child, int positionPreference) {
+ if (positionPreference == FIRST)
+ children.add(firstChildrenNo++, child);
+ else
+ if (positionPreference == LAST)
+ children.add(children.size() - lastChildrenNo++, child);
+ else // NO PREFERENCE
+ children.add(children.size() - lastChildrenNo, child);
+ // detach from old parent, if any
+ //if (((HelpContribution) child).parent != null)
+ // ((HelpContribution) child).parent.children.removeElement(child);
+ // set the new parent
+ ((HelpContribution) child).parent = this;
+ return child;
+ }
+ /**
+ * Adds a child and returns it
+ * @returns com.ibm.itp.contributions.HelpContribution
+ * @param parentNode com.ibm.itp.contributions.HelpContribution
+ */
+ public Contribution insertNeighbouringChild(
+ Contribution child,
+ Contribution newchild,
+ int positionPreference) {
+ // find position of existing child
+ int pos = -1;
+ for (int i = 0; i < children.size(); i++) {
+ if (children.get(i) == child) {
+ pos = i;
+ break;
+ }
+ }
+ if (pos == -1) {
+ //child not found
+ return null;
+ }
+ if (positionPreference == PREV)
+ children.add(pos, newchild);
+ else
+ children.add(pos + 1, newchild);
+ // detach from old parent, if any
+ //if (((HelpContribution) child).parent != null)
+ // ((HelpContribution) child).parent.children.removeElement(child);
+ // set the new parent
+ ((HelpContribution) newchild).parent = this;
+ return child;
+ }
+ /**
+ */
+ public void setID(String id) {
+ this.id = id;
+ }
+ /**
+ * Sets the label without translation, as it would appear if this was created from xml navigation file
+ * @param label - raw label, which needs to appear in the property fille, or untranslatable label
+ */
+ public void setRawLabel(String rawLabel) {
+ this.label = rawLabel;
+ }
+ /**
+ */
+ public String toString() {
+ return getID() + " " + getClass();
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInfoSet.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInfoSet.java
new file mode 100644
index 000000000..39ed8e482
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInfoSet.java
@@ -0,0 +1,93 @@
+package org.eclipse.help.internal.contributions.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.help.internal.contributors.*;
+import org.xml.sax.*;
+
+/**
+ * Views contribution implementation
+ */
+public class HelpInfoSet extends HelpContribution implements InfoSet {
+
+ protected String href;
+ protected boolean isStandalone;
+ /**
+ * @return com.ibm.itp.contributions.ViewSet
+ * @param id java.lang.String
+ */
+ public HelpInfoSet(Attributes attrs) {
+ super(attrs);
+ if (attrs != null) {
+ href = attrs.getValue(ViewContributor.INFOSET_HREF_ATTR);
+ isStandalone =
+ Boolean
+ .valueOf(attrs.getValue(ActionContributor.ACTIONS_STANDALONE_ATTR))
+ .booleanValue();
+ }
+
+ }
+ /**
+ * Implements the method for the Visitor pattern
+ * @param visitor com.ibm.itp.contributions.Visitor
+ */
+ public void accept(Visitor visitor) {
+ visitor.visit(this);
+ }
+ /**
+ * @return java.lang.String
+ */
+ public String getHref() {
+ return href;
+ }
+ /**
+ * getView method comment.
+ */
+ public InfoView getView(String name) {
+ for (Iterator it = getChildren(); it.hasNext();) {
+ InfoView view = (InfoView) it.next();
+ if (view.getID().equals(name))
+ return view;
+ }
+ return null;
+ }
+ /**
+ * getViewNames method comment.
+ */
+ public String[] getViewNames() {
+ InfoView[] views = getViews();
+ String[] names = new String[views.length];
+ for (int i = 0; i < names.length; i++)
+ names[i] = views[i].getID();
+ return names;
+ }
+ /**
+ * getViews method comment.
+ */
+ public InfoView[] getViews() {
+ InfoView[] views = new InfoView[children.size()];
+ Iterator it = getChildren();
+ for (int i = 0; it.hasNext(); i++) {
+ views[i] = (InfoView) it.next();
+ }
+ return views;
+ }
+ public boolean isStandalone() {
+ return isStandalone;
+ }
+ public void setHref(String href) {
+ this.href = href;
+ }
+ /**
+ * @return java.lang.String
+ */
+ public String toString() {
+ return getID();
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInfoView.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInfoView.java
new file mode 100644
index 000000000..3cf7a13ef
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInfoView.java
@@ -0,0 +1,92 @@
+package org.eclipse.help.internal.contributions.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+import org.xml.sax.*;
+
+/**
+ * View contribution implementation.
+ */
+public class HelpInfoView extends HelpContribution implements InfoView {
+ private Hashtable topicMap = new Hashtable(/* of Topic*/);
+ /**
+ * Constructor
+ */
+ public HelpInfoView(Attributes attrs) {
+ super(attrs);
+ }
+ /**
+ * @param visitor com.ibm.itp.ua.types.Visitor
+ */
+ public void accept(Visitor visitor) {
+ visitor.visit(this);
+ /*
+ // skip over the dummy root and visit its getChildren
+ Topic dummyRoot = (Topic)getRoot();
+ for (Enumeration e = dummyRoot.getChildren(); e.hasMoreElements(); )
+ {
+ Topic c = (Topic)e.nextElement();
+ c.accept(visitor);
+ }
+ */
+ }
+ /**
+ * Adds a child and returns it
+ * @returns com.ibm.itp.contributions.HelpContribution
+ * @param parentNode com.ibm.itp.contributions.HelpContribution
+ */
+ public Contribution addChild(Contribution child) {
+ children.add(child);
+ // detach from old parent, if any
+ if (((HelpContribution) child).parent != null)
+ ((HelpContribution) child).parent.children.remove(child);
+ // set the new parent
+ ((HelpContribution) child).parent = this;
+ return child;
+ }
+ public Contribution getContribution(String id) {
+ return (Contribution) topicMap.get(id);
+ }
+ public Topic getRoot() {
+ return (Topic) children.get(0);
+ }
+ /**
+ * Registers the topic with the view.
+ * The insert actions are for a specific view, so every time
+ * a topic is created must be registered with its view
+ *
+ * @param child com.ibm.itp.contributions.Contribution
+ */
+ public void registerTopic(Contribution topic) {
+ // If the topic already exists in the view then there are two cases:
+ // - the topic was directly inserted under the view because it did not
+ // exist in the view. In this case we must first detach the topic from the
+ // view so it will be re-attached later
+ // - or, this is caused by a second insertion of the same topic, in which case
+ // we must change its ID, assuming no further inserts are possible under it.
+ if (topicMap.containsKey(topic.getID())) {
+ // topic has been inserted more than once, so we need a new,
+ // unique id for the new topic object.
+ ((HelpContribution) topic).setID(
+ topic.getID() + "_" + SequenceGenerator.next());
+ } else {
+ // first time the topic has been added to the view, do nothing
+ }
+ // Keep track of this topic object
+ topicMap.put(topic.getID(), topic);
+ }
+ /**
+ * @return java.lang.String
+ */
+ public String toString() {
+ return id;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInsert.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInsert.java
new file mode 100644
index 000000000..fbcd6bbf8
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpInsert.java
@@ -0,0 +1,43 @@
+package org.eclipse.help.internal.contributions.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.xml.sax.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+
+/**
+ * Default implementation for a topic contribution
+ */
+public class HelpInsert extends HelpContribution implements Insert {
+ protected String fromID;
+ protected String toID;
+ protected String asID;
+ public HelpInsert(Attributes attrs) {
+ super(attrs);
+ if (attrs != null) {
+ fromID = attrs.getValue(ActionContributor.INSERT_FROM_ATTR);
+ toID = attrs.getValue(ActionContributor.INSERT_TO_ATTR);
+ asID = attrs.getValue(ActionContributor.INSERT_AS_ATTR);
+ }
+ }
+ public String getMode() {
+ return asID;
+ }
+ public String getSource() {
+ return fromID;
+ }
+ public String getTarget() {
+ return toID;
+ }
+ public String getView() {
+ Contribution p = this;
+ while (p.getParent() != null)
+ p = p.getParent();
+ return ((Action) p).getView();
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopic.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopic.java
new file mode 100644
index 000000000..9b4e972b3
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopic.java
@@ -0,0 +1,43 @@
+package org.eclipse.help.internal.contributions.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.help.internal.contributors.TopicContributor;
+import org.eclipse.help.internal.contributions.Topic;
+import org.eclipse.help.internal.contributions.Visitor;
+import org.xml.sax.*;
+import org.eclipse.help.IHelpTopic;
+
+/**
+ * Default implementation for a topic contribution
+ */
+public class HelpTopic extends HelpContribution implements Topic, IHelpTopic {
+
+ protected String href;
+
+ /**
+ * HelpTopic constructor comment.
+ */
+ public HelpTopic(Attributes attrs) {
+ super(attrs);
+ if (attrs != null)
+ href = attrs.getValue(TopicContributor.TOPIC_HREF_ATTR);
+ }
+ /**
+ * Implements the method for the Visitor pattern
+ * @param visitor com.ibm.itp.contributions.Visitor
+ */
+ public void accept(Visitor visitor) {
+ visitor.visit(this);
+ }
+ public String getHref() {
+ return href;
+ }
+ public void setHref(String href) {
+ this.href = href;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopicFactory.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopicFactory.java
new file mode 100644
index 000000000..0905d9575
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopicFactory.java
@@ -0,0 +1,61 @@
+package org.eclipse.help.internal.contributions.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.eclipse.help.internal.contributions.*;
+
+/**
+ * Factory for topic contributions.
+ * Each topic is also registered with the specified view,
+ * as topics are created for a view only.
+ */
+public class HelpTopicFactory {
+ protected static final HelpTopicFactory instance = new HelpTopicFactory();
+ protected Map topicPool = new HashMap();
+ protected static InfoView view;
+
+ /**
+ * HelpTopicFactory constructor comment.
+ */
+ protected HelpTopicFactory() {
+ super();
+ }
+ /**
+ */
+ public static Topic createTopic(Topic topicNode) {
+ Topic topic = new HelpTopicRef(topicNode);
+ if (view != null)
+ ((HelpInfoView) view).registerTopic(topic);
+ return topic;
+ }
+ /**
+ */
+ public static HelpTopicFactory getFactory() {
+ return instance;
+ }
+ /**
+ */
+ public Topic getTopic(Topic topicNode) {
+ Topic topic = (Topic) topicPool.get(topicNode);
+ if (topic == null) {
+ topic = new HelpTopicRef(topicNode);
+ topicPool.put(topicNode, topic);
+ }
+ return topic;
+ }
+ /**
+ */
+ public static void setView(InfoView v) {
+ view = v;
+ }
+ /**
+ */
+ public static void setView(HelpInfoView v) {
+ view = v;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopicRef.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopicRef.java
new file mode 100644
index 000000000..1a617d4aa
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributions/xml/HelpTopicRef.java
@@ -0,0 +1,38 @@
+package org.eclipse.help.internal.contributions.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.xml.sax.*;
+import org.eclipse.help.internal.contributors.TopicContributor;
+import org.eclipse.help.internal.contributions.*;
+
+/**
+ * Default implementation for a topic contribution
+ */
+public class HelpTopicRef extends HelpTopic implements TopicRef {
+ protected Topic topic;
+ public HelpTopicRef(Topic topic) {
+ super(null);
+ this.topic = topic;
+ id = topic.getID();
+ }
+ public String getHref() {
+ return topic.getHref();
+ }
+ public String getID() {
+ return id;
+ }
+ public String getLabel() {
+ return topic.getLabel();
+ }
+ public String getRawLabel() {
+ return ((HelpTopic) topic).getRawLabel();
+ }
+ public Topic getTopic() {
+ return topic;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ActionContributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ActionContributor.java
new file mode 100644
index 000000000..1d9969f76
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ActionContributor.java
@@ -0,0 +1,28 @@
+package org.eclipse.help.internal.contributors;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * Map (contexts) contributor
+ */
+public interface ActionContributor extends Contributor {
+ public static final String ACTIONS_ELEM = "actions";
+ public static final String ACTIONS_NAME_ATTR = NAME_ATTR;
+ public static final String ACTIONS_VIEW_ATTR = "infoview";
+ public static final String ACTIONS_STANDALONE_ATTR = "standalone";
+ public static final String INSERT_AS_ATTR = "as";
+ public static final String INSERT_AS_CHILD = "child";
+ public static final String INSERT_AS_FIRST_CHILD = "first-child";
+ public static final String INSERT_AS_LAST_CHILD = "last-child";
+ public static final String INSERT_AS_NEXT_SIB = "next-sib";
+ public static final String INSERT_AS_PREV_SIB = "prev-sib";
+ public static final String INSERT_ELEM = "insert";
+ public static final String INSERT_FROM_ATTR = "from";
+ public static final String INSERT_TO_ATTR = "to";
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContextContributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContextContributor.java
new file mode 100644
index 000000000..42c68b88a
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContextContributor.java
@@ -0,0 +1,32 @@
+package org.eclipse.help.internal.contributors;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+import org.eclipse.help.internal.util.*;
+
+/**
+ * Map (contexts) contributor
+ */
+public interface ContextContributor extends Contributor {
+
+ // Only for DESC_TXT_BOLD property, lets use the properties file
+ // since ID writers get exposed to this field.
+ public static final String MAP_ELEM = "map";
+ public static final String CONTEXT_ELEM = "context";
+ public static final String CONTEXTS_ELEM = "contexts";
+ public static final String DESC_ELEM = "description";
+ public static final String RELATED_ELEM = "topic";
+ public static final String RELATED_HREF = "href";
+ public static final String RELATED_LABEL = "label";
+ public static final String BOLD_CLOSE_TAG =
+ "</" + Resources.getString("bold_tag_name") + ">";
+ public static final String BOLD_TAG =
+ "<" + Resources.getString("bold_tag_name") + ">";
+ public static final String DESC_TXT_BOLD = Resources.getString("bold_tag_name");
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContextManager.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContextManager.java
new file mode 100644
index 000000000..c64c57706
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContextManager.java
@@ -0,0 +1,50 @@
+package org.eclipse.help.internal.contributors;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.Iterator;
+import org.eclipse.help.*;
+
+/**
+ * ContextManager maintains the list of contexts
+ * and performs look-ups.
+ */
+public interface ContextManager {
+
+ public static final String CONTEXT_EXTENSION = "org.eclipse.help.contexts";
+
+ /**
+ * Finds the context, given context ID.
+ */
+ public IContext getContext(String contextId);
+ /**
+ * Get contributions of some type, like contexts, topics, actions
+ * or views from a specified plugin.
+ * @return java.util.Iterator
+ * @param typeName java.lang.String
+ * @param pluginId java.lang.String
+ */
+ public Iterator getContributionsOfType(String pluginId, String typeName);
+ /**
+ * Finds the context description to display, given
+ * a an ordered list of (nested) context objects.
+ */
+ public String getDescription(Object[] contexts);
+ /**
+ * Finds the context related topics to display, given
+ * a an ordered list of (nested) context objects.
+ * Finds rest of the topics not returned by
+ * getRelatedTopics(Object[]). May take long to execute.
+ */
+ public IHelpTopic[] getMoreRelatedTopics(Object[] contexts);
+ /**
+ * Finds the context related topics to display, given
+ * a an ordered list of (nested) context objects
+ * Finds only some of the topics.
+ */
+ public IHelpTopic[] getRelatedTopics(Object[] contexts);
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContributionManager.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContributionManager.java
new file mode 100644
index 000000000..e210ea65d
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContributionManager.java
@@ -0,0 +1,29 @@
+package org.eclipse.help.internal.contributors;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.Iterator;
+
+/**
+ * Contributions manager.
+ */
+public interface ContributionManager {
+ public static final String CONTRIBUTION_EXTENSION =
+ "org.eclipse.help.contributions";
+
+ /**
+ */
+ Iterator getContributingPlugins();
+ /**
+ */
+ Iterator getContributionsOfType(String typeName);
+ /**
+ */
+ boolean hasNewContributions();
+ /** Saves the contribution info */
+ public void versionContributions();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/Contributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/Contributor.java
new file mode 100644
index 000000000..fd593b709
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/Contributor.java
@@ -0,0 +1,28 @@
+package org.eclipse.help.internal.contributors;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.core.runtime.IPluginDescriptor;
+
+/**
+ * Contributor objects. Reads the contribution documents of a certain type.
+ */
+public interface Contributor {
+ public static final String NAME_ATTR = "name";
+ public static final String ID_ATTR = "id";
+
+ /**
+ */
+ Contribution getContribution();
+ /**
+ */
+ IPluginDescriptor getPlugin();
+ /**
+ */
+ String getType();
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContributorCreator.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContributorCreator.java
new file mode 100644
index 000000000..7ca6b918c
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ContributorCreator.java
@@ -0,0 +1,21 @@
+package org.eclipse.help.internal.contributors;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.IPluginDescriptor;
+
+/**
+ * Contributor factory.
+ */
+public interface ContributorCreator {
+ /**
+ */
+ Contributor create(
+ IPluginDescriptor plugin,
+ IConfigurationElement configuration);
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/TopicContributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/TopicContributor.java
new file mode 100644
index 000000000..a871f59aa
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/TopicContributor.java
@@ -0,0 +1,24 @@
+package org.eclipse.help.internal.contributors;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * Topic contributor.
+ */
+public interface TopicContributor extends Contributor {
+ public static final String TOPICS_ELEM = "topics";
+ public static final String TOPICS_NAME_ATTR = NAME_ATTR;
+ public static final String TOPICS_ID_ATTR = ID_ATTR;
+
+ public static final String TOPIC_ELEM = "topic";
+ public static final String TOPIC_ID_ATTR = ID_ATTR;
+ public static final String TOPIC_LABEL_ATTR = "label";
+ public static final String TOPIC_HREF_ATTR = "href";
+
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ViewContributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ViewContributor.java
new file mode 100644
index 000000000..75cc60fce
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/ViewContributor.java
@@ -0,0 +1,25 @@
+package org.eclipse.help.internal.contributors;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * View Contributor
+ */
+public interface ViewContributor extends Contributor {
+
+ public static final String VIEW_ELEM = "infoview";
+ public static final String VIEW_ID_ATTR = ID_ATTR;
+ public static final String VIEW_LABEL_ATTR = "label";
+ public static final String INFOSET_ELEM = "infoset";
+ public static final String INFOSET_HREF_ATTR = "href";
+ public static final String INFOSET_ID_ATTR = ID_ATTR;
+ public static final String INFOSET_LABEL_ATTR = "label";
+ public static final String INFOSET_NAME_ATTR = NAME_ATTR;
+ public static final String INFOSET_STANDALONE_ATTR = "standalone";
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributionFactory.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributionFactory.java
new file mode 100644
index 000000000..adb068e9e
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributionFactory.java
@@ -0,0 +1,52 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.xml.sax.*;
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.xml.*;
+
+/**
+ * ContributionFactory
+ */
+public class ContributionFactory {
+ protected static final ContributionFactory instance = new ContributionFactory();
+ /**
+ * ContributionFactory constructor.
+ */
+ public ContributionFactory() {
+ super();
+ }
+ public Contribution createContribution(String name, Attributes atts) {
+ Contribution e = null;
+ if (name.equals(TopicContributor.TOPIC_ELEM))
+ e = new HelpTopic(atts);
+ else
+ if (name.equals(ActionContributor.ACTIONS_ELEM))
+ e = new HelpAction(atts);
+ else
+ if (name.equals(TopicContributor.TOPICS_ELEM))
+ e = new HelpContribution(atts);
+ else
+ if (name.equals(ActionContributor.INSERT_ELEM))
+ e = new HelpInsert(atts);
+ else
+ if (name.equals(ViewContributor.INFOSET_ELEM))
+ e = new HelpInfoSet(atts);
+ else
+ if (name.equals(ViewContributor.VIEW_ELEM))
+ e = new HelpInfoView(atts);
+ else
+ return null;
+
+ return e;
+ }
+ public static ContributionFactory instance() {
+ return instance;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributionParser.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributionParser.java
new file mode 100644
index 000000000..2bc9bd193
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributionParser.java
@@ -0,0 +1,185 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.xml.sax.*;
+import java.util.*;
+import java.io.*;
+import org.eclipse.help.internal.HelpSystem;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.help.internal.contributions.xml.HelpContribution;
+
+import java.net.URL;
+import org.apache.xerces.parsers.SAXParser;
+
+/**
+ * Parser for xml file
+ */
+public class ContributionParser
+ extends SAXParser
+ implements ErrorHandler, ContentHandler {
+ protected Stack elementStack = new Stack();
+ protected Contribution contribution;
+ protected ContributionFactory factory;
+ protected boolean FATAL_ERROR_OCCURRED = false;
+
+ public ContributionParser() {
+ this(ContributionFactory.instance());
+ }
+ public ContributionParser(ContributionFactory factory) {
+ super();
+ this.factory = factory;
+ try {
+ setContinueAfterFatalError(false);
+ } catch (SAXNotSupportedException e) {
+ } catch (SAXNotRecognizedException e) {
+ }
+ setErrorHandler(this);
+ setContentHandler((ContentHandler) this);
+ }
+ /**
+ * Receive notification of character data.
+ */
+ public void characters(char ch[], int start, int length) throws SAXException {
+ // no op
+ }
+ /**
+ * Receive notification of the end of a document.
+ */
+ public void endDocument() throws SAXException {
+ // no op
+ }
+ /**
+ * Receive notification of the end of an element.
+ */
+ public void endElement(String namespaceURI, String localName, String qName)
+ throws SAXException {
+ // only pop when no error has occurred.
+ if (!FATAL_ERROR_OCCURRED)
+ elementStack.pop();
+ }
+ public void endPrefixMapping(String s) {
+ }
+ /** Recoverable parser errors, such as an invalid document */
+
+ public void error(SAXParseException ex) {
+
+ String message = getMessage("E001", ex);
+ Logger.logError(message, null);
+ }
+ /** Irrecoverable errors, such as a document that is not well formed */
+
+ public void fatalError(SAXParseException ex) throws SAXException {
+ // capture that error has occurred. The way we handle contribution files with
+ // errors is by trying to add as much of the file as possible. The minute an error
+ // is detected, no other contributions from this file are created.
+ FATAL_ERROR_OCCURRED = true;
+
+ // create message string from exception
+ String message = getMessage("E002", ex);
+
+ // Log the error.
+ Logger.logError(message, ex);
+
+ // now pass it to the RuntimeHelpStatus object explicitly because we
+ // still need to display errors even if Logging is turned off.
+ RuntimeHelpStatus.getInstance().addParseError(message, ex.getSystemId());
+ }
+ public Contribution getContribution() {
+ // return null the minute an error occurres. Null is handled properly by calling
+ // classes.
+ if (FATAL_ERROR_OCCURRED)
+ return null;
+ else
+ return contribution;
+ }
+ protected ContributionFactory getContributionFactory() {
+ return factory;
+ }
+ private String getLocationString(SAXParseException ex) {
+ String systemId = ex.getSystemId();
+ return systemId;
+ }
+ private String getMessage(String messageID, SAXParseException ex) {
+ String param1 = getLocationString(ex);
+ String param2 = Integer.toString(ex.getLineNumber());
+ String param3 = Integer.toString(ex.getColumnNumber());
+ String param4 = ex.getMessage();
+ String message = Resources.getString(messageID, param1, param2, param3, param4);
+ return message;
+ }
+ /**
+ * Receive notification of ignorable whitespace in element content.
+ */
+ public void ignorableWhitespace(char ch[], int start, int length)
+ throws SAXException {
+ // no op
+ }
+ /**
+ * Receive notification of a processing instruction.
+ */
+ public void processingInstruction(String target, String data)
+ throws SAXException {
+ // no op
+ }
+ /**
+ * Receive an object for locating the origin of SAX document events.
+ */
+ public void setDocumentLocator(Locator locator) {
+ // no op
+ if (Logger.DEBUG)
+ Logger.logDebugMessage(
+ "ContributionParser",
+ "setDocumentLocator called with: " + locator.getPublicId());
+ }
+ public void skippedEntity(String s) {
+ }
+ /**
+ * Receive notification of the beginning of a document.
+ *
+ * <p>The SAX parser will invoke this method only once, before any
+ * other methods in this interface or in DTDHandler (except for
+ * setDocumentLocator).</p>
+ *
+ * @exception org.xml.sax.SAXException Any SAX exception, possibly
+ * wrapping another exception.
+ */
+ public void startDocument() throws SAXException {
+ // no op
+ }
+ /**
+ * Receive notification of the beginning of an element.
+ */
+ public void startElement(
+ String namespaceURI,
+ String localName,
+ String qName,
+ Attributes atts)
+ throws SAXException {
+ // make sure that no error has already occurred before adding to stack.
+ // for performance, do not create Contribution if error has already occurred.
+ if (!FATAL_ERROR_OCCURRED) {
+ Contribution e = getContributionFactory().createContribution(qName, atts);
+ if (e == null)
+ return;
+
+ if (elementStack.empty())
+ contribution = e;
+ else
+ ((HelpContribution) elementStack.peek()).addChild(e);
+ elementStack.push(e);
+ }
+ }
+ public void startPrefixMapping(String prefix, String uri) throws SAXException {
+ }
+ public void warning(SAXParseException ex) {
+
+ String message = getMessage("E003", ex);
+ Logger.logWarning(message);
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributorFactory.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributorFactory.java
new file mode 100644
index 000000000..efd9551ad
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/ContributorFactory.java
@@ -0,0 +1,81 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.contributors.*;
+
+/**
+ * Contributor factory:
+ */
+public class ContributorFactory {
+ protected static final ContributorFactory instance = new ContributorFactory();
+
+ protected Hashtable creators; // replace with HashMap later
+ /**
+ * ContributorFactory constructor.
+ */
+ protected ContributorFactory() {
+ super();
+
+ creators = new Hashtable();
+ creators.put(TopicContributor.TOPICS_ELEM, new XMLTopicContributorCreator());
+ creators.put(ViewContributor.INFOSET_ELEM, new XMLViewContributorCreator());
+ creators.put(ActionContributor.ACTIONS_ELEM, new XMLActionContributorCreator());
+ creators.put(
+ ContextContributor.CONTEXTS_ELEM,
+ new XMLContextContributorCreator());
+ }
+ /**
+ * @param id java.lang.String
+ * @param creator com.ibm.itp.ua.contribution.ContributorCreator
+ */
+ public void addContributorCreator(String id, ContributorCreator creator) {
+ creators.put(id, creator);
+ }
+ /**
+ * @return com.ibm.itp.ua.contribution.Contributor
+ * @param type java.lang.String
+ */
+ public Contributor createContributor(
+ IPluginDescriptor plugin,
+ IConfigurationElement contribution) {
+ ContributorCreator creator =
+ (ContributorCreator) creators.get(contribution.getName());
+
+ if ((creator == null) || (plugin == null) || (contribution == null)) {
+ // unknown contribution type, or invalid plugin or contribution
+ // returning null is properly handled by calling class.
+ return null;
+ } else {
+ return creator.create(plugin, contribution);
+ }
+ }
+ /**
+ * @return java.lang.String[]
+ */
+ public String[] getContributorTypes() {
+ Vector tmpTypes = new Vector();
+ Enumeration e = creators.keys();
+
+ while (e.hasMoreElements()) {
+ tmpTypes.addElement((String) e.nextElement());
+ }
+
+ String[] types = new String[tmpTypes.size()];
+ tmpTypes.copyInto(types);
+
+ return types;
+ }
+ /**
+ * @return com.ibm.itp.help.contribution.ContributorFactory
+ */
+ public static ContributorFactory getFactory() {
+ return instance;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContextManager.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContextManager.java
new file mode 100644
index 000000000..669c823b6
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContextManager.java
@@ -0,0 +1,321 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.w3c.dom.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributors.xml.*;
+import org.eclipse.help.*;
+import org.eclipse.help.internal.HelpSystem;
+import org.eclipse.help.internal.contributions.xml.*;
+import org.eclipse.help.internal.util.*;
+
+/**
+ * Maintains the list of contexts
+ * and performs look-ups.
+ */
+public class HelpContextManager implements ContextManager {
+ /** contexts are indexed by each plugin */
+ Map pluginsContexts = new Hashtable(/*of Map of Context*/);
+ /**
+ * HelpContextManager constructor.
+ */
+ public HelpContextManager() {
+ super();
+ }
+ private void addMap(String plugin, Element map) {
+ /*
+ if (map == null) return;
+
+ Map pluginContexts = (Map)pluginsContexts.get(plugin);
+ if (pluginContexts == null)
+ {
+ pluginContexts = new Hashtable();
+ pluginsContexts.put(plugin, pluginContexts);
+ }
+
+ NodeList children = map.getChildNodes();
+ for (int i=0; i<children.getLength(); i++)
+ {
+ Node child = children.item(i);
+ if (child.getNodeType() != Node.ELEMENT_NODE) continue;
+ Element contextElement = (Element)child;
+ String id = contextElement.getAttribute(ContextContributor.ID_ATTR);
+ // Try merging an existing context with the same id
+ // with the new one. If none exists, just add it.
+ Context oldContext = (Context)pluginContexts.get(id);
+ if (oldContext == null)
+ {
+ Context newContext = new Context(contextElement);
+ pluginContexts.put(id, newContext);
+ }
+ else
+ {
+ oldContext.merge(contextElement);
+ }
+ }
+ */
+ }
+ /**
+ * Finds the context, given context ID.
+ */
+ public IContext getContext(String contextId) {
+ if (contextId == null)
+ return null;
+ String plugin = contextId;
+ String id = contextId;
+ int dot = contextId.lastIndexOf('.');
+ if (dot != -1) {
+ plugin = contextId.substring(0, dot);
+ id = contextId.substring(dot + 1);
+ }
+
+ Map contexts = (Map) pluginsContexts.get(plugin);
+ if (contexts == null) {
+ // parse the xml context contribution files and load the context
+ // defintion (NOTE: the side-effect is that all the contexts defined
+ // by this plugin get loaded)
+ contexts = loadContext(plugin);
+ }
+
+ return (IContext) contexts.get(id);
+
+ }
+ /**
+ * Get contributions of some type, like contexts, topics, actions
+ * or views from a specified plugin. If no contributors are found, or
+ * if errors are encountered, return an empty Iterator.
+ * @return java.util.Iterator
+ * @param typeName java.lang.String
+ * @param pluginId java.lang.String
+ */
+ public Iterator getContributionsOfType(String pluginId, String typeName) {
+ List typedContributors = new ArrayList();
+
+ try {
+ // Get the help contributions for this plugin
+ IPluginDescriptor plugin =
+ Platform.getPluginRegistry().getPluginDescriptor(pluginId);
+ IExtension[] extensions = plugin.getExtensions();
+ IExtension helpContributions = null;
+ // Loop through all the contributions and find the help ones.
+ // Then, get the one specified by the typeName
+ for (int i = 0; extensions != null && i < extensions.length; i++) {
+ if (!ContextManager
+ .CONTEXT_EXTENSION
+ .equals(extensions[i].getExtensionPointUniqueIdentifier()))
+ continue;
+
+ helpContributions = extensions[i];
+ IConfigurationElement[] pluginContributions =
+ helpContributions.getConfigurationElements();
+ for (int j = 0; j < pluginContributions.length; j++) {
+ if (pluginContributions[j].getName().equals(typeName)) {
+ Contributor contributor =
+ ContributorFactory.getFactory().createContributor(
+ plugin,
+ pluginContributions[j]);
+ if (contributor != null)
+ typedContributors.add(contributor);
+ }
+ }
+ }
+ return typedContributors.iterator();
+ } catch (Exception e) {
+ // log failure.
+ String msg = Resources.getString("E011", pluginId);
+ Logger.logError(msg, e);
+ // this puts an empty Map in the pluginsContexts HashMap, which forces
+ // looking into nested Context objects.
+ return typedContributors.iterator();
+ }
+
+ }
+ /**
+ * Finds the context to display (text and related topics), given
+ * a an ordered list of (nested) context objects
+ */
+ public String getDescription(Object[] contexts) {
+ if (contexts == null)
+ return null;
+
+ // Scan the list and return the description from the first context containing data
+ for (int i = 0; i < contexts.length; i++) {
+ String description = getDescription(contexts[i]);
+ if (description != null)
+ return description;
+ }
+ // worst case scenario. Could not find description from any context object.
+ return null;
+ }
+ /**
+ * Finds the context description to display, given
+ * a an ordered list of (nested) context objects.
+ */
+ private String getDescription(Object context) {
+ if (context instanceof IContext)
+ return ((IContext) context).getText();
+
+ if (!(context instanceof String))
+ return null;
+
+ String contextId = (String) context;
+ String plugin = contextId;
+ String id = contextId;
+ int dot = contextId.lastIndexOf('.');
+ if (dot != -1) {
+ plugin = contextId.substring(0, dot);
+ id = contextId.substring(dot + 1);
+ }
+
+ Map contexts = (Map) pluginsContexts.get(plugin);
+ if (contexts == null) {
+ // parse the xml context contribution files and load the context
+ // defintion (NOTE: the side-effect is that all the contexts defined
+ // by this plugin get loaded)
+ contexts = loadContext(plugin);
+ }
+
+ IContext contextNode = (IContext) contexts.get(id);
+ if (contextNode != null)
+ return contextNode.getText();
+ else
+ // no context defined for this object. return null to enable
+ // lookup of description from other Contexts.
+ return null;
+ }
+ /**
+ * Finds the context related topics to display, given
+ * a an ordered list of (nested) context objects.
+ * Finds rest of the topics not returned by
+ * getRelatedTopics(Object[]). May take long to execute.
+ */
+ public IHelpTopic[] getMoreRelatedTopics(Object[] contexts) {
+ if (contexts == null)
+ return null;
+
+ ArrayList relatedTopics = new ArrayList();
+ // Skip the first one the list and return the related topics from the other contexts
+ for (int i = 1; i < contexts.length; i++) {
+ IHelpTopic[] topics = getRelatedTopics(contexts[i]);
+ if (topics != null) {
+ for (int j = 0; j < topics.length; j++)
+ relatedTopics.add(topics[j]);
+ }
+ }
+ IHelpTopic[] moreRelated = new IHelpTopic[relatedTopics.size()];
+ return (IHelpTopic[]) relatedTopics.toArray(moreRelated);
+ }
+ // NL enables a description string.
+ private String getNLdescription(String pluginID, String description) {
+ // if description starts with %, need to translate.
+ if (description.indexOf('%') == 0) {
+ // strip off the leading %
+ description = description.substring(1);
+ // now translate
+ description = DocResources.getPluginString(pluginID, description);
+ }
+
+ return description;
+
+ }
+ /**
+ * Finds the context to display (text and related topics), given
+ * a an ordered list of (nested) context objects
+ */
+ public IHelpTopic[] getRelatedTopics(Object[] contexts) {
+ if (contexts == null)
+ return null;
+
+ // Scan the list and return the related topics from the first context containing data
+ for (int i = 0; i < contexts.length; i++) {
+ IHelpTopic[] topics = getRelatedTopics(contexts[i]);
+ if (topics != null)
+ return topics;
+ }
+
+ // worst case scenario. Could not find related Topics in any context object.
+ return null;
+ }
+ /**
+ * Finds the context related topics to display, given
+ * a an ordered list of (nested) context objects
+ * Finds only some of the topics.
+ */
+ private IHelpTopic[] getRelatedTopics(Object context) {
+ if (context instanceof IContext)
+ return ((IContext) context).getRelatedTopics();
+
+ if (!(context instanceof String))
+ return null;
+
+ String contextId = (String) context;
+ String plugin = contextId;
+ String id = contextId;
+ int dot = contextId.lastIndexOf('.');
+ if (dot != -1) {
+ plugin = contextId.substring(0, dot);
+ id = contextId.substring(dot + 1);
+ }
+
+ Map contexts = (Map) pluginsContexts.get(plugin);
+ if (contexts == null) {
+ // parse the xml context contribution files and load the context
+ // defintion (NOTE: the side-effect is that all the contexts defined
+ // by this plugin get loaded)
+ contexts = loadContext(plugin);
+ }
+ IContext contextNode = (IContext) contexts.get(id);
+ if (contextNode != null)
+ return contextNode.getRelatedTopics();
+ else
+ // no context defined for this object. return null to enable
+ // lookup of description from other Contexts.
+ return null;
+ }
+ /**
+ * Finds the context to display (text and related topics), given
+ * a an ordered list of (nested) context objects
+ */
+ private Map loadContext(String plugin) {
+ Map contexts = (Map) pluginsContexts.get(plugin);
+ if (contexts == null) {
+ // read the context info from the XML contributions
+ Iterator contextsContributors =
+ getContributionsOfType(plugin, ContextContributor.CONTEXTS_ELEM);
+ contexts = new HashMap();
+ pluginsContexts.put(plugin, contexts);
+ // iterator over all contexts contributors and add all the contexts
+ // defined by this plugin
+ // NOTE: if performance is a problem, this can be improved by a better
+ // use of the SAX parser
+ while (contextsContributors.hasNext()) {
+ Contributor contextContributor = (Contributor) contextsContributors.next();
+ Contribution contrib = contextContributor.getContribution();
+
+ // contrib could be null if there was an error parsing the manifest file!
+ if (contrib == null);
+ // do nothing here because we need to load other Context files.
+ else {
+ for (Iterator contextIterator = contrib.getChildren();
+ contextIterator.hasNext();
+ ) {
+ HelpContext contextNode = (HelpContext) contextIterator.next();
+ String description = contextNode.getDescription();
+ description = getNLdescription(plugin, description);
+ contextNode.setDescription(description);
+ contexts.put(contextNode.getID(), contextNode);
+ }
+ }
+ }
+ }
+ return contexts;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContributionManager.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContributionManager.java
new file mode 100644
index 000000000..28c484702
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContributionManager.java
@@ -0,0 +1,134 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+
+/**
+ * Contributions manager
+ */
+public class HelpContributionManager implements ContributionManager {
+ // Versioning info for detecting changes
+ protected static final String PLUGIN_VERSION_FILE =
+ Resources.getString("contribution_versions");
+ protected PluginVersionInfo pluginVersions = null;
+
+ // Manifest contributions
+ protected List contributors = new ArrayList();
+ protected List contributingPlugins = null;
+ public HelpContributionManager() {
+ super();
+ // create the help contributors based on plugin.xml files
+ createContributors();
+
+ }
+ /**
+ * Create a contributor (for actions,topics, or infosets)
+ */
+ private Contributor createContributor(
+ IPluginDescriptor plugin,
+ IConfigurationElement contribution) {
+ return ContributorFactory.getFactory().createContributor(plugin, contribution);
+ }
+ /**
+ * Creates the list of contributors for each help contributions
+ */
+ private void createContributors() {
+ // read extension point and retrieve all contributions
+ IExtensionPoint xpt =
+ Platform.getPluginRegistry().getExtensionPoint(CONTRIBUTION_EXTENSION);
+ if (xpt == null)
+ return; // no contributions...
+
+ IExtension[] extensions = xpt.getExtensions();
+ //// (1) For now, we keep track of all the plugins with contributions
+ /// including those without manifest
+ contributingPlugins = new Vector(extensions.length);
+
+ for (int i = 0; i < extensions.length; i++) {
+ IPluginDescriptor plugin = extensions[i].getDeclaringPluginDescriptor();
+ contributingPlugins.add(plugin); //// see above comment (1)
+ IConfigurationElement[] pluginContributions =
+ extensions[i].getConfigurationElements();
+ for (int j = 0; j < pluginContributions.length; j++) {
+ ///if (MapContributor.MAP_ELEM.equals(pluginContributions[j].getName())) continue;
+ Contributor contributor = createContributor(plugin, pluginContributions[j]);
+ if (contributor != null) {
+ contributors.add(contributor);
+ }
+ }
+ }
+ }
+ /**
+ * @return java.util.Vector
+ */
+ public Iterator getContributingPlugins() {
+ /*
+ /////NOTE: Uncomment this later, when only want to know the real contributors
+ //// Currently all the plugins with a contribution, even without manifests are returned.
+ //// This is done to allow migration from old manifests to new format....
+
+ if (contributingPlugins == null)
+ {
+ contributingPlugins = new Vector(contributors.size());
+ for (Enumeration e = contributors.elements(); e.hasMoreElements(); )
+ {
+ IPluginDescriptor pluginDescriptor = ((Contributor) e.nextElement()).getPlugin();
+ if (!contributingPlugins.contains(pluginDescriptor))
+ {
+ contributingPlugins.addElement(pluginDescriptor);
+ }
+ }
+ }
+ */
+ if (contributingPlugins == null)
+ return null;
+ else
+ return contributingPlugins.iterator();
+ }
+ /**
+ * Get contributions of some type, like topics, actions or views
+ * @return java.util.Iterator
+ * @param typeName java.lang.String
+ */
+ public Iterator getContributionsOfType(String typeName) {
+ List contribDocs = new ArrayList();
+ for (Iterator it = contributors.iterator(); it.hasNext();) {
+ Contributor c = (Contributor) it.next();
+ if (c.getType().equals(typeName)) { // CASE SENSITIVE
+ Contribution contrib = c.getContribution();
+ if (contrib != null) {
+ contribDocs.add(contrib);
+ }
+ }
+ }
+
+ return contribDocs.iterator();
+ }
+ /**
+ * @return boolean
+ */
+ public boolean hasNewContributions() {
+ if (pluginVersions == null) {
+ // see what has changed since last time
+ pluginVersions =
+ new PluginVersionInfo(PLUGIN_VERSION_FILE, getContributingPlugins());
+ }
+ return pluginVersions.detectChange();
+ }
+ /**
+ * Insert the method's description here.
+ *
+ */
+ public void versionContributions() {
+ pluginVersions.save();
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContributionManagerProxy.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContributionManagerProxy.java
new file mode 100644
index 000000000..76fb0f6f7
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/HelpContributionManagerProxy.java
@@ -0,0 +1,124 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import java.io.*;
+import java.net.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.xml.*;
+import org.eclipse.help.internal.contributions.*;
+
+import org.eclipse.help.internal.HelpSystem;
+import org.eclipse.help.internal.server.TempURL;
+
+/**
+ * A proxy to the real contribution manager.
+ * Since the online contribution are on the server
+ * this should first copy the information locally and
+ * then create a real contribution manager to handle
+ * the calls.
+ */
+public class HelpContributionManagerProxy implements ContributionManager {
+ /** The real contribution manager */
+ private HelpContributionManager contributionManager;
+
+ /** Empty iterator*/
+ private static Iterator emptyIterator = (new ArrayList(0)).iterator();
+ /** the infosets obtained from the server */
+ private ArrayList infosets = null;
+
+ /**
+ * HelpContributionManagerProxy constructor comment.
+ */
+ public HelpContributionManagerProxy() {
+ super();
+ }
+ /**
+ * Not supported on the proxy.
+ */
+ public Iterator getContributingPlugins() {
+ return emptyIterator;
+ }
+ /**
+ * For remote install we only return the infosets
+ */
+ public Iterator getContributionsOfType(String typeName) {
+ if (!typeName.equals(ViewContributor.INFOSET_ELEM))
+ return emptyIterator;
+
+ // we already got them, so return it
+ if (infosets != null)
+ return infosets.iterator();
+
+ // get them from the server
+ infosets = new ArrayList();
+ InputStream in = null;
+ try {
+ URL remoteInfosetFile =
+ new URL(
+ HelpSystem.getRemoteHelpServerURL(),
+ HelpSystem.getRemoteHelpServerPath()
+ + "/"
+ + TempURL.getPrefix()
+ + "/infosets.tab");
+ // may want to define constants as a resource
+
+ if (Logger.DEBUG)
+ Logger.logDebugMessage(
+ "HelpContributionManagerProxy",
+ "Loading infosets= " + remoteInfosetFile.toExternalForm());
+
+ BufferedReader reader = null;
+ try {
+ reader =
+ new BufferedReader(new InputStreamReader(remoteInfosetFile.openStream()));
+ } catch (Exception ioe) {
+ Logger.logError("Could not copy the infoset data from server", ioe);
+ return emptyIterator;
+ }
+
+ String line;
+ while ((line = reader.readLine()) != null) {
+ StringTokenizer tokens =
+ new StringTokenizer(line, PersistentMap.columnSeparator, true);
+ HelpInfoSet infoset = new HelpInfoSet(null);
+ infoset.setID(tokens.nextToken());
+ infoset.setRawLabel(tokens.nextToken());
+ infosets.add(infoset);
+ }
+ try {
+ in.close();
+ } catch (Exception ioe) {
+ }
+ } catch (Exception ioe) {
+ Logger.logError("Could not copy the infoset data from server", ioe);
+ try {
+ if (in != null)
+ in.close();
+ } catch (IOException e) {
+ }
+ } finally {
+ return infosets.iterator();
+ }
+ }
+ /**
+ */
+ public Iterator getContributionsOfType(String pluginId, String typeName) {
+ return emptyIterator;
+ }
+ /**
+ */
+ public boolean hasNewContributions() {
+ return false;
+ }
+ /** Saves the contribution info */
+ public void versionContributions() {
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLActionContributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLActionContributor.java
new file mode 100644
index 000000000..11eaf063a
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLActionContributor.java
@@ -0,0 +1,47 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.Contribution;
+
+/**
+ * Action contributor
+ */
+public class XMLActionContributor
+ extends XMLContributor
+ implements ActionContributor {
+ /**
+ * XMLActionContributor constructor comment.
+ * @param plugin com.ibm.itp.core.api.plugins.IPluginDescriptor
+ * @param configuration com.ibm.itp.core.api.plugins.IConfigurationElement
+ */
+ public XMLActionContributor(
+ IPluginDescriptor plugin,
+ IConfigurationElement configuration) {
+ super(plugin, configuration);
+ }
+ /**
+ * getActions method comment.
+ */
+ public Contribution getContribution() {
+ return getContribution(ACTIONS_NAME_ATTR);
+ }
+ /**
+ * @return java.lang.String
+ */
+ public String getType() {
+ return ActionContributor.ACTIONS_ELEM;
+ }
+ /**
+ * @param doc org.w3c.dom.Document
+ */
+ protected void preprocess(Contribution contrib) {
+ /// XXX TO DO - ensure ALL ids are fully qualified
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLActionContributorCreator.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLActionContributorCreator.java
new file mode 100644
index 000000000..72fa0fc04
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLActionContributorCreator.java
@@ -0,0 +1,30 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.contributors.*;
+
+/**
+ * XML Action Contribution Creator
+ */
+public class XMLActionContributorCreator implements ContributorCreator {
+ /**
+ * XMLTopicContributorCreator constructor
+ */
+ public XMLActionContributorCreator() {
+ super();
+ }
+ /**
+ * create
+ */
+ public Contributor create(
+ IPluginDescriptor plugin,
+ IConfigurationElement configuration) {
+ return new XMLActionContributor(plugin, configuration);
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContextContributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContextContributor.java
new file mode 100644
index 000000000..ca6c68821
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContextContributor.java
@@ -0,0 +1,202 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.xml.sax.*;
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.help.internal.contributions.xml.*;
+import org.eclipse.help.internal.util.*;
+
+/**
+ * Context contributor
+ */
+public class XMLContextContributor
+ extends XMLContributor
+ implements ContextContributor {
+ static class ContextContributionFactory extends ContributionFactory {
+ // Override the super class static field
+ protected static final ContextContributionFactory instance =
+ new ContextContributionFactory();
+ /**
+ * ContributionFactory constructor comment.
+ */
+ public ContextContributionFactory() {
+ super();
+ }
+
+ public Contribution createContribution(String name, Attributes atts) {
+ Contribution e = null;
+ // NOTE: we don't create an element for the description
+ if (name.equals(ContextContributor.CONTEXTS_ELEM))
+ e = new HelpContribution(atts);
+ else
+ if (name.equals(ContextContributor.CONTEXT_ELEM))
+ e = new HelpContext(atts);
+ else
+ if (name.equals(ContextContributor.RELATED_ELEM))
+ e = new HelpTopic(atts);
+ else
+ return null;
+
+ return e;
+ }
+
+ public static ContributionFactory instance() {
+ return instance;
+ }
+ }
+
+ static class ContextContributionParser extends ContributionParser {
+ StringBuffer buffer = new StringBuffer();
+ boolean seenDescription = false;
+
+ public ContextContributionParser() {
+ super(ContextContributionFactory.instance());
+ }
+
+ public void characters(char ch[], int start, int length) throws SAXException {
+ if (seenDescription)
+ buffer.append(ch, start, length);
+
+ if (Logger.DEBUG)
+ Logger.logDebugMessage(
+ "XMLContextContributor",
+ "got char from parser= "
+ + new StringBuffer().append(ch, start, length).toString());
+
+ }
+
+ public void endElement(String namespaceURI, String localName, String qName)
+ throws SAXException {
+ // make sure that no error has already occurred before adding to stack.
+ if (!FATAL_ERROR_OCCURRED) {
+ // We don't create a description element
+ if (qName.equals(ContextContributor.DESC_ELEM)) {
+ seenDescription = false;
+ ((HelpContext) elementStack.peek()).setDescription(buffer.toString());
+ buffer.setLength(0);
+ } else
+ if (qName.equals(ContextContributor.DESC_TXT_BOLD)) {
+ // pop the starting bold tag
+ elementStack.pop();
+ if (!(elementStack.peek()).equals(ContextContributor.BOLD_TAG))
+ buffer.append(ContextContributor.BOLD_CLOSE_TAG);
+
+ } else
+ super.endElement(namespaceURI, localName, qName);
+ }
+ }
+
+ public void startElement(
+ String namespaceURI,
+ String localName,
+ String qName,
+ Attributes atts)
+ throws SAXException {
+ // make sure that no error has already occurred before adding to stack.
+ if (!FATAL_ERROR_OCCURRED) {
+ // We don't create a description element
+ if (qName.equals(ContextContributor.DESC_ELEM))
+ seenDescription = true;
+ else
+ if (qName.equals(ContextContributor.DESC_TXT_BOLD)) {
+
+ // peek into stack to findout if a bold tag element already
+ // exists. If we find one, then we do not add the bold tag to
+ // the current StringBuffer of description.
+ // ie: there are many bold start tags in the stack, but we appended
+ // the tag only once to the description string.
+ // eg: (b) some text (b) more test (/b) more text (/b) will result
+ // in all of the sentence being bold.
+
+ if (!(elementStack.peek()).equals(ContextContributor.BOLD_TAG))
+ buffer.append(ContextContributor.BOLD_TAG);
+ elementStack.push(ContextContributor.BOLD_TAG);
+ } else
+ super.startElement(namespaceURI, localName, qName, atts);
+ }
+ }
+ }
+
+ /**
+ * XMLViewContributor constructor comment.
+ * @param plugin com.ibm.itp.core.api.plugins.IPluginDescriptor
+ * @param configuration com.ibm.itp.core.api.plugins.IConfigurationElement
+ */
+ public XMLContextContributor(
+ IPluginDescriptor plugin,
+ IConfigurationElement configuration) {
+ super(plugin, configuration);
+ }
+ /**
+ * getViews method comment.
+ */
+ public Contribution getContribution() {
+ return getContribution(NAME_ATTR);
+ }
+ /**
+ * Returns the contribution factory.
+ * Use the default contribution factory, but certain contributors can
+ * provide specialized subclasses.
+ */
+ protected ContributionParser getContributionParser() {
+ if (contributionParser == null)
+ contributionParser = new ContextContributionParser();
+ return contributionParser;
+ }
+ /**
+ * @return String
+ */
+ public String getType() {
+ return ContextContributor.MAP_ELEM;
+ }
+ /**
+ */
+ protected void preprocess(Contribution contrib) {
+ // update the ids and href only for child Topics (ie: related topics).
+ // we know that we a Context contributrion to start with.
+ // this is stored as a HelpContribution)
+ for (Iterator children = contrib.getChildren(); children.hasNext();) {
+ // update the id and href only for Topic node.
+ // may need to revist! we may need to update the ids of Context also.
+ Object child = children.next();
+ if (child instanceof Topic) {
+ updateIDs((Contribution) child);
+ updateHrefs((Topic) child);
+ } else
+ if (child instanceof Context) {
+ preprocess((Contribution) child);
+ }
+ }
+ }
+ /**
+ * Utility method that scans the topics for all href attributes and update them
+ * to include the plugin id (i.e. create a help url).
+ */
+ protected void updateHrefs(Topic topic) {
+ // set the href on the input contribution
+ String href = topic.getHref();
+ if (href == null)
+ ((HelpTopic) topic).setHref("");
+ else {
+ if (!href.equals("") // no empty link
+ && !href.startsWith("/") // no help url
+ && href.indexOf(':') == -1) // no other protocols
+ {
+ ((HelpTopic) topic).setHref("/" + plugin.getUniqueIdentifier() + "/" + href);
+ }
+ }
+
+ // recurse to children
+ for (Iterator topics = topic.getChildren(); topics.hasNext();) {
+ updateHrefs((Topic) topics.next());
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContextContributorCreator.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContextContributorCreator.java
new file mode 100644
index 000000000..8d309589d
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContextContributorCreator.java
@@ -0,0 +1,30 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.contributors.*;
+
+/**
+ * Factory for map contributors
+ */
+public class XMLContextContributorCreator implements ContributorCreator {
+ /**
+ * XMLTopicContributorCreator constructor.
+ */
+ public XMLContextContributorCreator() {
+ super();
+ }
+ /**
+ * create method.
+ */
+ public Contributor create(
+ IPluginDescriptor plugin,
+ IConfigurationElement configuration) {
+ return new XMLContextContributor(plugin, configuration);
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContributor.java
new file mode 100644
index 000000000..cc7dad6d6
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLContributor.java
@@ -0,0 +1,156 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.xml.sax.*;
+import java.util.*;
+import java.io.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+import java.net.*;
+import org.eclipse.help.internal.contributions.xml.HelpContribution;
+
+/**
+ * Basic contributor
+ */
+public abstract class XMLContributor implements Contributor {
+ protected IPluginDescriptor plugin = null;
+ protected IConfigurationElement configuration = null;
+ protected Contribution contribution = null;
+ // always call the getContributionParser() to use this....
+ protected ContributionParser contributionParser = null;
+
+ /**
+ * XMLContributor constructor comment.
+ */
+ public XMLContributor(
+ IPluginDescriptor plugin,
+ IConfigurationElement configuration) {
+ super();
+
+ this.plugin = plugin;
+ this.configuration = configuration;
+ }
+ /**
+ * @return java.lang.String
+ * @param plugin com.ibm.itp.core.api.plugins.IPluginDescriptor
+ */
+ protected String createUniqueID(IPluginDescriptor plugin) {
+ return plugin.getUniqueIdentifier() + "." + SequenceGenerator.next();
+ }
+ /**
+ * @return org.w3c.dom.Document
+ */
+ public abstract Contribution getContribution();
+ /**
+ * @return org.w3c.dom.Document
+ * @param contributionType java.lang.String
+ * @param idAttributeName java.lang.String
+ */
+ protected Contribution getContribution(String contributionNameAttribute) {
+ if (contribution == null) {
+ contribution = load(contributionNameAttribute);
+ if (contribution != null) {
+ preprocess(contribution);
+ }
+ }
+ return contribution;
+ }
+ /**
+ * Returns the contribution factory.
+ * Use the default contribution factory, but certain contributors can
+ * provide specialized subclasses.
+ */
+ protected ContributionParser getContributionParser() {
+ if (contributionParser == null)
+ contributionParser = new ContributionParser();
+ return contributionParser;
+ }
+ /**
+ * getPluginID method comment.
+ */
+ public IPluginDescriptor getPlugin() {
+ return plugin;
+ }
+ /**
+ * @return boolean
+ * @param shortID java.lang.String
+ */
+ protected boolean isValidShortID(String shortID) {
+ return shortID.indexOf(".") == -1;
+ }
+ /**
+ * @param elementType java.lang.String
+ * @param documentList java.util.Vector
+ */
+ protected Contribution load(String nameAttribute) {
+ Contribution contribution = null;
+ URL xmlURL = null;
+ try {
+ xmlURL =
+ new URL(plugin.getInstallURL(), configuration.getAttribute(nameAttribute));
+ InputStream stream = xmlURL.openStream();
+ if (stream == null)
+ return null;
+
+ InputSource source = new InputSource(stream);
+ // set id info for parser exceptions.
+ // use toString method to capture protocol...etc
+ source.setSystemId(xmlURL.toString());
+
+ ContributionParser parser = getContributionParser();
+ parser.parse(source);
+ stream.close();
+ contribution = parser.getContribution();
+ } catch (MalformedURLException ue) {
+ Logger.logError(ue.getMessage(), ue);
+ } catch (SAXException se) {
+ Logger.logError(se.getMessage(), se);
+ } catch (IOException ioe) {
+ String msg = Resources.getString("E009", xmlURL.toString());
+ Logger.logError(msg, ioe);
+ // now pass it to the RuntimeHelpStatus object explicitly because we
+ // still need to display errors even if Logging is turned off.
+ RuntimeHelpStatus.getInstance().addParseError(msg, xmlURL.toString());
+ }
+
+ return contribution;
+ }
+ /**
+ * @param doc org.w3c.dom.Document
+ */
+ protected abstract void preprocess(Contribution contribution);
+ /**
+ * Utility method that scans the Document for all id attributes and update them
+ * to include the plugin id (i.e. create a fully qualified
+ * id).
+ * @param doc org.w3c.dom.Document
+ */
+ protected void updateIDs(Contribution contrib) {
+ // set the id on the input contribution
+ String id = contrib.getID();
+ if (id != null) {
+ // is valid node name?
+ if (isValidShortID(id)) {
+ ((HelpContribution) contrib).setID(plugin.getUniqueIdentifier() + "." + id);
+ } else {
+ // XXX ? Set the id to nothing?
+ }
+ } else {
+ // Create a unique id for the topic...
+ ((HelpContribution) contrib).setID(createUniqueID(plugin));
+ }
+
+ // recurse to children
+ for (Iterator contribs = contrib.getChildren(); contribs.hasNext();) {
+ HelpContribution c = (HelpContribution) contribs.next();
+ updateIDs(c);
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLTopicContributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLTopicContributor.java
new file mode 100644
index 000000000..faf0ad73f
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLTopicContributor.java
@@ -0,0 +1,74 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.help.internal.contributions.xml.HelpTopic;
+
+/**
+ * Topic contributor
+ */
+public class XMLTopicContributor
+ extends XMLContributor
+ implements TopicContributor {
+ /**
+ * @param plugin com.ibm.itp.core.api.plugins.IPluginDescriptor
+ * @param configuration com.ibm.itp.core.api.plugins.IConfigurationElement
+ */
+ public XMLTopicContributor(
+ IPluginDescriptor plugin,
+ IConfigurationElement configuration) {
+ super(plugin, configuration);
+
+ }
+ /**
+ * @return org.w3c.dom.Document
+ */
+ public Contribution getContribution() {
+ return getContribution(TOPICS_NAME_ATTR);
+ }
+ /**
+ * @return java.lang.String
+ */
+ public String getType() {
+ return TopicContributor.TOPICS_ELEM;
+ }
+ /**
+ * @param doc org.w3c.dom.Document
+ */
+ protected void preprocess(Contribution contrib) {
+ updateIDs(contrib);
+ for (Iterator topics = contrib.getChildren(); topics.hasNext();)
+ updateHrefs((Topic) topics.next());
+ }
+ /**
+ * Utility method that scans the topics for all href attributes and update them
+ * to include the plugin id (i.e. create a help url).
+ */
+ protected void updateHrefs(Topic topic) {
+ // set the href on the input contribution
+ String href = topic.getHref();
+ if (href == null)
+ ((HelpTopic) topic).setHref("");
+ else {
+ if (!href.equals("") // no empty link
+ && !href.startsWith("/") // no help url
+ && href.indexOf(':') == -1) // no other protocols
+ {
+ ((HelpTopic) topic).setHref("/" + plugin.getUniqueIdentifier() + "/" + href);
+ }
+ }
+
+ // recurse to children
+ for (Iterator topics = topic.getChildren(); topics.hasNext();) {
+ updateHrefs((Topic) topics.next());
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLTopicContributorCreator.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLTopicContributorCreator.java
new file mode 100644
index 000000000..ec1d9103c
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLTopicContributorCreator.java
@@ -0,0 +1,30 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.contributors.*;
+
+/**
+ * Factory for topic contributors
+ */
+public class XMLTopicContributorCreator implements ContributorCreator {
+ /**
+ * XMLTopicContributorCreator constructor comment.
+ */
+ public XMLTopicContributorCreator() {
+ super();
+ }
+ /**
+ * create method comment.
+ */
+ public Contributor create(
+ IPluginDescriptor plugin,
+ IConfigurationElement configuration) {
+ return new XMLTopicContributor(plugin, configuration);
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLViewContributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLViewContributor.java
new file mode 100644
index 000000000..561b2bbd1
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLViewContributor.java
@@ -0,0 +1,65 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.xml.HelpInfoSet;
+import org.eclipse.help.internal.contributions.Contribution;
+
+/**
+ * View contributor
+ */
+public class XMLViewContributor
+ extends XMLContributor
+ implements ViewContributor {
+
+ /**
+ * XMLViewContributor constructor comment.
+ * @param plugin com.ibm.itp.core.api.plugins.IPluginDescriptor
+ * @param configuration com.ibm.itp.core.api.plugins.IConfigurationElement
+ */
+ public XMLViewContributor(
+ IPluginDescriptor plugin,
+ IConfigurationElement configuration) {
+ super(plugin, configuration);
+ }
+ /**
+ * getViews method comment.
+ */
+ public Contribution getContribution() {
+ return getContribution(INFOSET_NAME_ATTR);
+ }
+ /**
+ * @return java.lang.String
+ */
+ public String getType() {
+ return ViewContributor.INFOSET_ELEM;
+ }
+ /**
+ * @param doc org.w3c.dom.Document
+ */
+ protected void preprocess(Contribution contrib) {
+ updateIDs(contrib);
+
+ // set the href on the input infoset
+ if (contrib instanceof HelpInfoSet) {
+ HelpInfoSet infoset = (HelpInfoSet) contrib;
+ String href = infoset.getHref();
+ if (href == null)
+ infoset.setHref("");
+ else {
+ if (!href.equals("") // no empty link
+ && !href.startsWith("/") // no help url
+ && href.indexOf(':') == -1) // no other protocols
+ {
+ infoset.setHref("/" + plugin.getUniqueIdentifier() + "/" + href);
+ }
+ }
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLViewContributorCreator.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLViewContributorCreator.java
new file mode 100644
index 000000000..9f8dd2b3f
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/contributors/xml/XMLViewContributorCreator.java
@@ -0,0 +1,30 @@
+package org.eclipse.help.internal.contributors.xml;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.contributors.*;
+
+/**
+ * Factory for view contributors
+ */
+public class XMLViewContributorCreator implements ContributorCreator {
+ /**
+ * XMLTopicContributorCreator constructor comment.
+ */
+ public XMLViewContributorCreator() {
+ super();
+ }
+ /**
+ * create method comment.
+ */
+ public Contributor create(
+ IPluginDescriptor plugin,
+ IConfigurationElement configuration) {
+ return new XMLViewContributor(plugin, configuration);
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/HelpNavigationManager.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/HelpNavigationManager.java
new file mode 100644
index 000000000..f4c0602ee
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/HelpNavigationManager.java
@@ -0,0 +1,191 @@
+package org.eclipse.help.internal.navigation;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.help.internal.HelpSystem;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.help.internal.contributors.xml.*;
+import org.eclipse.help.internal.util.*;
+
+/**
+ * Manages the navigation model. It generates it and it reas it back
+ * and instantiates the model for future rendering.
+ * There is a model (notifier) for each <views> node.
+ */
+public class HelpNavigationManager {
+ private NavigationModel currentModel;
+ private Map navigationModels = new HashMap(/* of NavigationModel */);
+
+ public final static String INFOSETS_FILE = "infosets";
+
+ private String currentInfosetId;
+
+ private Collection validInfosetIds = new ArrayList();
+
+ /**
+ * HelpNavigationManager constructor comment.
+ */
+ public HelpNavigationManager() {
+ super();
+
+ try {
+ // build collection of all valid (installed) infosets
+ ContributionManager cmgr = HelpSystem.getContributionManager();
+ Iterator infoSetContributors =
+ cmgr.getContributionsOfType(ViewContributor.INFOSET_ELEM);
+ while (infoSetContributors.hasNext()) {
+ InfoSet infoset = (InfoSet) infoSetContributors.next();
+ String infosetId = infoset.getID();
+ if (infosetId == null)
+ continue;
+ //if (!infoset.isStandalone() || !isEmpty(infosetId))
+ validInfosetIds.add(infosetId);
+ }
+
+ // build all the info sets: build the structure and generate the xml's
+ // Note: it is cheaper to do all the info sets now, since we've taken the hit to
+ // to some extra processing in parsing actions, etc.
+ // Also, in most cases there is only one info set.
+ if (cmgr.hasNewContributions()) {
+ // suggest memory cleanup, as we're going to use a bit of it
+ System.gc();
+
+ createNavigationModels();
+ cmgr.versionContributions();
+
+ // attemp to cleanup all the memory no longer needed
+ //System.gc();
+ }
+ } catch (Exception e) {
+ Logger.logError(e.getMessage(), e);
+ }
+ }
+ private void createNavigationModels() {
+ try {
+ // Keep track of all the infosets available
+ PersistentMap infosetsMap = new PersistentMap(INFOSETS_FILE);
+
+ ContributionManager cmgr = HelpSystem.getContributionManager();
+ InfosetBuilder builder = new InfosetBuilder(cmgr);
+ // merges all topics into views
+ Map infosets = builder.buildInformationSets();
+ for (Iterator it = infosets.values().iterator(); it.hasNext();) {
+ InfoSet infoset = (InfoSet) it.next();
+ NavigationModel m = new NavigationModel(infoset);
+ navigationModels.put(infoset.getID(), m);
+
+ // generate navigation file for each infoset
+ generateNavForInfoSet(infoset);
+
+ infosetsMap.put(infoset.getID(), infoset.getLabel());
+ }
+ // Save a file with all the infosets ids and labels
+ infosetsMap.save();
+ } catch (Exception e) {
+ Logger.logError(e.getMessage(), e);
+ }
+ }
+ /**
+ * @param viewSet com.ibm.itp.ua.view.ViewSet
+ * @param outputDir java.io.File
+ */
+ private void generateInfoSetNav(InfoSet infoSet, File outputDir) {
+ XMLNavGenerator navGen = new XMLNavGenerator(infoSet, outputDir);
+ navGen.generate();
+ }
+ /**
+ * @param viewSet com.ibm.itp.ua.view.ViewSet
+ */
+ private void generateNavForInfoSet(InfoSet infoSet) {
+ IPath path =
+ HelpSystem
+ .getPlugin()
+ .getStateLocation()
+ .addTrailingSeparator()
+ .append(infoSet.getID());
+
+ File outDir = path.toFile();
+ if (!outDir.exists()) {
+ outDir.mkdirs();
+ }
+
+ generateInfoSetNav(infoSet, outDir);
+ }
+ /**
+ * Returns the current navigation model
+ */
+ public InfoSet getCurrentInfoSet() {
+ NavigationModel navModel = getCurrentNavigationModel();
+ if (navModel == null)
+ return null;
+ else
+ return (InfoSet) navModel.getRootElement();
+ }
+ /**
+ * Returns the current navigation model
+ */
+ public NavigationModel getCurrentNavigationModel() {
+ if (currentModel == null) {
+ // no previous InfoSet loaded, find an InfoSet
+ /*ContributionManager cmgr = HelpSystem.getContributionManager();
+ Iterator infoSetContributors =
+ cmgr.getContributionsOfType(ViewContributor.INFOSET_ELEM);
+ if (infoSetContributors.hasNext())
+ setCurrentInfoSet(((InfoSet) infoSetContributors.next()).getID());*/
+ if (validInfosetIds.size() > 0)
+ setCurrentInfoSet((String) validInfosetIds.iterator().next());
+ }
+ return currentModel;
+ }
+ /**
+ * Returns the navigation model for an infoset
+ */
+ public InfoSet getInfoSet(String id) {
+ NavigationModel navModel = getNavigationModel(id);
+ if (navModel == null)
+ return null;
+ else
+ return (InfoSet) navModel.getRootElement();
+ }
+ /**
+ * Returns the navigation model for an infoset
+ */
+ public NavigationModel getNavigationModel(String id) {
+ if (id == null || id.equals(""))
+ return null;
+
+ // First check the cache
+ NavigationModel m = (NavigationModel) navigationModels.get(id);
+ if (m == null && validInfosetIds.contains(id)) {
+ m = new NavigationModel(id);
+ navigationModels.put(id, m);
+ }
+ return m;
+ }
+ /**
+ * Sets the current model
+ */
+ public void setCurrentInfoSet(String infosetId) {
+ if (validInfosetIds.contains(infosetId)) {
+ // Set global infoset and navigation model
+ currentInfosetId = infosetId;
+ // Set the current navigation model.
+ // Side effect: the model may be loaded at this time.
+ currentModel = getNavigationModel(infosetId);
+ }
+ }
+ /**
+ * Sets the current model
+ */
+ public void setCurrentNavigationModel(NavigationModel m) {
+ currentModel = m;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/InfosetBuilder.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/InfosetBuilder.java
new file mode 100644
index 000000000..7f07a3c8c
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/InfosetBuilder.java
@@ -0,0 +1,448 @@
+package org.eclipse.help.internal.navigation;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.help.internal.contributions.xml.*;
+
+/**
+ * Builder for the contribution hierarchy using the insert contributions.
+ */
+public class InfosetBuilder {
+ // Contributions data
+ private Iterator infosets;
+ private Iterator topics;
+ private Iterator actions;
+
+ // Topics data indexed by ID
+ private Map topicNodeMap = new HashMap(/* of <topic> Node */);
+ private Map topicSetNodeMap = new HashMap(/* of <topics> Node */);
+
+ // Infosets
+ private Map infoSetMap = new HashMap(/* of InfoSet */);
+
+ // Views data indexed by ID
+ private Map viewNodeMap = new HashMap(/* of <view> Node */);
+ // Actions data indexed by view ID
+ private Map actionNodeMap = new HashMap(/* of Vector of <action> Node */);
+ // Solo (default) actions data indexed by view ID
+ private Map soloActionNodeMap = new HashMap(/* of Vector of <action> Node */);
+
+ // Keep track of plugins with inserted topics
+ private Set integratedPlugins = new HashSet(/* of String */);
+
+ /*******************************************************/
+ /***** InsertAction ***********************************/
+ /*******************************************************/
+ // Action command to execute the insert scripts
+ class InsertAction //extends HelpContribution
+ {
+ private InfoView view;
+ private Insert insertNode;
+
+ public InsertAction(InfoView view, Insert insertNode) {
+ //super(node);
+ this.view = view;
+ HelpTopicFactory.setView(this.view);
+ this.insertNode = insertNode;
+ }
+
+ /**
+ * Execute the insert action. May need to execute nested action if not successful.
+ */
+ public boolean execute() {
+ String fromID = insertNode.getSource();
+ String toID = insertNode.getTarget();
+ String asType = insertNode.getMode();
+ // check conditions
+ if (isKnownView(fromID))
+ return false;
+ if ((isKnownTopic(fromID) || isKnownTopicSet(fromID))
+ && (isKnownView(toID) || isKnownTopic(toID))) {
+ int pref = HelpContribution.NORMAL;
+ if (asType.equals(ActionContributor.INSERT_AS_FIRST_CHILD)) {
+ pref = HelpContribution.FIRST;
+ } else
+ if (asType.equals(ActionContributor.INSERT_AS_LAST_CHILD)) {
+ pref = HelpContribution.LAST;
+ } else
+ if (asType.equals(ActionContributor.INSERT_AS_PREV_SIB)) {
+ pref = HelpContribution.PREV;
+ } else
+ if (asType.equals(ActionContributor.INSERT_AS_NEXT_SIB)) {
+ pref = HelpContribution.NEXT;
+ }
+ if (insertTopic(fromID, toID, view, pref))
+ return true;
+ }
+ return executeNested();
+ }
+
+ private boolean executeNested() {
+ // execute each action in part
+ for (Iterator nested = insertNode.getChildren(); nested.hasNext();) {
+ InsertAction action = new InsertAction(view, (HelpInsert) nested.next());
+ return action.execute();
+ }
+ return false;
+ }
+ }
+ /**
+ * HelpViewManager constructor comment.
+ */
+ public InfosetBuilder(ContributionManager cmgr) {
+ infosets = cmgr.getContributionsOfType(ViewContributor.INFOSET_ELEM);
+ topics = cmgr.getContributionsOfType(TopicContributor.TOPICS_ELEM);
+ actions = cmgr.getContributionsOfType(ActionContributor.ACTIONS_ELEM);
+ }
+ /**
+ * Builds the views objects from the view data
+ */
+ public Map buildInformationSets() {
+ // Index actions and topics by ID for easier lookup
+ sortTopics();
+ sortActions();
+
+ // Create the views set objects
+ while (infosets.hasNext()) {
+ InfoSet infoset = (InfoSet) infosets.next();
+ infoSetMap.put(infoset.getID(), infoset);
+ // build the views for this info set
+ buildViews(infoset);
+ }
+
+ // run the solo actions to build stand-alone navigation
+ buildStandaloneNavigation();
+
+ // do not keep empty infosets that were tagged as standalone
+ discardEmptyStandaloneInfosets();
+
+ return infoSetMap;
+ }
+ /**
+ * Builds the topics contributed by standalone actions
+ */
+ private void buildStandaloneNavigation() {
+ Iterator infosets = infoSetMap.values().iterator();
+ while (infosets.hasNext()) {
+ InfoSet infoset = (InfoSet) infosets.next();
+ InfoView[] infoviews = infoset.getViews();
+ for (int i = 0; i < infoviews.length; i++) {
+ // get list of solo actions for this view
+ List actions = (List) soloActionNodeMap.get(infoviews[i].getID());
+ List validSoloActions = getValidSoloActions(actions);
+ executeActions(infoviews[i], validSoloActions);
+ }
+ }
+ }
+ /**
+ * Builds the view object by wiring up the topics
+ * as specified in the insert actions.
+ * @return
+ * @param viewName java.lang.String
+ */
+ private void buildView(InfoView view) {
+ String viewID = view.getID();
+ // Registers the view as a topic, so <insert from=topic to=view> work
+ ((HelpInfoView) view).registerTopic(view);
+ topicNodeMap.put(viewID, view);
+
+ // Get build actions for this view
+ List actions = (List) actionNodeMap.get(viewID);
+ executeActions(view, actions);
+ }
+ /**
+ * Builds the views objects for an info set
+ * @return
+ * @param viewName java.lang.String
+ */
+ private void buildViews(InfoSet infoSet) {
+ for (Iterator views = infoSet.getChildren(); views.hasNext();) {
+ InfoView view = (InfoView) views.next();
+ // build the rest of the view (wire up all the topics)
+ buildView(view);
+ }
+ }
+ /**
+ * Remove empty standalone infosets
+ */
+ private void discardEmptyStandaloneInfosets() {
+ Iterator infosets = infoSetMap.values().iterator();
+ while (infosets.hasNext()) {
+ InfoSet infoset = (InfoSet) infosets.next();
+ if (!infoset.isStandalone())
+ continue;
+ InfoView[] infoviews = infoset.getViews();
+ boolean foundNonEmptyView = false;
+ for (int i = 0; !foundNonEmptyView && i < infoviews.length; i++)
+ if (!infoviews[i].getChildrenList().isEmpty())
+ foundNonEmptyView = true;
+
+ if (!foundNonEmptyView)
+ infosets.remove();
+ }
+ }
+ /**
+ * Builds the view object by wiring up the topics
+ * as specified in the insert actions.
+ * @return
+ * @param viewName java.lang.String
+ */
+ private void executeActions(InfoView view, List actions) {
+ if (actions == null)
+ return;
+ List unexecutedActions = new ArrayList();
+ for (Iterator e = actions.iterator(); e.hasNext();) {
+ Action actionsNode = (Action) e.next();
+
+ // execute each action in part
+ for (Iterator actionsList = actionsNode.getChildren();
+ actionsList.hasNext();
+ ) {
+ Insert insertNode = (Insert) actionsList.next();
+ InsertAction action = new InsertAction(view, insertNode);
+ if (!action.execute())
+ unexecutedActions.add(action);
+ }
+ }
+ // executing delayed actions
+ int noDelayed = 0;
+ while (unexecutedActions.size() != noDelayed) {
+ noDelayed = unexecutedActions.size();
+ for (int i = 0; i < unexecutedActions.size(); i++) {
+ InsertAction action = (InsertAction) unexecutedActions.get(i);
+ if (action.execute())
+ unexecutedActions.remove(i--);
+ }
+ }
+ }
+ /**
+ * Returns the actions are valid as solo actions.
+ * Valid actions are those whose "from" topics are from non-integrated plugins.
+ */
+ private List getValidSoloActions(List actions) {
+ if (actions == null)
+ return null;
+ List validSoloActions = new ArrayList(actions.size());
+ for (Iterator e = actions.iterator(); e.hasNext();) {
+ Action actionsNode = (Action) e.next();
+
+ // check each action in part
+ boolean isSoloAction = true;
+ for (Iterator actionsList = actionsNode.getChildren();
+ isSoloAction && actionsList.hasNext();
+ ) {
+ Insert insertNode = (Insert) actionsList.next();
+ String from = insertNode.getSource();
+ int index = from.lastIndexOf('.');
+ if (index == -1)
+ continue;
+ String plugin = from.substring(0, index);
+ if (integratedPlugins.contains(plugin))
+ isSoloAction = false;
+ }
+ if (isSoloAction)
+ validSoloActions.add(actionsNode);
+ }
+
+ return validSoloActions;
+ }
+ /**
+ * Inserts the topic and creates the HelpTopic objects
+ */
+ private boolean insertTopic(
+ String fromTopic,
+ String toTopic,
+ InfoView view,
+ int positionPreference) {
+ if ((positionPreference == HelpContribution.PREV)
+ || (positionPreference == HelpContribution.NEXT))
+ return insertTopicAsSib(fromTopic, toTopic, view, positionPreference);
+ else
+ return insertTopicAsChild(fromTopic, toTopic, view, positionPreference);
+ }
+ /**
+ * Inserts the topic and creates the HelpTopic objects
+ */
+ private boolean insertTopicAsChild(
+ String fromTopic,
+ String toTopic,
+ InfoView view,
+ int positionPreference) {
+ // do a simple insert
+ if (isKnownTopic(fromTopic)) {
+ Contribution parent = ((HelpInfoView) view).getContribution(toTopic);
+ if (parent == null)
+ parent = HelpTopicFactory.createTopic((Topic) topicNodeMap.get(toTopic));
+ Contribution child = ((HelpInfoView) view).getContribution(fromTopic);
+ if (child == null)
+ child = HelpTopicFactory.createTopic((Topic) topicNodeMap.get(fromTopic));
+ ((HelpContribution) parent).insertChild(child, positionPreference);
+
+ // keep track of this insertion for handling solo actions
+ trackTopic(fromTopic);
+
+ // now recursively insert all the children
+ Contribution topicNode = child;
+ if (child instanceof TopicRef)
+ topicNode = ((TopicRef) child).getTopic();
+
+ for (Iterator childTopics = topicNode.getChildren(); childTopics.hasNext();) {
+ Contribution childNode = (Contribution) childTopics.next();
+ String newFromTopic = childNode.getID();
+ insertTopic(newFromTopic, fromTopic, view, HelpContribution.NORMAL);
+ }
+ } else
+ if (isKnownTopicSet(fromTopic)) {
+ // insert all the child topics nodes
+ Contribution topicSet = (Contribution) topicSetNodeMap.get(fromTopic);
+ for (Iterator topics = topicSet.getChildren(); topics.hasNext();) {
+ Contribution topic = (Contribution) topics.next();
+ insertTopic(topic.getID(), toTopic, view, positionPreference);
+ }
+ }
+ return true; //success
+ }
+ /**
+ * Inserts the topic and creates the HelpTopic objects
+ */
+ private boolean insertTopicAsSib(
+ String fromTopic,
+ String nearTopic,
+ InfoView view,
+ int positionPreference) {
+ // do a simple insert
+ if (isKnownTopic(fromTopic)) {
+ Contribution refSib = ((HelpInfoView) view).getContribution(nearTopic);
+ if (refSib == null)
+ return false; //sibling must already be inserted
+ Contribution parent = refSib.getParent();
+ if (parent == null)
+ return false; //parent must exist for proper insertion
+ Contribution newSib = ((HelpInfoView) view).getContribution(fromTopic);
+ if (newSib == null)
+ newSib = HelpTopicFactory.createTopic((Topic) topicNodeMap.get(fromTopic));
+ ((HelpContribution) parent).insertNeighbouringChild(
+ refSib,
+ newSib,
+ positionPreference);
+
+ // keep track of this insertion for handling solo actions
+ trackTopic(fromTopic);
+
+ // now recursively insert all the children
+ Contribution topicNode = newSib;
+ if (newSib instanceof TopicRef)
+ topicNode = ((TopicRef) newSib).getTopic();
+
+ for (Iterator childTopics = topicNode.getChildren(); childTopics.hasNext();) {
+ Contribution childNode = (Contribution) childTopics.next();
+ String newFromTopic = childNode.getID();
+ insertTopic(newFromTopic, fromTopic, view, HelpContribution.NORMAL);
+ }
+ } else
+ if (isKnownTopicSet(fromTopic)) {
+ Contribution refSib = ((HelpInfoView) view).getContribution(nearTopic);
+ if (refSib == null)
+ return false; //sibling must exist
+ Contribution parent = refSib.getParent();
+ if (parent == null)
+ return false; //parent must exist for proper insertion
+ // insert all the child topics nodes
+ Contribution topicSet = (Contribution) topicSetNodeMap.get(fromTopic);
+ List topics = topicSet.getChildrenList();
+ if (positionPreference == HelpContribution.NEXT) {
+ for (int i = topics.size() - 1; i >= 0; i--) {
+ Contribution topic = (Contribution) topics.get(i);
+ insertTopic(topic.getID(), nearTopic, view, positionPreference);
+ }
+ } else {
+ for (int i = 0; i < topics.size(); i++) {
+ Contribution topic = (Contribution) topics.get(i);
+ insertTopic(topic.getID(), nearTopic, view, positionPreference);
+ }
+ }
+ }
+ return true; //success
+ }
+ public boolean isKnownTopic(String topicID) {
+ return topicNodeMap.get(topicID) != null;
+ }
+ public boolean isKnownTopicSet(String topicSetID) {
+ return topicSetNodeMap.get(topicSetID) != null;
+ }
+ private boolean isKnownView(String viewName) {
+ return (viewNodeMap.get(viewName) != null);
+ }
+ /**
+ * Indexes actions by view id
+ * @return java.util.Vector
+ * @param viewName java.lang.String
+ */
+ private void sortActions() {
+ while (actions.hasNext()) {
+ Action actionNode = (Action) actions.next();
+ String viewID = actionNode.getView();
+ if (viewID.equals("")) {
+ // XXX EXCEPTION!!!
+ } else {
+ // do a CASE SENSITIVE match on the view name.
+ // We store a vector of actions under one id
+ if (actionNode.isStandalone()) {
+ List actions = (List) soloActionNodeMap.get(viewID);
+ if (actions == null)
+ actions = new ArrayList();
+ actions.add(actionNode);
+ soloActionNodeMap.put(viewID, actions);
+ } else {
+ List actions = (List) actionNodeMap.get(viewID);
+ if (actions == null)
+ actions = new ArrayList();
+ actions.add(actionNode);
+ actionNodeMap.put(viewID, actions);
+ }
+ }
+ }
+ }
+ /**
+ * Indexes topics by their ID for easier lookup
+ */
+ private void sortTopics() {
+ while (topics.hasNext()) {
+ Contribution topicSet = (Contribution) topics.next();
+ topicSetNodeMap.put(topicSet.getID(), topicSet);
+
+ // Put all the topics (the whole nested tree) into a hashtable indexed by id
+ Stack stack = new Stack();
+ stack.push(topicSet.getChildren());
+ while (!stack.isEmpty()) {
+ Iterator children = (Iterator) stack.pop();
+ while (children.hasNext()) {
+ Contribution topic = (Contribution) children.next();
+ topicNodeMap.put(topic.getID(), topic);
+ Iterator subtopics = topic.getChildren();
+ if (subtopics.hasNext())
+ stack.push(subtopics);
+ }
+ }
+ }
+ }
+ /**
+ * Tracks the topics by its plugin.
+ * All the integrated plugins will be remembered, so the solo actions
+ * will not be applied to them.
+ */
+ private void trackTopic(String topicId) {
+ int i = topicId.lastIndexOf('.');
+ if (i == -1)
+ return;
+ String pluginId = topicId.substring(0, i);
+ integratedPlugins.add(pluginId);
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/NavigationModel.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/NavigationModel.java
new file mode 100644
index 000000000..35043b23f
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/NavigationModel.java
@@ -0,0 +1,235 @@
+package org.eclipse.help.internal.navigation;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.xml.sax.*;
+import java.util.*;
+import java.io.*;
+import org.eclipse.help.internal.HelpSystem;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.help.internal.contributions.*;
+import java.net.*;
+import org.eclipse.help.internal.contributors.xml.*;
+import org.eclipse.core.runtime.IPath;
+
+import org.eclipse.help.internal.server.TempURL;
+
+/**
+ * Domain notifier for the help model.
+ * It holds the model (views and topic elements).
+ */
+public class NavigationModel {
+
+ // the map of topic url to all possible topics
+ private Map urlToTopicMap = new HashMap();
+
+ private Contribution infoset;
+ private String infosetID;
+
+ /**
+ * HelpDomainNotifier constructor comment.
+ */
+ public NavigationModel(String infoset) {
+ super();
+ this.infosetID = infoset;
+
+ if (HelpSystem.isClient())
+ loadFromServer();
+ else
+ load();
+
+ registerURLs();
+ }
+ /**
+ * HelpDomainNotifier constructor comment.
+ */
+ public NavigationModel(Contribution infoset) {
+ super();
+ this.infoset = infoset;
+ registerURLs();
+ }
+ /**
+ * Generate the XML navigation file for this model (infoset)
+ */
+ private void generateNavigation() {
+ if (infoset == null)
+ return;
+
+ IPath path =
+ HelpSystem
+ .getPlugin()
+ .getStateLocation()
+ .addTrailingSeparator()
+ .append(infoset.getID());
+
+ File outDir = path.toFile();
+ if (!outDir.exists()) {
+ outDir.mkdirs();
+ }
+
+ XMLNavGenerator navGen = new XMLNavGenerator((InfoSet) infoset, outDir);
+ navGen.generate();
+ }
+ public Set getAllURLs() {
+ return urlToTopicMap.keySet();
+ }
+ /**
+ * Insert the method's description here.
+ * @return java.lang.String
+ */
+ public String getID() {
+ return infosetID;
+ }
+ public Contribution getRootElement() {
+ return infoset;
+ }
+ public Topic[] getTopicsWithURL(String url) {
+ // Correct URL format first to what is recorded in the map
+ int pos = url.indexOf("?");
+ if (pos > 0)
+ url = url.substring(0, pos);
+ else {
+ pos = url.indexOf("#");
+ if (pos > 0)
+ url = url.substring(0, pos);
+ }
+
+ // strip off the http://host:port/path
+ URL helpServerURL = HelpSystem.getLocalHelpServerURL();
+ if (helpServerURL != null && url.startsWith(helpServerURL.getProtocol())) {
+ url = url.substring(helpServerURL.toExternalForm().length());
+ } else
+ if (url.indexOf('/') != 0)
+ url = "/" + url;
+
+ // get topics for corrected URL from the map
+ return (Topic[]) urlToTopicMap.get(url);
+ }
+ /**
+ * Loads the xml model and creates the ui elements
+ */
+ private void load() {
+ String xmlFile =
+ HelpSystem
+ .getPlugin()
+ .getStateLocation()
+ .append(infosetID)
+ .append(XMLNavGenerator.NAV_XML_FILENAME)
+ .toOSString();
+ try {
+ ContributionParser parser = new ContributionParser();
+ if (Logger.DEBUG)
+ Logger.logDebugMessage("NavigationModel", "Loading _nav= " + xmlFile);
+ InputStream input = new FileInputStream(xmlFile);
+ parser.parse(new InputSource(input));
+ infoset = parser.getContribution();
+
+ } catch (SAXException se) {
+ Logger.logError(se.getMessage(), se);
+ } catch (IOException ioe) {
+ String msg = Resources.getString("E009", xmlFile.toString());
+ Logger.logError(msg, ioe);
+
+ // now pass it to the RuntimeHelpStatus object explicitly because we
+ // still need to display errors even if Logging is turned off.
+ RuntimeHelpStatus.getInstance().addParseError(msg, xmlFile);
+ }
+
+ }
+ /**
+ * Loads the xml model from the help server and creates the ui elements
+ */
+ private void loadFromServer() {
+ BufferedInputStream in = null;
+ try {
+ URL remoteNavFile =
+ new URL(
+ HelpSystem.getRemoteHelpServerURL(),
+ HelpSystem.getRemoteHelpServerPath()
+ + "/"
+ + TempURL.getPrefix()
+ + "/"
+ + infosetID
+ + "/"
+ + XMLNavGenerator.NAV_XML_FILENAME);
+
+ in = new BufferedInputStream(remoteNavFile.openStream());
+
+ ContributionParser parser = new ContributionParser();
+ if (Logger.DEBUG)
+ Logger.logDebugMessage(
+ "NavigationModel",
+ "Loading _nav= " + remoteNavFile.toExternalForm());
+ InputSource source = new InputSource(in);
+ parser.parse(source);
+ infoset = parser.getContribution();
+ in.close();
+
+ } catch (SAXException se) {
+ Logger.logError(se.getMessage(), se);
+ } catch (Exception ioe) {
+ Logger.logError("Could not copy the model data from server", ioe);
+ try {
+ if (in != null)
+ in.close();
+ } catch (IOException e) {
+ }
+ }
+
+ }
+ /**
+ * Registers an element with the model
+ */
+ private void registerURL(Topic topic) {
+ // if it is a topic, map it to its url;
+ String url = topic.getHref();
+ if (url == null || "".equals(url))
+ return;
+
+ // see if mapped already
+ Object t = urlToTopicMap.get(url);
+ Topic[] topics;
+ if (t == null) {
+ topics = new Topic[1];
+ topics[0] = topic;
+ } else {
+ topics = new Topic[((Topic[]) t).length + 1];
+ for (int i = 0; i < ((Topic[]) t).length; i++) {
+ topics[i] = ((Topic[]) t)[i];
+ }
+ topics[((Topic[]) t).length] = topic;
+ }
+ urlToTopicMap.put(url, topics);
+
+ }
+ /**
+ * Register all the topics by url
+ */
+ private void registerURLs() {
+ if (infoset == null)
+ return;
+ // Get the views
+ for (Iterator views = infoset.getChildren(); views.hasNext();) {
+ Contribution view = (Contribution) views.next();
+ Stack stack = new Stack();
+ stack.push(view.getChildren());
+ while (!stack.isEmpty()) {
+ Iterator topics = (Iterator) stack.pop();
+ while (topics.hasNext()) {
+ Topic topic = (Topic) topics.next();
+ registerURL(topic);
+ Iterator subtopics = topic.getChildren();
+ if (subtopics.hasNext())
+ stack.push(subtopics);
+ }
+ }
+ }
+ }
+ private void save() {
+ generateNavigation();
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/XMLGenerator.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/XMLGenerator.java
new file mode 100644
index 000000000..4ec6345f8
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/XMLGenerator.java
@@ -0,0 +1,70 @@
+package org.eclipse.help.internal.navigation;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.help.internal.contributions.*;
+
+/**
+ * Visitor class to walk the help structure and generate navigation xml
+ */
+public abstract class XMLGenerator extends HelpVisitor {
+
+ protected File outputDir = null;
+ protected PrintWriter out = null;
+ protected char viewChar = 'a';
+ private SequenceGenerator idGenerator = SequenceGenerator.getNewGenerator();
+ protected InfoSet infoSet = null;
+
+ /**
+ * HTMLGenerator constructor comment.
+ */
+ public XMLGenerator(InfoSet infoSet, File outputDir) {
+ super();
+
+ this.infoSet = infoSet;
+ this.outputDir = outputDir;
+ }
+ /**
+ */
+ public void generate() {
+ // The html generator is a visitor that needs to start from the view set
+ // and will descend to children, etc....
+ infoSet.accept(this);
+ }
+ /**
+ * @return java.lang.String
+ * @param viewNode com.ibm.itp.contribution.View
+ */
+ protected String generateID(InfoView view) {
+ return view.getID().replace('.', '_');
+ }
+ /**
+ * Simplifies url path by removing "/.." with the parent directory from the path
+ * @return java.lang.String
+ * @param url java.lang.String
+ */
+ protected static String reduceURL(String url) {
+ if (url == null)
+ return url;
+ while (true) {
+ int index = url.lastIndexOf("/../");
+ if (index <= 0)
+ break; //there is no "/../" or nothing before "/../" to simplify
+ String part1 = url.substring(0, index);
+ String part2 = url.substring(index + "/..".length());
+ index = part1.lastIndexOf("/");
+ if (index >= 0)
+ url = part1.substring(0, index) + part2;
+ else
+ url = part2;
+ }
+ return url;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/XMLNavGenerator.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/XMLNavGenerator.java
new file mode 100644
index 000000000..c3878781f
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/navigation/XMLNavGenerator.java
@@ -0,0 +1,160 @@
+package org.eclipse.help.internal.navigation;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.help.internal.contributions.xml.HelpContribution;
+
+/**
+ * This generates the XML file for the help navigation.
+ */
+public class XMLNavGenerator extends XMLGenerator {
+ protected StringBuffer pad = new StringBuffer();
+ protected final static String indent = " "; // two blanks indentation
+ protected Vector viewNames = new Vector();
+
+ protected static final String NAV_XML_FILENAME = "_nav.xml";
+
+ /**
+ * @param viewSet com.ibm.itp.ua.view.ViewSet
+ * @param outputDir java.io.File
+ */
+ public XMLNavGenerator(InfoSet infoSet, File outputDir) {
+ super(infoSet, outputDir);
+ viewChar = 'a';
+ }
+ /**
+ * @param view com.ibm.itp.ua.view.View
+ */
+ public void visit(InfoSet infoSet) {
+ try {
+ File outputFile = new File(outputDir, NAV_XML_FILENAME);
+ out = new PrintWriter(new BufferedWriter(new FileWriter(outputFile)));
+
+ out.println("<?xml version=\"1.0\"?>");
+ out.println("<?xml-stylesheet href=\"tree.xsl\" type=\"text/xsl\"?>");
+
+ out.println();
+
+ String href = infoSet.getHref();
+ String id = infoSet.getID();
+ String plugin = id.substring(0, id.lastIndexOf("."));
+ boolean standalone = infoSet.isStandalone();
+
+ StringBuffer options = new StringBuffer();
+ options.append("id=\"");
+ options.append(infoSet.getID());
+ options.append("\" label=\"");
+ options.append(((HelpContribution) infoSet).getRawLabel());
+ options.append("\" ");
+ if (!"".equals(href)) {
+ options.append("href=\"");
+ options.append(href);
+ options.append("\" ");
+ }
+ if (standalone) {
+ options.append("standalone=\"true\" ");
+ }
+
+ out.print("<infoset ");
+ out.print(options);
+ out.println(">");
+
+ out.println();
+
+ visitChildren(infoSet);
+
+ out.println("</infoset>");
+ out.println();
+
+ out.flush();
+ out.close();
+
+ } catch (IOException ioe) {
+ Logger.logError(Resources.getString("Error_in_generating_navigation"), ioe);
+ }
+ }
+ /**
+ * @param view com.ibm.itp.ua.view.View
+ */
+ public void visit(InfoView view) {
+
+ StringBuffer options = new StringBuffer();
+ options.append("id=\"");
+ options.append(generateID(view));
+ options.append("\" label=\"");
+ options.append(((HelpContribution) view).getRawLabel());
+ options.append("\" ");
+
+ out.println(
+ "<!-- "
+ + ((HelpContribution) view).getRawLabel()
+ + " infoview ["
+ + view.getID()
+ + "] -->");
+ out.print("<infoview ");
+ out.print(options.toString());
+ out.println(">");
+
+ // Generate the content of this view
+ visitChildren(view);
+
+ out.println("</infoview>"); // close the view division
+ out.println(
+ "<!-- End of " + ((HelpContribution) view).getRawLabel() + " infoview -->");
+ out.println();
+
+ // Use a new character for the identifiers in next view
+ viewChar++;
+ }
+ /**
+ * @param viewNode com.ibm.itp.ua.view.ViewNode
+ */
+ public void visit(Topic topic) {
+ try {
+ String href = reduceURL(topic.getHref());
+ String id = topic.getID();
+ String plugin = id.substring(0, id.lastIndexOf("."));
+ /*
+ if (href == null || "".equals(href)) {
+ href = "";
+ } else {
+ href = "/" + plugin + "/" + href;
+ }
+ */
+ StringBuffer anchor = new StringBuffer();
+ pad.append(indent);
+ anchor
+ .append(pad)
+ .append("<topic href=\"")
+ .append(href)
+ .append("\" id=\"")
+ .append(id)
+ .append("\" label=\"")
+ .append(((HelpContribution) topic).getRawLabel())
+ .append("\" >");
+
+ if (topic.getChildren().hasNext()) {
+ out.println(anchor.toString());
+
+ // Generate nested topics
+ visitChildren(topic);
+ } else
+ out.print(anchor.toString());
+
+ out.print(pad);
+ out.println("</topic>");
+
+ pad.setLength(pad.length() - indent.length());
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/Help.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/Help.java
new file mode 100644
index 000000000..e03938f06
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/Help.java
@@ -0,0 +1,65 @@
+package org.eclipse.help.internal.remote;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.*;
+
+import org.eclipse.help.internal.HelpSystem;
+
+/**
+ * This class is an implementation of the pluggable help support.
+ * It does not use the support extension point, as it is hard-coded
+ * so it works in the same install image to the real help plugin.
+ */
+public class Help implements IHelp {
+ /**
+ * BaseHelpViewer constructor comment.
+ */
+ public Help() {
+ super();
+ }
+ /**
+ * Displays context-sensitive help for specified contexts
+ * @param url java.lang.Object[]
+ */
+ public void displayHelp(Object[] contextIds, int x, int y) {
+ // NOT CURRENTLY SUPPORTED
+ }
+ /**
+ * Displays context-sensitive help for specified contexts
+ * @param trigger java.lang.Object object triggering help
+ * @param contextIds java.lang.String[]
+ */
+ public void displayHelp(String[] contexts, int x, int y) {
+
+ // NOT CURRENTLY SUPPORTED
+ }
+ /**
+ * Displays context-sensitive help for specified contexts
+ * @param trigger java.lang.Object object triggering help
+ * @param contextIds java.lang.String[]
+ */
+ public void displayHelp(IContext[] contexts, int x, int y) {
+
+ // NOT CURRENTLY SUPPORTED
+ }
+ /**
+ * Display help.
+ */
+ public void displayHelp(String url) {
+ // NOT CURRENTLY SUPPORTED
+ }
+ /**
+ * Computes context information for a given context ID.
+ * @param contextID java.lang.String ID of the context
+ * @return IContext
+ */
+ public IContext findContext(String contextID) {
+ return HelpSystem.getContextManager().getContext(contextID);
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/ServletFacade.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/ServletFacade.java
new file mode 100644
index 000000000..18ab4eacd
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/ServletFacade.java
@@ -0,0 +1,119 @@
+package org.eclipse.help.internal.remote;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.boot.IPlatformRunnable;
+import org.eclipse.help.internal.server.*;
+import java.io.*;
+
+import org.eclipse.help.internal.util.*;
+
+import java.util.*;
+import java.net.URL;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.*;
+
+/**
+ * Launcher for standalone help system
+ */
+public class ServletFacade implements IPlatformRunnable {
+
+ final static String errorString =
+ "<html><body>The topic that you have requested is not available. The link may be wrong, or you may not have the corresponding product feature installed. This online help only includes documentation for features that are installed.</body></html>";
+ /**
+ * StandaloneHelpSystem constructor comment.
+ */
+ public ServletFacade() {
+ super();
+
+ HelpSystem.setPlugin(HelpPlugin.getDefault());
+
+ // Tell the help system this is a remote install
+ HelpSystem.setInstall(2);
+
+ // Initialize configuration
+ try {
+ readINIFile();
+ HelpSystem.startup();
+ } catch (CoreException e) {
+ }
+ }
+ public void fillContent(String url, OutputStream out) {
+ try {
+ Logger.logInfo("url =" + url);
+ HelpURL helpURL = HelpURLFactory.createHelpURL(url);
+ Logger.logInfo("helpURL: " + helpURL.getClass());
+ InputStream stream = helpURL.openStream();
+ if (stream != null)
+ HelpContentManager.fillInResponse(helpURL, stream, out);
+ else
+ if (!helpURL.toString().endsWith(".class")) {
+ // this is needed when the class loader
+ // wants to load a property file and queries
+ // for doc_en_us.class
+ HelpURL errorURL =
+ HelpURLFactory.createHelpURL(
+ "/org.eclipse.help/" + Resources.getString("notopic.html"));
+ stream = errorURL.openStream();
+ HelpContentManager.fillInResponse(errorURL, stream, out);
+ }
+ } catch (IOException e) {
+ Logger.logError(e.getMessage(), e);
+ }
+ }
+ /**
+ * Read the help ini file.
+ * Unlike the other plugins, this only cares about the
+ * log level.
+ * The plugin should call this if needed...
+ */
+ public void readINIFile() throws CoreException {
+
+ URL iniPathURL = null;
+ IPluginDescriptor descriptor = null;
+
+ try {
+ // get the ini file URL
+ descriptor = HelpPlugin.getDefault().getDescriptor();
+ URL installURL = descriptor.getInstallURL();
+ iniPathURL = new URL(installURL, "remote.ini");
+
+ // now load the config properties
+ Properties ini = new Properties();
+ InputStream is = iniPathURL.openStream();
+ ini.load(is);
+
+ int debug_level = Integer.getInteger(ini.getProperty("log_level")).intValue();
+ HelpSystem.setDebugLevel(debug_level);
+
+ is.close();
+ } catch (Exception e) {
+ // pass the error to System.err AND to the internal platform log.
+ System.err.println(Resources.getString("E004", iniPathURL.toString()));
+
+ HelpPlugin.getDefault().getLog().log(
+ new Status(
+ IStatus.ERROR,
+ descriptor.getUniqueIdentifier(),
+ 0,
+ Resources.getString("E004", iniPathURL.toString()),
+ e));
+ }
+
+ }
+ public Object run(Object args) {
+ return this;
+ }
+ /**
+ * Shuts down this plug-in and discards all plug-in state.
+ * @exception CoreException if this method fails to shut down
+ * this plug-in
+ */
+ public void shutdown() throws CoreException {
+ HelpSystem.shutdown();
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/StandaloneFacade.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/StandaloneFacade.java
new file mode 100644
index 000000000..9796758b4
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/remote/StandaloneFacade.java
@@ -0,0 +1,40 @@
+package org.eclipse.help.internal.remote;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.boot.IPlatformRunnable;
+import org.eclipse.help.internal.server.*;
+import org.eclipse.help.internal.HelpSystem;
+import java.io.*;
+
+import org.eclipse.help.internal.util.*;
+
+import org.eclipse.help.IHelp;
+
+/**
+ * Launcher for standalone help system
+ */
+public class StandaloneFacade implements IPlatformRunnable {
+ private static StandaloneFacade instance = new StandaloneFacade();
+ private IHelp help;
+ /**
+ * StandaloneHelpSystem constructor comment.
+ */
+ public StandaloneFacade() {
+ super();
+ help = new Help();
+ }
+ public void displayHelp(String infoSet) {
+ help.displayHelp(infoSet);
+ }
+ public StandaloneFacade instance() {
+ return instance;
+ }
+ public Object run(Object args) {
+ return this;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/search/ISearchEngine.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/search/ISearchEngine.java
new file mode 100644
index 000000000..a3f487168
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/search/ISearchEngine.java
@@ -0,0 +1,43 @@
+package org.eclipse.help.internal.search;
+
+import org.eclipse.core.runtime.*;
+
+/**
+ * Search Engine interface
+ */
+public interface ISearchEngine {
+
+ /**
+ * Returns highlight information for a search result
+ * Note: it is recommeded to synchronize this method.
+ */
+ public int[][] getHighlightInfo(
+ String infoSet,
+ String locale,
+ byte[] docBuffer,
+ int docNumber);
+ /**
+ * Remote Search.
+ * Returns an XML result
+ * @param query url string containing user query, locale
+ */
+ public String getRemoteSearchResults(String infoSet, String query);
+ /**
+ * Searches index for documents containing an expression.
+ * If the index hasn't been built then return null.
+ * Note: it is recommeded to synchronize this method, to serialize access to search.
+ * @return an XML representation of the results <topics><topic>...
+ * @param query query to search for in the index, contains locale
+ */
+ public String getSearchResults(String infoset, String query);
+ /**
+ * Returns true when updates to the infoset requires index updates
+ */
+ public boolean isIndexingNeeded(String infoSet, String locale);
+ /**
+ * Updates index. Checks if all contributions were indexed.
+ * If not, it indexes them (Currently reindexes everything).
+ */
+ public void updateIndex(String infoSet, IProgressMonitor pm, String locale)
+ throws OperationCanceledException, Exception;
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/search/XMLSearchContributor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/search/XMLSearchContributor.java
new file mode 100644
index 000000000..52a6c5b20
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/search/XMLSearchContributor.java
@@ -0,0 +1,82 @@
+package org.eclipse.help.internal.search;
+
+import java.io.*;
+import org.xml.sax.*;
+import org.eclipse.help.internal.contributors.*;
+import org.eclipse.help.internal.contributions.*;
+import org.eclipse.help.internal.contributions.xml.*;
+import org.eclipse.help.internal.contributors.xml.*;
+import org.eclipse.help.internal.util.Logger;
+
+/**
+ * Creates a search model for the search results
+ * that were presented as XML
+ */
+public class XMLSearchContributor implements Contributor {
+ private Contribution resultsNode = null;
+ private String results;
+ static class SearchContributionFactory extends ContributionFactory {
+ // Override the super class static field
+ protected static final SearchContributionFactory instance =
+ new SearchContributionFactory();
+ /**
+ * ContributionFactory constructor comment.
+ */
+ public SearchContributionFactory() {
+ super();
+ }
+
+ public Contribution createContribution(String name, Attributes atts) {
+ Contribution e = null;
+ if (name.equals(TopicContributor.TOPICS_ELEM))
+ e = new HelpContribution(atts);
+ else
+ if (name.equals(TopicContributor.TOPIC_ELEM))
+ e = new HelpTopic(atts);
+ else
+ return null;
+
+ return e;
+ }
+
+ public static ContributionFactory instance() {
+ return instance;
+ }
+ }
+
+ /**
+ * XMLSearchContributor constructor comment.
+ */
+ public XMLSearchContributor(String xmlResultsAsString) {
+ super();
+ this.results = xmlResultsAsString;
+ }
+ /**
+ */
+ public Contribution getContribution() {
+ if (resultsNode == null) {
+ try {
+ InputSource input = new InputSource(new StringReader(results));
+ ContributionParser parser =
+ new ContributionParser(SearchContributionFactory.instance());
+ parser.parse(input);
+ resultsNode = parser.getContribution();
+ } catch (SAXException se) {
+ Logger.logError(se.getMessage(), se);
+ } catch (IOException ioe) {
+ Logger.logError(ioe.getMessage(), ioe);
+ }
+ }
+ return resultsNode;
+ }
+ /**
+ */
+ public org.eclipse.core.runtime.IPluginDescriptor getPlugin() {
+ return null;
+ }
+ /**
+ */
+ public String getType() {
+ return null;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/AddressTest.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/AddressTest.java
new file mode 100644
index 000000000..2d9275db6
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/AddressTest.java
@@ -0,0 +1,117 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.net.*;
+import org.eclipse.help.internal.util.Resources;
+
+/**
+ * Test the local addresses to find out where one can connect
+ * to the help server
+ */
+public class AddressTest {
+ long timeout;
+
+ // The connection class creates the socket.
+ class Connection extends Thread {
+ long timeout;
+ int port;
+ InetAddress inetAddress;
+ String stringAddress;
+
+ public Connection(String host, int port, long timeout) {
+ this.stringAddress = host;
+ this.port = port;
+ this.timeout = timeout;
+ setDaemon(true);
+ }
+
+ public void run() {
+ if (socket != null)
+ return;
+
+ try {
+ if (inetAddress != null) {
+ socket = new Socket(inetAddress, port);
+ HelpServer.setHost(inetAddress.getHostName());
+ } else {
+ socket = new Socket(stringAddress, port);
+ //System.out.println("USING " + stringAddress + " " + port);
+ HelpServer.setHost(stringAddress);
+ }
+ socket.setTcpNoDelay(true);
+ } catch (IOException e) {
+ try {
+ if (socket != null)
+ socket.close();
+ } catch (IOException ex) {
+ }
+ socket = null;
+ } finally {
+ try {
+ if (socket != null)
+ socket.close();
+ } catch (IOException ex) {
+ }
+ }
+ }
+ };
+
+ Connection connection;
+
+ // The socket, or null if it couldn't be created.
+ static Socket socket;
+ // Constructor. This addressTest will use Socket (String, int) to create
+ // the socket.
+ public AddressTest(String host, int port, long timeout) {
+ connection = new Connection(host, port, timeout);
+ }
+ public static void main(String[] args) {
+ try {
+ int portNumber = 81;
+ // 500 ms is a good number, don't use a number that is too small or you'll get wrong result
+ int Timeout = 500;
+
+ String host = InetAddress.getLocalHost().getHostName();
+ System.out.println(Resources.getString("host_", host));
+ InetAddress[] addr = InetAddress.getAllByName(host);
+ System.out.println(addr.length + Resources.getString("address(es)_retrieved"));
+
+ for (int i = 0; i < addr.length; i++) {
+ System.out.println(Resources.getString("address_1", addr[i].getHostAddress()));
+ testConnect(addr[i].getHostAddress(), portNumber, Timeout);
+ // test all addresses retrieved from your system
+ }
+
+ System.out.println("\n");
+ testConnect("127.0.0.1", portNumber, Timeout); // test 127.0.0.1
+
+ System.out.println("\n");
+ testConnect("9.9.9.9", portNumber, Timeout); // test an obviously invalid IP
+
+ } catch (IOException e) {
+ System.out.println(Resources.getString("Error") + e);
+ }
+ }
+ // Make a test connection.
+
+ static void testConnect(String address, int port, long timeout) {
+ // the connection starts in a separate thread
+ AddressTest test = new AddressTest(address, port, timeout);
+ test.connection.start();
+
+ // after the timeout expires, wakeup, interrupt the connection (if established)
+ // and check the result.
+ try {
+ test.connection.join(timeout);
+ } catch (InterruptedException e) {
+ }
+ test.connection.interrupt();
+
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/CSSEmbedProcessor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/CSSEmbedProcessor.java
new file mode 100644
index 000000000..01c6485be
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/CSSEmbedProcessor.java
@@ -0,0 +1,68 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.help.internal.HelpSystem;
+import org.eclipse.help.internal.navigation.HelpNavigationManager;
+import org.eclipse.help.internal.util.Resources;
+
+/**
+ * This class inserts links to a CSS file in HTML code
+ */
+class CSSEmbedProcessor implements OutputProcessor {
+ private static final byte[] headTagBegin = "<head".getBytes();
+ private static final byte[] headTagBeginCaps = "<HEAD".getBytes();
+ private static final char headTagEnd = '>';
+ private static final String href =
+ "/org.eclipse.help/" + Resources.getString("CSS_location");
+ private static final byte[] cssLink =
+ ("\n<link rel=\"stylesheet\" type=\"text/css\" href=\"" + href + "\">")
+ .getBytes();
+ public CSSEmbedProcessor() {
+ }
+ public byte[] processOutput(byte[] input) {
+ // Create new buffer
+ byte[] buffer = new byte[input.length + cssLink.length];
+ int bufPointer = 0;
+ int inputPointer = 0;
+ boolean foundHeadTagBegin = false;
+ boolean foundHeadTagEnd = false;
+ while (inputPointer < input.length) {
+ // copy character
+ buffer[bufPointer++] = input[inputPointer++];
+ // look for head tag copied
+ if (!foundHeadTagEnd
+ && !foundHeadTagBegin
+ && (bufPointer >= headTagBegin.length)) {
+ for (int i = 0; i < headTagBegin.length; i++) {
+ if ((buffer[bufPointer - headTagBegin.length + i] != headTagBegin[i])
+ && (buffer[bufPointer - headTagBegin.length + i] != headTagBeginCaps[i])) {
+ break;
+ }
+ if (i == headTagBegin.length - 1)
+ foundHeadTagBegin = true;
+ }
+ }
+ if (!foundHeadTagEnd && foundHeadTagBegin && buffer[bufPointer - 1] == '>') {
+ foundHeadTagEnd = true;
+ //embed CSS
+ System.arraycopy(cssLink, 0, buffer, bufPointer, cssLink.length);
+ bufPointer += cssLink.length;
+ // copy rest
+ System.arraycopy(
+ input,
+ inputPointer,
+ buffer,
+ bufPointer,
+ input.length - inputPointer);
+ return buffer;
+ }
+ }
+ return buffer;
+
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpContentManager.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpContentManager.java
new file mode 100644
index 000000000..64d47ce6f
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpContentManager.java
@@ -0,0 +1,81 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+
+/**
+ * Handles a request
+ */
+public class HelpContentManager {
+ private static final int DATA_READ_SIZE = 8192; // buffer size
+ /**
+ * Creates output processors, required
+ * @return vector of OutputProcessor;
+ */
+ private static Vector createOutputProcessor(HelpURL url) {
+ Vector processors = new Vector(2);
+ // only deal with html files
+ if (!"text/html".equals(url.getContentType()))
+ return processors;
+
+ // search result
+ if (url.getValue("resultof") != null)
+ processors.add(new HighlightProcessor(url));
+
+ // add the CSS to all html files
+ processors.add(new CSSEmbedProcessor());
+
+ return processors;
+ }
+ public static void fillInResponse(
+ HelpURL helpURL,
+ InputStream inputStream,
+ OutputStream out)
+ throws IOException {
+ Vector outputProcessors = createOutputProcessor(helpURL);
+ if ((outputProcessors == null) || (outputProcessors.size() <= 0)) {
+ // Read from inputStream and write to out
+ transferContent(inputStream, out);
+ } else {
+ ByteArrayOutputStream tempOut = new ByteArrayOutputStream(DATA_READ_SIZE);
+ transferContent(inputStream, tempOut);
+ byte[] tempBuffer = tempOut.toByteArray();
+ for (int i = 0; i < outputProcessors.size(); i++) {
+ tempBuffer =
+ ((OutputProcessor) outputProcessors.elementAt(i)).processOutput(tempBuffer);
+ }
+ ByteArrayInputStream tempIn = new ByteArrayInputStream(tempBuffer);
+ transferContent(tempIn, out);
+ }
+
+ }
+ /**
+ * Write the body to the response
+ */
+ private static void transferContent(InputStream inputStream, OutputStream out)
+ throws IOException {
+
+ // Prepare the input stream for reading
+ BufferedInputStream dataStream = new BufferedInputStream(inputStream);
+
+ // Create a fixed sized buffer for reading.
+ // We could create one with the size of availabe data...
+ byte[] temp = new byte[DATA_READ_SIZE];
+ int len = 0;
+ while (true) {
+ //int count = 5000; //dataStream.available();
+ //if (count == 0) break;
+ //byte[] temp = new byte [ count ];
+ len = dataStream.read(temp); // Read file into the byte array
+ if (len == -1)
+ break;
+ out.write(temp, 0, len);
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpConnection.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpConnection.java
new file mode 100644
index 000000000..3d5c1b2aa
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpConnection.java
@@ -0,0 +1,53 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.net.*;
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import org.eclipse.help.internal.util.Logger;
+
+/**
+ * Thread server class to handle clients.
+ */
+class HelpHttpConnection extends Thread {
+ Socket client; // client socket
+ // Pass the socket as a argument to the constructor
+ HelpHttpConnection(Socket client) throws SocketException {
+ this.client = client;
+ // Set the thread priority down so that the ServerSocket
+ // will be responsive to new clients.
+ setPriority(NORM_PRIORITY - 1);
+ setName("Connection");
+ }
+ /**
+ * Handles a connection request.
+ * NOTE: move some of the constants to properties and do better
+ * handling of requests, including SECURITY issues (originating machine, etc.)
+ **/
+ public void handleRequest() {
+ try {
+ HelpHttpRequest request = new HelpHttpRequest(client.getInputStream());
+ HelpHttpResponse response =
+ new HelpHttpResponse(client.getOutputStream(), request);
+ request.processRequest(response);
+ client.close(); // close the client socket
+ } catch (IOException e) {
+ Logger.logDebugMessage(
+ "HelpHttpConnection",
+ "connection failed: " + e.getMessage());
+ }
+
+ }
+ /**
+ * Handles a connection request.
+ **/
+ public void run() {
+ handleRequest();
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpRequest.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpRequest.java
new file mode 100644
index 000000000..e929385a8
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpRequest.java
@@ -0,0 +1,183 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import java.net.*;
+import org.eclipse.help.internal.HelpSystem;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.help.internal.navigation.HelpNavigationManager;
+import org.eclipse.help.internal.util.Resources;
+
+/**
+ * Handles a request
+ */
+public class HelpHttpRequest {
+ private static final int NONE = 0;
+ private static final int GET = 1;
+ private static final int POST = 2;
+ private static final int HEAD = 3;
+
+ BufferedReader in; // request input reader
+ int method; // request method: GET, POST...
+ String version; // protocol version
+
+ HelpURL helpURL; // the help URL
+
+ InputStream contentStream; // stream of data to be sent to client
+
+ protected int contentLength = 0;
+ private static byte[] errorStringBytes =
+ ("<html><body>" + Resources.getString("topicNotAvailable") + "</body></html>")
+ .getBytes();
+
+ /**
+ * HelpRequest constructor comment.
+ */
+ public HelpHttpRequest(InputStream inputStream) {
+ super();
+
+ try {
+ // Use the client socket to obtain an input stream from it.
+ InputStream sockInput = inputStream;
+
+ // For text input we wrap an InputStreamReader around
+ // the raw input stream and set ASCII character encoding.
+ InputStreamReader isr = new InputStreamReader(sockInput, "8859_1");
+
+ // Finally, use a BufferReader wrapper to obtain
+ // buffering and higher order read methods.
+ in = new BufferedReader(isr);
+ } catch (UnsupportedEncodingException e) {
+ Logger.logDebugMessage("HelpHttpRequest", "encoding error: " + e.getMessage());
+ } catch (Exception e) {
+ Logger.logDebugMessage("HelpHttpRequest", "request failed: " + e.getMessage());
+ }
+ }
+ public HelpURL getURL() {
+ return helpURL;
+ }
+ public boolean isHTTP() {
+ return (version != null && version.indexOf("HTTP/") != -1);
+ }
+ /**
+ * Insert the method's description here.
+ *
+ * @param req com.ibm.itp.help.server.HelpContentManager
+ */
+ public void processRequest(HelpHttpResponse response) {
+ readHeader();
+ if (method == POST) {
+ readBody();
+ }
+
+ if (method == GET || method == POST) {
+ try {
+ // Open a stream to the file.
+ if (helpURL == null)
+ return;
+
+ // Prepare the output stream to the browser
+ OutputStream out = response.getOutputStream();
+
+ //Info.log(helpURL);
+ InputStream inputStream = helpURL.openStream();
+ if (inputStream == null) {
+ HelpURL errorURL =
+ HelpURLFactory.createHelpURL(
+ "/org.eclipse.help/" + Resources.getString("notopic.html"));
+ inputStream = errorURL.openStream();
+ }
+ if (inputStream == null) {
+ out.write(errorStringBytes);
+ out.flush();
+ return;
+ }
+
+ // Send header first
+ response.sendHeader();
+
+ // Fill the response body
+ HelpContentManager.fillInResponse(helpURL, inputStream, out);
+
+ // Flush all the buffered data before closing the stream
+ out.flush();
+ } catch (IOException e) {
+ Logger.logDebugMessage(
+ "HelpHttpRequest",
+ "processRequest failed: " + e.getMessage());
+ }
+ } else
+ Logger.logInfo(
+ Resources.getString("request")
+ + method
+ + Resources.getString("url_1")
+ + helpURL);
+ }
+ /**
+ * Insert the method's description here.
+ *
+ */
+ protected void readBody() {
+ try {
+ if (contentLength > 0) {
+ char[] inputLine = new char[contentLength];
+ in.read(inputLine); // slurp all remaining content
+ helpURL.addQuery(String.valueOf(inputLine));
+ }
+
+ } catch (SocketException e) {
+ Logger.logDebugMessage("HelpHttpRequest", "readBody failed: " + e.getMessage());
+ } catch (IOException e) {
+ Logger.logDebugMessage("HelpHttpRequest", "readBody failed: " + e.getMessage());
+ }
+ }
+ /**
+ * Insert the method's description here.
+ *
+ */
+ protected void readHeader() {
+ try {
+ String inputLine = in.readLine();
+ if (inputLine == null)
+ return;
+ // empty request. Note: do we need to write and end of line in the output stream??
+
+ StringTokenizer st = new StringTokenizer(inputLine);
+ String methodString = new String(st.nextToken());
+ if (methodString.equals("GET"))
+ this.method = GET;
+ else
+ if (methodString.equals("POST"))
+ this.method = POST;
+ else
+ if (methodString.equals("HEAD"))
+ this.method = HEAD;
+ this.helpURL = HelpURLFactory.createHelpURL(st.nextToken());
+ this.version = st.nextToken();
+ while ((inputLine = in.readLine()) != null) {
+ if (inputLine.length() == 0)
+ break;
+ if (inputLine.startsWith("Content-Length")) {
+ contentLength =
+ Integer.parseInt(inputLine.substring(inputLine.lastIndexOf(" ") + 1), 10);
+ }
+ }
+
+ } catch (SocketException e) {
+ Logger.logDebugMessage(
+ "HelpHttpRequest",
+ "readHeader failed: " + e.getMessage());
+ } catch (IOException e) {
+ Logger.logDebugMessage(
+ "HelpHttpRequest",
+ "readHeader failed: " + e.getMessage());
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpResponse.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpResponse.java
new file mode 100644
index 000000000..b8e29e777
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpHttpResponse.java
@@ -0,0 +1,49 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.Date;
+
+/**
+ * Response for a request
+ */
+public class HelpHttpResponse {
+ private OutputStream out; // the output stream back to the client
+ private HelpHttpRequest request; // the request for which this response is for
+ /**
+ * HelpResponse constructor comment.
+ */
+ public HelpHttpResponse(OutputStream out, HelpHttpRequest req) {
+ super();
+ this.out = out;
+ this.request = req;
+ }
+ public OutputStream getOutputStream() {
+ return out;
+ }
+ public void sendHeader() {
+ try {
+ if (request.isHTTP()) {
+ out.write("HTTP/1.1 200 OK\r\n".getBytes());
+ Date now = new Date();
+ out.write(("Date: " + now + "\r\n").getBytes());
+ out.write("Server: HelpServer 1.0\r\n".getBytes());
+ if (request.getURL().isCacheable())
+ out.write("Cache-Control: max-age=10000\r\n".getBytes());
+ else
+ out.write("Cache-Control: no-cache\r\n".getBytes());
+
+ //out.write(
+ // ("Content-Length: " + request.getURL().getContentSize() + "\r\n").getBytes());
+ out.write(
+ ("Content-Type: " + request.getURL().getContentType() + "\r\n\r\n").getBytes());
+ }
+ } catch (IOException e) {
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpServer.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpServer.java
new file mode 100644
index 000000000..036c1a31d
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpServer.java
@@ -0,0 +1,204 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.net.*;
+import org.eclipse.help.internal.util.*;
+
+/**
+ * Lightweight web server for help content.
+ * It listens on a local address at a system generated port.
+ */
+public class HelpServer extends Thread {
+
+ static int port = 0; // let the system select a port
+ ServerSocket ssocket = null;
+ static HelpServer _this = null;
+ public static int timeout = 1000;
+ static Object lock = new Object();
+ static String host = null;
+
+ public HelpServer() {
+ super();
+
+ setDaemon(true);
+ setName("HelpServer");
+ try {
+ ssocket = new ServerSocket(port);
+ this.port = ssocket.getLocalPort();
+ } catch (Exception e1) {
+ ssocket = null;
+ if (port != 0 )
+ // try again with port 0 (system selects port)
+ try
+ {
+ ssocket = new ServerSocket(port);
+ this.port = ssocket.getLocalPort();
+ } catch (Exception e2) {
+ ssocket = null;
+ Logger.logError(e1.getMessage(), e2);
+ return;
+ }
+ }
+ //catch (UnknownHostException e)
+ //{
+ //System.out.println("*** cannot find IP for local host ***");
+ //}
+
+ // do a dummy accept() to trigger the listen().
+ // Java does not provide a listen() method, so we need to make
+ // sure the server is listening before waking up the client
+ int timeout = 0;
+ try {
+ timeout = ssocket.getSoTimeout();
+ ssocket.setSoTimeout(1); // quick accept
+ ssocket.accept();
+ ssocket.setSoTimeout(timeout);
+ } catch (IOException exc) {
+ try {
+ ssocket.setSoTimeout(timeout);
+ } catch (SocketException sockEx) {
+ }
+ }
+ }
+ public void close() {
+ // close the zips
+ PluginURL.clear();
+ // close the communication channel
+ try {
+ if (ssocket != null)
+ ssocket.close();
+ } catch (IOException e) {
+ Logger.logDebugMessage("HelpServer", e.getMessage());
+ } finally {
+ ssocket = null;
+ }
+ }
+ public static void discoverServerAddress() {
+ try {
+ // First try the localhost address
+ AddressTest.testConnect("127.0.0.1", port, timeout);
+ if (HelpServer.host != null)
+ return;
+ String host = InetAddress.getLocalHost().getHostName();
+ InetAddress[] addr = InetAddress.getAllByName(host);
+ for (int i = 0; i < addr.length; i++) {
+ //System.out.println("address=" + addr[i].getHostAddress());
+ // test all addresses retrieved from your system
+ AddressTest.testConnect(addr[i].getHostAddress(), port, timeout);
+
+ if (host != null)
+ return;
+ }
+
+ /*
+ // Try the localhost by name
+ AddressTest.testConnect("localhost", port, timeout);
+ if (HelpServer.goodAddress != null) return;
+ */
+ } catch (IOException e) {
+ System.out.println(Resources.getString("Error_1") + e);
+ } finally {
+ // If all fails, use localhost
+ if (HelpServer.host == null)
+ HelpServer.host = "localhost";
+ }
+ }
+ public void finalize() {
+ close();
+ }
+ /**
+ * Returns the first valid internet address for this machine.
+ */
+ public static URL getAddress() {
+ try {
+ return new URL("http", HelpServer.host, port, "");
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+ public static HelpServer instance() {
+ if (_this == null) {
+ _this = new HelpServer();
+ //_this.setPriority(Thread.currentThread().getPriority()+1);
+ _this.start();
+
+ // Discover the address on which the server listens
+ if (host == null || host.length() == 0)
+ discoverServerAddress();
+ }
+ return _this;
+ }
+ public void run() {
+ try {
+
+ // Here we loop indefinitely, just waiting for
+ // clients to connect
+ while (true) {
+ // accept() does not return until a client
+ // requests a connection.
+ Socket sock = ssocket.accept();
+
+ sock.setTcpNoDelay(true); // local transfer, so maximize troughput
+
+ // Now that a client has arrived, create an instance
+ // of our special thread subclass to respond to it.
+ HelpHttpConnection connection = new HelpHttpConnection(sock);
+ connection.start();
+ } // Now loop back around and wait
+ // for next client to be accepted.
+ } catch (IOException e) {
+ Logger.logInfo(e.getMessage());
+ } finally {
+ }
+ }
+ public static void setAddress(String hostValue, String portValue) {
+ String oldHost = host;
+ int oldPort = port;
+
+ if (hostValue != null && hostValue.trim().length() > 0)
+ setHost(hostValue.trim());
+ else
+ setHost(null);
+ try {
+ int port = Integer.parseInt(portValue);
+ if (0 <= port && port < 0xffff)
+ setPort(port);
+ else
+ setPort(0);
+ } catch (Exception e) {
+ setPort(0);
+ }
+
+ // Restart the server the local address has changed
+
+ // nothing to do when the server does not exists
+ if (_this == null)
+ return;
+
+ // test for changess:
+ // if the ports and the hosts are the same, nothing to do
+ if ( oldPort == port)
+ if (oldHost == null && host == null)
+ return;
+ else if (oldHost != null && oldHost.equals(host))
+ return;
+
+ // restart the server
+ _this.close();
+ _this = null;
+ _this = instance();
+
+ }
+ public static void setHost(String hostValue) {
+ host = hostValue;
+ }
+ public static void setPort(int portValue) {
+ port = portValue;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpURL.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpURL.java
new file mode 100644
index 000000000..d0eb3f645
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpURL.java
@@ -0,0 +1,173 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+
+import java.net.URLDecoder;
+
+/**
+ * Manages a help URL. Note that there is a limitation in handling
+ * queries; only one instance of a name=value pair exists at at time.
+ */
+public class HelpURL {
+ protected String url; // url string
+ protected StringBuffer query;
+ protected HashMap arguments = null;
+ protected long contentSize; // length of input data
+ /**
+ * HelpURL constructor comment.
+ */
+ public HelpURL(String url) {
+ this(url, "");
+ }
+ /**
+ * HelpURL constructor comment.
+ */
+ public HelpURL(String url, String query) {
+ this.url = url;
+ this.query = new StringBuffer(query);
+
+ parseQuery(query);
+ }
+ /**
+ *
+ */
+ public void addQuery(String newQuery) {
+ if (newQuery != null && !"".equals(newQuery)) {
+ query.append('&').append(newQuery);
+ parseQuery(newQuery);
+ }
+ }
+ /**
+ * Insert the method's description here.
+ *
+ * @return long
+ */
+ public long getContentSize() {
+ return contentSize;
+ }
+ public String getContentType() {
+ // NOTE: MAY NEED TO OVERRIDE FOR SearchURL or when there is a query string
+
+ // Check if the file is hypertext or plain text
+ String ContentType;
+ String file = url.toLowerCase();
+ if (file.endsWith(".html") || file.endsWith(".htm"))
+ return "text/html";
+ else
+ if (file.endsWith(".css"))
+ return "text/css";
+ else
+ if (file.endsWith(".gif"))
+ return "image/gif";
+ else
+ if (file.endsWith(".jpg"))
+ return "image/jpeg";
+ else
+ if (file.endsWith(".pdf"))
+ return "application/pdf";
+ else
+ if (file.endsWith(".xml"))
+ return "application/xml";
+ else
+ if (file.endsWith(".xsl"))
+ return "application/xsl";
+ return "text/plain";
+ }
+ /**
+ *
+ */
+ public Vector getMultiValue(String name) {
+ if (arguments != null) {
+ Object value = arguments.get(name);
+ if (value instanceof Vector)
+ return (Vector) value;
+ else
+ return null;
+ }
+ return null;
+ }
+ public String getPath() {
+ // The stored url starts with plugin id.
+ // We need to return /pluginid/filename
+ return "/" + url;
+ }
+ /**
+ *
+ */
+ public String getValue(String name) {
+ if (arguments == null)
+ return null;
+ Object value = arguments.get(name);
+ String stringValue = null;
+ if (value instanceof String)
+ stringValue = (String) value;
+ else
+ if (value instanceof Vector)
+ stringValue = (String) ((Vector) value).firstElement();
+ else
+ return null;
+ try {
+ return URLDecoder.decode(stringValue);
+ } catch (Exception e) {
+ return null;
+ }
+
+ }
+ // this returns whether or not a response created for a request
+ // to this URL is cached by the browser client.
+ public boolean isCacheable() {
+ return false;
+ }
+ /**
+ * Opens a stream for reading.
+ *
+ * @return java.io.InputStream
+ */
+ public InputStream openStream() {
+ return null;
+ }
+ /**
+ * NOTE: need to add support for multi-valued parameters (like filtering)
+ * Multiple values are added as vectors
+ */
+ protected void parseQuery(String theQuery) {
+ if (theQuery != null && !"".equals(theQuery)) {
+ if (arguments == null) {
+ arguments = new HashMap(5);
+ }
+
+ StringTokenizer stok = new StringTokenizer(theQuery, "&");
+ while (stok.hasMoreTokens()) {
+ String aQuery = stok.nextToken();
+ int equalsPosition = aQuery.indexOf("=");
+ if (equalsPosition > -1) { // well formed name/value pair
+ String arg = aQuery.substring(0, equalsPosition);
+ String val = aQuery.substring(equalsPosition + 1);
+ Object existing = arguments.get(arg);
+ if (existing == null)
+ arguments.put(arg, val);
+ else
+ if (existing instanceof Vector) {
+ ((Vector) existing).add(val);
+ arguments.put(arg, existing);
+ } else {
+ Vector v = new Vector(2);
+ v.add(existing);
+ v.add(val);
+ arguments.put(arg, v);
+ }
+ }
+ }
+ }
+ }
+ public String toString() {
+ return url;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpURLFactory.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpURLFactory.java
new file mode 100644
index 000000000..d68e28cbe
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HelpURLFactory.java
@@ -0,0 +1,47 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.net.*;
+
+/**
+ * Creates the URL objects according to the their type
+ */
+public class HelpURLFactory {
+ /**
+ * HelpURLFactory constructor.
+ */
+ public HelpURLFactory() {
+ super();
+ }
+ public static HelpURL createHelpURL(String url) {
+ if (url == null || url.length() == 0)
+ return new PluginURL("", "");
+
+ // Strip off the leading "/" and the query
+ String query = "";
+ int indx = url.indexOf("?");
+ if (indx != -1) {
+ query = url.substring(indx + 1);
+ url = url.substring(1, indx);
+ } else
+ url = url.substring(1);
+
+ if (url.startsWith(TempURL.getPrefix())) // "/working"
+ return new TempURL(url.substring(TempURL.getPrefix().length() + 1), query);
+
+ else
+ if (url.startsWith(SearchURL.getPrefix()))
+ return new SearchURL(
+ //request.substring(URLResolver.getSearchContext().length() + 1),
+ "", query);
+
+ else ////if (url.startsWith(PluginURL.getPrefix()))
+ return new PluginURL(url.substring(PluginURL.getPrefix().length()), query);
+
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HighlightProcessor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HighlightProcessor.java
new file mode 100644
index 000000000..4ac528f1b
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/HighlightProcessor.java
@@ -0,0 +1,239 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import java.net.URLDecoder;
+import org.eclipse.help.internal.navigation.HelpNavigationManager;
+import org.eclipse.help.internal.HelpSystem;
+
+/**
+ * This class should perhaps be changed a bit, and so
+ * should the SearchURL. Factor out some search utility
+ * and have it return the correct processed stream.
+ */
+class HighlightProcessor implements OutputProcessor {
+ private HelpURL url;
+ private static final byte[] headTagBegin = "<head".getBytes();
+ private static final byte[] headTagBeginCaps = "<HEAD".getBytes();
+ private static final char headTagEnd = '>';
+ private static final String scriptPart1 =
+ "\n<script language=\"JavaScript\">\n<!--\nvar keywords = new Array (";
+ private static final String scriptPart3 =
+ ");\nonload=highlight;\nfunction highlight()\n{\nvar newText = document.body.createTextRange();\nfor (var i = 0; i < keywords.length; i++) {\nwhile (newText.findText(keywords[i]) )\n{\nvar replacement = newText.text\nnewText.pasteHTML(\"<span class=highlight style='background-color:lightgrey'>\" + replacement + \"</span>\");\n}\nnewText = document.body.createTextRange();\n}\n}\n// -->\n</script>\n";
+
+ //private int docNumber;
+ private String query;
+
+ /**
+ * HighlightProcessor constructor.
+ */
+ public HighlightProcessor() {
+ super();
+ }
+ public HighlightProcessor(HelpURL url) {
+ this.url = url;
+ //docNumber = Integer.parseInt(url.getValue("hitOrder"));
+ query = url.getValue("resultof");
+ }
+ /**
+ * Crates Java Script that does hightlighting
+ */
+ private byte[] createJScript(Collection keywords) {
+ StringBuffer buf = new StringBuffer(scriptPart1);
+ Iterator it = keywords.iterator();
+ if (!it.hasNext())
+ return null;
+ String keyword = (String) it.next();
+ buf.append("\"").append(keyword).append("\"");
+ while (it.hasNext()) {
+ keyword = (String) it.next();
+ buf.append(", \"").append(keyword).append("\"");
+ }
+ buf.append(scriptPart3);
+ return buf.toString().getBytes();
+ }
+ /**
+ * Extract keywords from query in the GTR format
+ * @return Collection of String
+ */
+ private Collection getKeywords() {
+ Collection tokens = new ArrayList();
+ //Divide along quotation marks and brackets
+ StringTokenizer qTokenizer = new StringTokenizer(query.trim(), "\"()", true);
+ boolean withinQuotation = false;
+ String quotedString = "";
+ while (qTokenizer.hasMoreTokens()) {
+ String curToken = qTokenizer.nextToken();
+ if (curToken.equals("\"")) {
+ if (!withinQuotation) {
+ //beginning of quoted string
+ quotedString = "";
+ } else {
+ //end of quoted string
+ tokens.add(quotedString);
+ }
+ withinQuotation = !withinQuotation;
+ continue;
+ }
+ if (withinQuotation) {
+ quotedString += (curToken);
+ } else {
+ //divide not quoted strings along white space
+ StringTokenizer parser = new StringTokenizer(curToken.trim());
+ while (parser.hasMoreTokens()) {
+ tokens.add(parser.nextToken());
+ }
+ }
+
+ }
+
+ Collection keywords = new HashSet(); // to eliminate duplicate words
+ for (Iterator it = tokens.iterator(); it.hasNext();) {
+ String token = (String) it.next();
+ String tokenLowerCase = token.toLowerCase();
+ if (!tokenLowerCase.equals("\"")
+ && !tokenLowerCase.equals("(")
+ && !tokenLowerCase.equals(")")
+ && !tokenLowerCase.equals("and")
+ && !tokenLowerCase.equals("or")
+ && !tokenLowerCase.equals("not"))
+ keywords.add(token);
+ }
+ return keywords;
+
+ }
+ /**
+ * Encodes strings inside collection for embedding in HTML source
+ * @return Collection of String
+ */
+ private Collection JavaScriptEncode(Collection col) {
+ if (col == null)
+ return col;
+ Collection result = new ArrayList();
+ for (Iterator it = col.iterator(); it.hasNext();) {
+ String keyword = (String) it.next();
+
+ int l = keyword.length();
+ if (l < 1)
+ continue;
+ char[] keywordChars = new char[l];
+ keyword.getChars(0, l, keywordChars, 0);
+ StringBuffer jsEncoded = new StringBuffer();
+ for (int j = 0; j < keywordChars.length; j++) {
+ String charInHex = Integer.toString((int) keywordChars[j], 16).toUpperCase();
+ switch (charInHex.length()) {
+ case 1 :
+ jsEncoded.append("\\u000").append(charInHex);
+ break;
+ case 2 :
+ jsEncoded.append("\\u00").append(charInHex);
+ break;
+ case 3 :
+ jsEncoded.append("\\u0").append(charInHex);
+ break;
+ default :
+ jsEncoded.append("\\u").append(charInHex);
+ break;
+ }
+ }
+ result.add(jsEncoded.toString());
+
+ }
+ return result;
+ }
+ public byte[] processOutput(byte[] input) {
+ if (query == null)
+ return input;
+
+ Collection keywords = getKeywords();
+ keywords = removeWildCards(keywords);
+ keywords = JavaScriptEncode(keywords);
+ byte[] script = createJScript(keywords);
+ if (script == null)
+ return input;
+
+ // Create new buffer
+ byte[] buffer = new byte[input.length + script.length];
+ int bufPointer = 0;
+ int inputPointer = 0;
+ boolean foundHeadTagBegin = false;
+ boolean foundHeadTagEnd = false;
+ while (inputPointer < input.length) {
+ // copy character
+ buffer[bufPointer++] = input[inputPointer++];
+ // look for head tag copied
+ if (!foundHeadTagEnd
+ && !foundHeadTagBegin
+ && (bufPointer >= headTagBegin.length)) {
+ for (int i = 0; i < headTagBegin.length; i++) {
+ if ((buffer[bufPointer - headTagBegin.length + i] != headTagBegin[i])
+ && (buffer[bufPointer - headTagBegin.length + i] != headTagBeginCaps[i])) {
+ break;
+ }
+ if (i == headTagBegin.length - 1)
+ foundHeadTagBegin = true;
+ }
+ }
+ if (!foundHeadTagEnd && foundHeadTagBegin && buffer[bufPointer - 1] == '>') {
+ foundHeadTagEnd = true;
+ //embed Script
+ System.arraycopy(script, 0, buffer, bufPointer, script.length);
+ bufPointer += script.length;
+ // copy rest
+ System.arraycopy(
+ input,
+ inputPointer,
+ buffer,
+ bufPointer,
+ input.length - inputPointer);
+ return buffer;
+ }
+ }
+ return buffer;
+ }
+ /**
+ * Removes wildcard characters from keywords, by splitting keywords around wild cards
+ * @return Collection of String
+ */
+ private Collection removeWildCards(Collection col) {
+ if (col == null)
+ return col;
+
+ // Split keywords into parts: before "*" and after "*"
+ Collection resultPass1 = new ArrayList();
+ for (Iterator it = col.iterator(); it.hasNext();) {
+ String keyword = (String) it.next();
+ int index;
+ while((index=keyword.indexOf("*"))>=0){
+ if(index>0)
+ resultPass1.add(keyword.substring(0, index));
+ if(keyword.length()>index)
+ keyword=keyword.substring(index+1);
+ }
+ if(keyword.length()>0)
+ resultPass1.add(keyword);
+ }
+
+ // Split keywords into parts: before "?" and after "?"
+ Collection resultPass2 = new ArrayList();
+ for (Iterator it = resultPass1.iterator(); it.hasNext();) {
+ String keyword = (String) it.next();
+ int index;
+ while((index=keyword.indexOf("?"))>=0){
+ if(index>0)
+ resultPass2.add(keyword.substring(0, index));
+ if(keyword.length()>index)
+ keyword=keyword.substring(index+1);
+ }
+ if(keyword.length()>0)
+ resultPass2.add(keyword);
+ }
+
+ return resultPass2;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/OutputProcessor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/OutputProcessor.java
new file mode 100644
index 000000000..6bdb9f304
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/OutputProcessor.java
@@ -0,0 +1,16 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.lang.*;
+
+/**
+ * Pre-processes the content of a help url before sending it to client
+ */
+public interface OutputProcessor {
+ byte[] processOutput(byte[] input);
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/PluginURL.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/PluginURL.java
new file mode 100644
index 000000000..607e3fa68
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/PluginURL.java
@@ -0,0 +1,233 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+import java.util.zip.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.util.Logger;
+import java.net.*;
+
+import org.eclipse.help.internal.HelpSystem;
+
+/**
+ * URL for documentation coming from a plugin.
+ */
+public class PluginURL extends HelpURL {
+ // Keep track of all the zip files so they won't be
+ // opened again. We may need to close them all at
+ // some point, or maintain a window of just a few
+ // simultaneously opened zip files.
+ private static Hashtable zips = new Hashtable(/*of ZipFile */);
+
+ private final static String lang = "lang";
+
+ /**
+ * FileURL constructor comment.
+ * @param url java.lang.String
+ */
+ public PluginURL(String url, String query) {
+ super(url, query);
+ }
+ public static synchronized void clear() {
+ for (Enumeration it = zips.elements(); it.hasMoreElements();) {
+ try {
+ ZipFile z = (ZipFile) it.nextElement();
+ z.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ private String getFile() {
+ // Strip the plugin id
+ int start = url.indexOf("/") + 1;
+
+ // Strip query string or anchor bookmark
+ int end = url.indexOf("?");
+ if (end == -1)
+ end = url.indexOf("#");
+ if (end == -1)
+ end = url.length();
+
+ return url.substring(start, end);
+ }
+ private String getLocation() {
+ // Assume the url is pluginID/path_to_topic.html
+ int i = url.indexOf('/');
+ String plugin = i == -1 ? "" : url.substring(0, i);
+ IPluginDescriptor descriptor =
+ Platform.getPluginRegistry().getPluginDescriptor(plugin);
+ if (descriptor != null)
+ return descriptor.getInstallURL().getFile().replace(File.separatorChar, '/');
+ else
+ return null;
+ }
+ private IPluginDescriptor getPlugin() {
+ // Assume the url is pluginID/path_to_topic.html
+ int i = url.indexOf('/');
+ String plugin = i == -1 ? "" : url.substring(0, i);
+ return Platform.getPluginRegistry().getPluginDescriptor(plugin);
+ }
+ /** Returns the path prefix that identifies the URL. */
+ public static String getPrefix() {
+ return "";
+ }
+ public boolean isCacheable() {
+ if (getValue("resultof") != null)
+ return false;
+ else
+ return true;
+ }
+ /**
+ * Opens a stream for reading.
+ *
+ * @return java.io.InputStream
+ */
+ public InputStream openStream() {
+ // if it is client install,
+ // forward request to the remote server
+ if (HelpSystem.isClient()) {
+ try {
+ URL forwardingURL;
+ if (query != null && !"".equals(query))
+ forwardingURL =
+ new URL(
+ HelpSystem.getRemoteHelpServerURL(),
+ HelpSystem.getRemoteHelpServerPath() + "/" + url + "?" + query);
+ else
+ forwardingURL =
+ new URL(
+ HelpSystem.getRemoteHelpServerURL(),
+ HelpSystem.getRemoteHelpServerPath() + "/" + url);
+ return forwardingURL.openStream();
+ } catch (MalformedURLException mue) {
+ return null;
+ } catch (IOException ioe) {
+ return null;
+ }
+ }
+
+ IPluginDescriptor plugin = getPlugin();
+ if (plugin == null)
+ return null;
+
+ String fileWithoutLocalePath = getFile();
+ String fileWithLocalePath = fileWithoutLocalePath;
+ String localePath = null;
+ InputStream inputStream = null;
+
+ URL purl = plugin.getInstallURL();
+
+ Locale locale = Locale.getDefault();
+ String clientLocale = getValue(lang);
+
+ // The clientLocale takes precedent over the Help Server locale.
+ if (clientLocale != null) {
+ if (clientLocale.indexOf("_") != -1) {
+ locale = new Locale(clientLocale.substring(0, 2), clientLocale.substring(3, 5));
+ } else {
+ locale = new Locale(clientLocale.substring(0, 2), "_ ");
+ // In case client locale only contains language info and no country info
+ }
+ }
+
+ /*
+ The code looks up the doc in the following fasion (using en_US as example):
+ 1. It looks for the doc.zip file in "plugin directory/.nl/xx_XX" and unzip the file to retrieve the .html doc file
+ 2. Then, it looks for the doc.zip file in "plugin directory/.nl/xx" and unzip the file to retrieve the .html doc file
+ 3. Then, it looks for the doc.zip file in the root directory of plugin directory and unzip the file to retrieve the default .html doc file
+ 4. Then, it looks for the .html doc file in "plugin directory/.nl/xx_XX"
+ 5. Then, it looks for the .html doc file in "plugin directory/.nl/xx"
+ 6. Then, it looks for the default .html doc file in the root directory of plugin directory
+ */
+
+ if (inputStream == null) {
+ localePath = ".nl/" + locale.getLanguage() + "_" + locale.getCountry() + "/";
+ inputStream =
+ openStreamFromZip(locale, fileWithoutLocalePath, localePath, purl);
+ }
+ if (inputStream == null) {
+ localePath = ".nl/" + locale.getLanguage() + "/";
+ inputStream =
+ openStreamFromZip(locale, fileWithoutLocalePath, localePath, purl);
+ }
+ if (inputStream == null) {
+ localePath = "./";
+ inputStream =
+ openStreamFromZip(locale, fileWithoutLocalePath, localePath, purl);
+ }
+
+ if (inputStream == null) {
+ fileWithLocalePath =
+ ".nl/"
+ + locale.getLanguage()
+ + "_"
+ + locale.getCountry()
+ + "/"
+ + fileWithoutLocalePath;
+ inputStream = openStreamFromFile(locale, fileWithLocalePath, purl);
+ }
+ if (inputStream == null) {
+ fileWithLocalePath =
+ ".nl/" + locale.getLanguage() + "/" + fileWithoutLocalePath;
+ inputStream = openStreamFromFile(locale, fileWithLocalePath, purl);
+ }
+ if (inputStream == null) {
+ fileWithLocalePath = "./";
+ inputStream = openStreamFromFile(locale, fileWithoutLocalePath, purl);
+ }
+
+ return inputStream;
+
+ }
+ /**
+ * @return java.io.InputStream
+ * @param locale java.util.Locale
+ * @param file java.lang.String
+ * @param purl java.net.URL
+ */
+ private InputStream openStreamFromFile(Locale locale, String file, URL purl) {
+ InputStream inputStream = null;
+ try {
+ URL furl = new URL(purl, file);
+
+ try {
+ inputStream = furl.openStream();
+ } catch (IOException e) {
+ inputStream = null;
+ }
+ } catch (IOException e) {
+ }
+ return inputStream;
+ }
+ /**
+ * @return java.io.InputStream
+ * @param locale java.util.Locale
+ * @param file java.lang.String
+ * @param purl java.net.URL
+ */
+ private InputStream openStreamFromZip(
+ Locale locale,
+ String file,
+ String localePath,
+ URL purl) {
+ InputStream inputStream = null;
+ try {
+ URL jurl =
+ new URL("jar", "", purl.toExternalForm() + localePath + "doc.zip!/" + file);
+
+ try {
+ inputStream = jurl.openStream();
+ } catch (IOException e) {
+ inputStream = null;
+ }
+ } catch (IOException e) {
+ }
+ return inputStream;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/SearchURL.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/SearchURL.java
new file mode 100644
index 000000000..719206b45
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/SearchURL.java
@@ -0,0 +1,189 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.help.internal.HelpSystem;
+import org.eclipse.help.internal.navigation.HelpNavigationManager;
+import org.eclipse.help.internal.search.*;
+import org.w3c.dom.*;
+import org.eclipse.help.internal.util.*;
+import org.eclipse.core.runtime.NullProgressMonitor;
+
+/**
+ * URL to the search server.
+ */
+public class SearchURL extends HelpURL {
+
+ // Maximum number of displayed hits.
+ // This is different than maximum number of hits returned by GTR.
+ // We allow GTR to search for more hits,
+ // and than display only few top ranked ones.
+ private final static int MAX_HITS_DISP = 15;
+ // Maximum number of search results.
+ // This is how many sets of MAX_HITS_DISP we provide
+ private final static int MAX_SETS = 6;
+ private ISearchEngine searchManager;
+
+ // This is a cheat to keep the last query string around.
+ // This won't work if we need to support multithreaded SearchURLs.
+ protected static String lastQuery = null;
+ protected final static String QUERY_ARG = Resources.getString("keyword");
+ protected final static String REFINE_SEARCH_ARG = Resources.getString("within");
+
+ /**
+ * SearchURL constructor comment.
+ * @param url java.lang.String
+ */
+ public SearchURL(String url) {
+ this(url, "");
+ }
+ /**
+ * SearchURL constructor comment.
+ * @param url java.lang.String
+ */
+ public SearchURL(String url, String query) {
+ super(url, query);
+ searchManager = HelpSystem.getSearchManager();
+ }
+ /**
+ * Creates result HTML page from result vector.
+ * @return HTML page
+ * @param results the search result
+ * @param baseURL directory under which plugins are installed
+ * (including "/" at the end), this will be prepended to file
+ * paths when creating URL of links to the documents.
+ */
+ private final String formatSearchResults(String results) {
+ /*
+ String doc;
+ baseURL = baseURL.replace('\\', '/');
+
+ //document header
+ doc = getFileHeader();
+
+ // results
+ if (results==null || results.getSize() == 0)
+ {
+ doc += "<b>" + Resources.getString("returned_no_matches") + "</b>";
+ }
+ else
+ {
+ // Display 5 sets of results at most, 1-20, 21-40, etc.
+ int maxResultsSets = (results.getSize() + MAX_HITS_DISP - 1) / MAX_HITS_DISP;
+ int resultSetCount = Math.min(maxResultsSets, MAX_SETS);
+ NodeList documents = results.getXML().getElementsByTagName("topic");
+
+ doc += "<div style='display:None; margin-left:-5' id=searchResultsc>\r\n";
+
+ for (int r = 0; r < resultSetCount; r++)
+ {
+ // the range of results displayed
+ int resultsBegin = 1 + r * MAX_HITS_DISP;
+ int resultsEnd = Math.min((r + 1) * MAX_HITS_DISP, results.getSize());
+ doc += "<a id=Range"
+ + r
+ + " class=tree_search_results href=\"javascript:void 0\">Results "
+ + resultsBegin
+ + "..."
+ + resultsEnd
+ + "</a>\r\n";
+ doc += "<div id=Range" + r + "c style='display:None;'>\r\n";
+
+ //Inserting results rows here
+ int maxRange = Math.min(results.getSize(), resultsEnd);
+ for (int i = r * MAX_HITS_DISP; i < maxRange; i++)
+ {
+ Element result = (Element)documents.item(i);
+ String url = result.getAttribute("href");
+ url = url.replace('\\', '/');
+ doc += " <a href='"
+ + baseURL
+ + url
+ + "' id=Result"
+ + i
+ + " class=tree onclick='javascript:highlightText();return true;'>"
+ + result.getAttribute("label")
+ + "</a>\r\n";
+ } //end of results
+ doc += "</div>\r\n";
+ }
+ doc += "</div>\r\n";
+ //System.out.println(doc);
+ }
+ //document footer
+ doc += "</body></html>" + "\r\n";
+
+ return doc;
+ */
+ return results;
+ }
+ private String getFileHeader() {
+ String doc =
+ "<html><head><title>"
+ + Resources.getString("Search_Results")
+ + "</title>"
+ + "\n"
+ + "<script language=\"JavaScript\">\r\n "
+ //+ "function loadFrame(url){ \r\n"
+ //+ " parent.opener.parent.document.frames.content.location.href = url; \r\n"
+ //+ "}\r\n"
+ +"function handleOnload(){ \r\n"
+ + " parent.searchComplete(); \r\n"
+ + "}\r\n"
+ + "</script>\r\n"
+ + "</head>"
+ + "<body onload='handleOnload()'>\r\n";
+ return doc;
+ }
+ /** Returns the path prefix that identifies the URL. */
+ public static String getPrefix() {
+ return "search";
+ }
+ /**
+ * Opens a stream for reading.
+ *
+ * @return java.io.InputStream
+ */
+ public InputStream openStream() {
+ Logger.logInfo("begining search..");
+ if (searchManager == null) {
+ Logger.logError(Resources.getString("search_not_installed"), null);
+ return new ByteArrayInputStream(
+ "<?xml version=\"1.0\"?>\n<topics/>".getBytes());
+ }
+
+ // The url string should contain the search parameters.
+ try {
+ String infoSet = (String) arguments.get("infoset");
+ try {
+ searchManager.updateIndex(infoSet, new NullProgressMonitor(), getValue("lang"));
+ } catch (Exception e) {
+ Logger.logError(Resources.getString("search_index_update_error"), null);
+ return new ByteArrayInputStream(
+ "<?xml version=\"1.0\"?>\n<topics/>".getBytes());
+ }
+ String results = searchManager.getSearchResults(infoSet, query.toString());
+ System.out.println("search results=" + results);
+ String formattedResults = formatSearchResults(results);
+
+ InputStream is =
+ new ByteArrayInputStream(formattedResults.getBytes(/* can add encoding */));
+ if (is != null) {
+ contentSize = is.available();
+ } else {
+ Logger.logError(Resources.getString("index_is_busy"), null);
+ }
+ return is;
+ } catch (IOException e) {
+ System.out.println(e.getMessage());
+ e.printStackTrace();
+ return null;
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/TempURL.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/TempURL.java
new file mode 100644
index 000000000..faf9511a9
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/server/TempURL.java
@@ -0,0 +1,90 @@
+package org.eclipse.help.internal.server;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import org.eclipse.help.internal.HelpSystem;
+import org.eclipse.help.internal.util.*;
+
+/**
+ * URL to files in the plugin's working directory, as well as
+ * to temporary files that might be generated on the fly.
+ * One instance of this is a "Table of Contents" URL.
+ * Example: http://localhost:80/temp/TableOfContents
+ * /?topicId=org.eclipse.help.examples.ex1.someTopicId
+ * &viewId=org.eclipse.help.examples.ex1.someViewId
+ * &infosetId=org.eclipse.help.examples.ex1.someInfosetId
+ */
+public class TempURL extends HelpURL {
+ // the prefix that identifies a Table Of Contents Temp URL.
+ public static String TABLE_OF_CONTENTS_PREFIX = "TableOfContents";
+
+ public TempURL(String url) {
+ super(url);
+ }
+ public TempURL(String url, String query) {
+ super(url, query);
+ }
+ /**
+ * generates a Table Of Contents as an InputStream
+ */
+ private InputStream generateTableOfContents() {
+ // delegate to the TableOfContentsGenerator
+ String infosetId = getValue("infosetId");
+ String viewId = getValue("viewId");
+ String topicId = getValue("topicId");
+ TableOfContentsGenerator generator = new TableOfContentsGenerator();
+ return generator.generateTableOfContents(infosetId, viewId, topicId);
+
+ }
+ public String getContentType() {
+ //** this is a special case for a Table Of Contents url
+ //** need to override parent behavior
+ if (isTableOfContentsURL())
+ return "text/html";
+ else
+ return super.getContentType();
+ }
+ /**
+ * Returns the path prefix that identifies the URL.
+ */
+ public static String getPrefix() {
+ return "temp";
+ }
+ public boolean isTableOfContentsURL() {
+ if (url.startsWith(TABLE_OF_CONTENTS_PREFIX))
+ return true;
+ else
+ return false;
+ }
+ /**
+ * Opens a stream for reading.
+ *
+ * @return java.io.InputStream
+ */
+ public InputStream openStream() {
+
+ // First check if this is a special "Table Of Contents" request.
+ // If it is, do HTML generation on the client.
+ if (isTableOfContentsURL())
+ return generateTableOfContents();
+
+ String path =
+ HelpSystem.getPlugin().getStateLocation().toFile().getAbsolutePath().replace(
+ File.separatorChar,
+ '/');
+ try {
+ File f = new File(path + "/" + url);
+ if (!f.exists())
+ return null;
+ contentSize = f.length();
+ return new FileInputStream(f);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/BelongsToPluginsFileFilter.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/BelongsToPluginsFileFilter.java
new file mode 100644
index 000000000..4be46fbbe
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/BelongsToPluginsFileFilter.java
@@ -0,0 +1,50 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import java.io.FilenameFilter;
+
+/**
+ * Filters out filenames, accepting only files
+ * belonging to any of plugins given in the constructor
+ */
+public class BelongsToPluginsFileFilter implements FilenameFilter {
+
+ Collection plugins;
+
+ /**
+ * Constructs BelongsToPluginsFileFilter
+ */
+ public BelongsToPluginsFileFilter(Collection plugins) {
+ super();
+ this.plugins = plugins;
+ }
+ /**
+ * accepts filenames that belongs to one of give plugins.
+ * @param dirName not used, required by interface
+ * @parama fileName file name
+ * @returns true if file name has been accepted
+ */
+ public boolean accept(java.io.File dirName, String fileName) {
+ if (fileName == null || fileName.length() < 1)
+ return false;
+ String plugin = fileName;
+ if (plugin.charAt(0) == '/')
+ plugin = plugin.substring(1);
+ if (fileName.length() < 1)
+ return false;
+ int pos = plugin.indexOf('/');
+ if (pos > 0)
+ plugin = plugin.substring(0, pos);
+ else
+ return false;
+ if (plugins.contains(plugin))
+ return true;
+ return false;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/DocResources.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/DocResources.java
new file mode 100644
index 000000000..590cec380
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/DocResources.java
@@ -0,0 +1,159 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import java.io.File;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.HelpSystem;
+import java.net.*;
+
+/**
+ * Uses a resource bundle to load images and strings from
+ * a property file in a documentation plugin
+ */
+public class DocResources {
+
+ static HashMap resourceBundleTable = new HashMap();
+ static ArrayList pluginsWithoutResources = new ArrayList();
+ static HashMap propertiesTable = new HashMap();
+
+ /**
+ * Resources constructort.
+ */
+ public DocResources() {
+ super();
+ }
+ /**
+ * Returns a string from a property file.
+ * It uses 'name' as a the key to retrieve from a doc.properties file.
+ * this is used for translation of all manifest files (including F1)
+ */
+ public static String getPluginString(String pluginID, String name) {
+
+ // resource loader
+ ClassLoader resourceLoader = null;
+ // base url for the plugin
+ URL pluginBaseURL = null;
+
+ // Shortcuts
+ try {
+ // try plugins without resources
+ if (pluginsWithoutResources.contains(pluginID))
+ return name;
+
+ // try local plugins
+ ResourceBundle resBundlePlugin =
+ (ResourceBundle) resourceBundleTable.get(pluginID);
+ if (resBundlePlugin != null) {
+ String value = resBundlePlugin.getString(name);
+ if (value == null)
+ value = name;
+ return value;
+ }
+
+ // try remote plugins
+ Properties properties = (Properties) propertiesTable.get(pluginID);
+ if (properties != null) {
+ String value = properties.getProperty(name);
+ if (value == null)
+ value = name;
+ return value;
+ }
+
+ // None of the resources is caches, so try to load it
+
+ /*
+ The sequence classpath that is specified in the ClassLoader is:
+ 1. "plugin dir"/.nl/xx_XX
+ 2. "plugin dir"/.nl/xx
+ 3. "plugin dir"
+ The file it looks for is doc.properties
+ */
+
+ IPluginDescriptor pd =
+ Platform.getPluginRegistry().getPluginDescriptor(pluginID);
+
+ // If the plugin is not installed locally try to get it from
+ // a remote installation
+ if (pd == null)
+ return getRemotePluginString(pluginID, name);
+
+ pluginBaseURL = pd.getInstallURL();
+ resourceLoader =
+ new URLClassLoader(
+ new URL[] {
+ new URL(pluginBaseURL, ".nl/" + Locale.getDefault() + "/"),
+ new URL(pluginBaseURL, ".nl/" + Locale.getDefault().getLanguage() + "/"),
+ pluginBaseURL },
+ null);
+
+ resBundlePlugin =
+ ResourceBundle.getBundle("doc", Locale.getDefault(), resourceLoader);
+
+ // Get the string
+ if (resBundlePlugin == null) {
+ pluginsWithoutResources.add(pluginID);
+ return name;
+ } else {
+ resourceBundleTable.put(pluginID, resBundlePlugin);
+ String value = resBundlePlugin.getString(name);
+ if (value == null)
+ value = name;
+ return value;
+ }
+ } catch (Throwable ex) {
+ // could not create resource bundle
+ Logger.logError(
+ Resources.getString("E010", pluginID, Locale.getDefault().toString(), name),
+ ex);
+ return name;
+ } finally {
+ resourceLoader = null; // don't need it after we have the bundle
+ }
+ }
+ /**
+ * Returns a string from a property file of a
+ * documentation plugin installed remotely
+ */
+ private static String getRemotePluginString(String pluginID, String name) {
+ // We don't do cache lookup here, as it
+ // was done in getPluginString()
+ Properties properties = null;
+ URL propertiesURL = null;
+ try {
+ propertiesURL =
+ new URL(
+ HelpSystem.getRemoteHelpServerURL(),
+ HelpSystem.getRemoteHelpServerPath()
+ + "/"
+ + pluginID
+ + "/doc.properties?lang="
+ + Locale.getDefault().toString());
+
+ properties = new Properties();
+ properties.load(propertiesURL.openStream());
+ propertiesTable.put(pluginID, properties);
+ } catch (MalformedURLException e) {
+ // could not create resource bundle
+ //propertiesTable.put(pluginID, properties);
+ } catch (Throwable ex) {
+ // could not create resource bundle
+ //propertiesTable.put(pluginID, properties);
+ }
+
+ if (properties != null) {
+ String value = properties.getProperty(name);
+ if (value == null)
+ value = name;
+ return value;
+ } else {
+ pluginsWithoutResources.add(pluginID);
+ return name;
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpException.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpException.java
new file mode 100644
index 000000000..3ba96f226
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpException.java
@@ -0,0 +1,25 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+
+/**
+ * Generic help system exception.
+ * NOTE: we should better start using it...
+ */
+public class HelpException extends CoreException {
+
+ /**
+ * HelpException constructor comment.
+ * @param plugin com.ibm.itp.core.api.plugins.IPluginDescriptor
+ * @param status com.ibm.itp.core.api.resources.IStatus
+ */
+ public HelpException(IStatus status) {
+ super(status);
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpLogListener.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpLogListener.java
new file mode 100644
index 000000000..b8ab2cc9e
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpLogListener.java
@@ -0,0 +1,109 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.Date;
+import java.text.DateFormat;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.HelpSystem;
+
+/**
+ * Help Log Listener is a sink for text messages
+ * coming from Logger.
+ */
+class HelpLogListener implements ILogListener {
+ PrintWriter log = null;
+ public HelpLogListener() {
+ try {
+ // ** Initialize log file location here.
+ IPath path =
+ HelpSystem
+ .getPlugin()
+ .getStateLocation()
+ .addTrailingSeparator()
+ .append(".log");
+ File outputFile = path.toFile();
+ log =
+ new PrintWriter(
+ new BufferedWriter(new FileWriter(outputFile.toString(), false)),
+ true);
+ } catch (Exception e) {
+ // ** can not log anything.
+ log = null;
+ }
+
+ }
+ public void logging(IStatus status) {
+ if (log == null)
+ return;
+ else {
+ String date = new Date().toString();
+ log.println(date);
+ int severity = status.getSeverity();
+ if (severity == IStatus.ERROR) {
+ log.print("ERROR");
+ } else
+ if (severity == IStatus.WARNING) {
+ log.print("WARNING");
+ } else
+ if (severity == IStatus.INFO) {
+ log.print("INFO");
+ } else
+ if (severity == IStatus.OK) {
+ log.print("DEBUG");
+ }
+
+ log.print(" ");
+ log.print(status.getPlugin());
+ // removed for now because we do not use Error codes.
+ //log.print(" ");
+ //log.print(status.getCode());
+ log.print(" ");
+ log.println(status.getMessage());
+ if (status.getException() != null)
+ status.getException().printStackTrace(log);
+ if (status.isMultiStatus()) {
+ IStatus[] children = status.getChildren();
+ for (int i = 0; i < children.length; i++)
+ loggingChild(children[i]);
+ }
+ log.println("---------------------------------------------------------------");
+ }
+
+ }
+ public void logging(IStatus status, String plugin) {
+ logging(status);
+ }
+ /**
+ * @param tmp org.eclipse.core.runtime.IStatus
+ */
+ private void loggingChild(IStatus status) {
+ if (log == null)
+ return;
+ else {
+ int severity = status.getSeverity();
+ log.print("\t");
+ log.println(status.getMessage());
+ if (status.getException() != null)
+ status.getException().printStackTrace(log);
+ if (status.isMultiStatus()) {
+ IStatus[] children = status.getChildren();
+ for (int i = 0; i < children.length; i++)
+ logging(children[i]);
+ }
+ }
+
+ }
+ public void shutdown() {
+ if (log == null)
+ return;
+ log.flush();
+ log.close();
+ log = null;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpVisitor.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpVisitor.java
new file mode 100644
index 000000000..6651b67cb
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/HelpVisitor.java
@@ -0,0 +1,46 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.eclipse.help.internal.contributions.*;
+
+/**
+ * Default help contributions visitor
+ */
+public class HelpVisitor implements Visitor {
+ /**
+ * HelpVisitor constructor comment.
+ */
+ public HelpVisitor() {
+ super();
+ }
+ /**
+ * @param viewSet com.ibm.itp.ua.view.ViewSet
+ */
+ public void visit(InfoSet infoSet) {
+ visitChildren(infoSet);
+ }
+ /**
+ * visit method comment.
+ */
+ public void visit(InfoView view) {
+ visitChildren(view);
+ }
+ /**
+ * visit method comment.
+ */
+ public void visit(Topic topic) {
+ visitChildren(topic);
+ }
+ public void visitChildren(Contribution con) {
+ for (Iterator e = con.getChildren(); e.hasNext();) {
+ Contribution c = (Contribution) e.next();
+ c.accept(this);
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/Logger.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/Logger.java
new file mode 100644
index 000000000..093efb5f3
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/Logger.java
@@ -0,0 +1,146 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.HelpSystem;
+
+/**
+ * Generic Help System Logger class for handling logging and tracing.
+ *
+ * debug options are determined by HelpSystem debug_level field:
+ *
+ * DEBUG boolean flag for optimizing out heavy duty Level 3 developer messages
+ */
+public class Logger {
+ // This SHOULD be set to false in production
+ public final static boolean DEBUG = false;
+
+ // Cashed workbenchPlugin Log, LogListener instances
+ private static ILog helpSystemLog = null;
+ private static HelpLogListener helpLogListener = null;
+
+ // Cashed workbenchPlugin ID
+ private static String workbenchPluginID = null;
+
+ // Controls logging level
+ private static int debug_level = 0;
+
+ // Captures initialization errors
+ private static boolean init_ok = true;
+
+ static {
+ initialize();
+ }
+
+ private static void initialize() {
+ try {
+ // get the debug level from the HelpSystem instance
+ debug_level = HelpSystem.getDebugLevel();
+
+ // get unique pluging ID and cash it for later use.
+ Plugin workbenchPlugin = HelpSystem.getPlugin();
+ workbenchPluginID = workbenchPlugin.getDescriptor().getUniqueIdentifier();
+ helpSystemLog = workbenchPlugin.getLog();
+ if (helpLogListener == null)
+ helpLogListener = new HelpLogListener();
+ helpSystemLog.addLogListener(helpLogListener);
+
+ } catch (Exception e) {
+ // Errors occured during initialize, disable logging
+ init_ok = false;
+ }
+ }
+ /*
+ * Log a Debug message. This is intended to be wrapped as follows:
+ * if (Logger.DEBUG)
+ * Logger.logDebugMessage("someClassName", "someMessage");
+ *
+ * and the output will be:
+ *
+ * ---------------------------------------------------------------
+ * DEBUG org.eclipse.help.ui someClassName
+ * someMessage
+ * ---------------------------------------------------------------
+ *
+ *
+ * Note that since this message is only for developer debugging, it does not
+ * need to be localized to proper local.
+ */
+
+ public static synchronized void logDebugMessage(
+ String className,
+ String message) {
+ if ((init_ok) && (debug_level >= HelpSystem.LOG_DEBUG)) {
+ // ie: print all INFO, WARNING and ERROR messages
+ MultiStatus debugStatus =
+ new MultiStatus(workbenchPluginID, IStatus.OK, className, null);
+ Status infoStatus =
+ new Status(IStatus.OK, workbenchPluginID, IStatus.OK, message, null);
+ debugStatus.add(infoStatus);
+ helpSystemLog.log(debugStatus);
+ }
+ }
+ /*
+ * Log an Error message with an exception. Note that the message should already
+ * be localized to proper local.
+ * ie: Resource.getString() should already have been called
+ */
+
+ public static synchronized void logError(String message, Throwable ex) {
+ if ((init_ok) && (debug_level >= HelpSystem.LOG_ERROR)) {
+ // ie: print only ERROR messages
+ if (message == null)
+ message = "";
+ Status errorStatus =
+ new Status(IStatus.ERROR, workbenchPluginID, IStatus.OK, message, ex);
+ helpSystemLog.log(errorStatus);
+
+ }
+ }
+ /*
+ * Log an Information message with an exception. Note that the message should already
+ * be localized to proper local.
+ * ie: Resource.getString() should already have been called
+ */
+
+ public static synchronized void logInfo(String message) {
+ if ((init_ok) && (debug_level >= HelpSystem.LOG_DEBUG)) {
+ if (message == null)
+ message = "";
+ // ie: print all INFO, WARNING and ERROR messages
+ Status infoStatus =
+ new Status(IStatus.INFO, workbenchPluginID, IStatus.OK, message, null);
+ helpSystemLog.log(infoStatus);
+
+ }
+
+ }
+ /*
+ * Log a Warning message with an exception. Note that the message should already
+ * be localized to proper local.
+ * ie: Resource.getString() should already have been called
+ */
+
+ public static synchronized void logWarning(String message) {
+ if ((init_ok) && (debug_level >= HelpSystem.LOG_WARNING)) {
+ if (message == null)
+ message = "";
+ // ie: print all WARNING and ERROR messages
+ Status warningStatus =
+ new Status(IStatus.WARNING, workbenchPluginID, IStatus.OK, message, null);
+ helpSystemLog.log(warningStatus);
+ }
+
+ }
+ public static synchronized void setDebugLevel(int level) {
+ debug_level = level;
+ }
+ public static void shutdown() {
+ helpLogListener.shutdown();
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/PersistentMap.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/PersistentMap.java
new file mode 100644
index 000000000..95286c465
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/PersistentMap.java
@@ -0,0 +1,150 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.help.internal.HelpSystem;
+
+/**
+ * Persistant Hashtable with keys and values of type String.
+ */
+public class PersistentMap extends Hashtable {
+ public static final String columnSeparator = "|";
+ private File file = null;
+ private File tempfile = null;
+ protected String name = null;
+ /**
+ * Creates empty table for use by Help Plugin.
+ * @param name name of the table;
+ */
+ public PersistentMap(String name) {
+ super();
+ this.name = name;
+ file =
+ new File(HelpSystem.getPlugin().getStateLocation().toFile(), name + ".tab");
+ tempfile =
+ new File(HelpSystem.getPlugin().getStateLocation().toFile(), name + "_.tab");
+ }
+ /**
+ * Creates empty table for use by Help Plugin.
+ * @param name name of the table;
+ */
+ public PersistentMap(String dir, String name) {
+ super();
+ this.name = name;
+ file = new File(dir, name + ".tab");
+ tempfile = new File(dir, name + "_.tab");
+ }
+ public boolean exists() {
+ return file.exists() || tempfile.exists();
+ }
+ /**
+ * Restores contents of the table from a file.
+ * @return true if persistant data was read in
+ */
+ public boolean restore() {
+ File usedfile = file;
+ BufferedReader bufr = null;
+ String line = null;
+ boolean loaded = false;
+ if (!usedfile.exists()) {
+ usedfile = tempfile;
+ }
+ if (!usedfile.exists()) {
+ return loaded;
+ }
+ clear();
+ try {
+ bufr =
+ new BufferedReader(
+ new InputStreamReader(
+ new FileInputStream(usedfile) /* can specify encoding */));
+ line = bufr.readLine();
+ while (line != null) {
+ StringTokenizer tokens = new StringTokenizer(line, columnSeparator, true);
+ try {
+ String key, value;
+ key = tokens.nextToken();
+ if (key.equals(columnSeparator)) {
+ // key was empty, separator read.
+ key = "";
+ } else {
+ // read the separator
+ value = tokens.nextToken();
+ }
+ if (tokens.hasMoreElements()) {
+ value = tokens.nextToken();
+ } else {
+ value = "";
+ }
+ this.put(key, value);
+ loaded = true;
+ } catch (NoSuchElementException nsee) {
+ // Probably got an emtpy line at the end
+ break;
+ }
+ line = bufr.readLine();
+ }
+ } catch (IOException ioe00) {
+ Logger.logError(Resources.getString("Table", name), null);
+ Logger.logError(Resources.getString("File4", usedfile.getName()), null);
+ loaded = false;
+ } finally {
+ if (bufr != null)
+ try {
+ bufr.close();
+ } catch (IOException ioe10) {
+ }
+ }
+ return loaded;
+ }
+ /**
+ * Saves contents of the table to a file.
+ * @return true if operation was successful
+ */
+ public boolean save() {
+ PrintWriter buf = null;
+ boolean ret = false;
+ tempfile.delete();
+ if (tempfile.exists()) {
+ Logger.logError(
+ Resources.getString("Table2", name, tempfile.getAbsolutePath()),
+ null);
+ return ret;
+ }
+ try {
+ buf =
+ new PrintWriter(
+ new OutputStreamWriter(
+ new BufferedOutputStream(new FileOutputStream(tempfile))),
+ false);
+ for (Enumeration e = this.keys(); e.hasMoreElements();) {
+ String name = (String) e.nextElement();
+ buf.println(name + columnSeparator + this.get(name));
+ }
+ buf.flush();
+ ret = true;
+ } catch (IOException ioe00) {
+ Logger.logError(
+ Resources.getString("Exception_occured", name, tempfile.getAbsolutePath()),
+ null);
+ } finally {
+ if (buf != null) {
+ buf.close();
+ }
+ }
+ if (tempfile.exists()) {
+ file.delete();
+ if (tempfile.renameTo(file)) {
+ } else {
+ ret = false;
+ }
+ }
+ return ret;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/PluginVersionInfo.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/PluginVersionInfo.java
new file mode 100644
index 000000000..912ef151c
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/PluginVersionInfo.java
@@ -0,0 +1,139 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.core.runtime.*;
+
+/**
+ * Table of plugins. Records all plugins and their version.
+ */
+public class PluginVersionInfo extends PersistentMap {
+ boolean doComparison = true;
+ boolean hasChanged = false;
+
+ Collection added = new ArrayList();
+ Collection removed = new ArrayList();
+
+ /**
+ * Creates table of current contributing plugins and their version.
+ * @param list vector of current contributions (IConfigurationElement type)
+ */
+ public PluginVersionInfo(String name, Iterator it) {
+ super(name);
+ if (it == null)
+ return;
+ // create table of current contributions
+ for (; it.hasNext();) {
+ IPluginDescriptor plugin = (IPluginDescriptor) it.next();
+ this.put(
+ plugin.getUniqueIdentifier(),
+ plugin.getVersionIdentifier().toString());
+ }
+ }
+ /**
+ * Creates table of current contributing plugins and their version.
+ * @param list vector of current contributions (IConfigurationElement type)
+ */
+ public PluginVersionInfo(String name, List list) {
+ super(name);
+ // create table of current contributions
+ for (Iterator it = list.iterator(); it.hasNext();) {
+ IPluginDescriptor plugin = (IPluginDescriptor) it.next();
+ this.put(
+ plugin.getUniqueIdentifier(),
+ plugin.getVersionIdentifier().toString());
+ }
+ }
+ /**
+ * Creates table of current contributing plugins and their version.
+ * @param list vector of current contributions (IConfigurationElement type)
+ */
+ public PluginVersionInfo(String name, Vector list) {
+ super(name);
+ // create table of current contributions
+ for (int i = 0; i < list.size(); i++) {
+ IPluginDescriptor plugin = (IPluginDescriptor) list.elementAt(i);
+ this.put(
+ plugin.getUniqueIdentifier(),
+ plugin.getVersionIdentifier().toString());
+ }
+ }
+ /**
+ * Detects changes in contributions or their version
+ * since last time the contribution table was saved.
+ * @return true if contributions have changed
+ */
+ public boolean detectChange() {
+ if (!doComparison)
+ return hasChanged;
+
+ // Create table of contributions present before last save()
+ PersistentMap oldContrs = new PersistentMap(this.name);
+ oldContrs.restore();
+ // check if contributions changed
+ hasChanged = false;
+ //
+ for (Enumeration keysEnum = this.keys(); keysEnum.hasMoreElements();) {
+ String oneContr = (String) keysEnum.nextElement();
+ if (!oldContrs.containsKey(oneContr)) {
+ added.add(oneContr);
+ } else
+ if (!this.get(oneContr).equals(oldContrs.get(oneContr))) {
+ added.add(oneContr);
+ }
+ }
+
+ for (Enumeration keysEnum = oldContrs.keys(); keysEnum.hasMoreElements();) {
+ String oneContr = (String) keysEnum.nextElement();
+ if (!this.containsKey(oneContr)) {
+ removed.add(oneContr);
+ } else
+ if (!oldContrs.get(oneContr).equals(this.get(oneContr))) {
+ removed.add(oneContr);
+ }
+ }
+
+ hasChanged = added.size() > 0 || removed.size() > 0;
+ doComparison = false;
+ return hasChanged;
+ }
+ /**
+ * @return String - Collection of IDs of contributions that were added
+ * or upgraded
+ */
+ public Collection getAdded() {
+ if (doComparison)
+ detectChange();
+ return added;
+ }
+ /**
+ * @return String - Collection of IDs of contributions that were removed
+ * or upgraded
+ */
+ public Collection getRemoved() {
+ if (doComparison)
+ detectChange();
+ return removed;
+ }
+ /**
+ * Saves contributions to a file.
+ * After this method is called, calls to detectChange() will return false.
+ * @return true if operation was successful
+ */
+ public boolean save() {
+ if (super.save()) {
+ doComparison = false;
+ hasChanged = false;
+ added = new ArrayList();
+ removed = new ArrayList();
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/Resources.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/Resources.java
new file mode 100644
index 000000000..dfa1bc1d9
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/Resources.java
@@ -0,0 +1,177 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import java.io.File;
+import java.net.*;
+import org.eclipse.core.runtime.*;
+import org.eclipse.help.internal.HelpSystem;
+
+/**
+ * Uses a resource bundle to load images and strings from
+ * a property file.
+ */
+public class Resources {
+ private static ResourceBundle resBundle;
+ static {
+ resBundle = ResourceBundle.getBundle("Help", Locale.getDefault());
+ }
+ /**
+ * Resources constructort.
+ */
+ public Resources() {
+ super();
+ }
+ /**
+ * Returns a string from a property file
+ */
+ public static String getString(String name) {
+ try {
+ return resBundle.getString(name);
+ } catch (Exception e) {
+ return name;
+ }
+
+ }
+ /**
+ * Returns a string from a property file
+ */
+ public static String getString(String name, String replace1) {
+ try {
+ String stringFromPropertiesFile = resBundle.getString(name);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%1", replace1);
+ return stringFromPropertiesFile;
+ } catch (Exception e) {
+ return name;
+ }
+
+ }
+ /**
+ * Returns a string from a property file
+ */
+ public static String getString(String name, String replace1, String replace2) {
+ try {
+ String stringFromPropertiesFile = resBundle.getString(name);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%1", replace1);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%2", replace2);
+ return stringFromPropertiesFile;
+ } catch (Exception e) {
+ return name;
+ }
+
+ }
+ /**
+ * Returns a string from a property file
+ */
+ public static String getString(
+ String name,
+ String replace1,
+ String replace2,
+ String replace3) {
+ try {
+ String stringFromPropertiesFile = resBundle.getString(name);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%1", replace1);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%2", replace2);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%3", replace3);
+ return stringFromPropertiesFile;
+ } catch (Exception e) {
+ return name;
+ }
+
+ }
+ /**
+ * Returns a string from a property file
+ */
+ public static String getString(
+ String name,
+ String replace1,
+ String replace2,
+ String replace3,
+ String replace4) {
+ try {
+ String stringFromPropertiesFile = resBundle.getString(name);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%1", replace1);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%2", replace2);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%3", replace3);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%4", replace4);
+ return stringFromPropertiesFile;
+ } catch (Exception e) {
+ return name;
+ }
+
+ }
+ /**
+ * Returns a string from a property file
+ */
+ public static String getString(
+ String name,
+ String replace1,
+ String replace2,
+ String replace3,
+ String replace4,
+ String replace5) {
+ try {
+ String stringFromPropertiesFile = resBundle.getString(name);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%1", replace1);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%2", replace2);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%3", replace3);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%4", replace4);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%5", replace5);
+ return stringFromPropertiesFile;
+ } catch (Exception e) {
+ return name;
+ }
+
+ }
+ /**
+ * Returns a string from a property file
+ */
+ public static String getString(
+ String name,
+ String replace1,
+ String replace2,
+ String replace3,
+ String replace4,
+ String replace5,
+ String replace6) {
+ try {
+ String stringFromPropertiesFile = resBundle.getString(name);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%1", replace1);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%2", replace2);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%3", replace3);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%4", replace4);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%5", replace5);
+ stringFromPropertiesFile =
+ TString.change(stringFromPropertiesFile, "%6", replace6);
+ return stringFromPropertiesFile;
+ } catch (Exception e) {
+ return name;
+ }
+
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/RuntimeHelpStatus.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/RuntimeHelpStatus.java
new file mode 100644
index 000000000..4dc4ad08a
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/RuntimeHelpStatus.java
@@ -0,0 +1,125 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.*;
+import org.xml.sax.*;
+import org.eclipse.core.runtime.*;
+
+/**
+ * This class is intended to capture all runtime exception happening during
+ * the execution of the Help System.
+ */
+
+public class RuntimeHelpStatus {
+ private static RuntimeHelpStatus inst = null;
+
+ // contains Status objects of errors occurred
+ private ArrayList errorList = new ArrayList();
+
+ // contains File names (Strings) of invalid contribution files.
+ private ArrayList badFilesList = new ArrayList();
+
+ // contains the error messages (Strings) from the parser
+ private ArrayList parserErrorMessagesList = new ArrayList();
+
+ /**
+ * RuntimeHelpStatus constructor comment.
+ */
+ public RuntimeHelpStatus() {
+ super();
+ }
+ public synchronized void addError(Status status) {
+ errorList.add(status);
+
+ }
+ public synchronized void addParseError(
+ String message,
+ String invalidFileName) {
+ // add the Exception to the files list only once. These exceptions will be used to
+ // produce the list of files with errors.
+ if (!badFilesList.contains(invalidFileName))
+ badFilesList.add(invalidFileName);
+
+ // now add the message. All parser messages are added
+ parserErrorMessagesList.add(message);
+
+ }
+ public synchronized void addParseError(
+ String message,
+ SAXParseException parseException) {
+ // add the Exception to the files list only once. These exceptions will be used to
+ // produce the list of files with errors.
+ if (!badFilesList.contains(parseException))
+ badFilesList.add(parseException);
+
+ // now add the message. All parser messages are added
+ parserErrorMessagesList.add(message);
+
+ }
+ public boolean errorsExist() {
+ if (errorList.isEmpty()
+ && parserErrorMessagesList.isEmpty()
+ && badFilesList.isEmpty())
+ return false;
+ else
+ return true;
+ }
+ public static synchronized RuntimeHelpStatus getInstance() {
+ if (inst == null) // create instance
+ inst = new RuntimeHelpStatus();
+ return inst;
+ }
+ /**
+ * clears RuntimeHelpStatus object.
+ */
+ public void reset() {
+ errorList.clear();
+ badFilesList.clear();
+ parserErrorMessagesList.clear();
+ }
+ public synchronized String toString() {
+ StringBuffer fullText = new StringBuffer();
+ if (!errorList.isEmpty()) {
+ fullText.append(Resources.getString("E006"));
+ fullText.append("***************************** \n");
+ for (int i = 0; i < errorList.size(); i++) {
+ fullText.append(((Status) (errorList.get(i))).getMessage());
+ fullText.append("\n");
+ }
+ }
+
+ if (fullText.length() > 0)
+ fullText.append("\n");
+
+ if (!parserErrorMessagesList.isEmpty()) {
+ // display the files that failed to parse
+ fullText.append(Resources.getString("E007"));
+ fullText.append("***************************** \n");
+ for (int i = 0; i < badFilesList.size(); i++) {
+ fullText.append(((String) (badFilesList.get(i))));
+ fullText.append("\n");
+ }
+
+ fullText.append("\n");
+
+ // and the parse error message
+ fullText.append(Resources.getString("E008"));
+ fullText.append("******************** \n");
+ for (int i = 0; i < parserErrorMessagesList.size(); i++) {
+ fullText.append(((String) (parserErrorMessagesList.get(i))));
+ fullText.append("\n");
+ }
+ }
+
+ if (fullText.length() > 0)
+ return fullText.toString();
+ else
+ return "null status object";
+
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/SearchableDocFileNameFilter.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/SearchableDocFileNameFilter.java
new file mode 100644
index 000000000..782a1a501
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/SearchableDocFileNameFilter.java
@@ -0,0 +1,38 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.FilenameFilter;
+
+/**
+ * Filters out filenames, accepting only
+ * htm, html, txt, xml extensions.
+ */
+public class SearchableDocFileNameFilter implements FilenameFilter {
+ /**
+ * Constructs SearchableDocFileNameFilter
+ */
+ public SearchableDocFileNameFilter() {
+ super();
+ }
+ /**
+ * accepts filenames of the htm, html, txt, xml extensions.
+ * @param dirName not used, required by interface
+ * @parama fileName file name
+ * @returns true if file name has been accepted
+ */
+ public boolean accept(java.io.File dirName, String fileName) {
+ fileName = fileName.toLowerCase();
+ if (fileName.endsWith(".htm")
+ || fileName.endsWith(".html")
+ || fileName.endsWith(".txt")
+ || fileName.endsWith(".xml")) {
+ return true;
+ }
+ return false;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/SequenceGenerator.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/SequenceGenerator.java
new file mode 100644
index 000000000..a28271d9d
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/SequenceGenerator.java
@@ -0,0 +1,45 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+/**
+ * Generates incremental numbers for different contribution ids
+ */
+public class SequenceGenerator {
+ protected static final SequenceGenerator instance = new SequenceGenerator();
+ protected long sequence = 0;
+ /**
+ * SequenceGenerator constructor comment.
+ */
+ protected SequenceGenerator() {
+ super();
+ }
+ /**
+ * @return com.ibm.itp.help.util.SequenceGenerator
+ */
+ public static SequenceGenerator getDefaultGenerator() {
+ return instance;
+ }
+ /**
+ * @return com.ibm.itp.help.util.SequenceGenerator
+ */
+ public static SequenceGenerator getNewGenerator() {
+ return new SequenceGenerator();
+ }
+ /**
+ * @return long
+ */
+ public synchronized long getNext() {
+ return ++sequence;
+ }
+ /**
+ * @return long
+ */
+ public synchronized static long next() {
+ return ++instance.sequence;
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/TString.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/TString.java
new file mode 100644
index 000000000..75d8fba28
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/TString.java
@@ -0,0 +1,323 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.util.StringTokenizer;
+
+/**
+ * This class provides static methods for some of the
+ * very used IString operations
+ */
+public class TString {
+ private static final String ALPHABET =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ private static final String ALPHANUMERIC =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ private static final String NUMERIC = "0123456789";
+
+ // change all occurrences of oldPat to newPat
+ public static String change(String in, String oldPat, String newPat) {
+ if (oldPat.length() == 0)
+ return in;
+ if (oldPat.length() == 1 && newPat.length() == 1)
+ return in.replace(oldPat.charAt(0), newPat.charAt(0));
+
+ int lastIndex = 0;
+ int newIndex = 0;
+ StringBuffer newString = new StringBuffer();
+ for (;;) {
+ newIndex = in.indexOf(oldPat, lastIndex);
+ if (newIndex != -1) {
+ newString.append(in.substring(lastIndex, newIndex) + newPat);
+ lastIndex = newIndex + oldPat.length();
+ } else {
+ newString.append(in.substring(lastIndex));
+ break;
+ }
+ }
+ return newString.toString();
+ }
+ // change the occurrences of oldPat to newPat starting at startPosition
+ // for number of numChanges
+ // Note: the 1st char in the string has position of 0
+
+ public static String change(
+ String in,
+ String oldPat,
+ String newPat,
+ int startPos,
+ int numChanges) {
+ if (oldPat.length() == 0)
+ return in;
+ if (oldPat.length() == 1 && newPat.length() == 1)
+ return in.replace(oldPat.charAt(0), newPat.charAt(0));
+
+ int inLen = in.length();
+
+ if (startPos >= inLen)
+ return in;
+
+ int lastIndex = startPos;
+ int newIndex = 0;
+ int countChanges = 0;
+
+ StringBuffer newString = new StringBuffer();
+
+ for (;;) {
+ newIndex = in.indexOf(oldPat, lastIndex);
+ if (newIndex != -1) {
+ newString.append(in.substring(lastIndex, newIndex) + newPat);
+ lastIndex = newIndex + oldPat.length();
+ countChanges++;
+ } else {
+ newString.append(in.substring(lastIndex));
+ break;
+ }
+
+ if (countChanges == numChanges) {
+ newString.append(in.substring(lastIndex));
+ break;
+ }
+ }
+
+ return newString.toString();
+ }
+ // return true if the " " appears within srcString
+ // example:
+ // srcString = "a m"
+ // return = true
+
+ public static boolean containsDoubleBlanks(String srcString) {
+ String bb = " ";
+ char b = bb.charAt(0);
+
+ if (srcString.length() > 0) {
+ for (int i = 0; i < (srcString.length() - 1); i++) {
+ if ((b == srcString.charAt(i)) & (b == srcString.charAt(i + 1)))
+ return true;
+ }
+ }
+ return false;
+ }
+ // return a string that contains number of copies of srcString
+ // example:
+ // srcString = "abc"
+ // numberOfCopies = 2
+ // return string = "abcabc"
+
+ public static String copy(String srcString, int numberOfCopies) {
+ StringBuffer result = new StringBuffer();
+
+ if (numberOfCopies > 0) {
+ for (int i = 1; i <= numberOfCopies; i++)
+ result.append(srcString);
+ } else
+ result = new StringBuffer(srcString);
+
+ return result.toString();
+ }
+ public static long getLong(String str) {
+ try {
+ return Long.parseLong(str);
+ } catch (Exception m) {
+ return 0;
+ }
+ }
+ // return the first index within srcString that is not in the validString
+ // example:
+ // srcString = "abcdefg"
+ // validString = "bcfg"
+ // return = 0 (i.e. char a is not in "bcfg") - 1st index = 0
+
+ public static int indexOfAnyBut(String srcString, String validString) {
+ int result = -1;
+ int srcLen = srcString.length();
+
+ // walk backward to find if a char within srcString is in validString
+ for (int i = 0; i < srcLen; i++) {
+ // not found, stop it
+ if (validString.indexOf(srcString.charAt(i)) == -1) {
+ result = i;
+ break;
+ }
+
+ }
+
+ return result;
+ }
+ //
+ // return true if all chars in srcString are in {a...z} or {A...Z}
+
+ public static boolean isAlphabetic(String srcString) {
+ return (lastIndexOfAnyBut(srcString, ALPHABET) == -1);
+ }
+ //
+ // return true if all chars in srcString are in {a...z,} or {A...Z} {0...9}
+
+ public static boolean isAlphanumeric(String srcString) {
+ return (lastIndexOfAnyBut(srcString, ALPHANUMERIC) == -1);
+ }
+ //
+ // return true if all chars are in '0' - '9'
+
+ public static boolean isDigits(String srcString) {
+ return (lastIndexOfAnyBut(srcString, NUMERIC) == -1);
+ }
+ // return the last index within srcString that is not in the validString
+ // example:
+ // srcString = "abcdefg"
+ // validString = "bcfg"
+ // return = 4 (i.e. char e is not in "bcfg") - 1st index = 0
+
+ public static int lastIndexOfAnyBut(String srcString, String validString) {
+ int result = -1;
+ int srcLen = srcString.length();
+
+ // walk backward to find if a char within srcString is in validString
+ for (int i = srcLen - 1; i >= 0; i--) {
+ // not found, stop it
+ if (validString.indexOf(srcString.charAt(i)) == -1) {
+ result = i;
+ break;
+ }
+
+ }
+
+ return result;
+ }
+ //
+ // return the string after the matching token is removed
+ public static String match(String in, String token) throws Exception {
+ if (in == null)
+ return null;
+
+ in = in.trim();
+ if (in.startsWith(token))
+ return in.substring(token.length(), in.length());
+ else
+ throw new Exception(Resources.getString("Expected", token, word(in, 1)));
+ }
+ public static int numWords(String in) {
+ StringTokenizer st = new StringTokenizer(in);
+ return st.countTokens();
+ }
+ // return number of occurrences of searchChar within srcString
+ // example:
+ // srcString = "::f::f::g"
+ // seachrChar = ':'
+ // return = 6
+
+ public static int occurrenceOf(String srcString, char searchChar) {
+ int result = 0;
+ // walk backward to find if a char within srcString is in validString
+ if (srcString.length() > 0) {
+
+ for (int i = 0; i < srcString.length(); i++) {
+ // found, increment the count
+ if (searchChar == srcString.charAt(i))
+ result++;
+ }
+ }
+
+ return result;
+ }
+ // strip the leading pString in the srcString
+ // example:
+ // srcString = "::f::f::g"
+ // pString "::"
+ // return = "f::f::g"
+
+ public static String stripLeading(String srcString, String pString) {
+ String result;
+
+ if (srcString.startsWith(pString)) // leading patString found
+ result = srcString.substring(pString.length(), srcString.length());
+ else // not found
+ result = srcString;
+
+ return result;
+ }
+ public static String stripSpace(String srcString) {
+ String b1 = " ";
+ int lastIndex = 0;
+ int newIndex = 0;
+ StringBuffer newString = new StringBuffer();
+ for (;;) {
+ newIndex = srcString.indexOf(b1, lastIndex);
+ if (newIndex != -1) {
+ newString.append(srcString.substring(lastIndex, newIndex));
+ lastIndex = newIndex + 1;
+ } else {
+ newString.append(srcString.substring(lastIndex));
+ break;
+ }
+ }
+ return newString.toString();
+ }
+ // strip the trailing pString in the srcString
+ // example:
+ // srcString = "f::f::g::"
+ // pString "::"
+ // return = "f::f::g"
+
+ public static String stripTrailing(String srcString, String pString) {
+ String result;
+
+ if (srcString.endsWith(pString)) // leading patString found
+ result = srcString.substring(0, srcString.lastIndexOf(pString));
+ else // not found
+ result = srcString;
+
+ return result;
+ }
+ /**
+ * strip the trailing blanks in the src
+ */
+ public static String stripTrailingBlanks(String src) {
+
+ if (src != null) {
+ while (src.length() > 0) {
+ if (src.endsWith(" "))
+ src = src.substring(0, src.length() - 1);
+ else
+ break;
+ }
+ }
+
+ return src;
+ }
+ public static String word(String in, int i) {
+ StringTokenizer st = new StringTokenizer(in);
+ if (i <= 0 || i > st.countTokens())
+ return "";
+ else {
+ String ret = new String();
+ while (st.hasMoreTokens()) {
+ ret = st.nextToken();
+ if (--i == 0)
+ return ret;
+ }
+ }
+ return "";
+ }
+ public static String words(String in, int i) {
+ StringTokenizer st = new StringTokenizer(in);
+ if (i <= 0 || i > st.countTokens())
+ return "";
+ else {
+ while (st.hasMoreTokens()) {
+ if (--i == 0)
+ break;
+ st.nextToken();
+ }
+ if (st.hasMoreTokens())
+ return st.nextToken("");
+ else
+ return "";
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/TableOfContentsGenerator.java b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/TableOfContentsGenerator.java
new file mode 100644
index 000000000..250cf804c
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/internal/util/TableOfContentsGenerator.java
@@ -0,0 +1,173 @@
+package org.eclipse.help.internal.util;
+
+/*
+ * Licensed Materials - Property of IBM,
+ * WebSphere Studio Workbench
+ * (c) Copyright IBM Corp 2000
+ */
+
+import java.io.*;
+import java.util.*;
+import org.eclipse.help.internal.HelpSystem;
+import org.eclipse.help.internal.contributions.*;
+
+/**
+ * This class is resposible for generating a Table of Contents for
+ * a given Topic hierarchy.
+ */
+public class TableOfContentsGenerator {
+
+ // flag needed when doing recursion in findTopic()
+ private static boolean foundTopic = false;
+ public TableOfContentsGenerator() {
+ super();
+ }
+ /**
+ * Recursively finds of a Topic in a list of Topics with the given topicId
+ */
+ private Topic findTopic(List children, String topicId) {
+ Topic topic = null;
+ for (int i = 0; i < children.size() && !foundTopic; i++) {
+ topic = ((Topic) children.get(i));
+ if (topic.getID().equals(topicId)) {
+ foundTopic = true;
+ break;
+ }
+ }
+
+ if (foundTopic)
+ return topic;
+ else {
+ for (int i = 0; i < children.size() && !foundTopic; i++) {
+ Topic child = topic = ((Topic) children.get(i));
+ topic = findTopic(child.getChildrenList(), topicId);
+ if ((topic != null) && (foundTopic))
+ return topic;
+ }
+ return null;
+ }
+
+ }
+ private void generateHeader(StringBuffer buffer) {
+ buffer.append("<HEAD>");
+ // officially, a HEAD element needs a TITLE. fake it.
+ buffer.append("<TITLE/>");
+
+ // make sure that we have everything in UTF-8 because this is
+ // what this string buffer will converted to.
+ buffer.append("<META http-equiv=\"Content-Type\" ");
+ buffer.append("content=\"text/html; charset=utf-8\">");
+
+ // set Expires to any old date to avoid caching by IE.
+ // HTTP servers sometimes return this info as part of the
+ // respone.
+ buffer.append("<META HTTP-EQUIV=\"Expires\" ");
+ buffer.append("CONTENT=\"Mon, 04 Dec 2000 11:11:11 GMT\"> ");
+ buffer.append("</HEAD>");
+
+ }
+ /**
+ * generates a Table Of Contents as an InputStream
+ */
+ private InputStream generateTableOfContents(Topic[] topicList) {
+
+ StringBuffer tableOfContents = new StringBuffer();
+ tableOfContents.append("<html>");
+ generateHeader(tableOfContents);
+
+ tableOfContents.append("<body>");
+ tableOfContents.append("<h1 ALIGN=CENTER>");
+ tableOfContents.append(Resources.getString("Table_Of_Contents"));
+ tableOfContents.append("</h1>");
+ tableOfContents.append("<h3>");
+
+ try {
+ tableOfContents.append("<ol>");
+ for (int i = 0; i < topicList.length; i++) {
+ tableOfContents.append("<li>");
+ tableOfContents.append(topicList[i].getLabel());
+ tableOfContents.append("</li>");
+ }
+ tableOfContents.append("<ol>");
+ tableOfContents.append("</h3>");
+
+ tableOfContents.append("</body></html>");
+ byte[] bytes = tableOfContents.toString().getBytes("UTF-8");
+
+ ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes);
+ return inputStream;
+ } catch (Exception e) {
+ // null handled by calling class
+ return null;
+ }
+
+ }
+ /**
+ * generates a Table Of Contents as an InputStream
+ */
+ public InputStream generateTableOfContents(
+ String infosetId,
+ String viewId,
+ String topicId) {
+
+ try {
+ // get to the topic in the navigation model. Find the infoset, and then
+ // the view.
+ InfoSet infoset =
+ HelpSystem.getInstance().getNavigationManager().getInfoSet(infosetId);
+ InfoView view = infoset.getView(viewId);
+ List children = view.getChildrenList();
+
+ // now find the topic in the view.
+ Topic topic = findTopic(children, topicId);
+
+ // cleanup for next rev.
+ foundTopic = false;
+
+ // create the list of children topics.
+ Topic[] topicList = getTopicList(topic);
+
+ return generateTableOfContents(topicList);
+
+ } catch (Exception e) {
+ // return null to signal problem.
+ return null;
+ }
+
+ }
+ /**
+ * Returns an Topic array off all topics to be printed.
+ * returns null if array could not be created.
+ */
+ public static Topic[] getTopicList(Topic rootTopic) {
+ try {
+ Vector objectVector = new Vector();
+ populateTopicVector(rootTopic, objectVector);
+
+ Topic[] topicList = new Topic[objectVector.size()];
+ objectVector.toArray(topicList);
+
+ return topicList;
+ } catch (Exception e) {
+ // signal problem
+ return null;
+ }
+ }
+ /**
+ * recursive method to generate the left to right, top to bottom
+ * list of topic URLs.
+ */
+ private static void populateTopicVector(Object selection, Vector topicVector) {
+
+ if (selection instanceof Topic) {
+ Topic topicElement = (Topic) selection;
+
+ if (topicElement.getHref() != null && topicElement.getHref() != "")
+ topicVector.add(topicElement);
+ java.util.List topicList = topicElement.getChildrenList();
+ for (int i = 0; i < topicList.size(); i++) {
+ populateTopicVector(topicList.get(i), topicVector);
+ }
+ }
+ }
+}
diff --git a/org.eclipse.help/Eclipse Help/org/eclipse/help/package.html b/org.eclipse.help/Eclipse Help/org/eclipse/help/package.html
new file mode 100644
index 000000000..b31a7f8e6
--- /dev/null
+++ b/org.eclipse.help/Eclipse Help/org/eclipse/help/package.html
@@ -0,0 +1,42 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="Author" content="IBM">
+ <meta name="GENERATOR" content="Mozilla/4.51 [en] (WinNT; U) [Netscape]">
+ <title>Package-level Javadoc</title>
+</head>
+<body>
+Provides core support for the Eclipse platform online
+help system.
+<h2>
+Package Specification</h2>
+There is a general mechanism (defined at the plug-in level) by which individual
+plug-ins contribute online help and context-sensitive help for their component.
+The help system UI is responsible for accessing this information and displaying
+it to the user.
+<p>The actual help system UI implementation is an optional piece that plugs
+in to the platform's standard <tt>org.eclipse.help.support</tt> extension
+point. At most one such help system UI should be contributed in any given
+configuration of the platform. In general terms, implementing a help system
+UI involves:
+<ul>
+<li>
+Implementing the <tt>IHelp</tt> interface to display help to the user.</li>
+
+<li>
+Declaring an extension of the <tt>org.eclipse.help.support</tt> extension
+point that mentions the name of that class.</li>
+
+<li>
+Ensuring that the platform is not configured with any other plug-ins which
+contribute to the <tt>org.eclipse.help.support</tt> extension point.</li>
+</ul>
+Note that the platform declares a plug-in (<tt>org.eclipse.help.workbench</tt>)
+which implements the help system UI. This plug-in would need to be omitted
+from the platform configuration when using a replacement.
+<br>&nbsp;
+<br>&nbsp;
+<br>&nbsp;
+</body>
+</html>
diff --git a/org.eclipse.help/build.properties b/org.eclipse.help/build.properties
new file mode 100644
index 000000000..def9a6a0f
--- /dev/null
+++ b/org.eclipse.help/build.properties
@@ -0,0 +1,2 @@
+build.includes=doc,dtd,html,plugin.jars,plugin.properties,plugin.xml,remote.ini
+build.source.help.jar=Eclipse Help
diff --git a/org.eclipse.help/doc/HelpSample.JPG b/org.eclipse.help/doc/HelpSample.JPG
new file mode 100644
index 000000000..ba4872ef8
--- /dev/null
+++ b/org.eclipse.help/doc/HelpSample.JPG
Binary files differ
diff --git a/org.eclipse.help/doc/org_eclipse_help.html b/org.eclipse.help/doc/org_eclipse_help.html
new file mode 100644
index 000000000..e8fa9e20d
--- /dev/null
+++ b/org.eclipse.help/doc/org_eclipse_help.html
@@ -0,0 +1,37 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.51 [en] (WinNT; U) [Netscape]">
+ <title>Help System Extension Points</title>
+</head>
+<body text="#000000" bgcolor="#FFFFFF" link="#0000FF" vlink="#800080" alink="#FF0000">
+
+<center>
+<h1>
+Help System</h1></center>
+The Help System plug-in, <tt>org.eclipse.help</tt>, defines two extension
+points (<tt>"contributions" </tt>and <tt>"contexts"</tt>) which allow individual
+plug-ins to contribute online help and context-sensitive help for their
+components. A typical plug-in would make use of these extension points.
+<p>For more advanced applications, there is also an extension point&nbsp;
+(<tt>"support"</tt>) for plugging in a a help system UI.
+<p>
+<hr WIDTH="100%">
+<h1>
+Extension Points</h1>
+The following extension points can be used to extend the help system:
+<ul>
+<li>
+<a href="org_eclipse_help_contributions.html">org.eclipse.help.contributions</a></li>
+
+<li>
+<a href="org_eclipse_help_contexts.html">org.eclipse.help.contexts</a></li>
+
+<li>
+<a href="org_eclipse_help_support.html">org.eclipse.help.support</a></li>
+</ul>
+<a href="org_eclipse_help_searchEngine.html"></a>
+<p><br><a href="hglegal.htm"><img SRC="ngibmcpy.gif" ALT="Copyright IBM Corporation 2000" BORDER=0 height=12 width=195></a>
+</body>
+</html>
diff --git a/org.eclipse.help/doc/org_eclipse_help_contexts.html b/org.eclipse.help/doc/org_eclipse_help_contexts.html
new file mode 100644
index 000000000..d466ad5d1
--- /dev/null
+++ b/org.eclipse.help/doc/org_eclipse_help_contexts.html
@@ -0,0 +1,73 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.5 [en] (Win98; I) [Netscape]">
+ <title>Help System extension points: Contexts</title>
+</head>
+<body link="#0000FF" vlink="#800080">
+
+<center>
+<h1>
+Contexts</h1></center>
+<b><i>Identifier: </i></b>org.eclipse.help.contexts
+<p><b><i>Description:</i></b> For defining context-sensitive help for an
+individual plug-in.
+<p><b><i>Configuration Markup:</i></b>
+<p><tt>&nbsp;&nbsp; &lt;!ELEMENT contexts EMPTY></tt>
+<br><tt>&nbsp;&nbsp; &lt;!ATTLIST contexts name CDATA #REQUIRED></tt>
+<ul>
+<li>
+<b>name</b> - the name of the manifest file which contains the context-sensitive
+help documentation for this plug-in.</li>
+</ul>
+<i><b>Configuration Markup for Contexts </b>(this is what goes into the
+contexts manifest file)<b>:</b></i>
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT contexts (context)* ) ></tt>
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT context (description?,topic*) ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST context id&nbsp; ID #REQUIRED ></tt>
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT description (#PCDATA)></tt>
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT topic (topic)* ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST topic id ID #IMPLIED ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST topic label CDATA #REQUIRED ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST topic href&nbsp; CDATA #IMPLIED
+></tt>
+<p>The contexts manifest files provide all the information needed when
+context-sensitive help is requested by the user. The id is passed by the
+platform to identify the currently active context. The context definition
+with a matching id is then retrieved. This context element contains the
+brief description that is to be displayed to the user, as well as related
+topics that the user might find useful for understanding the current context.
+<br>&nbsp;
+<p><b><i>Examples:</i></b>
+<p>The following is an example of using the <tt>contexts</tt> extension
+point.
+<p>(in file <tt>plugin.xml</tt>)
+<p><tt>&nbsp;&nbsp; &lt;extension point="org.eclipse.help.contexts"></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;contexts name="xyzContexts.xml"/></tt>
+<br><tt>&nbsp;&nbsp; &lt;/extension></tt>
+<br>&nbsp;
+<p>(in file <tt>xyzContexts.xml</tt>)
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;contexts></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;context&nbsp; id="generalContextId"></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;description> This
+is a sample F1 help string.&lt;/description></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;topic href="contexts/RelatedContext1.html"&nbsp;
+label="Help Related Topic 1"/></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;topic href="contexts/RelatedContext2.html"&nbsp;
+label="Help Related Topic 2"/></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;/context></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;/contexts></tt>
+<br>&nbsp;
+<p><b><i>API Information</i>: </b>No code is required to use this extension
+point. All that is needed is to supply the appropriate manifest file(s)
+mentioned in the <tt>plugin.xml</tt> file.
+<p><b><i>Supplied Implementation: </i></b>The optional default implementation
+of the help system UI supplied with the Eclipse platform fully supports
+the <tt>contexts</tt> extension point.
+<br>&nbsp;
+<br>&nbsp;
+<br>&nbsp;
+<p><a href="hglegal.htm"><img SRC="ngibmcpy.gif" ALT="Copyright IBM Corporation 2000" BORDER=0 height=12 width=195></a>
+</body>
+</html>
diff --git a/org.eclipse.help/doc/org_eclipse_help_contributions.html b/org.eclipse.help/doc/org_eclipse_help_contributions.html
new file mode 100644
index 000000000..a47c57ab0
--- /dev/null
+++ b/org.eclipse.help/doc/org_eclipse_help_contributions.html
@@ -0,0 +1,364 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.51 [en] (WinNT; U) [Netscape]">
+ <title>Help System extension points: Contributions</title>
+</head>
+<body link="#0000FF" vlink="#800080">
+
+<center>
+<h1>
+Contributions</h1></center>
+<b><i>Identifier: </i></b>org.eclipse.help.contributions
+<p><b><i>Description:</i></b> For registering an online help contribution
+for an individual plug-in.
+<p>Each plug-in that contributes help files should in general do the following:
+<ul>
+<ul>
+<li>
+author the html files and store them in the plug-in directory (perhaps
+using a subdirectory, for cleaner structure).</li>
+
+<li>
+create navigation manifest files that describe navigation (table of contents)
+for the help and the necessary topic interleaving. See the syntax below.</li>
+
+<li>
+the plugin.xml file should extend the <tt>org.eclipse.help.contributions</tt>
+extension point and specify the navigation file(s).</li>
+</ul>
+</ul>
+<b><i>Configuration Markup for the <tt>contributions</tt> extension point:</i></b>
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT topics EMPTY></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST topics name CDATA #REQUIRED></tt>
+<ul>
+<li>
+<b>name<i> </i></b>- the name of the manifest file which contains the table
+of contents/navigation for this plug-in's online help.</li>
+</ul>
+<tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT actions EMPTY></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST actions name CDATA #REQUIRED></tt>
+<ul>
+<li>
+<b>name<i> </i></b>- the name of the manifest file which contains the insertion
+rules for topic interleaving and wiring of topics to views<b><i>.</i></b></li>
+</ul>
+<tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT infoset EMPTY></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST infoset name CDATA #REQUIRED></tt>
+<ul>
+<li>
+<b>name</b> - the name of the manifest file defining the views.</li>
+</ul>
+<i><b>Configuration Markup for Topics </b>(this is what goes into the topics
+manifest file)<b>:</b></i>
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT topics (topic)* ) ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST topics id&nbsp; ID #REQUIRED ></tt>
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT topic (topic)* ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST topic id ID #IMPLIED ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST topic label CDATA #REQUIRED ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST topic href&nbsp; CDATA #IMPLIED
+></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; <font color="#000000">&lt;!ATTLIST topic insert-constraint
+(child | first-child | last-child | prev-sib | next-sib) "child"></font></tt>
+<p><i><b>Configuration Markup for Infosets </b>(this is what goes into
+the infoset manifest file)<b>:</b></i>
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT infoset (infoview)*&nbsp; ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST infoset&nbsp; id&nbsp; ID&nbsp;
+#REQUIRED ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST infoset&nbsp; label&nbsp; CDATA&nbsp;
+#REQUIRED ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST infoset&nbsp; standalone&nbsp;
+(false|true) false&nbsp; #IMPLIED ></tt>
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT infoview EMPTY></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST infoview id ID #REQUIRED ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST infoview label CDATA #IMPLIED ></tt>
+<p><i><b>Configuration Markup for Insert Actions </b>(this is what goes
+into the actions manifest file)<b>:</b></i>
+<p>&nbsp;<tt>&nbsp;&nbsp; &lt;!ELEMENT actions (insert)* ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST actions infoview CDATA #REQUIRED
+></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST actions standalone (true | false)
+false #IMPLIED ></tt>
+<p><tt>&nbsp;&nbsp;&nbsp; &lt;!ELEMENT insert (insert) ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST insert from CDATA #REQUIRED ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST insert to CDATA #REQUIRED ></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST insert as <font color="#000000">(child
+| first-child | last-child | prev-sib | next-sib) "child" ></font></tt>
+<br><tt>&nbsp;&nbsp;&nbsp; &lt;!ATTLIST insert label CDATA #IMPLIED ></tt>
+<p>In general, a plug-in that needs to provide online help will define
+its own topics manifests and the necessary actions manifests to wire the
+topics to the correct place. In the end, the help system is configured
+to be launched as some actions, and the id of the views manifest will be
+used to do so.
+<p>There are four types of XML elements a plug-in can use: the topic, the
+infoset, the actions, and the insert elements.
+<p><b>The topic element</b>
+<p>With respect to topics elements, all the topics are contributed as part
+of the topics container element. They can have a hierarchical structure,
+or can be listed as a flat list. A topics manifest is viewed as a data
+source for further topics interleaving and organization into an integrated
+web, with different view perspectives.&nbsp; In addition, topics can be
+acted upon by specifying their id's, but one can also act on a group of
+topics by specifying the id of the topics element that contains them.&nbsp;
+Later when wiring topics to views or other topics, the structure defined
+in the topics manifest is maintained (subject to alterations done by insert
+actions).
+<p>The topic element is the workhorse of the navigation structure. There
+are three typical uses for the topic element:
+<p>1.&nbsp; To provide a link to a documentation file - often an HTML file
+in some doc.zip.
+<br>2.&nbsp; To act as a container for other topics, either in the same
+manifest or another.
+<br>3.&nbsp; To provide an insertion point for other topics, either in
+the same manifest or another.
+<p><b><i>1.&nbsp; Topics as links</i></b>
+<br>The simplest use of a topic is as a link to a documentation file.
+<p><tt>&lt;topic label="Some concept file" href="concepts/some_file.html"
+/></tt>
+<p>The href attribute is relative to the plug-in that the manifest file
+belongs to.&nbsp; If you need to access a file in another plug-in, you
+can use the syntax
+<p><tt>&lt;topic label="topic in another plug-in" href="../other.plugin.id/concepts/some_other_file.html"
+/></tt>
+<p><b><i>2.&nbsp; Topics as containers</i></b>
+<br>The next most common use of a topic is to use it as a container for
+other topics.&nbsp; The container topic itself can always refer to a particular
+file as well.
+<p><tt>&lt;topic label="Integrated Development Environment" href="concepts/ciover.htm"
+></tt>
+<br><tt>&nbsp; &lt;topic label="Starting the IDE" href="concepts/blah.htm"
+/></tt>
+<br><tt>&nbsp; ...</tt>
+<br><tt>&lt;/topic></tt>
+<p>If you leave the label off the topic, it acts as a "pure" container,
+used either as an anchor for other topics to insert around, or to simplify
+inserting a group of topics into a specific point in the merged navigation.
+<p><b><i>3.&nbsp; Topics as insertion points</i></b>
+<br>Topics can be used as insertion points.&nbsp; They provide a logical
+place for other topics to try and merge around.&nbsp; To act as an insertion
+point, the topic must have an id attribute.
+<p><b>The infoset element</b>
+<p><font color="#000000">An information set is an entry point into a documentation
+web: a collection of all the online documentation that can be displayed
+by the help viewer when launched. It can be thought of as a collection
+of views.</font>
+<p><font color="#000000">Views are intended to provide high level semantic
+groupings within a documentation web. They are defined using the </font><tt>infoview
+</tt><font color="#000000">element
+defined within an infoset. A documentation team could use a view to produce
+getting started, tasks, and references sections (or other views the product
+team defines). The platform does not specify the actual sections, only
+the mechanism for defining them.</font>
+<p><font color="#000000">For example, there can be a "task view" defined
+which is a merge of all the topics from a "how to do something" perspective.
+Another view, a "component view", can also be defined which is a topics
+tree displaying all components and their documentation. In the current
+implementation of the help system a "search view" is always added to the
+list of views. This view enables the user to access help topics by querying
+for a word/phrase.</font>
+<p>The infoview element represents a container for topics that can be "shared"
+across plug-ins.&nbsp; It is a perspective on the entire documentation.
+There may be times when a number of different plug-ins contribute to the
+same logical documentation component.&nbsp; This element ensures that during
+a "component view," they are correctly merged together into a coherent
+view.
+<p><b>The actions element</b>
+<p>The actions manifest contains scripting actions to be performed on topics
+and views. Currently there is only one kind of action, the insert action,
+which is used to write topics and views together into one integrated information
+web, with multiple views.
+<p>The actions are structural actions (insert) and, thus, apply to a certain
+infoview. So, all the insert actions in a manifest build the topic hierarchy
+in one infoview.
+<p><b>The insert element</b>
+<p>One of the most complicated parts of a componentized navigation is how
+to create an integrated information structure with a continuous flow of
+navigation.&nbsp; To do this, we need a mechanism to publish insertion
+points, choose which insertion point we want to use, and to indicate where
+we want to insert topics (parent, child, before, after).
+<p>The insertion points can be topics or views.&nbsp; A topic indicates
+its willingness to be an insertion point by providing an id. Views are
+required to have id's.&nbsp; Only fully qualified ids are use as references.
+<font color="#000000">For
+example, the fully qualified topic id of the topic &lt;topic id="concepts"
+label="Concepts">&nbsp; in the org.eclipse.help.examples.ex1
+</font>plug-in<font color="#000000">
+is org.eclipse.help.examples.ex1.concepts.</font>
+<p>Since the insertion points are typically located in other plug-ins,
+and these plug-in may not be installed, one can specify an alternate insertion
+point. By default, if none of the choices succeed, the topic stays under
+its component hierarchy. The "to" attribute specifies the target insertion
+point. The topic specified by the "from" attribute is the topic being inserted.&nbsp;
+Followings are some possible ways to insert a topic and they are specified
+using the as attribute:
+<ul>
+<li>
+As a child of the insertion point, which is the most common.</li>
+
+<li>
+As the first child of the insertion point</li>
+
+<li>
+As the last child of the insertion point</li>
+
+<li>
+As the previous sibling of the insertion point (i.e., just before the insertion
+point at the same level in the navigation tree)</li>
+
+<li>
+As the next sibling of the insertion point (i.e., just after the insertion
+point at the same level in the navigation tree)</li>
+</ul>
+Alternative insertion options are provided, when previous ones could not
+be performed. The nested insert subelements of the insert element provide
+these alternatives. This can be thought of as a "fall-back" mechanism where
+if an insert action fails, the nested insert action will be executed. Once
+the first choice insertion point has been satisfied, the other alternative
+insertion points are ignored.
+<br>&nbsp;
+<p><b><i>Examples:</i></b>
+<p>The following is an example of using the <tt>contributions</tt> extension
+point. Assume the following is for a plug-in with id&nbsp; named <tt>"com.example.isvguide"</tt>.
+(The example is intended as a general sample, and it should be noted that
+the same documentation hierarchy, resulting from all the following contribution
+files, could also be created with various combination of topics and actions
+files.)
+<p>(in file <tt>plugin.xml</tt>)
+<br>&nbsp;
+<p><tt>&nbsp;&nbsp; &lt;!-- Use the Help System contribution extension
+point to define Infosets, topics, --></tt>
+<br><tt>&nbsp;&nbsp; &lt;!-- and actions contribution files. For clarity,
+the extension point is used&nbsp;&nbsp;&nbsp;&nbsp; --></tt>
+<br><tt>&nbsp;&nbsp; &lt;!-- twice, once to define the Infoset and it's
+view, and another to define the&nbsp;&nbsp; --></tt>
+<br><tt>&nbsp;&nbsp; &lt;!-- Topics and their associated actions.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+--></tt>
+<br><tt>&nbsp;&nbsp; &lt;extension point="org.eclipse.help.contributions"></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp; &lt;infoset name="infoset.xml"/></tt>
+<br><tt>&nbsp;&nbsp; &lt;/extension></tt>
+<p><tt>&nbsp;&nbsp; &lt;extension point="org.eclipse.help.contributions"></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp; &lt;actions name="infosetActions.xml"/></tt>
+<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <tt>&lt;topics
+name="infosetTopics.xml"/></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp; &lt;topics name="concepts.xml"/></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp; &lt;topics name="tasks.xml"/></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp; &lt;topics name="reference.xml"/></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp; &lt;topics name="samples.xml"/></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp; &lt;topics name="pdfdocuments.xml"/></tt>
+<br><tt>&nbsp;&nbsp; &lt;/extension></tt>
+<br>&nbsp;
+<p>(in file <tt>infoset.xml</tt>)
+<blockquote><tt>&lt;!-- Define the Infoset, and any views it has. --></tt>
+<br><tt>&lt;infoset id="someinfosetid" label="Plug-In Development" href="isv_home.html"></tt>
+<br><tt>&nbsp; &lt;infoview id="topicsView" label="Topics"/></tt>
+<br><tt>&lt;/infoset></tt></blockquote>
+
+<p><br>(in file <tt>infosetTopics.xml</tt>)
+<blockquote><tt>&lt;!-- Now define a "container" topic that holds your
+general topics. This makes it --></tt>
+<br><tt>&lt;!-- easier to quickly insert all these general topics under
+the view in the&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --></tt>
+<br><tt>&lt;!-- Infoset.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+--></tt>
+<br><tt>&lt;topics id="topLevelTopics"></tt>
+<br><tt>&nbsp; &lt;topic id="concepts" label="Basic Concepts"/></tt>
+<br><tt>&nbsp; &lt;topic id="tasks" label="Tasks"/></tt>
+<br><tt>&nbsp; &lt;topic id="reference" label="Reference Information"/></tt>
+<br><tt>&nbsp; &lt;topic id="samples" label="Samples"/></tt>
+<br><tt>&nbsp; &lt;topic id="pdfdocs" label="PDF Documents"/></tt>
+<br><tt>&lt;/topics></tt></blockquote>
+
+<p><br>Define topics contained in the above general topics:
+<p>(in file <tt>concepts.xml</tt>)
+<blockquote><tt>&lt;topics id="Concepts_topics"></tt>
+<br><tt>&nbsp; &lt;topic id="aConceptId" label="Introduction" href="concepts/intro.html"/></tt>
+<br><tt>&lt;/topics></tt></blockquote>
+
+<p><br>(in file <tt>tasks.xml</tt>)
+<blockquote><tt>&lt;topics id="Tasks_topics"></tt>
+<br><tt>&nbsp; &lt;topic id="aTaskId" label="Creating a Project" href="tasks/createProject.html"/></tt>
+<br><tt>&lt;/topics></tt></blockquote>
+
+<p><br>(in file <tt>reference.xml</tt>)
+<blockquote><tt>&lt;topics id="Reference_topics"></tt>
+<br><tt>&nbsp; &lt;topic id="aReferenceId" label="Interfaces" href="ref/index.html"/></tt>
+<br><tt>&lt;/topics></tt></blockquote>
+
+<p><br>(in file <tt>samples.xml</tt>)
+<blockquote><tt>&lt;topics id="Samples_topics"></tt>
+<br><tt>&nbsp; &lt;topic id="aSampleId" label="Help System Sample" href="samples/helpSample1.html"/></tt>
+<br><tt>&lt;/topics></tt></blockquote>
+
+<p><br>(in file <tt>pdfdocuments.xml</tt>)
+<blockquote><tt>&lt;topics id="PDFDocument_topics"></tt>
+<br><tt>&nbsp; &lt;topic id="aPDFDocumentId" label="Plug-in development"
+href="pdf/isvdoc.pdf"/></tt>
+<br><tt>&lt;/topics></tt></blockquote>
+
+<p><br>Now define the insert actions necessary to create the documentation
+hierarchy :
+<p>(in file <tt>infosetActions.xml</tt>)
+<blockquote><tt>&lt;actions infoview="com.example.isvguide.topicsView"></tt>
+<p><tt>&nbsp; &lt;insert from="com.example.isvguide.topLevelTopics"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
+to="com.example.isvguide.topicsView" as="child"/></tt>
+<p><tt>&nbsp; &lt;insert from="com.example.isvguide.Concepts_topics"</tt>
+<br><tt>to="com.example.isvguide.concepts" as="child"/></tt>
+<p><tt>&nbsp; &lt;insert from="com.example.isvguide.Tasks_topics"</tt>
+<br><tt>to="com.example.isvguide.tasks" as="child"/></tt>
+<p><tt>&nbsp; &lt;insert from="com.example.isvguide.Reference_topics"</tt>
+<br><tt>to="com.example.isvguide.reference" as="child"/></tt>
+<p><tt>&nbsp; &lt;insert from="com.example.isvguide.Samples_topics"</tt>
+<br><tt>to="com.example.isvguide.samples" as="child"/></tt>
+<p><tt>&nbsp; &lt;insert from="com.example.isvguide.PDFDocument_topics"</tt>
+<br><tt>to="com.example.isvguide.pdfdocs" as="child"/></tt>
+<br><tt>&lt;/actions></tt></blockquote>
+
+<p><br>Here is the resulting documentation hierarchy in the Eclipse Workbench
+:
+<p><img SRC="HelpSample.JPG" height=497 width=674>
+<blockquote>&nbsp;</blockquote>
+
+<blockquote>&nbsp;</blockquote>
+
+<h4>
+Non-integrated components</h4>
+There is a variation in the default handling of contributions to allow
+for "non-integrated" components. Here is a simple scenario: an ISV creates
+a component that includes some documentation. The component can be installed
+by anybody using eclipse, including some larger products that have their
+own infosets. The ISV may or may not know in advance who are the potential
+users of his component. In that case, he wants to ensure that the documentation
+for the component can be accessed, no matter how the component is integrated.
+If there are well-known infosets in some products, the ISV can target its
+documentation for wiring into those infosets. In that case the default
+infoset provided by the component should not be shown. If there are no
+well-known infosets that the component can be wired into (because they
+have not been installed or they simply do not exist), then the component
+documentation should be shown in the default infoset provided with the
+component.
+<p>To support this non-integrated or loosely integrated documentation,
+a plugin can define an infoset and associated actions and set their <b>standalone</b>
+attribute to false. This has the effect of executing the inserts only when
+those topics have never been contributed anywhere else and only display
+the infoset if it is not empty. In other words, this behaves as: "if this
+is an independent plugin, and there are no topics contributed to some well-known
+infoset, then insert the documentation into a standalone info set". Empty
+standalone infosets are not shown. This really says that if the topics
+contributed by the plugin are inserted into well known infosets, then the
+standalone actions did not insert anything in the standalone infoset, so
+just ignore this empty infoset.
+<br>Setting standalone attributes on actions and infosets is useful when
+providing a "Catch all" scenario, when documentation cannot be contributed
+to a well-known infoset but the plugin documentation should still appear
+somewhere.
+<br>&nbsp;
+<p><b><i>API Information</i>:<font color="#CC0000"> </font></b>No code
+is required to use this extension point. All that is needed is to supply
+the appropriate manifest files mentioned in the <tt>plugin.xml</tt> file.
+<p><i><b>Supplied Implementation:</b> </i>The optional default implementation
+of the help system UI supplied with the Eclipse platform fully supports
+the <tt>contributions</tt> extension point.
+<p><a href="hglegal.htm"><img SRC="ngibmcpy.gif" ALT="Copyright IBM Corporation 2000" BORDER=0 height=12 width=195></a>
+</body>
+</html>
diff --git a/org.eclipse.help/doc/org_eclipse_help_support.html b/org.eclipse.help/doc/org_eclipse_help_support.html
new file mode 100644
index 000000000..3ced2dc3a
--- /dev/null
+++ b/org.eclipse.help/doc/org_eclipse_help_support.html
@@ -0,0 +1,43 @@
+<!doctype html public "-//w3c//dtd html 4.0 transitional//en">
+<html>
+<head>
+ <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+ <meta name="GENERATOR" content="Mozilla/4.5 [en] (Win98; I) [Netscape]">
+ <title>Help System extension points: Support</title>
+</head>
+<body link="#0000FF" vlink="#800080">
+
+<center>
+<h1>
+Support</h1></center>
+<b><i>Identifier: </i></b>org.eclipse.help.support
+<p><b><i>Description:</i></b> For configuring a help system UI. The platform
+should be configured with no more than one help system UI.
+<p><b><i>Configuration Markup:</i></b>
+<p><tt>&nbsp;&nbsp; &lt;!ELEMENT config EMPTY></tt>
+<br><tt>&nbsp;&nbsp; &lt;!ATTLIST config class CDATA #REQUIRED</tt> <tt>></tt>
+<ul>
+<li>
+<b>class</b> - the implementation class for displaying online and context-sensitive
+help. This class must implement the <tt>org.eclipse.help.IHelp</tt>
+interface.</li>
+</ul>
+<b><i>Examples:</i></b>
+<p>The following is a sample usage of the <tt>support</tt> extension point:
+<p>(in file <tt>plugin.xml</tt>)
+<p><tt>&nbsp;&nbsp; &lt;extension point="org.eclipse.help.support"></tt>
+<br><tt>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &lt;config class="com.example.XYZHelpUI"/></tt>
+<br><tt>&nbsp;&nbsp; &lt;/extension></tt>
+<p><b><i>API Information</i>: </b>The supplied class must implement the
+<tt>org.eclipse.help.IHelp</tt>
+interface. Methods in that interface determine what happens when a user
+asks for online help or context-sensitive help. The implementation should
+access the help information contributed via the <tt>org.eclipse.help.contributions</tt>
+and <tt>org.eclipse.help.contexts</tt> extension points.
+<p><i><b>Supplied Implementation:</b> </i>The <tt>org.eclipse.help.workbench</tt>
+plug-in contains an implementation of the help system UI. Although this
+plug-in is supplied with the Eclipse platform, it is entirely optional
+and can be safely omitted from the platform configuration.
+<p><a href="hglegal.htm"><img SRC="ngibmcpy.gif" ALT="Copyright IBM Corporation 2000" BORDER=0 height=12 width=195></a>
+</body>
+</html>
diff --git a/org.eclipse.help/dtd/actions.dtd b/org.eclipse.help/dtd/actions.dtd
new file mode 100644
index 000000000..8596b6fd8
--- /dev/null
+++ b/org.eclipse.help/dtd/actions.dtd
@@ -0,0 +1,10 @@
+
+<!ELEMENT actions (insert)* >
+<!ATTLIST actions infoview CDATA #REQUIRED >
+<!ATTLIST actions standalone (true | false) false #IMPLIED >
+
+<!ELEMENT insert (insert) >
+<!ATTLIST insert from CDATA #REQUIRED >
+<!ATTLIST insert to CDATA #REQUIRED >
+<!ATTLIST insert as (child | first-child | last-child | alpha | prev-sib | next-sib) "child" >
+<!ATTLIST insert label CDATA #IMPLIED >
diff --git a/org.eclipse.help/dtd/contexts.dtd b/org.eclipse.help/dtd/contexts.dtd
new file mode 100644
index 000000000..bab7d9cb4
--- /dev/null
+++ b/org.eclipse.help/dtd/contexts.dtd
@@ -0,0 +1,11 @@
+
+<!ELEMENT contexts (context)* >
+
+<!ELEMENT context (description, topic*) >
+<!ATTLIST context id ID #REQUIRED >
+
+<!ELEMENT description #PCDATA >
+
+<!ELEMENT topic (topic)* >
+<!ATTLIST topic label CDATA #REQUIRED >
+<!ATTLIST topic href CDATA #IMPLIED >
diff --git a/org.eclipse.help/dtd/infoset.dtd b/org.eclipse.help/dtd/infoset.dtd
new file mode 100644
index 000000000..09988f36a
--- /dev/null
+++ b/org.eclipse.help/dtd/infoset.dtd
@@ -0,0 +1,10 @@
+
+<!ELEMENT infoset (view)* >
+<!ATTLIST infoset id ID #REQUIRED >
+<!ATTLIST infoset label CDATA #REQUIRED >
+<!ATTLIST infoset href CDATA #IMPLIED >
+<!ATTLIST infoset standalone (true | false) false #IMPLIED >
+
+<!ELEMENT infoview EMPTY>
+<!ATTLIST infoview id ID #REQUIRED >
+<!ATTLIST infoview label CDATA #IMPLIED >
diff --git a/org.eclipse.help/dtd/topics.dtd b/org.eclipse.help/dtd/topics.dtd
new file mode 100644
index 000000000..da901e3db
--- /dev/null
+++ b/org.eclipse.help/dtd/topics.dtd
@@ -0,0 +1,8 @@
+
+<!ELEMENT topics (topic)* ) >
+<!ATTLIST topics id ID #REQUIRED >
+
+<!ELEMENT topic (topic)* >
+<!ATTLIST topic id ID #IMPLIED >
+<!ATTLIST topic label CDATA #REQUIRED >
+<!ATTLIST topic href CDATA #IMPLIED >
diff --git a/org.eclipse.help/html/default.css b/org.eclipse.help/html/default.css
new file mode 100644
index 000000000..b3628f49a
--- /dev/null
+++ b/org.eclipse.help/html/default.css
@@ -0,0 +1 @@
+/* following font face declarations need to be removed for DBCS */ body, h1, h2, h3, h4, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font-family: Arial, Helvetica} pre { font-family: Courier, Sanserif} /* end font face declarations */ /* following font size declarations should be OK for DBCS */ body, h1, h2, h3, h4, p, table, td, caption, th, ul, ol, dl, li, dd, dt {font-size: 10pt} pre { font-size: 10pt} /* end font size declarations */ body { background: #FFFFFF} h1 { font-size: 16pt; text-decoration: overline; margin-top: 5; margin-bottom: 1 } h2 { font-size: 14pt; margin-top: 25; margin-bottom: 3} h3 { Sanserif; font-size: 11pt; margin-top: 20; margin-bottom: 3 } h4 { font-size: 10pt; font-style: italic; margin-top: 20; margin-bottom: 3 } p { margin-top: 8; margin-bottom: 8; margin-left: 6} p.change { font-size: 8pt; } pre { margin-left: 6; font-size: 9pt; } p.relh { font-size: 9pt; font-variant: small-caps; text-transform: uppercase; font-weight: bold; margin-left: 20;margin-top: 25; margin-bottom:2;} p.rel_link { font-size: 9pt; margin-top:2;margin-bottom:2; margin-left: 35 } a:link { color: #0000FF; text-decoration: underline;font-weight: bold} a:hover { color: #000080; font-weight: bold} a:visited { text-decoration: underline;font-weight: bold} ul { margin-top: 1; margin-bottom: 12 } li { margin-top: 0; margin-bottom: 3} ol { margin-top: 1; margin-bottom: 12 } dl { margin-left: 6; margin-top: 1; margin-bottom: 12 } dt { margin-top: 1; margin-bottom: 1; font-weight: bold } dd { margin-top: 1; margin-bottom: 12 } strong { font-weight: bold} em { font-style: italic} var { font-style: italic} div.revision { border-left-style: solid; border-left-width: thin; border-left-color: #7B68EE; padding-left:5 } th { font-weight: bold } \ No newline at end of file
diff --git a/org.eclipse.help/html/default_home.html b/org.eclipse.help/html/default_home.html
new file mode 100644
index 000000000..31e3f496b
--- /dev/null
+++ b/org.eclipse.help/html/default_home.html
@@ -0,0 +1,14 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
+<html>
+
+<head>
+<title>Websphere Studio Workbench</title>
+<meta content="text/html; charset=windows-1252" http-equiv="Content-Type">
+</head>
+
+<body bgColor="#FFFFFF">
+
+<p><img border="0" src="images/workbench.jpg" width="515" height="272"></p>
+
+</body>
+</html>
diff --git a/org.eclipse.help/html/notopic.html b/org.eclipse.help/html/notopic.html
new file mode 100644
index 000000000..a53062353
--- /dev/null
+++ b/org.eclipse.help/html/notopic.html
@@ -0,0 +1,5 @@
+<html>
+<body>
+The topic that you have requested is <b>not available</b>. The link may be wrong, or you may not have the corresponding product feature installed. This online help only includes documentation for features that are installed.
+</body>
+</html> \ No newline at end of file
diff --git a/org.eclipse.help/html/workbench.jpg b/org.eclipse.help/html/workbench.jpg
new file mode 100644
index 000000000..54a391e04
--- /dev/null
+++ b/org.eclipse.help/html/workbench.jpg
Binary files differ
diff --git a/org.eclipse.help/plugin.jars b/org.eclipse.help/plugin.jars
new file mode 100644
index 000000000..3640e086e
--- /dev/null
+++ b/org.eclipse.help/plugin.jars
@@ -0,0 +1 @@
+help.jar=Eclipse Help \ No newline at end of file
diff --git a/org.eclipse.help/plugin.properties b/org.eclipse.help/plugin.properties
new file mode 100644
index 000000000..9547889d9
--- /dev/null
+++ b/org.eclipse.help/plugin.properties
@@ -0,0 +1,5 @@
+help_plugin_name = Default Help System Support
+support_extention_point_name = Pluggable Help Support
+contributions_extention_point_name = Help Contributions
+contexts_extention_point_name = Context Help
+searchengine_extention_point_name = Search Engine \ No newline at end of file
diff --git a/org.eclipse.help/plugin.xml b/org.eclipse.help/plugin.xml
new file mode 100644
index 000000000..0969aee15
--- /dev/null
+++ b/org.eclipse.help/plugin.xml
@@ -0,0 +1,92 @@
+<?xml version="1.0"?>
+
+<!-- ================================================= -->
+<!-- This is the plugin for user assistance (help). -->
+<!-- It defines the extension points for help -->
+<!-- contributions and the help support. -->
+<!-- ================================================= -->
+
+<plugin
+ name = "%help_plugin_name"
+ id = "org.eclipse.help"
+ version = "0.5"
+ vendor-name = "IBM"
+ class="org.eclipse.help.internal.HelpPlugin">
+
+ <requires>
+ <import plugin="org.eclipse.core.runtime"/>
+ <import plugin="org.apache.xerces"/>
+ </requires>
+
+ <runtime>
+ <library name="help.jar">
+ <export name="*"/>
+ </library>
+ </runtime>
+
+ <!-- For remote install, run this application -->
+ <!-- ======================================== -->
+ <extension id="workbench" point="org.eclipse.core.runtime.applications">
+ <application>
+ <run class="org.eclipse.help.internal.remote.StandaloneFacade">
+ <!--<parameter name="productInfo" value="product.ini"/>-->
+ </run>
+ </application>
+ </extension>
+
+
+
+ <!-- ========================================================================== -->
+ <!-- Extension point: org.eclipse.help.support -->
+ <!-- Purpose: Extension point for configuring a help system. -->
+ <!-- Only one help system can be registered to the platform. -->
+ <!-- Extension Implementation: must implement org.eclipse.help.IHelp -->
+ <!-- Sample usage: -->
+ <!-- <extension point="org.eclipse.help.support"> -->
+ <!-- <config class="com.xyzCompany.xyzIHelpImpl"/> -->
+ <!-- </extension> -->
+ <!-- ========================================================================== -->
+ <extension-point id="support" name="%support_extention_point_name"/>
+
+
+ <!-- ========================================================================== -->
+ <!-- Extension point: org.eclipse.help.contributions -->
+ <!-- Purpose: Extension point for registering documentation contributions -->
+ <!-- by individual plugins -->
+ <!-- Extension Implementation: must provide one or more manifest files for -->
+ <!-- the documentation navigation and interleaving -->
+ <!-- Sample usage: -->
+ <!-- <extension point="org.eclipse.help.contributions"> -->
+ <!-- <infoset name="infoSet.xml"/> -->
+ <!-- <topics name="infoTopics.xml"/> -->
+ <!-- <actions name="infoTopicsWiring.xml"/> -->
+ <!-- </extension> -->
+ <!-- ========================================================================== -->
+ <extension-point id="contributions" name="%contributions_extention_point_name"/>
+
+
+ <!-- ========================================================================== -->
+ <!-- Extension point: org.eclipse.help.contexts -->
+ <!-- Purpose: Extension point for registering context help contributions -->
+ <!-- by individual plugins -->
+ <!-- Extension Implementation: must provide one or more manifests files for -->
+ <!-- context help descriptions and links -->
+ <!-- Sample usage: -->
+ <!-- <extension point="org.eclipse.help.contexts"> -->
+ <!-- <contexts name="xyzContexts.xml"/> -->
+ <!-- </extension> -->
+ <!-- ========================================================================== -->
+ <extension-point id="contexts" name="%contexts_extention_point_name"/>
+
+
+ <!-- ========================================================================== -->
+ <!-- Extension point: org.eclipse.help.searchEngine -->
+ <!-- Purpose: Extension point for registering search engine -->
+ <!-- Extension Implementation: -->
+ <!-- must implement org.eclipse.help.internal.search.ISearchEngine -->
+ <!-- Note: this extension point is for internal use only, and might be removed. -->
+ <!-- ========================================================================== -->
+ <extension-point id="searchEngine" name="%searchengine_extention_point_name"/>
+
+
+</plugin>
diff --git a/org.eclipse.help/remote.ini b/org.eclipse.help/remote.ini
new file mode 100644
index 000000000..d64b9301b
--- /dev/null
+++ b/org.eclipse.help/remote.ini
@@ -0,0 +1,5 @@
+# 0 = log errors only
+# 1 = log errors and warnings
+# 2 = log everything (including some trace info)
+
+log_level=0 \ No newline at end of file

Back to the top