[297881] [editor] StructuredRegionProcessor issues with shared structured model
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredRegionProcessor.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredRegionProcessor.java
index b97de6d..7861f66 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredRegionProcessor.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/reconcile/StructuredRegionProcessor.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2009 IBM Corporation and others.
+ * Copyright (c) 2001, 2010 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -62,17 +62,32 @@
 		 * @see org.eclipse.wst.sse.core.internal.provisional.IModelLifecycleListener#processPreModelEvent(org.eclipse.wst.sse.core.internal.model.ModelLifecycleEvent)
 		 */
 		public void processPreModelEvent(ModelLifecycleEvent event) {
-			if (event.getType() == ModelLifecycleEvent.MODEL_DOCUMENT_CHANGED && event.getModel() == fCurrentModel) {
-				changing = event.getModel();
-				flushDirtyRegionQueue();
-				// note: old annotations are removed via the strategies on
-				// AbstractStructuredTextReconcilingStrategy#setDocument(...)
+			if(fCurrentDoc != null) {
+				IStructuredModel model = null;
+				try {
+					model = getStructuredModelForRead(fCurrentDoc);
+					if (event.getType() == ModelLifecycleEvent.MODEL_DOCUMENT_CHANGED && event.getModel() == model) {
+						changing = event.getModel();
+						flushDirtyRegionQueue();
+						// note: old annotations are removed via the strategies on
+						// AbstractStructuredTextReconcilingStrategy#setDocument(...)
+					}
+				} finally {
+					if(model != null) {
+						model.releaseFromRead();
+					}
+				}
 			}
 		}
 	}
 
+	/**
+	 * The life cycle listener used to listen to the current documents model even though
+	 * this class does not hold onto a reference to the model.
+	 */
 	private IModelLifecycleListener fLifeCycleListener = new ModelLifecycleListener();
-	IStructuredModel fCurrentModel = null;
+	/** Used to get the current model on demand so a model does not need to be held by permanently */
+	private IDocument fCurrentDoc = null;
 
 	/*
 	 * (non-Javadoc)
@@ -83,26 +98,33 @@
 	protected DirtyRegion getOuterRegion(DirtyRegion root, DirtyRegion possible) {
 		// first try simple region check if one region contains the other
 		DirtyRegion outer = super.getOuterRegion(root, possible);
-		if (outer == null) {
-			// now compare nodes
-			IStructuredModel sModel = fCurrentModel;
-
-			if (sModel != null) {
-				IndexedRegion rootRegion = sModel.getIndexedRegion(root.getOffset());
-				IndexedRegion possRegion = sModel.getIndexedRegion(possible.getOffset());
-				if (rootRegion != null && possRegion != null) {
-					int rootStart = rootRegion.getStartOffset();
-					int possStart = possRegion.getStartOffset();
-					// first just check if rootregion starts before
-					// possregion
-					if (rootStart <= possStart) {
-						// check if possregion is inside rootregion
-						outer = _getOuterRegion(root, possible, sModel, rootStart, possStart);
+		if (outer == null && fCurrentDoc != null) {
+			IStructuredModel sModel = null;
+			try {
+				sModel = getStructuredModelForRead(fCurrentDoc);
+				if (sModel != null) {
+					// now compare nodes
+					IndexedRegion rootRegion = sModel.getIndexedRegion(root.getOffset());
+					IndexedRegion possRegion = sModel.getIndexedRegion(possible.getOffset());
+					if (rootRegion != null && possRegion != null) {
+						int rootStart = rootRegion.getStartOffset();
+						int possStart = possRegion.getStartOffset();
+						// first just check if rootregion starts before
+						// possregion
+						if (rootStart <= possStart) {
+							// check if possregion is inside rootregion
+							outer = _getOuterRegion(root, possible, sModel, rootStart, possStart);
+						}
+						else {
+							// otherwise if rootregion is inside possregion
+							outer = _getOuterRegion(possible, root, sModel, possStart, rootStart);
+						}
 					}
-					else {
-						// otherwise if rootregion is inside possregion
-						outer = _getOuterRegion(possible, root, sModel, possStart, rootStart);
-					}
+				}
+				
+			} finally {
+				if(sModel != null) {
+					sModel.releaseFromRead();
 				}
 			}
 		}
@@ -175,7 +197,7 @@
 		String contentTypeId = null;
 		IStructuredModel sModel = null;
 		try {
-			sModel = StructuredModelManager.getModelManager().getExistingModelForRead(doc);
+			sModel = getStructuredModelForRead(doc);
 			if (sModel != null) {
 				contentTypeId = sModel.getContentTypeIdentifier();
 			}
@@ -204,23 +226,35 @@
 		if (!isInstalled() || isInRewriteSession() || dirtyRegion == null || getDocument() == null)
 			return;
 
-		// use structured model to determine area to process
-		IStructuredModel sModel = fCurrentModel;
-		if (sModel != null) {
-			int start = dirtyRegion.getOffset();
-			int end = start + dirtyRegion.getLength();
-			IndexedRegion irStart = sModel.getIndexedRegion(start);
-			IndexedRegion irEnd = sModel.getIndexedRegion(end);
+		// unhook old lifecycle listener
+		if(fCurrentDoc != null) {
+			IStructuredModel sModel = null;
+			try {
+				sModel = getStructuredModelForRead(fCurrentDoc);
+				
+				// use structured model to determine area to process
+				if (sModel != null) {
+					int start = dirtyRegion.getOffset();
+					int end = start + dirtyRegion.getLength();
+					IndexedRegion irStart = sModel.getIndexedRegion(start);
+					IndexedRegion irEnd = sModel.getIndexedRegion(end);
 
-			if (irStart != null) {
-				start = Math.min(start, irStart.getStartOffset());
+					if (irStart != null) {
+						start = Math.min(start, irStart.getStartOffset());
+					}
+					if (irEnd != null) {
+						end = Math.max(end, irEnd.getEndOffset());
+					}
+					super.process(createDirtyRegion(start, end - start, DirtyRegion.INSERT));
+				} else {
+					super.process(dirtyRegion);
+				}
+			} finally {
+				if(sModel != null) {
+					sModel.releaseFromRead();
+				}
 			}
-			if (irEnd != null) {
-				end = Math.max(end, irEnd.getEndOffset());
-			}
-			super.process(createDirtyRegion(start, end - start, DirtyRegion.INSERT));
-		}
-		else {
+		} else {
 			super.process(dirtyRegion);
 		}
 	}
@@ -236,20 +270,37 @@
 
 	public void setDocument(IDocument newDocument) {
 		// unhook old lifecycle listener
-		if (fCurrentModel != null)
-			fCurrentModel.removeModelLifecycleListener(fLifeCycleListener);
-
-		if (fCurrentModel != null) {
-			fCurrentModel.releaseFromRead();
-			fCurrentModel = null;
-		}
-		super.setDocument(newDocument);
-		if (newDocument != null) {
-			fCurrentModel = getStructuredModelForRead(newDocument);
+		if(fCurrentDoc != null) {
+			IStructuredModel oldModel = null;
+			try {
+				oldModel = getStructuredModelForRead(fCurrentDoc);
+				if(oldModel != null) {
+					oldModel.removeModelLifecycleListener(fLifeCycleListener);
+				}
+			} finally {
+				if(oldModel != null) {
+					oldModel.releaseFromRead();
+				}
+			}
 		}
 		
+		//set the new document
+		super.setDocument(newDocument);
+		fCurrentDoc = newDocument;
+		
 		// add new lifecycle listener
-		if (fCurrentModel != null)
-			fCurrentModel.addModelLifecycleListener(fLifeCycleListener);
+		if (newDocument != null) {
+			IStructuredModel newModel = null;
+			try {
+				newModel = getStructuredModelForRead(newDocument);
+				if(newModel != null) {
+					newModel.addModelLifecycleListener(fLifeCycleListener);
+				}
+			} finally {
+				if(newModel != null) {
+					newModel.releaseFromRead();
+				}
+			}
+		}
 	}
 }