### Eclipse Workspace Patch 1.0 #P org.eclipse.rse.ui Index: UI/org/eclipse/rse/ui/SystemBasePlugin.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/SystemBasePlugin.java,v retrieving revision 1.9 diff -u -r1.9 SystemBasePlugin.java --- UI/org/eclipse/rse/ui/SystemBasePlugin.java 27 Aug 2008 20:51:24 -0000 1.9 +++ UI/org/eclipse/rse/ui/SystemBasePlugin.java 26 Sep 2008 20:56:48 -0000 @@ -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 @@ 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 @@ 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) { Index: UI/org/eclipse/rse/ui/messages/SystemUIMessageFile.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.rse/plugins/org.eclipse.rse.ui/UI/org/eclipse/rse/ui/messages/SystemUIMessageFile.java,v retrieving revision 1.5 diff -u -r1.5 SystemUIMessageFile.java --- UI/org/eclipse/rse/ui/messages/SystemUIMessageFile.java 15 May 2007 23:54:30 -0000 1.5 +++ UI/org/eclipse/rse/ui/messages/SystemUIMessageFile.java 26 Sep 2008 20:56:48 -0000 @@ -59,11 +59,45 @@ } return result; } + + /** + * Factory method for constructing a SystemUIMessageFile. If an error occurs when + * reading the message file DTD then that is logged. + * + * The difference between this method and the getMessageFile(String,InputStream) + * method is that it loads the message file synchronously while this one doesn't. In order + * to address bug 246406, this message file URL needs to be passed in so that the file only + * gets loaded once in the appropriate worker thread. + * + * @param messageFileName The "registered" name of the message file. Used to determine + * if the message file has been loaded. + * @param messageFileURL The URL containing the message file. It is the + * @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; + } + private SystemUIMessageFile(String messageFileName, InputStream messageFileStream, InputStream dtdStream) { super(messageFileName, messageFileStream, dtdStream); } + + private SystemUIMessageFile(String messageFileName, + URL messageFileURL, URL dtdURL) { + super(messageFileName, messageFileURL, dtdURL); + } /** * Override this to provide different extended SystemMessage implementation #P org.eclipse.rse.services Index: clientserver/org/eclipse/rse/services/clientserver/messages/SystemMessageFile.java =================================================================== RCS file: /cvsroot/dsdp/org.eclipse.tm.rse/plugins/org.eclipse.rse.services/clientserver/org/eclipse/rse/services/clientserver/messages/SystemMessageFile.java,v retrieving revision 1.5 diff -u -r1.5 SystemMessageFile.java --- clientserver/org/eclipse/rse/services/clientserver/messages/SystemMessageFile.java 5 Jun 2007 10:37:08 -0000 1.5 +++ clientserver/org/eclipse/rse/services/clientserver/messages/SystemMessageFile.java 26 Sep 2008 20:56:49 -0000 @@ -12,7 +12,7 @@ * 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 *******************************************************************************/ package org.eclipse.rse.services.clientserver.messages; @@ -24,6 +24,7 @@ import java.io.PrintWriter; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import java.util.Hashtable; import java.util.LinkedList; import java.util.Vector; @@ -69,7 +70,49 @@ private static final String XML_ATTR_INDICATOR = "Indicator"; //$NON-NLS-1$ private static final String XML_ATTR_NAME = "Name"; //$NON-NLS-1$ - + 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() { + try { + InputStream messageFile = _messageFileURL.openStream(); + InputStream dtdFile = _dtdURL.openStream(); + fRealMessageFile = new SystemMessageFile(_messageFileName, messageFile,dtdFile); + messageFile.close(); + dtdFile.close(); + } + catch (IOException e){ + } + fIsLoaded = true; + notifyLoaded(); + } + + public synchronized void waitForLoad() + { + try + { + wait(); + } + catch (InterruptedException e) + { + return; + } + } + + + public synchronized void notifyLoaded() + { + notifyAll(); + } + } /** * Inner class @@ -108,6 +151,32 @@ } } + // this variables only used when using lazy loading + private LoadThread fInitJob = null; + private SystemMessageFile fRealMessageFile = null; + private boolean fIsLoaded = false; + + /** + * Constructor to use for lazy loading of a system message file. + * + * The difference between this constructor and the SystemMessageFile(String,InputStream,InputStream) + * constructor is that it loads synchronously while this one doesn't. In order to address bug 246406, + * the message file URL and the DTD URL need to be passed in so that those files only get loaded once in the + * load thread. + * + * @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 msgFileURL URL for the message file + * @param dtdURL URL for the DTD + * + * @since 3.1 + */ + public SystemMessageFile(final String messageFileName, final URL msgFileURL, final URL dtdURL) + { + load(messageFileName, msgFileURL, dtdURL); + } + + /** * Constructor * @param messageFileName - a key used to determine if a message file has already been loaded. @@ -128,13 +197,17 @@ msgFile=new MessageFileInfo(messageFileName.toUpperCase(), messageFileName, doc); msgfList.add(msgFile); //scanForDuplicates(); // don't keep this for production. Too expensive + + fIsLoaded = true; // indicates that the message file is loaded (since we're loading this synchronously) } } + + /** * 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) @@ -151,14 +224,8 @@ } - /** - * Use this method to retrieve a message from the message file. - * @param msgId - the ID of the message to retrieve. This is the concatenation of the - * message's component abbreviation, subcomponent abbreviation, and message ID as declared - * in the message xml file. - * @return SystemMessage object - */ - public SystemMessage getMessage(String msgId) + + private SystemMessage internalGetMessage(String msgId) { boolean echoErrorsToStandardOut = true; // DY Defect 42605 @@ -289,19 +356,10 @@ */ return null; } - try - { - msg = loadSystemMessage(componentAbbr, subComponentAbbr, msgNumber, msgIndicator, msgL1, msgL2); - messages.put(msgFile.getMessageShortFileName()+":"+msgId, msg); // add to cache so we find it immediately next time!! //$NON-NLS-1$ - return msg; - } - catch (IndicatorException e) - { - /** TODO - DKM move this somewhere else since system message now needs to be eclipse independent - SystemBasePlugin.logError("MessageFile:getMessage: "+e.toString(), e); - */ - } - break; + + msg = loadSystemMessage(componentAbbr, subComponentAbbr, msgNumber, msgIndicator, msgL1, msgL2); + messages.put(msgFile.getMessageShortFileName()+":"+msgId, msg); // add to cache so we find it immediately next time!! //$NON-NLS-1$ + return msg; } } return null; @@ -316,11 +374,10 @@ * @param msgL1 the first level text that describes the error * @param msgL2 the second level text that provides details about the error and possible recovery * @return the SystemMessage - * @throws IndicatorException if the message type indicator is invalid. * @see SystemMessage for message type indicator constants */ protected SystemMessage loadSystemMessage(String componentAbbr, String subComponentAbbr, String msgNumber, char msgIndicator, - String msgL1, String msgL2) throws IndicatorException + String msgL1, String msgL2) { return new SystemMessage(componentAbbr, subComponentAbbr, msgNumber, msgIndicator, msgL1, msgL2); } @@ -735,4 +792,42 @@ throw(ex); } + + /** + * Loads the message file in a job + * @param messageFileName name of the message file to load + * @param messageFileURL the message file to load + * @param dtdURL the dtd to load + */ + private void load(String messageFileName, URL messageFileURL, URL dtdURL){ + fInitJob = new LoadThread(messageFileName, messageFileURL, dtdURL); + fInitJob.start(); + } + + + private void waitUntilLoaded() { + synchronized(fInitJob) { + while(!fIsLoaded) { + fInitJob.waitForLoad(); + } + } + } + + /** + * Use this method to retrieve a message from the message file. + * @param msgId - the ID of the message to retrieve. This is the concatenation of the + * message's component abbreviation, subcomponent abbreviation, and message ID as declared + * in the message xml file. + * @return SystemMessage object + */ + public SystemMessage getMessage(String msgId) { + if (fRealMessageFile != null){ + waitUntilLoaded(); + return fRealMessageFile.getMessage(msgId); + } + else { + return internalGetMessage(msgId); + } + } + }