Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 145681 Details for
Bug 287096
[hotbug] ModelManagerImpl is highly susceptible to deadlock
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
Some Eclipse Foundation services are deprecated, or will be soon. Please ensure you've read
this important communication.
[patch]
Full patch for 3.2 stream
modelImpl32.patch (text/plain), 102.29 KB, created by
Min Idzelis
on 2009-08-26 10:25:23 EDT
(
hide
)
Description:
Full patch for 3.2 stream
Filename:
MIME Type:
Creator:
Min Idzelis
Created:
2009-08-26 10:25:23 EDT
Size:
102.29 KB
patch
obsolete
>### Eclipse Workspace Patch 1.0 >#P org.eclipse.wst.sse.core >Index: src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java >=================================================================== >RCS file: /cvsroot/webtools/sourceediting/plugins/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java,v >retrieving revision 1.17 >diff -u -r1.17 SSECorePlugin.java >--- src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java 25 Feb 2009 22:44:04 -0000 1.17 >+++ src/org/eclipse/wst/sse/core/internal/SSECorePlugin.java 26 Aug 2009 14:03:22 -0000 >@@ -16,6 +16,7 @@ > import org.eclipse.core.runtime.Preferences; > import org.eclipse.wst.sse.core.StructuredModelManager; > import org.eclipse.wst.sse.core.internal.encoding.CommonEncodingPreferenceNames; >+import org.eclipse.wst.sse.core.internal.model.ModelManagerImpl; > import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry; > import org.eclipse.wst.sse.core.internal.preferences.CommonModelPreferenceNames; > import org.eclipse.wst.sse.core.internal.provisional.IModelManager; >@@ -62,10 +63,13 @@ > public void stop(BundleContext context) throws Exception { > savePluginPreferences(); > >+ ((ModelManagerImpl) ModelManagerImpl.getInstance()).removePreferenceListener(); >+ > TaskScanningScheduler.shutdown(); > > FileBufferModelManager.shutdown(); > >+ > super.stop(context); > } > >Index: src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java >=================================================================== >RCS file: /cvsroot/webtools/sourceediting/plugins/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java,v >retrieving revision 1.36 >diff -u -r1.36 ModelManagerImpl.java >--- src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java 22 Apr 2009 03:58:35 -0000 1.36 >+++ src/org/eclipse/wst/sse/core/internal/model/ModelManagerImpl.java 26 Aug 2009 14:03:22 -0000 >@@ -40,6 +40,7 @@ > import org.eclipse.core.runtime.IPath; > import org.eclipse.core.runtime.IStatus; > import org.eclipse.core.runtime.NullProgressMonitor; >+import org.eclipse.core.runtime.OperationCanceledException; > import org.eclipse.core.runtime.Path; > import org.eclipse.core.runtime.Platform; > import org.eclipse.core.runtime.QualifiedName; >@@ -47,9 +48,17 @@ > import org.eclipse.core.runtime.content.IContentDescription; > import org.eclipse.core.runtime.jobs.ILock; > import org.eclipse.core.runtime.jobs.Job; >+import org.eclipse.core.runtime.preferences.ConfigurationScope; >+import org.eclipse.core.runtime.preferences.IEclipsePreferences; >+import org.eclipse.core.runtime.preferences.IPreferencesService; >+import org.eclipse.core.runtime.preferences.IScopeContext; >+import org.eclipse.core.runtime.preferences.InstanceScope; >+import org.eclipse.core.runtime.preferences.IEclipsePreferences.PreferenceChangeEvent; > import org.eclipse.jface.text.BadLocationException; > import org.eclipse.jface.text.IDocument; > import org.eclipse.jface.text.IRegion; >+import org.eclipse.osgi.service.runnable.ParameterizedRunnable; >+import org.eclipse.osgi.util.NLS; > import org.eclipse.text.edits.MultiTextEdit; > import org.eclipse.text.edits.ReplaceEdit; > import org.eclipse.text.edits.TextEdit; >@@ -83,61 +92,205 @@ > import org.eclipse.wst.sse.core.internal.util.Utilities; > > /** >- * Not intended to be subclassed, referenced or instantiated by clients. >+ * This class is not intended to be: sub-classed, referenced or instantiated by >+ * clients. > * > * This class is responsible for creating, retrieving, and caching >- * StructuredModels It retrieves the cached objects by an id which is >- * typically a String representing the resources URI. Note: Its important that >- * all clients that share a resource do so using <b>identical </b> >- * identifiers, or else different instances will be created and retrieved, >- * even if they all technically point to the same resource on the file system. >- * This class also provides a convenient place to register Model Loaders and >- * Dumpers based on 'type'. >+ * StructuredModels It retrieves the cached objects by an id which is typically >+ * a String representing the resources URI. Note: Its important that all clients >+ * that share a resource do so using <b>identical </b> identifiers, or else >+ * different instances will be created and retrieved, even if they all >+ * technically point to the same resource on the file system. This class also >+ * provides a convenient place to register Model Loaders and Dumpers based on >+ * 'type'. > */ > public class ModelManagerImpl implements IModelManager { > >- static class ReadEditType { >- ReadEditType(String type) { >+ private static int WAIT_DELAY = getInt("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad"); >+ private static boolean ALLOW_INTERRUPT_WAITING_THREAD = getBoolean("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad"); >+ private static IEclipsePreferences.IPreferenceChangeListener LISTENER; >+ static { >+ InstanceScope scope = new InstanceScope(); >+ IEclipsePreferences instancePrefs = scope.getNode(SSECorePlugin.ID); >+ LISTENER = new IEclipsePreferences.IPreferenceChangeListener() { >+ >+ public void preferenceChange(PreferenceChangeEvent event) { >+ >+ if ("modelmanager.maxWaitDuringConcurrentLoad".equals(event.getKey())) { >+ WAIT_DELAY = getInt("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad"); >+ } >+ else if ("modelmanager.allowInterruptsDuringConcurrentLoad".equals(event.getKey())) { >+ ALLOW_INTERRUPT_WAITING_THREAD = getBoolean("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad"); >+ } >+ } >+ }; >+ instancePrefs.addPreferenceChangeListener(LISTENER); >+ } >+ >+ class FileLoader implements ParameterizedRunnable { >+ private final IFile file; >+ private final String id; >+ private final IModelHandler handler; >+ private final URIResolver resolver; >+ private final ReadEditType rwType; >+ private final EncodingRule encodingRule; >+ >+ public FileLoader(IFile file, String id, IModelHandler handler, URIResolver resolver, >+ ReadEditType rwType, EncodingRule encodingRule) { >+ this.file = file; >+ this.id = id; >+ this.handler = handler; >+ this.resolver = resolver; >+ this.rwType = rwType; >+ this.encodingRule = encodingRule; >+ >+ } >+ >+ public Object run(Object context) throws Exception { >+ SharedObject sharedObject = (SharedObject) context; >+ _doCommonCreateModel(file, id, handler, resolver, rwType, encodingRule, sharedObject); >+ return null; >+ } >+ } >+ >+ class InputStreamLoader implements ParameterizedRunnable { >+ >+ private final InputStream inputStream; >+ private final String id; >+ private final IModelHandler handler; >+ private final URIResolver resolver; >+ private final ReadEditType rwType; >+ private final String encoding; >+ private final String lineDelimiter; >+ >+ public InputStreamLoader(InputStream inputStream, String id, IModelHandler handler, >+ URIResolver resolver, ReadEditType rwType, String encoding, String lineDelimiter) { >+ this.inputStream = inputStream; >+ this.id = id; >+ this.handler = handler; >+ this.resolver = resolver; >+ this.rwType = rwType; >+ this.encoding = encoding; >+ this.lineDelimiter = lineDelimiter; >+ } >+ >+ public Object run(Object context) throws Exception { >+ SharedObject sharedObject = (SharedObject) context; >+ _doCommonCreateModel(inputStream, id, handler, resolver, rwType, encoding, >+ lineDelimiter, sharedObject); >+ return null; >+ } >+ } >+ >+ class FileBufferDocumentLoader implements ParameterizedRunnable { >+ private final IStructuredDocument document; >+ private final ReadEditType rwType; >+ >+ public FileBufferDocumentLoader(IStructuredDocument document, ReadEditType rwType) { >+ this.document = document; >+ this.rwType = rwType; >+ } >+ >+ public Object run(Object context) throws Exception { >+ SharedObject sharedObject = (SharedObject) context; >+ synchronized (sharedObject.loadLock) { >+ IStructuredModel model = FileBufferModelManager.getInstance().getModel(document); >+ synchronized (sharedObject) { >+ sharedObject.theSharedModel = model; >+ _initCount(sharedObject, rwType); >+ sharedObject.setLoaded(); >+ } >+ } >+ return null; >+ } >+ } >+ >+ class FileBufferIFileLoader implements ParameterizedRunnable { >+ >+ private final IFile file; >+ private final String id; >+ private final ReadEditType rwType; >+ >+ public FileBufferIFileLoader(IFile file, String id, ReadEditType rwType) { >+ this.file = file; >+ this.id = id; >+ this.rwType = rwType; >+ >+ } >+ >+ public Object run(Object context) throws Exception { >+ SharedObject sharedObject = (SharedObject) context; >+ _doCommonGetModel(file, id, sharedObject, rwType); >+ return null; > } > } > >+ static class ReadEditType { >+ ReadEditType(String type) {} >+ } >+ > /** > * A Data class to track our shared objects > */ >- static class SharedObject { >+ static class SharedObject { > int referenceCountForEdit; > int referenceCountForRead; > IStructuredModel theSharedModel; > boolean initializing = true; >- boolean doWait = true; >- >+ volatile boolean doWait = true; >+ final Object loadLock = new Object(); >+ > SharedObject(IStructuredModel sharedModel) { > theSharedModel = sharedModel; > referenceCountForRead = 0; > referenceCountForEdit = 0; > } >- >+ > /** >- * Waits until this shared object has been attempted to be loaded. >- * The load is "attempted" because not all loads result in a model. >- * However, upon leaving this method, theShareModel variable >- * is up-to-date. >+ * Waits until this shared object has been attempted to be loaded. The >+ * load is "attempted" because not all loads result in a model. However, >+ * upon leaving this method, theShareModel variable is up-to-date. > */ > public synchronized void waitForLoadAttempt() { >- while(initializing) { >+ long start = System.currentTimeMillis(); >+ // Note: A WAIT_DELAY of 0 is infinite >+ int maxTimeMs = Math.max(0, WAIT_DELAY); >+ final int waitInterval = Math.min(250, maxTimeMs); >+ boolean interrupted = false; >+ while (initializing && maxTimeMs >= 0) { > try { >- wait(); >+ wait(waitInterval); >+ maxTimeMs -= waitInterval; > } > catch (InterruptedException e) { >- // ignore interruption! >+ interrupted = true; >+ if (ALLOW_INTERRUPT_WAITING_THREAD) { >+ break; >+ } > } > } >+ if (initializing) { >+ long totalWaitTime = System.currentTimeMillis() - start; >+ if (interrupted) { >+ throw new OperationCanceledException( >+ "Waiting thread interrupted during simultenous model load. Load aborted. (Waited " >+ + totalWaitTime + "ms)"); >+ } >+ else { >+ throw new OperationCanceledException( >+ "Waiting thread timed-out during simultenous model load. Load aborted. (Waited " >+ + totalWaitTime + "ms)"); >+ } >+ } >+ if (interrupted) { >+ // Propagate (don't swallow) the interrupt >+ Thread.currentThread().interrupt(); >+ } > } >- >+ > /** >- * Flags this model as loaded. All waiting methods on >- * {@link #waitForLoadAttempt()} will proceed after this >- * method returns. >+ * Flags this model as loaded. All waiting methods on >+ * {@link #waitForLoadAttempt()} will proceed after this method returns. > */ > public synchronized void setLoaded() { > initializing = false; >@@ -150,7 +303,7 @@ > /** > * Our singleton instance > */ >- private static ModelManagerImpl instance; >+ private static LotsOfEditsModelManager instance; > private final static int READ_BUFFER_SIZE = 4096; > > /** >@@ -161,11 +314,17 @@ > public synchronized static IModelManager getInstance() { > > if (instance == null) { >- instance = new ModelManagerImpl(); >+ instance = new LotsOfEditsModelManager(); > } > return instance; > } > >+ public void removePreferenceListener() { >+ InstanceScope scope = new InstanceScope(); >+ IEclipsePreferences instancePrefs = scope.getNode(SSECorePlugin.ID); >+ instancePrefs.removePreferenceChangeListener(LISTENER); >+ } >+ > /** > * Our cache of managed objects > */ >@@ -174,8 +333,9 @@ > private ModelHandlerRegistry fModelHandlerRegistry; > private final ReadEditType READ = new ReadEditType("read"); //$NON-NLS-1$ > private final ReadEditType EDIT = new ReadEditType("edit"); //$NON-NLS-1$ >- >+ > private final ILock SYNC = Job.getJobManager().newLock(); >+ > /** > * Intentionally default access only. > * >@@ -183,75 +343,120 @@ > ModelManagerImpl() { > super(); > fManagedObjects = new HashMap(); >- // To prevent deadlocks: always acquire multiple locks in this order: SYNC, sharedObject. >- // DO NOT acquire a SYNC within a sharedObject lock, unless you already own the SYNC lock >- // Tip: Try to hold the smallest number of locks you can >+ /** >+ * NOTES: To prevent deadlocks: always acquire multiple locks in this >+ * order: SYNC->sharedObject.loadLock->sharedObject DO NOT acquire a >+ * SYNC within a sharedObject lock, unless you already own the SYNC lock >+ * Tip: Try to hold the smallest number of locks you can >+ */ > } > >- private IStructuredModel _commonCreateModel(IFile file, String id, IModelHandler handler, URIResolver resolver, ReadEditType rwType, EncodingRule encodingRule) throws IOException,CoreException { >+ private IStructuredModel doLoad(String id, ReadEditType rwType, ParameterizedRunnable loader) >+ throws CoreException, IOException { > SharedObject sharedObject = null; >- >+ > SYNC.acquire(); >- sharedObject = (SharedObject) fManagedObjects.get(id); >- SYNC.release(); >- >- while(true) { >- if (sharedObject!=null) { >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { >+ SYNC.release(); >+ } >+ >+ while (true) { >+ if (sharedObject != null) { > sharedObject.waitForLoadAttempt(); > } >+ boolean createModel = false; > SYNC.acquire(); >- // we know this object's model has passed the load, however, we don't know >- // it's reference count status. It might have already been disposed. Or it could have >- // been disposed and a concurrent thread has already begun loading it, in which case >- // we should use the sharedobject they are loading. >- // NOTE: This pattern is applied 3 times in this class, but only doc'd once. The logic is >- // exactly the same. >- SharedObject testObject = (SharedObject) fManagedObjects.get(id); >- if (testObject==null) { >- // null means it's been disposed, we need to do the work to reload it. >- sharedObject = new SharedObject(null); >- fManagedObjects.put(id, sharedObject); >- SYNC.release(); >- _doCommonCreateModel(file, id, handler, resolver, rwType, encodingRule, >- sharedObject); >- break; >- } else if (sharedObject == testObject) { >- // if nothing happened, just increment the could and return the shared model >- synchronized(sharedObject) { >- if (sharedObject.theSharedModel!=null) { >- _incrCount(sharedObject, rwType); >+ try { >+ // we know this object's model has passed the load, however, we >+ // don't know it's reference count status. It might have already >+ // been disposed. Or it could have been disposed and a >+ // concurrent thread has already begun >+ // loading it, in which case we should use the SharedObject they >+ // are loading. >+ >+ SharedObject testObject = (SharedObject) fManagedObjects.get(id); >+ if (testObject == null) { >+ // null means it's been disposed, we need to do the work to >+ // reload it. >+ sharedObject = new SharedObject(null); >+ fManagedObjects.put(id, sharedObject); >+ createModel = true; >+ break; >+ } >+ else if (sharedObject == testObject) { >+ // if nothing happened, just increment the could and return >+ // the shared model >+ synchronized (sharedObject) { >+ Assert.isTrue(sharedObject.referenceCountForEdit >+ + sharedObject.referenceCountForRead > 0); >+ if (sharedObject.theSharedModel != null) { >+ _incrCount(sharedObject, rwType); >+ } > } >+ break; > } >+ else { >+ // sharedObject != testObject which means the object we were >+ // waiting on has been disposed a replacement has already >+ // been placed in the managedObjects table. Through away our >+ // stale sharedObject and continue on with the one we got >+ // from the queue. Note: We don't know its state, so >+ // continue the waitForLoad-check loop. >+ sharedObject = testObject; >+ } >+ } >+ finally { > SYNC.release(); >- break; >- } else { >- // sharedObject != testObject which means the object we were waiting on has been disposed >- // a replacement has already been placed in the managedObjects table. Through away our >- // stale sharedObject and continue on with the one we got from the queue. Note: We don't know its >- // state, so continue the waitForLoad-check loop. >- SYNC.release(); >- sharedObject = testObject; >+ if (createModel) { >+ try { >+ loader.run(sharedObject); >+ } >+ catch (CoreException e) { >+ // rethrow, since the exception came from the loader's >+ throw e; >+ } >+ catch (IOException e) { >+ // rethrow, since the exception came from the loader >+ throw e; >+ } >+ catch (Exception e) { >+ // log this unspecified exception >+ Logger.logException("Exception during load of model", e); >+ } >+ } > } > } >- >+ > // we expect to always return something > if (sharedObject == null) { > debugException = new Exception("instance only for stack trace"); //$NON-NLS-1$ > Logger.logException("Program Error: no model recorded for id " + id, debugException); //$NON-NLS-1$ > } >- >+ > // note: clients must call release for each time they call get. >- return sharedObject==null ? null : sharedObject.theSharedModel; >+ return sharedObject == null ? null : sharedObject.theSharedModel; >+ } >+ >+ private IStructuredModel _commonCreateModel(IFile file, String id, IModelHandler handler, >+ URIResolver resolver, ReadEditType rwType, EncodingRule encodingRule) >+ throws IOException, CoreException { >+ FileLoader loader = new FileLoader(file, id, handler, resolver, rwType, encodingRule); >+ return doLoad(id, rwType, loader); > } > > private void _decrCount(SharedObject sharedObject, ReadEditType type) { > if (type == READ) { > sharedObject.referenceCountForRead--; >- FileBufferModelManager.getInstance().disconnect(sharedObject.theSharedModel.getStructuredDocument()); >+ FileBufferModelManager.getInstance().disconnect( >+ sharedObject.theSharedModel.getStructuredDocument()); > } > else if (type == EDIT) { > sharedObject.referenceCountForEdit--; >- FileBufferModelManager.getInstance().disconnect(sharedObject.theSharedModel.getStructuredDocument()); >+ FileBufferModelManager.getInstance().disconnect( >+ sharedObject.theSharedModel.getStructuredDocument()); > } > else > throw new IllegalArgumentException(); >@@ -261,10 +466,10 @@ > URIResolver resolver, ReadEditType rwType, EncodingRule encodingRule, > SharedObject sharedObject) throws CoreException, IOException { > // XXX: Does not integrate with FileBuffers >- boolean doRemove = false; >- synchronized(sharedObject) { >+ IStructuredModel model = null; >+ synchronized (sharedObject.loadLock) { > InputStream inputStream = null; >- IStructuredModel model = null; >+ > try { > model = _commonCreateModel(id, handler, resolver); > IModelLoader loader = handler.getModelLoader(); >@@ -274,89 +479,69 @@ > catch (ResourceInUse e) { > // impossible, since we've already found > handleProgramError(e); >- } finally { >- if (inputStream!=null) { >- try { >+ } >+ finally { >+ if (inputStream != null) { >+ try { > inputStream.close(); >- } catch(IOException e) { > } >+ catch (IOException e) {} > } > } > if (model != null) { >- // add to our cache >- sharedObject.theSharedModel=model; >- _initCount(sharedObject, rwType); >- } else { >- doRemove = true; >+ synchronized (sharedObject) { >+ // add to our cache >+ sharedObject.theSharedModel = model; >+ _initCount(sharedObject, rwType); >+ } > } > } >- if (doRemove) { >- SYNC.acquire(); >- fManagedObjects.remove(id); >- SYNC.release(); >+ if (model == null) { >+ SYNC.acquire(); >+ try { >+ fManagedObjects.remove(id); >+ } >+ finally { >+ SYNC.release(); >+ } > } > sharedObject.setLoaded(); > } > >- private IStructuredModel _commonCreateModel(InputStream inputStream, String id, IModelHandler handler, URIResolver resolver, ReadEditType rwType, String encoding, String lineDelimiter) throws IOException { >- >- if (id == null) { >- throw new IllegalArgumentException("Program Error: id may not be null"); //$NON-NLS-1$ >+ private IStructuredModel _commonCreateModel(InputStream inputStream, String id, >+ IModelHandler handler, URIResolver resolver, ReadEditType rwType, String encoding, >+ String lineDelimiter) throws IOException { >+ org.eclipse.core.runtime.Assert.isLegal(id != null, "Program Error: id may not be null"); //$NON-NLS-1$ >+ >+ InputStreamLoader loader = new InputStreamLoader(inputStream, id, handler, resolver, >+ rwType, encoding, lineDelimiter); >+ try { >+ return doLoad(id, rwType, loader); > } >- SharedObject sharedObject = null; >- >- SYNC.acquire(); >- sharedObject = (SharedObject) fManagedObjects.get(id); >- SYNC.release(); >- >- while(true) { >- if (sharedObject!=null) { >- sharedObject.waitForLoadAttempt(); >- } >- SYNC.acquire(); >- SharedObject testObject = (SharedObject) fManagedObjects.get(id); >- if (testObject==null) { >- // it was removed ,so lets create it >- sharedObject = new SharedObject(null); >- fManagedObjects.put(id, sharedObject); >- SYNC.release(); >- _doCommonCreateModel(inputStream, id, handler, resolver, rwType, >- encoding, lineDelimiter, sharedObject); >- break; >- } else if (sharedObject == testObject) { >- synchronized(sharedObject) { >- if (sharedObject.theSharedModel!=null) { >- _incrCount(sharedObject, rwType); >- } >- } >- SYNC.release(); >- break; >- } else { >- SYNC.release(); >- sharedObject = testObject; >- } >+ catch (CoreException e) { >+ // This CoreException is a least-common-denominator side effect. The >+ // loader needs to call methods that sometimes return CoreException. >+ // However, the CoreException is only possible if it is invoked via >+ // FileLoader. >+ return null; > } >- >- // we expect to always return something >- Assert.isNotNull(sharedObject, "Program Error: no model recorded for id " + id); //$NON-NLS-1$ >- // note: clients must call release for each time they call get. >- return sharedObject.theSharedModel; >- > } > > private void _doCommonCreateModel(InputStream inputStream, String id, IModelHandler handler, > URIResolver resolver, ReadEditType rwType, String encoding, String lineDelimiter, > SharedObject sharedObject) throws IOException { >- boolean doRemove = false; >- synchronized(sharedObject) { >- IStructuredModel model = null; >+ IStructuredModel model = null; >+ synchronized (sharedObject.loadLock) { >+ > try { > model = _commonCreateModel(id, handler, resolver); > IModelLoader loader = handler.getModelLoader(); > if (inputStream == null) { >- Logger.log(Logger.WARNING, "model was requested for id " + id + " without a content InputStream"); //$NON-NLS-1$ //$NON-NLS-2$ >+ Logger.log(Logger.WARNING, >+ "model was requested for id " + id + " without a content InputStream"); //$NON-NLS-1$ //$NON-NLS-2$ > } >- loader.load(id, Utilities.getMarkSupportedStream(inputStream), model, encoding, lineDelimiter); >+ loader.load(id, Utilities.getMarkSupportedStream(inputStream), model, encoding, >+ lineDelimiter); > } > catch (ResourceInUse e) { > // impossible, since we've already found >@@ -366,37 +551,43 @@ > /** > * https://bugs.eclipse.org/bugs/show_bug.cgi?id=264228 > * >- * Ensure that the content type identifier field of the model >- * is properly set. This is normally handled by the >+ * Ensure that the content type identifier field of the model is >+ * properly set. This is normally handled by the > * FileBufferModelManager when working with files as it knows > * the content type in advance; here is where we handle it for > * streams. > */ > if (model instanceof AbstractStructuredModel) { > DocumentReader reader = new DocumentReader(model.getStructuredDocument()); >- IContentDescription description = Platform.getContentTypeManager().getDescriptionFor(reader, id, new QualifiedName[0]); >+ IContentDescription description = Platform.getContentTypeManager() >+ .getDescriptionFor(reader, id, new QualifiedName[0]); > reader.close(); > if (description != null && description.getContentType() != null) { >- ((AbstractStructuredModel) model).setContentTypeIdentifier(description.getContentType().getId()); >+ ((AbstractStructuredModel) model).setContentTypeIdentifier(description >+ .getContentType().getId()); > } > } >- >- sharedObject.theSharedModel = model; >- _initCount(sharedObject, rwType); >- } else { >- doRemove = true; >+ synchronized (sharedObject) { >+ sharedObject.theSharedModel = model; >+ _initCount(sharedObject, rwType); >+ } > } > } >- if (doRemove) { >+ if (model == null) { > SYNC.acquire(); >- // remove it if we didn't get one back >- fManagedObjects.remove(id); >- SYNC.release(); >+ try { >+ // remove it if we didn't get one back >+ fManagedObjects.remove(id); >+ } >+ finally { >+ SYNC.release(); >+ } > } > sharedObject.setLoaded(); > } > >- private IStructuredModel _commonCreateModel(String id, IModelHandler handler, URIResolver resolver) throws ResourceInUse { >+ private IStructuredModel _commonCreateModel(String id, IModelHandler handler, >+ URIResolver resolver) throws ResourceInUse { > > IModelLoader loader = handler.getModelLoader(); > IStructuredModel result = loader.createModel(); >@@ -417,7 +608,9 @@ > return result; > } > >- private IStructuredModel _commonGetModel(IFile iFile, ReadEditType rwType, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException { >+ private IStructuredModel _commonGetModel(IFile iFile, ReadEditType rwType, >+ EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, >+ CoreException { > IStructuredModel model = null; > > if (iFile != null && iFile.exists()) { >@@ -430,88 +623,63 @@ > return model; > } > >- private IStructuredModel _commonGetModel(IFile iFile, ReadEditType rwType, String encoding, String lineDelimiter) throws UnsupportedEncodingException, IOException, CoreException { >+ private IStructuredModel _commonGetModel(IFile iFile, ReadEditType rwType, String encoding, >+ String lineDelimiter) throws UnsupportedEncodingException, IOException, CoreException { > String id = calculateId(iFile); > IModelHandler handler = calculateType(iFile); > URIResolver resolver = calculateURIResolver(iFile); >- IStructuredModel model = _commonGetModel(iFile, id, handler, resolver, rwType, encoding, lineDelimiter); >+ IStructuredModel model = _commonGetModel(iFile, id, handler, resolver, rwType, encoding, >+ lineDelimiter); > > return model; > } > >- private IStructuredModel _commonGetModel(IFile file, String id, IModelHandler handler, URIResolver resolver, ReadEditType rwType, String encoding, String lineDelimiter) throws IOException, CoreException { >- if (id == null) >- throw new IllegalArgumentException("Program Error: id may not be null"); //$NON-NLS-1$ >+ private IStructuredModel _commonGetModel(IFile file, String id, IModelHandler handler, >+ URIResolver resolver, ReadEditType rwType, String encoding, String lineDelimiter) >+ throws IOException, CoreException { >+ org.eclipse.core.runtime.Assert.isLegal(id != null, "Program Error: id may not be null"); //$NON-NLS-1$ > >- SharedObject sharedObject = null; > if (file != null && file.exists()) { >- SYNC.acquire(); >- sharedObject = (SharedObject) fManagedObjects.get(id); >- SYNC.release(); >- >- while(true) { >- if (sharedObject!=null) { >- sharedObject.waitForLoadAttempt(); >- } >- SYNC.acquire(); >- SharedObject testObject = (SharedObject) fManagedObjects.get(id); >- if (testObject==null) { >- // it was removed ,so lets create it >- sharedObject = new SharedObject(null); >- fManagedObjects.put(id, sharedObject); >- >- SYNC.release(); >- _doCommonGetModel(file, id, sharedObject,rwType); >- break; >- } else if (sharedObject == testObject) { >- synchronized(sharedObject) { >- if (sharedObject.theSharedModel!=null) { >- _incrCount(sharedObject, rwType); >- } >- } >- SYNC.release(); >- break; >- } else { >- // we got a different object than what we were expecting >- SYNC.release(); >- // two threads were interested in models for the same id. >- // The other thread one, so lets back off and try again. >- sharedObject = testObject; >- } >- } >+ FileBufferIFileLoader loader = new FileBufferIFileLoader(file, id, rwType); >+ return doLoad(id, rwType, loader); > } >- >- // if we don't know how to create a model >- // for this type of file, return null >- >- // note: clients must call release for each time they call >- // get. >- >- return sharedObject==null ? null : sharedObject.theSharedModel; >- } >- >- private void _doCommonGetModel(IFile file, String id, SharedObject sharedObject,ReadEditType rwType) { >- boolean doRemove = false; >- synchronized(sharedObject) { >- sharedObject.doWait=false; >- IStructuredModel model = FileBufferModelManager.getInstance().getModel(file); >- sharedObject.doWait=true; >+ >+ return null; >+ } >+ >+ private void _doCommonGetModel(IFile file, String id, SharedObject sharedObject, >+ ReadEditType rwType) { >+ >+ IStructuredModel model = null; >+ synchronized (sharedObject.loadLock) { >+ sharedObject.doWait = false; >+ try { >+ model = FileBufferModelManager.getInstance().getModel(file); >+ } >+ finally { >+ sharedObject.doWait = true; >+ } > if (model != null) { >- sharedObject.theSharedModel=model; >- _initCount(sharedObject, rwType); >- } else { >- doRemove = true; >+ synchronized (sharedObject) { >+ sharedObject.theSharedModel = model; >+ _initCount(sharedObject, rwType); >+ } > } > } >- if (doRemove) { >+ if (model == null) { > SYNC.acquire(); >- fManagedObjects.remove(id); >- SYNC.release(); >+ try { >+ fManagedObjects.remove(id); >+ } >+ finally { >+ SYNC.release(); >+ } > } > sharedObject.setLoaded(); > } > >- private SharedObject _commonNewModel(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException { >+ private SharedObject _commonNewModel(IFile iFile, boolean force) throws ResourceAlreadyExists, >+ ResourceInUse, IOException, CoreException { > IStructuredModel aSharedModel = null; > // First, check if resource already exists on file system. > // if is does, then throw Resource in Use iff force==false >@@ -519,36 +687,37 @@ > if (iFile.exists() && !force) { > throw new ResourceAlreadyExists(); > } >- >+ > SharedObject sharedObject = null; > String id = calculateId(iFile); > try { > SYNC.acquire(); >- >- sharedObject = (SharedObject) fManagedObjects.get(id); >- >+ >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ > if (sharedObject != null && !force) { > // if in cache already, and force is not true, then this is an > // error > // in call > throw new ResourceInUse(); > } >- >+ > sharedObject = new SharedObject(null); > fManagedObjects.put(id, sharedObject); >- >- } finally { >+ >+ } >+ finally { > SYNC.release(); > } >- >+ > // if we get to here without above exceptions, then all is ok > // to get model like normal, but set 'new' attribute (where the > // 'new' attribute means this is a model without a corresponding > // underlying resource. > aSharedModel = FileBufferModelManager.getInstance().getModel(iFile); > aSharedModel.setNewState(true); >- >- sharedObject.theSharedModel=aSharedModel; >+ >+ sharedObject.theSharedModel = aSharedModel; > // when resource is provided, we can set > // synchronization stamp ... otherwise client should > // Note: one client which does this is FileModelProvider. >@@ -556,65 +725,40 @@ > return sharedObject; > } > >- public IStructuredModel _getModelFor(IStructuredDocument document, ReadEditType accessType) { >+ public IStructuredModel _getModelFor(IStructuredDocument document, ReadEditType rwType) { > > String id = FileBufferModelManager.getInstance().calculateId(document); > if (id == null) { >- if (READ == accessType) >+ if (READ == rwType) > return getExistingModelForRead(document); >- if (EDIT == accessType) >+ if (EDIT == rwType) > return getExistingModelForEdit(document); > Assert.isNotNull(id, "unknown IStructuredDocument " + document); //$NON-NLS-1$ > } >- >- SharedObject sharedObject = null; >- SYNC.acquire(); >- sharedObject = (SharedObject) fManagedObjects.get(id); >- SYNC.release(); >- >- while(true) { >- if (sharedObject!=null) { >- sharedObject.waitForLoadAttempt(); >- } >- SYNC.acquire(); >- SharedObject testObject = (SharedObject) fManagedObjects.get(id); >- if (testObject==null) { >- sharedObject = new SharedObject(null); >- fManagedObjects.put(id, sharedObject); >- SYNC.release(); >- synchronized(sharedObject) { >- sharedObject.theSharedModel = FileBufferModelManager.getInstance().getModel(document); >- _initCount(sharedObject, accessType); >- sharedObject.setLoaded(); >- } >- break; >- } else if (sharedObject == testObject) { >- synchronized(sharedObject) { >- Assert.isTrue(sharedObject.referenceCountForEdit + sharedObject.referenceCountForRead > 0); >- if (sharedObject.theSharedModel!=null) { >- _incrCount(sharedObject, accessType); >- } >- } >- SYNC.release(); >- break; >- } else { >- SYNC.release(); >- sharedObject = testObject; >- } >+ >+ FileBufferDocumentLoader loader = new FileBufferDocumentLoader(document, rwType); >+ try { >+ return doLoad(id, rwType, loader); >+ } >+ catch (Exception e) { >+ // Safe to ignore. FileBufferDocumentLoader#run does not throw >+ // exceptions. >+ return null; > } >- >- return sharedObject==null ? null : sharedObject.theSharedModel; >+ > } > > private void _incrCount(SharedObject sharedObject, ReadEditType type) { >- synchronized(sharedObject) { >+ synchronized (sharedObject) { > if (type == READ) { > sharedObject.referenceCountForRead++; >- FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument()); >+ FileBufferModelManager.getInstance().connect( >+ sharedObject.theSharedModel.getStructuredDocument()); > } > else if (type == EDIT) { > sharedObject.referenceCountForEdit++; >- FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument()); >+ FileBufferModelManager.getInstance().connect( >+ sharedObject.theSharedModel.getStructuredDocument()); > } > else > throw new IllegalArgumentException(); >@@ -622,13 +766,15 @@ > } > > private void _initCount(SharedObject sharedObject, ReadEditType type) { >- synchronized(sharedObject) { >+ synchronized (sharedObject) { > if (type == READ) { >- FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument()); >+ FileBufferModelManager.getInstance().connect( >+ sharedObject.theSharedModel.getStructuredDocument()); > sharedObject.referenceCountForRead = 1; > } > else if (type == EDIT) { >- FileBufferModelManager.getInstance().connect(sharedObject.theSharedModel.getStructuredDocument()); >+ FileBufferModelManager.getInstance().connect( >+ sharedObject.theSharedModel.getStructuredDocument()); > sharedObject.referenceCountForEdit = 1; > } > else >@@ -659,11 +805,10 @@ > } > } > >- > /** >- * Calculate id provides a common way to determine the id from the input >- * ... needed to get and save the model. It is a simple class utility, but >- * is an instance method so can be accessed via interface. >+ * Calculate id provides a common way to determine the id from the input ... >+ * needed to get and save the model. It is a simple class utility, but is an >+ * instance method so can be accessed via interface. > */ > public String calculateId(IFile file) { > return FileBufferModelManager.getInstance().calculateId(file); >@@ -677,7 +822,8 @@ > return cd; > } > >- private IModelHandler calculateType(String filename, InputStream inputStream) throws IOException { >+ private IModelHandler calculateType(String filename, InputStream inputStream) >+ throws IOException { > ModelHandlerRegistry cr = getModelHandlerRegistry(); > IModelHandler cd = cr.getHandlerFor(filename, inputStream); > return cd; >@@ -712,7 +858,8 @@ > // Note: calculateType(iFile) returns a default xml model handler if > // content type is null. > String contentTypeId = calculateType(iFile).getAssociatedContentTypeId(); >- String endOfLineCode = ContentBasedPreferenceGateway.getPreferencesString(contentTypeId, CommonEncodingPreferenceNames.END_OF_LINE_CODE); >+ String endOfLineCode = ContentBasedPreferenceGateway.getPreferencesString(contentTypeId, >+ CommonEncodingPreferenceNames.END_OF_LINE_CODE); > // endOfLineCode == null means the content type does not support this > // function (e.g. DTD) > // endOfLineCode == "" means no translation >@@ -736,8 +883,10 @@ > > if (i < lineCount - 1) { > String currentLineDelimiter = document.getLineDelimiter(i); >- if (currentLineDelimiter != null && currentLineDelimiter.compareTo(lineDelimiterToUse) != 0) >- multiTextEdit.addChild(new ReplaceEdit(lineEndOffset, currentLineDelimiter.length(), lineDelimiterToUse)); >+ if (currentLineDelimiter != null >+ && currentLineDelimiter.compareTo(lineDelimiterToUse) != 0) >+ multiTextEdit.addChild(new ReplaceEdit(lineEndOffset, >+ currentLineDelimiter.length(), lineDelimiterToUse)); > } > } > >@@ -798,8 +947,9 @@ > throw new ResourceInUse(); > } > sharedObject = new SharedObject(null); >- fManagedObjects.put(newId,sharedObject); >- } finally { >+ fManagedObjects.put(newId, sharedObject); >+ } >+ finally { > SYNC.release(); > } > // get loader based on existing type (note the type assumption) >@@ -808,22 +958,31 @@ > // IModelLoader loader = (IModelLoader) getModelLoaders().get(type); > // IModelLoader loader = (IModelLoader) getModelLoaders().get(type); > // ask the loader to copy >- synchronized(sharedObject) { >+ synchronized (sharedObject) { > sharedObject.doWait = false; >- newModel = copy(model, newId); >- sharedObject.doWait = true; >+ try { >+ newModel = copy(model, newId); >+ } >+ finally { >+ sharedObject.doWait = true; >+ } > } > if (newModel != null) { > // add to our cache >- synchronized(sharedObject) { >- sharedObject.theSharedModel=newModel; >+ synchronized (sharedObject) { >+ sharedObject.theSharedModel = newModel; > sharedObject.referenceCountForEdit = 1; > trace("copied model", newId, sharedObject.referenceCountForEdit); //$NON-NLS-1$ > } >- } else { >+ } >+ else { > SYNC.acquire(); >- fManagedObjects.remove(newId); >- SYNC.release(); >+ try { >+ fManagedObjects.remove(newId); >+ } >+ finally { >+ SYNC.release(); >+ } > } > sharedObject.setLoaded(); > return newModel; >@@ -831,8 +990,8 @@ > > /** > * Similar to clone, except the new instance has no content. Note: this >- * produces an unmanaged model, for temporary use. If a true shared model >- * is desired, use "copy". >+ * produces an unmanaged model, for temporary use. If a true shared model is >+ * desired, use "copy". > */ > public IStructuredModel createNewInstance(IStructuredModel oldModel) throws IOException { > IModelHandler handler = oldModel.getModelHandler(); >@@ -840,7 +999,8 @@ > IStructuredModel newModel = loader.createModel(oldModel); > newModel.setModelHandler(handler); > if (newModel instanceof AbstractStructuredModel) { >- ((AbstractStructuredModel) newModel).setContentTypeIdentifier(oldModel.getContentTypeIdentifier()); >+ ((AbstractStructuredModel) newModel).setContentTypeIdentifier(oldModel >+ .getContentTypeIdentifier()); > } > URIResolver oldResolver = oldModel.getResolver(); > newModel.setResolver(oldResolver); >@@ -858,15 +1018,16 @@ > > /** > * Factory method, since a proper IStructuredDocument must have a proper >- * parser assigned. Note: its assume that IFile does not actually exist as >- * a resource yet. If it does, ResourceAlreadyExists exception is thrown. >- * If the resource does already exist, then createStructuredDocumentFor is >- * the right API to use. >+ * parser assigned. Note: its assume that IFile does not actually exist as a >+ * resource yet. If it does, ResourceAlreadyExists exception is thrown. If >+ * the resource does already exist, then createStructuredDocumentFor is the >+ * right API to use. > * > * @throws ResourceInUse > * > */ >- public IStructuredDocument createNewStructuredDocumentFor(IFile iFile) throws ResourceAlreadyExists, IOException, CoreException { >+ public IStructuredDocument createNewStructuredDocumentFor(IFile iFile) >+ throws ResourceAlreadyExists, IOException, CoreException { > if (iFile.exists()) { > throw new ResourceAlreadyExists(iFile.getFullPath().toOSString()); > } >@@ -892,7 +1053,8 @@ > * > * @throws ResourceInUse > */ >- public IStructuredDocument createStructuredDocumentFor(IFile iFile) throws IOException, CoreException { >+ public IStructuredDocument createStructuredDocumentFor(IFile iFile) throws IOException, >+ CoreException { > if (!iFile.exists()) { > throw new FileNotFoundException(iFile.getFullPath().toOSString()); > } >@@ -904,24 +1066,24 @@ > IDocumentLoader loader = null; > IModelHandler handler = calculateType(iFile); > loader = handler.getDocumentLoader(); >- IStructuredDocument result = (IStructuredDocument) loader.createNewStructuredDocument(iFile); >+ IStructuredDocument result = (IStructuredDocument) loader >+ .createNewStructuredDocument(iFile); > return result; > } > > /** >- * Conveience method, since a proper IStructuredDocument must have a >- * proper parser assigned. It should only be used when an empty >- * structuredDocument is needed. Otherwise, use IFile form. >+ * Conveience method, since a proper IStructuredDocument must have a proper >+ * parser assigned. It should only be used when an empty structuredDocument >+ * is needed. Otherwise, use IFile form. > * > * @deprecated - TODO: to be removed by C4 do we really need this? I > * recommend to - use createStructuredDocumentFor(filename, >- * null, null) - the filename does not need to represent a >- * real - file, but can take for form of dummy.jsp, test.xml, >- * etc. - That way we don't hard code the handler, but specify >- * we - want the handler that "goes with" a certain type of - >- * file. >+ * null, null) - the filename does not need to represent a real >+ * - file, but can take for form of dummy.jsp, test.xml, etc. - >+ * That way we don't hard code the handler, but specify we - >+ * want the handler that "goes with" a certain type of - file. > */ >- public IStructuredDocument createStructuredDocumentFor(String contentTypeId) { >+ public IStructuredDocument createStructuredDocumentFor(String contentTypeId) { > IDocumentLoader loader = null; > ModelHandlerRegistry cr = getModelHandlerRegistry(); > IModelHandler handler = cr.getHandlerForContentTypeId(contentTypeId); >@@ -933,16 +1095,16 @@ > } > > /** >- * Conveience method, since a proper IStructuredDocument must have a >- * proper parser assigned. >+ * Conveience method, since a proper IStructuredDocument must have a proper >+ * parser assigned. > * > * @deprecated -- - TODO: to be removed by C4 I marked as deprecated to >- * discouage use of this method. It does not really work for >- * JSP fragments, since JSP Fragments need an IFile to >- * correctly look up the content settings. Use IFile form >- * instead. >+ * discouage use of this method. It does not really work for JSP >+ * fragments, since JSP Fragments need an IFile to correctly >+ * look up the content settings. Use IFile form instead. > */ >- public IStructuredDocument createStructuredDocumentFor(String filename, InputStream inputStream, URIResolver resolver) throws IOException { >+ public IStructuredDocument createStructuredDocumentFor(String filename, >+ InputStream inputStream, URIResolver resolver) throws IOException { > IDocumentLoader loader = null; > InputStream istream = Utilities.getMarkSupportedStream(inputStream); > if (istream != null) { >@@ -962,16 +1124,17 @@ > > /** > * Special case method. This method was created for the special case where >- * there is an encoding for input stream that should override all the >- * normal rules for encoding. For example, if there is an encoding >- * (charset) specified in HTTP response header, then that encoding is used >- * to translate the input stream to a string, but then the normal encoding >+ * there is an encoding for input stream that should override all the normal >+ * rules for encoding. For example, if there is an encoding (charset) >+ * specified in HTTP response header, then that encoding is used to >+ * translate the input stream to a string, but then the normal encoding > * rules are ignored, so that the string is not translated twice (for > * example, if its an HTML "file", then even if it contains a charset in >- * meta tag, its ignored since its assumed its all correctly decoded by >- * the HTTP charset. >+ * meta tag, its ignored since its assumed its all correctly decoded by the >+ * HTTP charset. > */ >- public IStructuredDocument createStructuredDocumentFor(String filename, InputStream inputStream, URIResolver resolver, String encoding) throws IOException { >+ public IStructuredDocument createStructuredDocumentFor(String filename, >+ InputStream inputStream, URIResolver resolver, String encoding) throws IOException { > String content = readInputStream(inputStream, encoding); > IStructuredDocument result = createStructuredDocumentFor(filename, content, resolver); > return result; >@@ -979,12 +1142,13 @@ > > /** > * Convenience method. This method can be used when the resource does not >- * really exist (e.g. when content is being created, but hasn't been >- * written to disk yet). Note that since the content is being provided as >- * a String, it is assumed to already be decoded correctly so no >- * transformation is done. >+ * really exist (e.g. when content is being created, but hasn't been written >+ * to disk yet). Note that since the content is being provided as a String, >+ * it is assumed to already be decoded correctly so no transformation is >+ * done. > */ >- public IStructuredDocument createStructuredDocumentFor(String filename, String content, URIResolver resolver) throws IOException { >+ public IStructuredDocument createStructuredDocumentFor(String filename, String content, >+ URIResolver resolver) throws IOException { > // TODO: avoid all these String instances > StringBuffer contentBuffer = new StringBuffer(content); > IDocumentLoader loader = null; >@@ -1017,17 +1181,20 @@ > // (even if it really is in use ... we don't care) > // this may need to be re-examined. > if (Logger.DEBUG_MODELMANAGER) >- Logger.log(Logger.INFO, "ModelMangerImpl::createUnManagedStructuredModelFor. Model unexpectedly in use."); //$NON-NLS-1$ //$NON-NLS-2$ >+ Logger >+ .log(Logger.INFO, >+ "ModelMangerImpl::createUnManagedStructuredModelFor. Model unexpectedly in use."); //$NON-NLS-1$ //$NON-NLS-2$ > } > > return result; > } > > /** >- * Conveience method. It depends on the loaders newModel method to return >- * an appropriate StrucuturedModel appropriately initialized. >+ * Conveience method. It depends on the loaders newModel method to return an >+ * appropriate StrucuturedModel appropriately initialized. > */ >- public IStructuredModel createUnManagedStructuredModelFor(IFile iFile) throws IOException, CoreException { >+ public IStructuredModel createUnManagedStructuredModelFor(IFile iFile) throws IOException, >+ CoreException { > IStructuredModel result = null; > result = createUnManagedEmptyModelFor(iFile); > >@@ -1040,18 +1207,19 @@ > } > > /** >- * Conveience method. It depends on the loaders newModel method to return >- * an appropriate StrucuturedModel appropriately initialized. >+ * Conveience method. It depends on the loaders newModel method to return an >+ * appropriate StrucuturedModel appropriately initialized. > */ >- public IStructuredModel createUnManagedStructuredModelFor(String contentTypeId) { >+ public IStructuredModel createUnManagedStructuredModelFor(String contentTypeId) { > return createUnManagedStructuredModelFor(contentTypeId, null); > } > > /** >- * Conveience method. It depends on the loaders newModel method to return >- * an appropriate StrucuturedModel appropriately initialized. >+ * Conveience method. It depends on the loaders newModel method to return an >+ * appropriate StrucuturedModel appropriately initialized. > */ >- public IStructuredModel createUnManagedStructuredModelFor(String contentTypeId, URIResolver resolver) { >+ public IStructuredModel createUnManagedStructuredModelFor(String contentTypeId, >+ URIResolver resolver) { > IStructuredModel result = null; > ModelHandlerRegistry cr = getModelHandlerRegistry(); > IModelHandler handler = cr.getHandlerForContentTypeId(contentTypeId); >@@ -1063,71 +1231,88 @@ > // (even if it really is in use ... we don't care) > // this may need to be re-examined. > if (Logger.DEBUG_MODELMANAGER) >- Logger.log(Logger.INFO, "ModelMangerImpl::createUnManagedStructuredModelFor. Model unexpectedly in use."); //$NON-NLS-1$ //$NON-NLS-2$ >+ Logger >+ .log(Logger.INFO, >+ "ModelMangerImpl::createUnManagedStructuredModelFor. Model unexpectedly in use."); //$NON-NLS-1$ //$NON-NLS-2$ > } > return result; > } > > private IStructuredModel getExistingModel(Object id) { > IStructuredModel result = null; >- >+ SharedObject sharedObject = null; >+ > SYNC.acquire(); >- /** >- * While a good check in theory, it's possible for an event fired to >- * cause a listener to access a method that calls this one. >- */ >- //Assert.isTrue(SYNC.getDepth()==1, "depth not equal to 1"); >- // let's see if we already have it in our cache >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- // if not, then we'll simply return null >- if (sharedObject != null) { >- SYNC.release(); >- sharedObject.waitForLoadAttempt(); >- result = sharedObject.theSharedModel; >- } else { >+ try { >+ /** >+ * While a good check in theory, it's possible for an event fired to >+ * cause a listener to access a method that calls this one. >+ * Assert.isTrue(SYNC.getDepth()==1, "depth not equal to 1"); >+ */ >+ >+ // let's see if we already have it in our cache >+ // if not, then we'll simply return null >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ >+ } >+ finally { > SYNC.release(); >+ if (sharedObject != null) { >+ synchronized (sharedObject) { >+ sharedObject.waitForLoadAttempt(); >+ result = sharedObject.theSharedModel; >+ } >+ } > } >- >+ > return result; > } > > /** >- * Note: users of this 'model' must still release it when finished. >- * Returns null if there's not a model corresponding to document. >+ * Note: users of this 'model' must still release it when finished. Returns >+ * null if there's not a model corresponding to document. > */ > public IStructuredModel getExistingModelForEdit(IDocument document) { > IStructuredModel result = null; >- >- SYNC.acquire(); >- // create a snapshot >- Set ids = new HashSet(fManagedObjects.keySet()); >- SYNC.release(); >+ Set ids; >+ >+ SYNC.acquire(); >+ try { >+ // create a snapshot >+ ids = new HashSet(fManagedObjects.keySet()); >+ } >+ finally { >+ SYNC.release(); >+ } > for (Iterator iterator = ids.iterator(); iterator.hasNext();) { > Object potentialId = iterator.next(); >- SYNC.acquire(); >- if (fManagedObjects.containsKey(potentialId)) { >- // check to see if still valid >+ boolean containsKey; >+ SYNC.acquire(); >+ try { >+ containsKey = fManagedObjects.containsKey(potentialId); >+ } >+ finally { > SYNC.release(); >+ } >+ if (containsKey) { > IStructuredModel tempResult = getExistingModel(potentialId); >- if (tempResult!=null && document == tempResult.getStructuredDocument()) { >+ if (tempResult != null && document == tempResult.getStructuredDocument()) { > result = getExistingModelForEdit(potentialId); > break; > } >- } else { >- SYNC.release(); > } > } >- >+ > return result; > } > > /** > * This is similar to the getModel method, except this method does not > * create a model. This method does increment the reference count (if it >- * exists). If the model does not already exist in the cache of models, >- * null is returned. >+ * exists). If the model does not already exist in the cache of models, null >+ * is returned. > */ >- public IStructuredModel getExistingModelForEdit(IFile iFile) { >+ public IStructuredModel getExistingModelForEdit(IFile iFile) { > > Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$ > Object id = calculateId(iFile); >@@ -1138,8 +1323,8 @@ > /** > * This is similar to the getModel method, except this method does not > * create a model. This method does increment the reference count (if it >- * exists). If the model does not already exist in the cache of models, >- * null is returned. >+ * exists). If the model does not already exist in the cache of models, null >+ * is returned. > * > * @deprecated use IFile form - this one will become protected or private > */ >@@ -1147,66 +1332,74 @@ > > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > IStructuredModel result = null; >- boolean doRelease = true; >+ SharedObject sharedObject = null; > // let's see if we already have it in our cache >+ SYNC.acquire(); > try { >- SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- // if not, then we'll simply return null >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ // if not found, then we'll simply return null >+ } >+ finally { >+ SYNC.release(); > if (sharedObject != null) { >- // if shared object is in our cache, then simply increment its ref >+ // if shared object is in our cache, then simply increment its >+ // ref > // count, > // and return the object. >- SYNC.release(); >- doRelease=false; >- synchronized(sharedObject) { >+ synchronized (sharedObject) { > if (sharedObject.doWait) { > sharedObject.waitForLoadAttempt(); > } >- if (sharedObject.theSharedModel!=null) { >+ if (sharedObject.theSharedModel != null) { > _incrCount(sharedObject, EDIT); > } > result = sharedObject.theSharedModel; > } > trace("got existing model for Edit: ", id); //$NON-NLS-1$ >- trace(" incremented referenceCountForEdit ", id, sharedObject.referenceCountForEdit); //$NON-NLS-1$ >- } >- } finally { >- if (doRelease) { >- SYNC.release(); >+ trace( >+ " incremented referenceCountForEdit ", id, sharedObject.referenceCountForEdit); //$NON-NLS-1$ > } > } >- >+ > return result; > } > > /** >- * Note: users of this 'model' must still release it when finished. >- * Returns null if there's not a model corresponding to document. >+ * Note: users of this 'model' must still release it when finished. Returns >+ * null if there's not a model corresponding to document. > */ > public IStructuredModel getExistingModelForRead(IDocument document) { > IStructuredModel result = null; >- >- SYNC.acquire(); >- // create a snapshot >- Set ids = new HashSet(fManagedObjects.keySet()); >- SYNC.release(); >+ >+ Set ids; >+ SYNC.acquire(); >+ try { >+ // create a snapshot >+ ids = new HashSet(fManagedObjects.keySet()); >+ } >+ finally { >+ SYNC.release(); >+ } > for (Iterator iterator = ids.iterator(); iterator.hasNext();) { > Object potentialId = iterator.next(); >- SYNC.acquire(); >- if (fManagedObjects.containsKey(potentialId)) { >- // check to see if still valid >+ boolean containsKey; >+ SYNC.acquire(); >+ try { >+ containsKey = fManagedObjects.containsKey(potentialId); >+ } >+ finally { > SYNC.release(); >+ } >+ if (containsKey) { >+ // check to see if still valid > IStructuredModel tempResult = getExistingModel(potentialId); >- if (tempResult!=null && document == tempResult.getStructuredDocument()) { >+ if (tempResult != null && document == tempResult.getStructuredDocument()) { > result = getExistingModelForRead(potentialId); > break; > } >- } else { >- SYNC.release(); > } > } >- >+ > return result; > } > >@@ -1221,40 +1414,40 @@ > /** > * This is similar to the getModel method, except this method does not > * create a model. This method does increment the reference count (if it >- * exists). If the model does not already exist in the cache of models, >- * null is returned. >+ * exists). If the model does not already exist in the cache of models, null >+ * is returned. > * > * @deprecated use IFile form - this one will become protected or private > */ >- public IStructuredModel getExistingModelForRead(Object id) { >+ public IStructuredModel getExistingModelForRead(Object id) { > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > IStructuredModel result = null; >- boolean doRelease = true; >- // let's see if we already have it in our cache >+ SharedObject sharedObject = null; >+ SYNC.acquire(); > try { >- SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- // if not, then we'll simply return null >+ // let's see if we already have it in our cache >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ // if not found, then we'll simply return null >+ } >+ finally { >+ SYNC.release(); > if (sharedObject != null) { >- // if shared object is in our cache, then simply increment its ref >+ // if shared object is in our cache, then simply increment its >+ // ref > // count, > // and return the object. > SYNC.release(); >- doRelease=false; > >- synchronized(sharedObject) { >+ synchronized (sharedObject) { > if (sharedObject.doWait) { > sharedObject.waitForLoadAttempt(); > } >- if (sharedObject.theSharedModel!=null) { >+ if (sharedObject.theSharedModel != null) { > _incrCount(sharedObject, READ); > } > result = sharedObject.theSharedModel; > } > } >- } finally { >- if (doRelease) >- SYNC.release(); > } > return result; > } >@@ -1262,17 +1455,18 @@ > /** > * @deprecated DMW: Tom, this is "special" for links builder Assuming its > * still needed, wouldn't it be better to change to >- * getExistingModels()? -- will be removed. Its not thread >- * safe for one thread to get the Enumeration, when underlying >- * data could be changed in another thread. >+ * getExistingModels()? -- will be removed. Its not thread safe >+ * for one thread to get the Enumeration, when underlying data >+ * could be changed in another thread. > */ >- public Enumeration getExistingModelIds() { >+ public Enumeration getExistingModelIds() { > try { > SYNC.acquire(); > // create a copy >- Vector keys = new Vector( fManagedObjects.keySet() ); >+ Vector keys = new Vector(fManagedObjects.keySet()); > return keys.elements(); >- } finally { >+ } >+ finally { > SYNC.release(); > } > } >@@ -1298,24 +1492,26 @@ > /** > * One of the primary forms to get a managed model > */ >- public IStructuredModel getModelForEdit(IFile iFile) throws IOException, CoreException { >+ public IStructuredModel getModelForEdit(IFile iFile) throws IOException, CoreException { > Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$ > return _commonGetModel(iFile, EDIT, null, null); > } > >- public IStructuredModel getModelForEdit(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException { >+ public IStructuredModel getModelForEdit(IFile iFile, EncodingRule encodingRule) >+ throws UnsupportedEncodingException, IOException, CoreException { > > Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$ > return _commonGetModel(iFile, EDIT, encodingRule); > } > >- public IStructuredModel getModelForEdit(IFile iFile, String encoding, String lineDelimiter) throws java.io.UnsupportedEncodingException, IOException, CoreException { >+ public IStructuredModel getModelForEdit(IFile iFile, String encoding, String lineDelimiter) >+ throws java.io.UnsupportedEncodingException, IOException, CoreException { > > Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$ > return _commonGetModel(iFile, EDIT, encoding, lineDelimiter); > } > >- public IStructuredModel getModelForEdit(IStructuredDocument document) { >+ public IStructuredModel getModelForEdit(IStructuredDocument document) { > return _getModelFor(document, EDIT); > } > >@@ -1323,7 +1519,8 @@ > * @see IModelManager > * @deprecated use IFile or String form > */ >- public IStructuredModel getModelForEdit(Object id, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException { >+ public IStructuredModel getModelForEdit(Object id, InputStream inputStream, URIResolver resolver) >+ throws java.io.UnsupportedEncodingException, IOException { > > Assert.isNotNull(id, "IFile parameter can not be null"); //$NON-NLS-1$ > String stringId = id.toString(); >@@ -1334,14 +1531,17 @@ > * @see IModelManager > * @deprecated - use IFile or String form > */ >- public IStructuredModel getModelForEdit(Object id, Object modelType, String encodingName, String lineDelimiter, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException { >+ public IStructuredModel getModelForEdit(Object id, Object modelType, String encodingName, >+ String lineDelimiter, InputStream inputStream, URIResolver resolver) >+ throws java.io.UnsupportedEncodingException, IOException { > > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > String stringId = id.toString(); > return getModelForEdit(stringId, Utilities.getMarkSupportedStream(inputStream), resolver); > } > >- public IStructuredModel getModelForEdit(String id, InputStream inputStream, URIResolver resolver) throws IOException { >+ public IStructuredModel getModelForEdit(String id, InputStream inputStream, URIResolver resolver) >+ throws IOException { > if (id == null) { > throw new IllegalArgumentException("Program Error: id may not be null"); //$NON-NLS-1$ > } >@@ -1361,23 +1561,25 @@ > /** > * One of the primary forms to get a managed model > */ >- public IStructuredModel getModelForRead(IFile iFile) throws IOException, CoreException { >+ public IStructuredModel getModelForRead(IFile iFile) throws IOException, CoreException { > > Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$ > return _commonGetModel(iFile, READ, null, null); > } > >- public IStructuredModel getModelForRead(IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException { >+ public IStructuredModel getModelForRead(IFile iFile, EncodingRule encodingRule) >+ throws UnsupportedEncodingException, IOException, CoreException { > Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$ > return _commonGetModel(iFile, READ, encodingRule); > } > >- public IStructuredModel getModelForRead(IFile iFile, String encodingName, String lineDelimiter) throws java.io.UnsupportedEncodingException, IOException, CoreException { >+ public IStructuredModel getModelForRead(IFile iFile, String encodingName, String lineDelimiter) >+ throws java.io.UnsupportedEncodingException, IOException, CoreException { > Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$ > return _commonGetModel(iFile, READ, encodingName, lineDelimiter); > } > >- public IStructuredModel getModelForRead(IStructuredDocument document) { >+ public IStructuredModel getModelForRead(IStructuredDocument document) { > return _getModelFor(document, READ); > } > >@@ -1385,7 +1587,8 @@ > * @see IModelManager > * @deprecated use IFile or String form > */ >- public IStructuredModel getModelForRead(Object id, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException { >+ public IStructuredModel getModelForRead(Object id, InputStream inputStream, URIResolver resolver) >+ throws java.io.UnsupportedEncodingException, IOException { > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > String stringId = id.toString(); > return getModelForRead(stringId, Utilities.getMarkSupportedStream(inputStream), resolver); >@@ -1395,13 +1598,16 @@ > * @see IModelManager > * @deprecated use IFile form > */ >- public IStructuredModel getModelForRead(Object id, Object modelType, String encodingName, String lineDelimiter, InputStream inputStream, URIResolver resolver) throws java.io.UnsupportedEncodingException, IOException { >+ public IStructuredModel getModelForRead(Object id, Object modelType, String encodingName, >+ String lineDelimiter, InputStream inputStream, URIResolver resolver) >+ throws java.io.UnsupportedEncodingException, IOException { > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > String stringId = id.toString(); > return getModelForRead(stringId, Utilities.getMarkSupportedStream(inputStream), resolver); > } > >- public IStructuredModel getModelForRead(String id, InputStream inputStream, URIResolver resolver) throws IOException { >+ public IStructuredModel getModelForRead(String id, InputStream inputStream, URIResolver resolver) >+ throws IOException { > InputStream istream = Utilities.getMarkSupportedStream(inputStream); > IModelHandler handler = calculateType(id, istream); > IStructuredModel result = null; >@@ -1422,10 +1628,11 @@ > /** > * @see IModelManager#getNewModelForEdit(IFile, boolean) > */ >- public IStructuredModel getNewModelForEdit(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException { >+ public IStructuredModel getNewModelForEdit(IFile iFile, boolean force) >+ throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException { > Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$ > SharedObject sharedObject = _commonNewModel(iFile, force); >- synchronized(sharedObject) { >+ synchronized (sharedObject) { > sharedObject.referenceCountForEdit = 1; > } > sharedObject.setLoaded(); >@@ -1435,17 +1642,22 @@ > /** > * @see IModelManager#getNewModelForRead(IFile, boolean) > */ >- public IStructuredModel getNewModelForRead(IFile iFile, boolean force) throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException { >+ public IStructuredModel getNewModelForRead(IFile iFile, boolean force) >+ throws ResourceAlreadyExists, ResourceInUse, IOException, CoreException { > > Assert.isNotNull(iFile, "IFile parameter can not be null"); //$NON-NLS-1$ > SharedObject sharedObject = _commonNewModel(iFile, force); > SYNC.acquire(); >- synchronized(sharedObject) { >- if (sharedObject.theSharedModel!=null) { >- sharedObject.referenceCountForRead = 1; >+ try { >+ synchronized (sharedObject) { >+ if (sharedObject.theSharedModel != null) { >+ sharedObject.referenceCountForRead = 1; >+ } > } > } >- SYNC.release(); >+ finally { >+ SYNC.release(); >+ } > sharedObject.setLoaded(); > return sharedObject.theSharedModel; > } >@@ -1454,24 +1666,34 @@ > * This function returns the reference count of underlying model. > * > * @param id >- * Object The id of the model TODO: try to refine the design >- * not to use this function >+ * Object The id of the model TODO: try to refine the design not >+ * to use this function > */ >- public int getReferenceCount(Object id) { >+ public int getReferenceCount(Object id) { > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > int count = 0; >- >+ >+ SharedObject sharedObject = null; > SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- if (sharedObject != null) { >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { > SYNC.release(); >- sharedObject.waitForLoadAttempt(); >- SYNC.acquire(); >- synchronized (sharedObject) { >- count = sharedObject.referenceCountForRead + sharedObject.referenceCountForEdit; >+ if (sharedObject != null) { >+ sharedObject.waitForLoadAttempt(); >+ SYNC.acquire(); >+ try { >+ synchronized (sharedObject) { >+ count = sharedObject.referenceCountForRead >+ + sharedObject.referenceCountForEdit; >+ } >+ } >+ finally { >+ SYNC.release(); >+ } > } > } >- SYNC.release(); > return count; > } > >@@ -1479,22 +1701,25 @@ > * This function returns the reference count of underlying model. > * > * @param id >- * Object The id of the model TODO: try to refine the design >- * not to use this function >+ * Object The id of the model TODO: try to refine the design not >+ * to use this function > */ > public int getReferenceCountForEdit(Object id) { > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > int count = 0; >+ SharedObject sharedObject = null; > SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- if (sharedObject != null) { >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { > SYNC.release(); >- sharedObject.waitForLoadAttempt(); >- synchronized(sharedObject) { >- count = sharedObject.referenceCountForEdit; >+ if (sharedObject != null) { >+ sharedObject.waitForLoadAttempt(); >+ synchronized (sharedObject) { >+ count = sharedObject.referenceCountForEdit; >+ } > } >- } else { >- SYNC.release(); > } > return count; > } >@@ -1503,27 +1728,38 @@ > * This function returns the reference count of underlying model. > * > * @param id >- * Object The id of the model TODO: try to refine the design >- * not to use this function >+ * Object The id of the model TODO: try to refine the design not >+ * to use this function > */ > public int getReferenceCountForRead(Object id) { > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > int count = 0; >+ SharedObject sharedObject = null; > SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- if (sharedObject != null) { >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { > SYNC.release(); >- sharedObject.waitForLoadAttempt(); >- SYNC.acquire(); >- synchronized(sharedObject) { >- count = sharedObject.referenceCountForRead; >+ if (sharedObject != null) { >+ sharedObject.waitForLoadAttempt(); >+ SYNC.acquire(); >+ try { >+ synchronized (sharedObject) { >+ count = sharedObject.referenceCountForRead; >+ } >+ } >+ finally { >+ SYNC.release(); >+ } > } > } >- SYNC.release(); > return count; > } > >- private void handleConvertLineDelimiters(IStructuredDocument structuredDocument, IFile iFile, EncodingRule encodingRule, EncodingMemento encodingMemento) throws CoreException, MalformedOutputExceptionWithDetail, UnsupportedEncodingException { >+ private void handleConvertLineDelimiters(IStructuredDocument structuredDocument, IFile iFile, >+ EncodingRule encodingRule, EncodingMemento encodingMemento) throws CoreException, >+ MalformedOutputExceptionWithDetail, UnsupportedEncodingException { > if (structuredDocument.getNumberOfLines() > 1) { > convertLineDelimiters(structuredDocument, iFile); > } >@@ -1538,21 +1774,32 @@ > * This function returns true if there are other references to the > * underlying model. > */ >- public boolean isShared(Object id) { >+ public boolean isShared(Object id) { > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > int count = 0; > boolean result = false; >+ SharedObject sharedObject = null; > SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- if (sharedObject != null) { >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { > SYNC.release(); >- sharedObject.waitForLoadAttempt(); >- SYNC.acquire(); >- synchronized(sharedObject) { >- count = sharedObject.referenceCountForRead + sharedObject.referenceCountForEdit; >+ if (sharedObject != null) { >+ sharedObject.waitForLoadAttempt(); >+ SYNC.acquire(); >+ try { >+ synchronized (sharedObject) { >+ count = sharedObject.referenceCountForRead >+ + sharedObject.referenceCountForEdit; >+ } >+ } >+ finally { >+ SYNC.release(); >+ } > } > } >- SYNC.release(); >+ > result = count > 1; > return result; > } >@@ -1564,20 +1811,29 @@ > * @param id > * Object The id of the model > */ >- public boolean isSharedForEdit(Object id) { >+ public boolean isSharedForEdit(Object id) { > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > int count = 0; > boolean result = false; >+ SharedObject sharedObject = null; > SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- if (sharedObject != null) { >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { > SYNC.release(); >- sharedObject.waitForLoadAttempt(); >- synchronized(sharedObject) { >- count = sharedObject.referenceCountForEdit; >+ if (sharedObject != null) { >+ sharedObject.waitForLoadAttempt(); >+ SYNC.acquire(); >+ try { >+ synchronized (sharedObject) { >+ count = sharedObject.referenceCountForEdit; >+ } >+ } >+ finally { >+ SYNC.release(); >+ } > } >- } else { >- SYNC.release(); > } > result = count > 1; > return result; >@@ -1590,21 +1846,30 @@ > * @param id > * Object The id of the model > */ >- public boolean isSharedForRead(Object id) { >+ public boolean isSharedForRead(Object id) { > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > int count = 0; > boolean result = false; >+ SharedObject sharedObject = null; > SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- if (sharedObject != null) { >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { > SYNC.release(); >- sharedObject.waitForLoadAttempt(); >- SYNC.acquire(); >- synchronized(sharedObject) { >- count = sharedObject.referenceCountForRead; >+ if (sharedObject != null) { >+ sharedObject.waitForLoadAttempt(); >+ SYNC.acquire(); >+ try { >+ synchronized (sharedObject) { >+ count = sharedObject.referenceCountForRead; >+ } >+ } >+ finally { >+ SYNC.release(); >+ } > } > } >- SYNC.release(); > result = count > 1; > return result; > } >@@ -1626,19 +1891,26 @@ > * not to use this function > */ > public void moveModel(Object oldId, Object newId) { >- org.eclipse.wst.sse.core.internal.util.Assert.isNotNull(oldId, "id parameter can not be null"); //$NON-NLS-1$ >+ org.eclipse.wst.sse.core.internal.util.Assert.isNotNull(oldId, >+ "id parameter can not be null"); //$NON-NLS-1$ >+ SharedObject sharedObject = null; > SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(oldId); >- // if not found in cache, ignore request. >- // this would normally be a program error >- if (sharedObject != null) { >- fManagedObjects.remove(oldId); >- fManagedObjects.put(newId, sharedObject); >+ try { >+ // if not found in cache, ignore request. >+ // this would normally be a program error >+ sharedObject = (SharedObject) fManagedObjects.get(oldId); >+ if (sharedObject != null) { >+ fManagedObjects.remove(oldId); >+ fManagedObjects.put(newId, sharedObject); >+ } >+ } >+ finally { >+ SYNC.release(); > } >- SYNC.release(); > } > >- private String readInputStream(InputStream inputStream, String ianaEncodingName) throws UnsupportedEncodingException, IOException { >+ private String readInputStream(InputStream inputStream, String ianaEncodingName) >+ throws UnsupportedEncodingException, IOException { > > String allText = null; > if ((ianaEncodingName != null) && (ianaEncodingName.length() != 0)) { >@@ -1699,7 +1971,7 @@ > return model; > } > >- void releaseFromEdit(IStructuredModel structuredModel) { >+ void releaseFromEdit(IStructuredModel structuredModel) { > Object id = structuredModel.getId(); > if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) { > cleanupDiscardedModel(structuredModel); >@@ -1709,8 +1981,8 @@ > } > > } >- >- void releaseFromRead(IStructuredModel structuredModel) { >+ >+ void releaseFromRead(IStructuredModel structuredModel) { > Object id = structuredModel.getId(); > if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) { > cleanupDiscardedModel(structuredModel); >@@ -1720,11 +1992,12 @@ > } > > } >+ > /** > * default for use in same package, not subclasses > * > */ >- private void releaseFromEdit(Object id) { >+ private void releaseFromEdit(Object id) { > // ISSUE: many of these asserts should be changed to "logs" > // and continue to limp along? > >@@ -1736,24 +2009,35 @@ > // to be called on them, for now, but the model manager > // doesn't need to do anything. > if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) { >- throw new IllegalArgumentException("Ids of UNMANAGED_MODEL or DUPLICATED_MODEL are illegal here"); >+ throw new IllegalArgumentException( >+ "Ids of UNMANAGED_MODEL or DUPLICATED_MODEL are illegal here"); > } > else { > SYNC.acquire(); >- sharedObject = (SharedObject) fManagedObjects.get(id); >- SYNC.release(); >- >- Assert.isNotNull(sharedObject, "release was requested on a model that was not being managed"); //$NON-NLS-1$ >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { >+ SYNC.release(); >+ } >+ >+ Assert.isNotNull(sharedObject, >+ "release was requested on a model that was not being managed"); //$NON-NLS-1$ > sharedObject.waitForLoadAttempt(); >- >+ > SYNC.acquire(); >- synchronized(sharedObject) { >- _decrCount(sharedObject, EDIT); >- if ((sharedObject.referenceCountForRead == 0) && (sharedObject.referenceCountForEdit == 0)) { >- discardModel(id, sharedObject); >+ try { >+ synchronized (sharedObject) { >+ _decrCount(sharedObject, EDIT); >+ if ((sharedObject.referenceCountForRead == 0) >+ && (sharedObject.referenceCountForEdit == 0)) { >+ discardModel(id, sharedObject); >+ } > } > } >- SYNC.release(); >+ finally { >+ SYNC.release(); >+ } > // if edit goes to zero, but still open for read, > // then we should reload here, so we are in synch with > // contents on disk. >@@ -1762,31 +2046,35 @@ > // flag for some reason. > // we need to address * that * too. > >- synchronized(sharedObject) { >- if ((sharedObject.referenceCountForRead > 0) && (sharedObject.referenceCountForEdit == 0) && sharedObject.theSharedModel.isDirty()) { >+ synchronized (sharedObject) { >+ if ((sharedObject.referenceCountForRead > 0) >+ && (sharedObject.referenceCountForEdit == 0) >+ && sharedObject.theSharedModel.isDirty()) { > signalPreLifeCycleListenerRevert(sharedObject.theSharedModel); > revertModel(id, sharedObject); > /* > * Because model events are fired to notify about the >- * revert's changes, and listeners can still get/release >- * the model from this thread (locking prevents it being >- * done from other threads), the reference counts could >- * have changed since we entered this if block, and the >- * model could have been discarded. Check the counts again. >+ * revert's changes, and listeners can still get/release the >+ * model from this thread (locking prevents it being done >+ * from other threads), the reference counts could have >+ * changed since we entered this if block, and the model >+ * could have been discarded. Check the counts again. > */ >- if (sharedObject.referenceCountForRead > 0 && sharedObject.referenceCountForEdit == 0) { >+ if (sharedObject.referenceCountForRead > 0 >+ && sharedObject.referenceCountForEdit == 0) { > sharedObject.theSharedModel.setDirtyState(false); > } > signalPostLifeCycleListenerRevert(sharedObject.theSharedModel); > } > } >- >+ > } > } > > // private for now, though public forms have been requested, in past. > private void revertModel(Object id, SharedObject sharedObject) { >- IStructuredDocument structuredDocument = sharedObject.theSharedModel.getStructuredDocument(); >+ IStructuredDocument structuredDocument = sharedObject.theSharedModel >+ .getStructuredDocument(); > FileBufferModelManager.getInstance().revert(structuredDocument); > } > >@@ -1806,12 +2094,25 @@ > > private void discardModel(Object id, SharedObject sharedObject) { > SYNC.acquire(); >- fManagedObjects.remove(id); >- SYNC.release(); >- IStructuredDocument structuredDocument = sharedObject.theSharedModel.getStructuredDocument(); >+ try { >+ fManagedObjects.remove(id); >+ } >+ finally { >+ SYNC.release(); >+ } >+ IStructuredDocument structuredDocument = sharedObject.theSharedModel >+ .getStructuredDocument(); > > if (structuredDocument == null) { >- Platform.getLog(SSECorePlugin.getDefault().getBundle()).log(new Status(IStatus.ERROR, SSECorePlugin.ID, IStatus.ERROR, "Attempted to discard a structured model but the underlying document has already been set to null: " + sharedObject.theSharedModel.getBaseLocation(), null)); >+ Platform >+ .getLog(SSECorePlugin.getDefault().getBundle()) >+ .log( >+ new Status( >+ IStatus.ERROR, >+ SSECorePlugin.ID, >+ IStatus.ERROR, >+ "Attempted to discard a structured model but the underlying document has already been set to null: " >+ + sharedObject.theSharedModel.getBaseLocation(), null)); > } > > cleanupDiscardedModel(sharedObject.theSharedModel); >@@ -1821,21 +2122,21 @@ > IStructuredDocument structuredDocument = structuredModel.getStructuredDocument(); > /* > * This call (and setting the StructuredDocument to null) were >- * previously done within the model itself, but for concurrency it >- * must be done here during a synchronized release. >+ * previously done within the model itself, but for concurrency it must >+ * be done here during a synchronized release. > */ > structuredModel.getFactoryRegistry().release(); > > /* >- * For structured documents originating from file buffers, disconnect >- * us from the file buffer, now. >+ * For structured documents originating from file buffers, disconnect us >+ * from the file buffer, now. > */ > FileBufferModelManager.getInstance().releaseModel(structuredDocument); > > /* > * Setting the document to null is required since some subclasses of >- * model might have "cleanup" of listeners, etc., to remove, which >- * were initialized during the initial setStructuredDocument. >+ * model might have "cleanup" of listeners, etc., to remove, which were >+ * initialized during the initial setStructuredDocument. > * > * The model itself in particular may have internal listeners used to > * coordinate the document with its own "structure". >@@ -1843,46 +2144,57 @@ > structuredModel.setStructuredDocument(null); > } > >- > /** > * default for use in same package, not subclasses > * > */ >- private void releaseFromRead(Object id) { >+ private void releaseFromRead(Object id) { > Assert.isNotNull(id, "id parameter can not be null"); //$NON-NLS-1$ > SharedObject sharedObject = null; > > if (id.equals(UNMANAGED_MODEL) || id.equals(DUPLICATED_MODEL)) { >- throw new IllegalArgumentException("Ids of UNMANAGED_MODEL or DUPLICATED_MODEL are illegal here"); >+ throw new IllegalArgumentException( >+ "Ids of UNMANAGED_MODEL or DUPLICATED_MODEL are illegal here"); > } > else { > SYNC.acquire(); >- sharedObject = (SharedObject) fManagedObjects.get(id); >- SYNC.release(); >- Assert.isNotNull(sharedObject, "release was requested on a model that was not being managed"); //$NON-NLS-1$ >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { >+ SYNC.release(); >+ } >+ Assert.isNotNull(sharedObject, >+ "release was requested on a model that was not being managed"); //$NON-NLS-1$ > sharedObject.waitForLoadAttempt(); > } > SYNC.acquire(); >- synchronized(sharedObject) { >- _decrCount(sharedObject, READ); >- if ((sharedObject.referenceCountForRead == 0) && (sharedObject.referenceCountForEdit == 0)) { >- discardModel(id, sharedObject); >+ try { >+ synchronized (sharedObject) { >+ _decrCount(sharedObject, READ); >+ if ((sharedObject.referenceCountForRead == 0) >+ && (sharedObject.referenceCountForEdit == 0)) { >+ discardModel(id, sharedObject); >+ } > } > } >- SYNC.release(); >+ finally { >+ SYNC.release(); >+ } > } > > /** > * This is similar to the getModel method, except this method does not use > * the cached version, but forces the cached version to be replaced with a >- * fresh, unchanged version. Note: this method does not change any >- * reference counts. Also, if there is not already a cached version of the >- * model, then this call is essentially ignored (that is, it does not put >- * a model in the cache) and returns null. >+ * fresh, unchanged version. Note: this method does not change any reference >+ * counts. Also, if there is not already a cached version of the model, then >+ * this call is essentially ignored (that is, it does not put a model in the >+ * cache) and returns null. > * > * @deprecated - will become protected, use reload directly on model > */ >- public IStructuredModel reloadModel(Object id, java.io.InputStream inputStream) throws java.io.UnsupportedEncodingException { >+ public IStructuredModel reloadModel(Object id, java.io.InputStream inputStream) >+ throws java.io.UnsupportedEncodingException { > > // get the existing model associated with this id > IStructuredModel structuredModel = getExistingModel(id); >@@ -1903,49 +2215,58 @@ > return structuredModel; > } > >- public void saveModel(IFile iFile, String id, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException { >+ public void saveModel(IFile iFile, String id, EncodingRule encodingRule) >+ throws UnsupportedEncodingException, IOException, CoreException { > > // let's see if we already have it in our cache >- >+ SharedObject sharedObject = null; > SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- if (sharedObject == null || sharedObject.theSharedModel == null) { >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { > SYNC.release(); >+ } >+ if (sharedObject == null || sharedObject.theSharedModel == null) { > throw new IllegalStateException(SSECoreMessages.Program_Error__ModelManage_EXC_); //$NON-NLS-1$ = "Program Error: ModelManagerImpl::saveModel. Model should be in the cache" >- } >- else { >- SYNC.release(); >- sharedObject.waitForLoadAttempt(); >- >- /** >- * https://bugs.eclipse.org/bugs/show_bug.cgi?id=221610 >- * >- * Sync removed from here to prevent deadlock. Although the model >- * instance may disappear or be made invalid while the save is >- * happening, the document itself still has the contents we're >- * trying to save. Simultaneous saves should be throttled by >- * resource locking without our intervention. >- */ >- boolean saved = false; >- // if this model was based on a File Buffer and we're writing back >- // to the same location, use the buffer to do the writing >- if (FileBufferModelManager.getInstance().isExistingBuffer(sharedObject.theSharedModel.getStructuredDocument())) { >- ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(sharedObject.theSharedModel.getStructuredDocument()); >- IPath fileLocation = FileBuffers.normalizeLocation(iFile.getFullPath()); >- if (fileLocation.equals(buffer.getLocation())) { >- buffer.commit(new NullProgressMonitor(), true); >- saved = true; >- } >- } >- if (!saved) { >- IStructuredModel model = sharedObject.theSharedModel; >- IStructuredDocument document = model.getStructuredDocument(); >- saveStructuredDocument(document, iFile, encodingRule); >- trace("saving model", id); //$NON-NLS-1$ >+ } >+ >+ // Note to self: not clear if this does anything. >+ // sharedObject.theSharedModel cannot be null, so what are we waiting >+ // for? >+ sharedObject.waitForLoadAttempt(); >+ >+ /** >+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=221610 >+ * >+ * Sync removed from here to prevent deadlock. Although the model >+ * instance may disappear or be made invalid while the save is >+ * happening, the document itself still has the contents we're trying to >+ * save. Simultaneous saves should be throttled by resource locking >+ * without our intervention. >+ */ >+ boolean saved = false; >+ // if this model was based on a File Buffer and we're writing back >+ // to the same location, use the buffer to do the writing >+ if (FileBufferModelManager.getInstance().isExistingBuffer( >+ sharedObject.theSharedModel.getStructuredDocument())) { >+ ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer( >+ sharedObject.theSharedModel.getStructuredDocument()); >+ IPath fileLocation = FileBuffers.normalizeLocation(iFile.getFullPath()); >+ if (fileLocation.equals(buffer.getLocation())) { >+ buffer.commit(new NullProgressMonitor(), true); >+ saved = true; > } >- sharedObject.theSharedModel.setDirtyState(false); >- sharedObject.theSharedModel.setNewState(false); >- } >+ } >+ if (!saved) { >+ IStructuredModel model = sharedObject.theSharedModel; >+ IStructuredDocument document = model.getStructuredDocument(); >+ saveStructuredDocument(document, iFile, encodingRule); >+ trace("saving model", id); //$NON-NLS-1$ >+ } >+ sharedObject.theSharedModel.setDirtyState(false); >+ sharedObject.theSharedModel.setNewState(false); >+ > } > > /** >@@ -1958,46 +2279,55 @@ > * @throws IOException > * @throws CoreException > */ >- public void saveModel(String id, EncodingRule encodingRule) throws UnsupportedEncodingException, IOException, CoreException { >+ public void saveModel(String id, EncodingRule encodingRule) >+ throws UnsupportedEncodingException, IOException, CoreException { > > // let's see if we already have it in our cache >- >+ SharedObject sharedObject = null; > SYNC.acquire(); >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- if (sharedObject == null) { >+ try { >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { > SYNC.release(); >+ } >+ if (sharedObject == null) { > throw new IllegalStateException(SSECoreMessages.Program_Error__ModelManage_EXC_); //$NON-NLS-1$ = "Program Error: ModelManagerImpl::saveModel. Model should be in the cache" > } >+ >+ // Note to self: not clear if this does anything. >+ // sharedObject.theSharedModel cannot be null, so what are we waiting >+ // for? >+ sharedObject.waitForLoadAttempt(); >+ /** >+ * https://bugs.eclipse.org/bugs/show_bug.cgi?id=221610 >+ * >+ * Sync removed from here to prevent deadlock. Although the model >+ * instance may disappear or be made invalid while the save is >+ * happening, the document itself still has the contents we're trying to >+ * save. Simultaneous saves should be throttled by resource locking >+ * without our intervention. >+ */ >+ /* >+ * if this model was based on a File Buffer and we're writing back to >+ * the same location, use the buffer to do the writing >+ */ >+ if (FileBufferModelManager.getInstance().isExistingBuffer( >+ sharedObject.theSharedModel.getStructuredDocument())) { >+ ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer( >+ sharedObject.theSharedModel.getStructuredDocument()); >+ buffer.commit(new NullProgressMonitor(), true); >+ } > else { >- SYNC.release(); >- sharedObject.waitForLoadAttempt(); >- /** >- * https://bugs.eclipse.org/bugs/show_bug.cgi?id=221610 >- * >- * Sync removed from here to prevent deadlock. Although the model >- * instance may disappear or be made invalid while the save is >- * happening, the document itself still has the contents we're >- * trying to save. Simultaneous saves should be throttled by >- * resource locking without our intervention. >- */ >- /* >- * if this model was based on a File Buffer and we're writing back >- * to the same location, use the buffer to do the writing >- */ >- if (FileBufferModelManager.getInstance().isExistingBuffer(sharedObject.theSharedModel.getStructuredDocument())) { >- ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(sharedObject.theSharedModel.getStructuredDocument()); >- buffer.commit(new NullProgressMonitor(), true); >- } >- else { >- IFile iFile = getFileFor(sharedObject.theSharedModel); >- IStructuredModel model = sharedObject.theSharedModel; >- IStructuredDocument document = model.getStructuredDocument(); >- saveStructuredDocument(document, iFile); >- trace("saving model", id); //$NON-NLS-1$ >- } >- sharedObject.theSharedModel.setDirtyState(false); >- sharedObject.theSharedModel.setNewState(false); >+ IFile iFile = getFileFor(sharedObject.theSharedModel); >+ IStructuredModel model = sharedObject.theSharedModel; >+ IStructuredDocument document = model.getStructuredDocument(); >+ saveStructuredDocument(document, iFile); >+ trace("saving model", id); //$NON-NLS-1$ > } >+ sharedObject.theSharedModel.setDirtyState(false); >+ sharedObject.theSharedModel.setNewState(false); >+ > } > > /** >@@ -2005,39 +2335,52 @@ > * requires an extra "copy" of byte array, and should be avoid > * in favor of the IFile form. > */ >- public void saveModel(String id, OutputStream outputStream, EncodingRule encodingRule) throws UnsupportedEncodingException, CoreException, IOException { >+ public void saveModel(String id, OutputStream outputStream, EncodingRule encodingRule) >+ throws UnsupportedEncodingException, CoreException, IOException { >+ SharedObject sharedObject = null; > SYNC.acquire(); >- // let's see if we already have it in our cache >- SharedObject sharedObject = (SharedObject) fManagedObjects.get(id); >- if (sharedObject == null) { >+ try { >+ // let's see if we already have it in our cache >+ sharedObject = (SharedObject) fManagedObjects.get(id); >+ } >+ finally { > SYNC.release(); >+ } >+ if (sharedObject == null) { >+ > throw new IllegalStateException(SSECoreMessages.Program_Error__ModelManage_EXC_); //$NON-NLS-1$ = "Program Error: ModelManagerImpl::saveModel. Model should be in the cache" > } >- else { >- SYNC.release(); >- sharedObject.waitForLoadAttempt(); >- synchronized(sharedObject) { >- CodedStreamCreator codedStreamCreator = new CodedStreamCreator(); >- codedStreamCreator.set(sharedObject.theSharedModel.getId(), new DocumentReader(sharedObject.theSharedModel.getStructuredDocument())); >- codedStreamCreator.setPreviousEncodingMemento(sharedObject.theSharedModel.getStructuredDocument().getEncodingMemento()); >- ByteArrayOutputStream byteArrayOutputStream = codedStreamCreator.getCodedByteArrayOutputStream(encodingRule); >- byte[] outputBytes = byteArrayOutputStream.toByteArray(); >- outputStream.write(outputBytes); >- trace("saving model", id); //$NON-NLS-1$ >- sharedObject.theSharedModel.setDirtyState(false); >- sharedObject.theSharedModel.setNewState(false); >- } >+ sharedObject.waitForLoadAttempt(); >+ synchronized (sharedObject) { >+ CodedStreamCreator codedStreamCreator = new CodedStreamCreator(); >+ codedStreamCreator.set(sharedObject.theSharedModel.getId(), new DocumentReader( >+ sharedObject.theSharedModel.getStructuredDocument())); >+ codedStreamCreator.setPreviousEncodingMemento(sharedObject.theSharedModel >+ .getStructuredDocument().getEncodingMemento()); >+ ByteArrayOutputStream byteArrayOutputStream = codedStreamCreator >+ .getCodedByteArrayOutputStream(encodingRule); >+ byte[] outputBytes = byteArrayOutputStream.toByteArray(); >+ outputStream.write(outputBytes); >+ trace("saving model", id); //$NON-NLS-1$ >+ sharedObject.theSharedModel.setDirtyState(false); >+ sharedObject.theSharedModel.setNewState(false); > } >+ > } > >- public void saveStructuredDocument(IStructuredDocument structuredDocument, IFile iFile) throws UnsupportedEncodingException, CoreException, IOException { >+ public void saveStructuredDocument(IStructuredDocument structuredDocument, IFile iFile) >+ throws UnsupportedEncodingException, CoreException, IOException { > saveStructuredDocument(structuredDocument, iFile, EncodingRule.CONTENT_BASED); > } > >- public void saveStructuredDocument(IStructuredDocument structuredDocument, IFile iFile, EncodingRule encodingRule) throws UnsupportedEncodingException, CoreException, IOException { >+ public void saveStructuredDocument(IStructuredDocument structuredDocument, IFile iFile, >+ EncodingRule encodingRule) throws UnsupportedEncodingException, CoreException, >+ IOException { > if (FileBufferModelManager.getInstance().isExistingBuffer(structuredDocument)) { >- ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer(structuredDocument); >- if (buffer.getLocation().equals(iFile.getFullPath()) || buffer.getLocation().equals(iFile.getLocation())) { >+ ITextFileBuffer buffer = FileBufferModelManager.getInstance().getBuffer( >+ structuredDocument); >+ if (buffer.getLocation().equals(iFile.getFullPath()) >+ || buffer.getLocation().equals(iFile.getLocation())) { > buffer.commit(new NullProgressMonitor(), true); > } > } >@@ -2059,7 +2402,8 @@ > // before writing to output stream. > handleConvertLineDelimiters(structuredDocument, iFile, encodingRule, encodingMemento); > >- ByteArrayOutputStream codedByteStream = codedStreamCreator.getCodedByteArrayOutputStream(encodingRule); >+ ByteArrayOutputStream codedByteStream = codedStreamCreator >+ .getCodedByteArrayOutputStream(encodingRule); > InputStream codedStream = new ByteArrayInputStream(codedByteStream.toByteArray()); > if (iFile.exists()) > iFile.setContents(codedStream, true, true, null); >@@ -2088,14 +2432,99 @@ > } > } > >- boolean isIdInUse(String newId) { >- boolean inUse = false; >- SYNC.acquire(); >- SharedObject object =(SharedObject) fManagedObjects.get(newId); >- if (object!=null) { >- inUse = object.theSharedModel!=null; >- } >+ boolean isIdInUse(String newId) { >+ SharedObject object = null; >+ SYNC.acquire(); >+ try { >+ object = (SharedObject) fManagedObjects.get(newId); >+ } >+ finally { > SYNC.release(); >- return inUse; > } >+ return object != null ? object.theSharedModel != null : false; >+ } >+ >+ private static String getProperty(String property) { >+ // Preference overrides system property overrides env-var >+ >+ IPreferencesService preferencesService = Platform.getPreferencesService(); >+ IScopeContext[] lookupOrder = new IScopeContext[] { >+ new InstanceScope(), new ConfigurationScope() >+ }; >+ String key = property; >+ if (property != null && property.startsWith(SSECorePlugin.ID)) { >+ // +1, include the "." >+ key = property.substring(SSECorePlugin.ID.length() + 1, property.length()); >+ } >+ String value = preferencesService.getString(SSECorePlugin.ID, key, null, lookupOrder); >+ if (value == null) { >+ value = System.getProperty(property); >+ } >+ if (value == null) { >+ value = System.getenv(property); >+ } >+ return value; >+ } >+ >+ private static String getDefault(String property) { >+ // this is the "default-default" >+ if ("org.eclipse.wst.sse.core.modelmanager.maxWaitDuringConcurrentLoad".equals(property)) { >+ return "0"; >+ } >+ else if ("org.eclipse.wst.sse.core.modelmanager.allowInterruptsDuringConcurrentLoad" >+ .equals(property)) { >+ return "false"; >+ } >+ return null; >+ } >+ >+ private static boolean getBoolean(String key) { >+ String property = getProperty(key); >+ // if (property != null) { >+ // System.out.println("Tweak: " + key + "=" + Boolean.parseBoolean(property)); //$NON-NLS-1$ //$NON-NLS-2$ >+ // } >+ return property != null ? Boolean.parseBoolean(property) : Boolean >+ .parseBoolean(getDefault(key)); >+ } >+ >+ private static int getInt(String key) { >+ String property = getProperty(key); >+ int size = 0; >+ if (property != null) { >+ try { >+ size = Integer.parseInt(property); >+ // System.out.println("Tweak: " + key + "=" + size); //$NON-NLS-1$ //$NON-NLS-2$ >+ } >+ catch (NumberFormatException e) { >+ size = getDefaultInt(key, property, size); >+ } >+ } >+ else { >+ size = getDefaultInt(key, property, size); >+ } >+ return size; >+ } >+ >+ private static int getDefaultInt(String key, String property, int size) { >+ // ignored >+ try { >+ size = Integer.parseInt(getDefault(key)); >+ } >+ catch (NumberFormatException e1) { >+ handleIntParseException(key, property, e1); >+ size = 0; >+ } >+ return size; >+ } >+ >+ private static void handleIntParseException(String key, String property, >+ NumberFormatException e1) { >+ Exception n = new Exception( >+ NLS >+ .bind( >+ "Exception during parse of default value for key ''{0}'' value was ''{1}''. Using 0 instead", //$NON-NLS-1$ >+ key, property), e1); >+ n.printStackTrace(); >+ } >+ > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 287096
:
144990
|
145676
| 145681 |
145821
|
145825
|
145829
|
146449
|
147495
|
147502
|
166062
|
166063