diff --git a/releng/org.eclipse.rse.updatesite/site.xml b/releng/org.eclipse.rse.updatesite/site.xml index ba8dd316b65..a07e8c3010e 100644 --- a/releng/org.eclipse.rse.updatesite/site.xml +++ b/releng/org.eclipse.rse.updatesite/site.xml @@ -405,7 +405,7 @@ - + @@ -417,10 +417,10 @@ - + - + diff --git a/rse/features/org.eclipse.rse-feature/feature.xml b/rse/features/org.eclipse.rse-feature/feature.xml index 4384406b5a1..1125039ad1c 100644 --- a/rse/features/org.eclipse.rse-feature/feature.xml +++ b/rse/features/org.eclipse.rse-feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/rse/features/org.eclipse.rse.core-feature/feature.xml b/rse/features/org.eclipse.rse.core-feature/feature.xml index 282c61e8ee6..7d7395b5aa9 100644 --- a/rse/features/org.eclipse.rse.core-feature/feature.xml +++ b/rse/features/org.eclipse.rse.core-feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/rse/features/org.eclipse.rse.sdk-feature/feature.xml b/rse/features/org.eclipse.rse.sdk-feature/feature.xml index afbb7ec75f3..5d8b89ae30a 100644 --- a/rse/features/org.eclipse.rse.sdk-feature/feature.xml +++ b/rse/features/org.eclipse.rse.sdk-feature/feature.xml @@ -2,7 +2,7 @@ diff --git a/rse/plugins/org.eclipse.rse.services/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.services/META-INF/MANIFEST.MF index 1e158158144..40126e98307 100644 --- a/rse/plugins/org.eclipse.rse.services/META-INF/MANIFEST.MF +++ b/rse/plugins/org.eclipse.rse.services/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.rse.services;singleton:=true -Bundle-Version: 3.0.100.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: org.eclipse.rse.internal.services.Activator Bundle-Vendor: %providerName Bundle-Localization: plugin diff --git a/rse/plugins/org.eclipse.rse.services/clientserver/org/eclipse/rse/services/clientserver/messages/SystemMessageFile.java b/rse/plugins/org.eclipse.rse.services/clientserver/org/eclipse/rse/services/clientserver/messages/SystemMessageFile.java index 4ac4d289991..a07b87a2549 100644 --- a/rse/plugins/org.eclipse.rse.services/clientserver/org/eclipse/rse/services/clientserver/messages/SystemMessageFile.java +++ b/rse/plugins/org.eclipse.rse.services/clientserver/org/eclipse/rse/services/clientserver/messages/SystemMessageFile.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2002, 2007 IBM Corporation and others. + * Copyright (c) 2002, 2008 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -7,12 +7,13 @@ * * Initial Contributors: * The following IBM employees contributed to the Remote System Explorer - * component that contains this file: David McKnight, Kushal Munir, - * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, + * component that contains this file: David McKnight, Kushal Munir, + * Michael Berger, David Dykstal, Phil Coulthard, Don Yantzi, Eric Simpson, * Emily Bruner, Mazen Faraj, Adrian Storisteanu, Li Ding, and Kent Hawley. - * + * * Contributors: - * {Name} (company) - description of contribution. + * David McKnight (IBM) [246406] [performance] Timeout waiting when loading SystemPreferencesManager$ModelChangeListener during startup + * Martin Oberhuber (Wind River) - [246406] Thread-safe support for Lazy Loading *******************************************************************************/ package org.eclipse.rse.services.clientserver.messages; @@ -24,8 +25,11 @@ import java.io.InputStream; import java.io.PrintWriter; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; +import java.util.Collections; import java.util.Hashtable; import java.util.LinkedList; +import java.util.List; import java.util.Vector; import javax.xml.parsers.DocumentBuilder; @@ -44,17 +48,20 @@ import org.xml.sax.SAXParseException; /** - * Use this class to open, and parse, a RSE-style message file. + * Use this class to open, and parse, a RSE-style message file. */ public class SystemMessageFile implements ErrorHandler { - - private static final LinkedList msgfList=new LinkedList(); + /** + * List of loaded message files to avoid double loading. + * Must be synchronized since queried from multiple Threads. + */ + private static final List msgfList = Collections.synchronizedList(new LinkedList()); private MessageFileInfo msgFile; private String defaultMsgFileLocation; private InputStream dtdInputStream; - // the following is an attempt to improve response time, and reduce memory requirements, by + // the following is an attempt to improve response time, and reduce memory requirements, by // caching SystemMessage objects for previously issued messages. Phil private Hashtable messages = new Hashtable(); // XML TAG AND ELEMENT NAMES... @@ -68,19 +75,24 @@ public class SystemMessageFile implements ErrorHandler private static final String XML_ATTR_ID = "ID"; //$NON-NLS-1$ private static final String XML_ATTR_INDICATOR = "Indicator"; //$NON-NLS-1$ private static final String XML_ATTR_NAME = "Name"; //$NON-NLS-1$ - - - + + // when using lazy loading, this is the thread that loads the message file + private final Thread fLoadThread; + + // indicates whether the lazy load thread is done + private boolean fLoadThreadFinished = false; + /** - * Inner class + * File info node in msgfList to avoid duplicate loading. + * Thread-safe since immutable. */ - private class MessageFileInfo + private static class MessageFileInfo { - private String filename=null; - private String shortName=null; - private Document xmlDocument=null; - - public MessageFileInfo(String ucFileName, String lcFileName, Document doc) + private final String filename; + private final String shortName; + private final Document xmlDocument; + + public MessageFileInfo(String ucFileName, String lcFileName, Document doc) { filename=ucFileName; int idx=lcFileName.lastIndexOf('\\'); @@ -88,61 +100,159 @@ public class SystemMessageFile implements ErrorHandler idx = lcFileName.lastIndexOf('/'); if (idx >= 0) shortName = lcFileName.substring(idx+1); - else + else shortName = lcFileName; xmlDocument=doc; } - - public String getMessageFullFileName() + + public String getMessageFullFileName() { return filename; } - public String getMessageShortFileName() + public String getMessageShortFileName() { return shortName; } - - public Document getXMLDocument() + + public Document getXMLDocument() { return xmlDocument; } } /** - * Constructor - * @param messageFileName - a key used to determine if a message file has already been loaded. - * Usually the name of the xml file containing the message file. - * @param messageFile the stream containing the message file. - * @param dtdStream the stream containing the dtd for this message file. + * Thread for loading a message file asynchronously. + * + * Opens Streams, creates an internal message file info object holding the + * DTD, and closes Streams. In case of error, the message file info object + * is not set (remains null). + * + * As a result, + *
    + *
  • The {@link #msgFile} variable is set to the loaded message file info + * node if successful.
  • + *
  • The {@link #fLoadThreadFinished} is guaranteed to be set + * true.
  • + *
  • All waiting Threads are notified.
  • + *
*/ - public SystemMessageFile (String messageFileName, InputStream messageFile, InputStream dtdStream) + private class LoadThread extends Thread { + private URL _messageFileURL; + private URL _dtdURL; + private String _messageFileName; + + public LoadThread(String messageFileName, URL messageFileURL, URL dtdURL) { + _messageFileName = messageFileName; + _messageFileURL = messageFileURL; + _dtdURL = dtdURL; + } + + public void run() { + InputStream messageFile = null; + InputStream dtdFile = null; + try { + messageFile = _messageFileURL.openStream(); + dtdFile = _dtdURL.openStream(); + SystemMessageFile realFile = new SystemMessageFile(_messageFileName, messageFile, dtdFile); + msgFile = realFile.msgFile; + } catch (IOException e) { + // problem loading message file -- msgFile is not set. + } finally { + // Notify that work is finished before closing Streams - + // Avoid not getting this set due to a RuntimeError + synchronized (this) { + fLoadThreadFinished = true; + notifyAll(); + } + if (messageFile != null) { + try { + safeClose(messageFile); + } finally { + if (dtdFile != null) + safeClose(dtdFile); + } + } + } + } + + private void safeClose(InputStream s) { + try { + s.close(); + } catch (IOException e) { + /* ignore */ + } + } + } + + + + /** + * Constructor to use for lazy loading of a system message file. + * + * The difference between the {@link #SystemMessageFile(String,InputStream,InputStream)} + * constructor and this one is that the former loads the message file synchronously while + * this one loads the message file in a thread. The message file and DTD URLs are passed + * in here so that the opening of their input streams can be deferred until the time when + * the worker thread is started and able to load the message file. + * + * @param messageFileName the name of the system message file + * @param msgFileURL the URL to the message file + * @param dtdURL the URL to the DTD for the message file + * + * @since 3.1 + */ + public SystemMessageFile(final String messageFileName, final URL msgFileURL, final URL dtdURL) { // have we already loaded this message file? msgFile = getFromCache(messageFileName); - - // now, we haven't. Load it now. + if (msgFile == null){ + // will set msgFile variable and fLoadThreadFinished when done + fLoadThread = new LoadThread(messageFileName, msgFileURL, dtdURL); + fLoadThread.start(); + } + else { // there's already a cached message file for this + // no need to load it, just use the msgFile + fLoadThread = null; + } + } + + + /** + * Constructor + * @param messageFileName - a key used to determine if a message file has already been loaded. + * Usually the name of the xml file containing the message file. + * @param messageFile the stream containing the message file. + * @param dtdStream the stream containing the dtd for this message file. + */ + public SystemMessageFile (String messageFileName, InputStream messageFile, InputStream dtdStream) + { + // have we already loaded this message file? + msgFile = getFromCache(messageFileName); + + // now, we haven't. Load it now. this.dtdInputStream = dtdStream; - if (msgFile == null) + if (msgFile == null) { Document doc = loadAndParseXMLFile(messageFile); msgFile=new MessageFileInfo(messageFileName.toUpperCase(), messageFileName, doc); msgfList.add(msgFile); //scanForDuplicates(); // don't keep this for production. Too expensive - } + } + fLoadThread = null; } /** * If the named message file has already been loaded return its * MessageFileInfo - * @param messageFileName + * @param messageFileName name of the message file * @return the MessageFileInfo for this message file */ protected MessageFileInfo getFromCache(String messageFileName) { - for (int i=0; i0)) nodeText += textNode.getNodeValue(); - } + } return nodeText.trim(); } @@ -346,50 +470,51 @@ public class SystemMessageFile implements ErrorHandler * log file. * @return true if duplicates found. */ - public boolean scanForDuplicates() + public boolean scanForDuplicates() { boolean echoErrorsToStandardOut = true; - if (msgFile.getXMLDocument() == null) - return issueErrorMessage("No XML document for message file", echoErrorsToStandardOut); //$NON-NLS-1$ - + waitUntilLoaded(); + if (msgFile == null || msgFile.getXMLDocument() == null) + return issueErrorMessage("No XML document for message file", echoErrorsToStandardOut); + // parse out the Abbr attr of the first Component element NodeList componentElementList = msgFile.getXMLDocument().getElementsByTagName(XML_TAG_COMPONENT); if ((componentElementList == null) || (componentElementList.getLength() == 0)) - return issueErrorMessage("Unable to find any Component elements",echoErrorsToStandardOut); //$NON-NLS-1$ + return issueErrorMessage("Unable to find any Component elements",echoErrorsToStandardOut); Element componentElement = (Element)componentElementList.item(0); String componentAbbr = componentElement.getAttribute(XML_ATTR_ABBR); - + // get list of all Subcomponent elements... NodeList subComponentList=msgFile.getXMLDocument().getElementsByTagName(XML_TAG_SUBCOMPONENT); - + if ((subComponentList == null) || (subComponentList.getLength() == 0)) - return issueErrorMessage("Unable to find any Subcomponent elements",echoErrorsToStandardOut); //$NON-NLS-1$ - + return issueErrorMessage("Unable to find any Subcomponent elements",echoErrorsToStandardOut); + // scan all subcomponents... boolean anyDupes = false; - for (int subComponentIdx=0; subComponentIdx0)) messageListNode = (Element)msgListNodes.item(0); else { - issueWarningMessage("unable to find MessageList nodes for subComponent " + subComponentElement.getAttribute(XML_ATTR_NAME),echoErrorsToStandardOut); //$NON-NLS-1$ + issueWarningMessage("unable to find MessageList nodes for subComponent " + subComponentElement.getAttribute(XML_ATTR_NAME),echoErrorsToStandardOut); continue; } - + NodeList msgNodes = messageListNode.getElementsByTagName(XML_TAG_MESSAGE); if ((msgNodes==null) || (msgNodes.getLength()==0)) { - issueWarningMessage("unable to find Message nodes for subComponent " + subComponentElement.getAttribute(XML_ATTR_NAME),echoErrorsToStandardOut); //$NON-NLS-1$ + issueWarningMessage("unable to find Message nodes for subComponent " + subComponentElement.getAttribute(XML_ATTR_NAME),echoErrorsToStandardOut); continue; } for (int msgIdx = 0; (msgIdx < msgNodes.getLength()); msgIdx++) @@ -399,7 +524,7 @@ public class SystemMessageFile implements ErrorHandler if (msgsById.contains(msgId)) { anyDupes = true; - issueWarningMessage("Warning: duplicate message " + msgId + " found", echoErrorsToStandardOut); //$NON-NLS-1$ //$NON-NLS-2$ + issueWarningMessage("Warning: duplicate message " + msgId + " found", echoErrorsToStandardOut); } else msgsById.addElement(msgId); @@ -414,25 +539,26 @@ public class SystemMessageFile implements ErrorHandler * @param fullFileName - the fully qualified name of the file to write to. Overwrites current contents. * @return true if it went well, false if it failed for some reason, such as given a bad file name. Errors written to standard out. */ - public boolean printHTML(String fullFileName) + public boolean printHTML(String fullFileName) { boolean echoErrorsToStandardOut = true; - if (msgFile.getXMLDocument() == null) - return issueErrorMessage("No XML document for message file", echoErrorsToStandardOut); //$NON-NLS-1$ - + waitUntilLoaded(); + if (msgFile == null || msgFile.getXMLDocument() == null) + return issueErrorMessage("No XML document for message file", echoErrorsToStandardOut); + // parse out the Abbr attr of the first Component element NodeList componentElementList = msgFile.getXMLDocument().getElementsByTagName(XML_TAG_COMPONENT); if ((componentElementList == null) || (componentElementList.getLength() == 0)) - return issueErrorMessage("Unable to find any Component elements",echoErrorsToStandardOut); //$NON-NLS-1$ + return issueErrorMessage("Unable to find any Component elements",echoErrorsToStandardOut); Element componentElement = (Element)componentElementList.item(0); String componentAbbr = componentElement.getAttribute(XML_ATTR_ABBR); - + // get list of all Subcomponent elements... NodeList subComponentList=msgFile.getXMLDocument().getElementsByTagName(XML_TAG_SUBCOMPONENT); - + if ((subComponentList == null) || (subComponentList.getLength() == 0)) - return issueErrorMessage("Unable to find any Subcomponent elements",echoErrorsToStandardOut); //$NON-NLS-1$ + return issueErrorMessage("Unable to find any Subcomponent elements",echoErrorsToStandardOut); File outFile = new File(fullFileName); PrintWriter outFileStream = null; @@ -454,11 +580,11 @@ public class SystemMessageFile implements ErrorHandler } catch (IOException exc) { - return issueErrorMessage("Unable to open given html file in printHTML: " + exc.getMessage(), echoErrorsToStandardOut); //$NON-NLS-1$ + return issueErrorMessage("Unable to open given html file in printHTML: " + exc.getMessage(), echoErrorsToStandardOut); } // pre-scan all subcomponents... - for (int subComponentIdx=0; subComponentIdx"); //$NON-NLS-1$ // scan all subcomponents... - for (int subComponentIdx=0; subComponentIdx0)) messageListNode = (Element)msgListNodes.item(0); else { - issueWarningMessage("unable to find MessageList nodes for subComponent " + subComponentElement.getAttribute(XML_ATTR_NAME),echoErrorsToStandardOut); //$NON-NLS-1$ + issueWarningMessage("unable to find MessageList nodes for subComponent " + subComponentElement.getAttribute(XML_ATTR_NAME),echoErrorsToStandardOut); continue; } - + NodeList msgNodes = messageListNode.getElementsByTagName(XML_TAG_MESSAGE); if ((msgNodes==null) || (msgNodes.getLength()==0)) { - issueWarningMessage("unable to find Message nodes for subComponent " + subComponentElement.getAttribute(XML_ATTR_NAME),echoErrorsToStandardOut); //$NON-NLS-1$ + issueWarningMessage("unable to find Message nodes for subComponent " + subComponentElement.getAttribute(XML_ATTR_NAME),echoErrorsToStandardOut); continue; } if (subComponentIdx > 0) @@ -504,32 +630,32 @@ public class SystemMessageFile implements ErrorHandler { Element node = (Element)msgNodes.item(msgIdx); String msgId = msgPrefix + node.getAttribute(XML_ATTR_ID); - char msgIndicator=node.getAttribute(XML_ATTR_INDICATOR).toUpperCase().charAt(0); + char msgIndicator=node.getAttribute(XML_ATTR_INDICATOR).toUpperCase().charAt(0); String msgSeverity = "Unknown"; //$NON-NLS-1$ if (msgIndicator == SystemMessage.ERROR) - msgSeverity = "Error"; //$NON-NLS-1$ + msgSeverity = "Error"; else if (msgIndicator == SystemMessage.WARNING) - msgSeverity = "Warning"; //$NON-NLS-1$ + msgSeverity = "Warning"; else if (msgIndicator == SystemMessage.INQUIRY) - msgSeverity = "Question"; //$NON-NLS-1$ + msgSeverity = "Question"; else if (msgIndicator == SystemMessage.INFORMATION) - msgSeverity = "Information"; //$NON-NLS-1$ + msgSeverity = "Information"; else if (msgIndicator == SystemMessage.COMPLETION) - msgSeverity = "Completion"; //$NON-NLS-1$ + msgSeverity = "Completion"; else if (msgIndicator == SystemMessage.UNEXPECTED) - msgSeverity = "Unexpected"; //$NON-NLS-1$ - + msgSeverity = "Unexpected"; + String msgL1 = ""; //$NON-NLS-1$ String msgL2 = ""; //$NON-NLS-1$ // search for the l1 & l2 text for (Node msgNode=node.getFirstChild(); - msgNode!=null; msgNode=msgNode.getNextSibling()) + msgNode!=null; msgNode=msgNode.getNextSibling()) { - // get Level One text - if (msgNode.getNodeName().equals(XML_TAG_LEVELONE)) + // get Level One text + if (msgNode.getNodeName().equals(XML_TAG_LEVELONE)) msgL1 = getNodeText(msgNode); - // get Level Two text - else if (msgNode.getNodeName().equals(XML_TAG_LEVELTWO)) + // get Level Two text + else if (msgNode.getNodeName().equals(XML_TAG_LEVELTWO)) msgL2 = getNodeText(msgNode); } outFileStream.println("

"+msgId+"

"); //$NON-NLS-1$ //$NON-NLS-2$ @@ -543,19 +669,19 @@ public class SystemMessageFile implements ErrorHandler outFileStream.close(); return true; } - + /** * Issue an error message */ private boolean issueErrorMessage(String errormsg, boolean echoStandardOut) { - + /** TODO - DKM move this somewhere else since system message now needs to be eclipse independent * - SystemBasePlugin.logError("MessageFile error for msg file " + msgFile.getMessageShortFileName() + ": " + errormsg); + SystemBasePlugin.logError("MessageFile error for msg file " + msgFile.getMessageShortFileName() + ": " + errormsg); **/ if (echoStandardOut) - System.out.println("MessageFile error for msg file " + msgFile.getMessageShortFileName() + ": " + errormsg); //$NON-NLS-1$ //$NON-NLS-2$ + System.out.println("MessageFile error for msg file " + msgFile.getMessageShortFileName() + ": " + errormsg); return false; } /** @@ -564,13 +690,13 @@ public class SystemMessageFile implements ErrorHandler private boolean issueWarningMessage(String errormsg, boolean echoStandardOut) { /** TODO - DKM move this somewhere else since system message now needs to be eclipse independent - SystemBasePlugin.logError("MessageFile warning for msg file " + msgFile.getMessageShortFileName() + ": " + errormsg); + SystemBasePlugin.logError("MessageFile warning for msg file " + msgFile.getMessageShortFileName() + ": " + errormsg); */ if (echoStandardOut) - System.out.println("MessageFile warning for msg file " + msgFile.getMessageShortFileName() + ": " + errormsg); //$NON-NLS-1$ //$NON-NLS-2$ + System.out.println("MessageFile warning for msg file " + msgFile.getMessageShortFileName() + ": " + errormsg); return false; } - + /** * Create the XML parser * Set its entity resolver and error handler. @@ -591,11 +717,11 @@ public class SystemMessageFile implements ErrorHandler return null; } // DOMParser parser=new DOMParser(); -// try +// try // { // parser.setFeature( "http://xml.org/sax/features/validation", true); // } -// catch (SAXNotRecognizedException e) +// catch (SAXNotRecognizedException e) // { // // the feature was not recognized // /** TODO - DKM move this somewhere else since system message now needs to be eclipse independent @@ -603,7 +729,7 @@ public class SystemMessageFile implements ErrorHandler // */ // return null; // } -// catch (SAXNotSupportedException e) +// catch (SAXNotSupportedException e) // { // // the feature requested was not supported // /** TODO - DKM move this somewhere else since system message now needs to be eclipse independent @@ -612,15 +738,15 @@ public class SystemMessageFile implements ErrorHandler // return null; // } parser.setEntityResolver(new EntityResolver() { - public InputSource resolveEntity(String publicId, String systemId) throws SAXException, java.io.IOException + public InputSource resolveEntity(String publicId, String systemId) throws SAXException, java.io.IOException { /* // This code does not work with fragments Path path = new Path(systemId); - if (systemId.toUpperCase().endsWith("MESSAGEFILE.DTD")) + if (systemId.toUpperCase().endsWith("MESSAGEFILE.DTD")) { - if (SystemPlugin.getBaseDefault().getDescriptor().find(path)==null) - { + if (SystemPlugin.getBaseDefault().getDescriptor().find(path)==null) + { path = new Path("messageFile.dtd"); } } @@ -630,7 +756,7 @@ public class SystemMessageFile implements ErrorHandler if (dtdInputStream != null) { return new InputSource(dtdInputStream); - } + } else // if we have the directory containing the DTD use that { // yantzi:artemis6.2 changed to use URI instead of URL (URIs handle the spaces) @@ -650,66 +776,66 @@ public class SystemMessageFile implements ErrorHandler { // ignore and continue } - + return new InputSource(systemId); } - } + } }); parser.setErrorHandler(this); return parser; } /** - * loadAndParseXMLFile: + * loadAndParseXMLFile: * tries to load and parse the specified XML file . * @param String messageFile: InputStream containing the XML file */ - private Document loadAndParseXMLFile (InputStream messageFile) + private Document loadAndParseXMLFile (InputStream messageFile) { DocumentBuilder parser = createXmlParser(); - try + try { InputSource in = new InputSource(messageFile); - + // DKM - hack! // If systemId is null for the InputSource, then // the current parser hits a fatal exception. // This hack prevents that exception so that the // specified EntityResolver will get used. in.setSystemId("foo"); //$NON-NLS-1$ - Document document = parser.parse(in); - + Document document = parser.parse(in); + //Document document = parser.parse(messageFile); return document; } - catch (SAXException e) + catch (SAXException e) { e.printStackTrace(); // the parser was unable to parse the file. return null; } - catch (IOException e) + catch (IOException e) { e.printStackTrace(); /** TODO - DKM move this somewhere else since system message now needs to be eclipse independent - */ + */ return null; - } + } } - - /** - * XML Parser-required method: XML-parser warning. + + /** + * XML Parser-required method: XML-parser warning. */ - public void warning(SAXParseException ex) + public void warning(SAXParseException ex) { /** TODO - DKM move this somewhere else since system message now needs to be eclipse independent SystemBasePlugin.logError("SystemMessageFile: warning parsing message file: "+ex.toString()); */ } - /** - * XML Parser-required method: XML-parser Error. + /** + * XML Parser-required method: XML-parser Error. */ - public void error(SAXParseException ex) + public void error(SAXParseException ex) { /** TODO - DKM move this somewhere else since system message now needs to be eclipse independent SystemBasePlugin.logError("SystemMessageFile: Error parsing message file: "+ex.toString(), ex); @@ -724,15 +850,15 @@ public class SystemMessageFile implements ErrorHandler */ } - /** - * XML Parser-required method: XML-parser Fatal error. - */ - public void fatalError(SAXParseException ex) throws SAXException - { - /** TODO - DKM move this somewhere else since system message now needs to be eclipse independent + /** + * XML Parser-required method: XML-parser Fatal error. + */ + public void fatalError(SAXParseException ex) throws SAXException + { + /** TODO - DKM move this somewhere else since system message now needs to be eclipse independent SystemBasePlugin.logError("SystemMessageFile: Fatal Error parsing message file: "+ex.toString(), ex); */ throw(ex); - } - + } + } diff --git a/rse/plugins/org.eclipse.rse.ui/META-INF/MANIFEST.MF b/rse/plugins/org.eclipse.rse.ui/META-INF/MANIFEST.MF index 801fc264c4c..f28d5ef8540 100644 --- a/rse/plugins/org.eclipse.rse.ui/META-INF/MANIFEST.MF +++ b/rse/plugins/org.eclipse.rse.ui/META-INF/MANIFEST.MF @@ -2,7 +2,7 @@ Manifest-Version: 1.0 Bundle-ManifestVersion: 2 Bundle-Name: %pluginName Bundle-SymbolicName: org.eclipse.rse.ui;singleton:=true -Bundle-Version: 3.0.100.qualifier +Bundle-Version: 3.1.0.qualifier Bundle-Activator: org.eclipse.rse.ui.RSEUIPlugin Bundle-Localization: plugin Require-Bundle: org.eclipse.core.runtime, @@ -14,7 +14,7 @@ Require-Bundle: org.eclipse.core.runtime, org.eclipse.ui.ide, org.eclipse.ui.views, org.eclipse.ui.workbench.texteditor, - org.eclipse.rse.services;bundle-version="[3.0.0,4.0.0)", + org.eclipse.rse.services;bundle-version="[3.1.0,4.0.0)", org.eclipse.rse.core;bundle-version="[3.0.0,4.0.0)" Import-Package: com.ibm.icu.lang, com.ibm.icu.text, diff --git a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/SystemBasePlugin.java b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/SystemBasePlugin.java index 8d03e47d631..817fc902b4a 100644 --- a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/SystemBasePlugin.java +++ b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/SystemBasePlugin.java @@ -15,11 +15,11 @@ * Martin Oberhuber (Wind River) - [168870] refactor org.eclipse.rse.core package of the UI plugin * David McKnight (IBM) - [243263] NPE on expanding a filter * David McKnight (IBM) - [244454] SystemBasePlugin.getWorkBench() incorrectly returns null when called during Eclipse startup + * David McKnight (IBM) [246406] [performance] Timeout waiting when loading SystemPreferencesManager$ModelChangeListener during startup ********************************************************************************/ package org.eclipse.rse.ui; -import java.io.InputStream; import java.net.URL; import java.util.Hashtable; import java.util.Locale; @@ -302,9 +302,7 @@ public abstract class SystemBasePlugin extends AbstractUIPlugin try { URL url = resolveBundleNameNL(bundle, fileName); if (url != null) { - InputStream messageFileStream = url.openStream(); - mf = SystemUIMessageFile.getMessageFile(fileName, messageFileStream); - messageFileStream.close(); + mf = SystemUIMessageFile.getMessageFile(fileName, url); ok = true; } } catch (Throwable t) { @@ -345,10 +343,8 @@ public abstract class SystemBasePlugin extends AbstractUIPlugin boolean ok = false; try { URL url = bundle.getEntry("/"+fileName); //$NON-NLS-1$ - if (url != null) { - InputStream messageFileStream = url.openStream(); - mf = SystemUIMessageFile.getMessageFile(fileName, messageFileStream); - messageFileStream.close(); + if (url != null) { + mf = SystemUIMessageFile.getMessageFile(fileName, url); ok = true; } } catch (Throwable t) { diff --git a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/messages/SystemUIMessageFile.java b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/messages/SystemUIMessageFile.java index 2b448f0e0aa..98e47976e8b 100644 --- a/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/messages/SystemUIMessageFile.java +++ b/rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/messages/SystemUIMessageFile.java @@ -1,5 +1,5 @@ /******************************************************************************** - * Copyright (c) 2004, 2007 IBM Corporation and others. All rights reserved. + * Copyright (c) 2004, 2008 IBM Corporation and others. All rights reserved. * This program and the accompanying materials are made available under the terms * of the Eclipse Public License v1.0 which accompanies this distribution, and is * available at http://www.eclipse.org/legal/epl-v10.html @@ -12,6 +12,7 @@ * * Contributors: * Martin Oberhuber (Wind River) - [168870] refactor org.eclipse.rse.core package of the UI plugin + * David McKnight (IBM) [246406] [performance] Timeout waiting when loading SystemPreferencesManager$ModelChangeListener during startup ********************************************************************************/ package org.eclipse.rse.ui.messages; @@ -33,8 +34,8 @@ import org.eclipse.rse.ui.SystemBasePlugin; public class SystemUIMessageFile extends SystemMessageFile { /** - * Factory method for constructing a SystemUIMessageFile. If an error occurs when - * reading the message file DTD then that is logged. + * Factory method for constructing a SystemUIMessageFile that loads the message file synchronously. + * If an error occurs when reading the message file DTD then that is logged. * @param messageFileName The "registered" name of the message file. Used to determine * if the message file has been loaded. * @param messageFileStream The stream containing the message file. It is the @@ -59,12 +60,57 @@ public class SystemUIMessageFile extends SystemMessageFile { } return result; } + + /** + * Factory method for constructing a SystemUIMessageFile that loads the message file in a thread. + * + * The difference between {@link #getMessageFile(String,InputStream)} and this method + * is that the former calls the constructor that loads the message file synchronously + * while this one loads the message file in a worker thread. The message file URL is + * passed in here so that the opening of it's input stream can be deferred until the + * time when the worker thread is started and able to load the message file. + * + * @param messageFileName The name of the message file to load. + * @param messageFileURL The URL to the message file. + * @return The message file that was constructed. + * + * @since 3.1 + */ + public static SystemUIMessageFile getMessageFile(String messageFileName, + URL messageFileURL) { + SystemUIMessageFile result = null; + URL dtdURL = RSEUIPlugin.getDefault().getMessageFileDTD(); + if (dtdURL != null) { + result = new SystemUIMessageFile(messageFileName,messageFileURL, dtdURL); + } else { + SystemBasePlugin.logError("Could not find mesage file DTD."); //$NON-NLS-1$ + } + return result; + } + + /** + * Constructor for synchronous loading of the message file. + * + * This is private because this is not to be called directly, but rather + * from {@link #getMessageFile(String, InputStream)}. + */ private SystemUIMessageFile(String messageFileName, InputStream messageFileStream, InputStream dtdStream) { super(messageFileName, messageFileStream, dtdStream); } + /** + * Constructor for lazy loading of the message file. + * + * This is private because this is not to be called directly, but rather + * from {@link #getMessageFile(String, URL)}. + */ + private SystemUIMessageFile(String messageFileName, + URL messageFileURL, URL dtdURL) { + super(messageFileName, messageFileURL, dtdURL); + } + /** * Override this to provide different extended SystemMessage implementation *