[290059] StructuredTextEditor validates file buffer changes to documents
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/FileBufferModelManager.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/FileBufferModelManager.java
index f0a5b2e..dc0db24 100644
--- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/FileBufferModelManager.java
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/FileBufferModelManager.java
@@ -33,7 +33,6 @@
 import org.eclipse.core.resources.IFolder;
 import org.eclipse.core.resources.IProject;
 import org.eclipse.core.resources.IResource;
-import org.eclipse.core.resources.IWorkspace;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.CoreException;
 import org.eclipse.core.runtime.IPath;
@@ -44,11 +43,9 @@
 import org.eclipse.core.runtime.content.IContentDescription;
 import org.eclipse.core.runtime.content.IContentType;
 import org.eclipse.core.runtime.content.IContentTypeManager;
-import org.eclipse.jface.text.DocumentEvent;
 import org.eclipse.jface.text.IDocument;
 import org.eclipse.wst.common.uriresolver.internal.provisional.URIResolverPlugin;
 import org.eclipse.wst.common.uriresolver.internal.util.URIHelper;
-import org.eclipse.wst.sse.core.internal.document.IDocumentStateValidationListener;
 import org.eclipse.wst.sse.core.internal.ltk.modelhandler.IModelHandler;
 import org.eclipse.wst.sse.core.internal.model.AbstractStructuredModel;
 import org.eclipse.wst.sse.core.internal.modelhandler.ModelHandlerRegistry;
@@ -56,7 +53,6 @@
 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
 import org.eclipse.wst.sse.core.internal.provisional.exceptions.ResourceInUse;
 import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
-import org.eclipse.wst.sse.core.internal.text.BasicStructuredDocument;
 import org.eclipse.wst.sse.core.internal.util.URIResolver;
 
 /**
@@ -86,8 +82,6 @@
 		 */
 		IStructuredModel model = null;
 
-		IDocumentStateValidationListener listener = null;
-
 		/**
 		 * Whether FileBufferModelManager called connect() for this
 		 * DocumentInfo's text filebuffer
@@ -262,41 +256,16 @@
 		public void bufferCreated(IFileBuffer buffer) {
 			if (buffer instanceof ITextFileBuffer) {
 				ITextFileBuffer textBuffer = (ITextFileBuffer) buffer;
-				IDocument document = textBuffer.getDocument();
-				if (!(document instanceof IStructuredDocument))
+				if (!(textBuffer.getDocument() instanceof IStructuredDocument))
 					return;
 
 				if (Logger.DEBUG_TEXTBUFFERLIFECYCLE) {
 					Logger.log(Logger.INFO, "Learned new buffer: " + buffer.getLocation().toString() + " " + buffer + " " + ((ITextFileBuffer) buffer).getDocument()); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
 				}
-				final DocumentInfo info = new DocumentInfo();
+				DocumentInfo info = new DocumentInfo();
 				info.buffer = textBuffer;
 				info.contentTypeID = detectContentType(buffer.getLocation()).getId();
 				info.bufferReferenceCount++;
-
-				/*
-				 * Adds a document state validation listener to the document.
-				 * The file buffer validates its state and returns the result
-				 */
-				if (document instanceof BasicStructuredDocument) {
-					BasicStructuredDocument structuredDocument = (BasicStructuredDocument) document;
-					info.listener = new IDocumentStateValidationListener() {
-
-						public boolean validateDocumentState(DocumentEvent event) {
-							boolean validated = false;
-							try {
-								info.buffer.validateState(null, IWorkspace.VALIDATE_PROMPT);
-								if (info.buffer.isStateValidated() && info.buffer.getStatus().isOK())
-									validated = true;
-							} catch (CoreException e) {
-								Logger.logException(e);
-							}
-							return validated;
-						}
-
-					};
-					structuredDocument.setDocumentStateValidationListener(info.listener);
-				}
 				fDocumentMap.put(textBuffer.getDocument(), info);
 			}
 		}
@@ -338,18 +307,6 @@
 						info.model.resetSynchronizationStamp(workspaceFile);
 					}
 				}
-
-				/*
-				 * Adds or removes the listener from the document based on the
-				 * dirty state of the buffer
-				 */
-				if (info != null && info.listener != null && textBuffer.getDocument() instanceof BasicStructuredDocument) {
-					BasicStructuredDocument document = (BasicStructuredDocument) textBuffer.getDocument();
-					if (isDirty)
-						document.setDocumentStateValidationListener(null);
-					else
-						document.setDocumentStateValidationListener(info.listener);
-				}
 			}
 		}
 
@@ -800,11 +757,8 @@
 	 * references
 	 */
 	private void checkReferenceCounts(DocumentInfo info, IDocument document) {
-		if (info.bufferReferenceCount == 0 && info.modelReferenceCount == 0) {
+		if (info.bufferReferenceCount == 0 && info.modelReferenceCount == 0)
 			fDocumentMap.remove(document);
-			if (document instanceof BasicStructuredDocument)
-				((BasicStructuredDocument) document).setDocumentStateValidationListener(null);
-		}
 	}
 
 	public boolean isExistingBuffer(IDocument document) {
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/IDocumentStateValidationListener.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/IDocumentStateValidationListener.java
deleted file mode 100644
index e5f202d..0000000
--- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/document/IDocumentStateValidationListener.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.eclipse.wst.sse.core.internal.document;
-
-import org.eclipse.jface.text.DocumentEvent;
-
-/**
- * Listener for document events that should have the document's state
- * validated first.
- */
-public interface IDocumentStateValidationListener {
-
-	/**
-	 * Validates the document's state.
-	 * @param event the document event that triggered document state validation
-	 * @return true if the document is in a state valid of being edited; false otherwise.
-	 */
-	public boolean validateDocumentState(DocumentEvent event);
-}
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NoChangeEvent.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NoChangeEvent.java
index 86c30f0..d5004bc 100644
--- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NoChangeEvent.java
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/provisional/events/NoChangeEvent.java
@@ -46,11 +46,6 @@
 	 * changed, not the content itself.
 	 */
 	public final static int READ_ONLY_STATE_CHANGE = 4;
-	/**
-	 * INVALID_STATE means that the changes were not made to the document due to
-	 * the document being in a state that prevents editing
-	 */
-	public final static int INVALID_STATE = 16;
 
 	/**
 	 * set to one of the above detailed reasons for why no change was done.
diff --git a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java
index 0a1c230..8ba87a5 100644
--- a/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java
+++ b/bundles/org.eclipse.wst.sse.core/src/org/eclipse/wst/sse/core/internal/text/BasicStructuredDocument.java
@@ -57,7 +57,6 @@
 import org.eclipse.jface.text.Position;
 import org.eclipse.jface.text.TypedRegion;
 import org.eclipse.wst.sse.core.internal.Logger;
-import org.eclipse.wst.sse.core.internal.document.IDocumentStateValidationListener;
 import org.eclipse.wst.sse.core.internal.document.StructuredDocumentFactory;
 import org.eclipse.wst.sse.core.internal.encoding.EncodingMemento;
 import org.eclipse.wst.sse.core.internal.ltk.parser.RegionParser;
@@ -290,9 +289,6 @@
 
 	private List fDocumentRewriteSessionListeners;
 
-	private IDocumentStateValidationListener fDocumentStateValidationListener;
-	private byte[] stateListenerLock = new byte[0];
-
 	private ILineTracker fTracker;
 	private IStructuredTextUndoManager fUndoManager;
 	private IStructuredDocumentRegion lastDocumentRegion;
@@ -1909,38 +1905,31 @@
 		try {
 			// Note: event must be computed before 'fire' method called
 			fDocumentEvent = new DocumentEvent(this, start, replacementLength, changes);
-			if (!fireDocumentStateValidation()) {
-				NoChangeEvent noChangeEvent = new NoChangeEvent(this, requester, changes, start, replacementLength);
-				noChangeEvent.reason = NoChangeEvent.INVALID_STATE;
-				result = noChangeEvent;
+			fireDocumentAboutToChanged();
+
+			try {
+				acquireLock();
+
+				if (!ignoreReadOnlySettings && (containsReadOnly(start, replacementLength))) {
+					NoChangeEvent noChangeEvent = new NoChangeEvent(this, requester, changes, start, replacementLength);
+					noChangeEvent.reason = NoChangeEvent.READ_ONLY_STATE_CHANGE;
+					result = noChangeEvent;
+				}
+				else {
+					result = updateModel(requester, start, replacementLength, changes);
+				}
 			}
-			else {
-				fireDocumentAboutToChanged();
-	
-				try {
-					acquireLock();
-	
-					if (!ignoreReadOnlySettings && (containsReadOnly(start, replacementLength))) {
-						NoChangeEvent noChangeEvent = new NoChangeEvent(this, requester, changes, start, replacementLength);
-						noChangeEvent.reason = NoChangeEvent.READ_ONLY_STATE_CHANGE;
-						result = noChangeEvent;
-					}
-					else {
-						result = updateModel(requester, start, replacementLength, changes);
-					}
-				}
-				finally {
-					releaseLock();
-				}
-	
-	
-				if (Debug.perfTestRawStructuredDocumentOnly || Debug.perfTest) {
-					long stopStreamTime = System.currentTimeMillis();
-					System.out.println("\n\t\t\t\t Time for IStructuredDocument raw replaceText: " + (stopStreamTime - startStreamTime)); //$NON-NLS-1$
-				}
-				if (Debug.debugStructuredDocument) {
-					System.out.println("event type returned by replaceTextWithNoDebuggingThread: " + result); //$NON-NLS-1$
-				}
+			finally {
+				releaseLock();
+			}
+
+
+			if (Debug.perfTestRawStructuredDocumentOnly || Debug.perfTest) {
+				long stopStreamTime = System.currentTimeMillis();
+				System.out.println("\n\t\t\t\t Time for IStructuredDocument raw replaceText: " + (stopStreamTime - startStreamTime)); //$NON-NLS-1$
+			}
+			if (Debug.debugStructuredDocument) {
+				System.out.println("event type returned by replaceTextWithNoDebuggingThread: " + result); //$NON-NLS-1$
 			}
 		}
 		finally {
@@ -1987,8 +1976,7 @@
 						}
 						else {
 							if (result instanceof NoChangeEvent) {
-								if (((NoChangeEvent) result).reason != NoChangeEvent.INVALID_STATE)
-									fireStructuredDocumentEvent((NoChangeEvent) result);
+								fireStructuredDocumentEvent((NoChangeEvent) result);
 							}
 							else {
 								// if here, this means a new event was created
@@ -2974,28 +2962,4 @@
 			l.documentRewriteSessionChanged(event);
 		}
 	}
-
-	/**
-	 * Fires document state check events. If the state is validated as editable,
-	 * returns true.
-	 * @return true if the document has been validated as editable
-	 */
-	private boolean fireDocumentStateValidation() {
-		boolean stateValidated = true;
-		synchronized (stateListenerLock) {
-			if (fDocumentStateValidationListener != null)
-				stateValidated = fDocumentStateValidationListener.validateDocumentState(fDocumentEvent);
-		}
-		return stateValidated;
-	}
-
-	/**
-	 * Sets the document state validation listener for the document
-	 * @param listener the state validation listener that should be notified before document edits 
-	 */
-	public void setDocumentStateValidationListener(IDocumentStateValidationListener listener) {
-		synchronized (stateListenerLock) {
-			fDocumentStateValidationListener = listener;
-		}
-	}
 }
diff --git a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/extension/DropActionProxy.java b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/extension/DropActionProxy.java
index d58ab8f..104f49a 100644
--- a/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/extension/DropActionProxy.java
+++ b/bundles/org.eclipse.wst.sse.ui/src/org/eclipse/wst/sse/ui/internal/extension/DropActionProxy.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -22,6 +22,8 @@
 
 import org.eclipse.jface.action.IAction;
 import org.eclipse.jface.text.IDocument;
+import org.eclipse.ui.texteditor.ITextEditor;
+import org.eclipse.ui.texteditor.ITextEditorExtension2;
 import org.eclipse.wst.sse.core.StructuredModelManager;
 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
 import org.eclipse.wst.sse.core.internal.undo.IStructuredTextUndoManager;
@@ -122,17 +124,8 @@
 					editor = (IExtendedSimpleEditor) args[1];
 				}
 				beginRecording();
-				if ((editor != null) && !(obj instanceof ISelfValidateEditAction)) {
-					
-					// TODO: cleanup validateEdit
-					// just leaving this check and following code here for transition. 
-					// I assume we'll remove all need for 'validateEdit'
-					// or move to platform editor's validateState 
-					
-//					IStatus status = editor.validateEdit(getDisplay().getActiveShell());
-//					if (!status.isOK()) {
-//						return null;
-//					}
+				if ((args[1] instanceof ITextEditor) && !(obj instanceof ISelfValidateEditAction) && !isEditable((ITextEditor) args[1])) {
+					return Boolean.FALSE;
 				}
 			}
 			result = m.invoke(obj, args);
@@ -147,4 +140,10 @@
 		}
 		return result;
 	}
+
+	private boolean isEditable(ITextEditor editor) {
+		if (editor instanceof ITextEditorExtension2)
+			return ((ITextEditorExtension2) editor).validateEditorInputState();
+		return editor.isEditable();
+	}
 }
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java
index 11a4dd6..bc64eb0 100644
--- a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/TreeContentHelper.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004-2006 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 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
@@ -17,8 +17,13 @@
 import java.util.List;
 import java.util.Vector;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
 import org.eclipse.ui.PlatformUI;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
 import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMWriter;
 import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
 import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
@@ -265,6 +270,34 @@
 	 * 
 	 */
 	public void setNodeValue(Node node, String value) {
+		setNodeValue(node, value, null);
+	}
+
+	/**
+	 * Checks that the resource backing the model is writeable utilizing <code>validateEdit</code>
+	 * on a given <tt>IWorkspace</tt>.
+	 * 
+	 * @param model the model to be checked
+	 * @param context the shell context for which <code>validateEdit</code> will be run
+	 * @return boolean result of checking <code>validateEdit</code>. If the resource is unwriteable, <code>status.isOK()</code>
+	 * will return true; otherwise, false.
+	 */
+	private boolean validateEdit(IStructuredModel model, Shell context) {
+		if (model != null && model.getBaseLocation() != null) {
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(model.getBaseLocation()));
+			return !file.isAccessible() || ResourcesPlugin.getWorkspace().validateEdit(new IFile[] {file}, context).isOK();
+		}
+		return false;
+	}
+
+	/**
+	 * 
+	 */
+	public void setNodeValue(Node node, String value, Shell context) {
+		// Model should not be edited because base location is read-only
+		if (node instanceof IDOMNode && !validateEdit(((IDOMNode) node).getModel(), context)) {
+			return;
+		}
 		int nodeType = node.getNodeType();
 		try {
 			switch (nodeType) {
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java
index 00694e7..c712681 100644
--- a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTableTreeViewer.java
@@ -385,7 +385,7 @@
 			String oldValue = treeContentHelper.getNodeValue((Node) item.getData());
 			String newValue = value.toString();
 			if ((newValue != null) && !newValue.equals(oldValue)) {
-				treeContentHelper.setNodeValue((Node) item.getData(), value.toString());
+				treeContentHelper.setNodeValue((Node) item.getData(), value.toString(), getControl().getShell());
 			}
 		}
 
diff --git a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java
index dfcfc5a..b8601f8 100644
--- a/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java
+++ b/bundles/org.eclipse.wst.xml.ui/src-multipage/org/eclipse/wst/xml/ui/internal/tabletree/XMLTreeExtension.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2004, 2008 IBM Corporation and others.
+ * Copyright (c) 2004, 2009 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
@@ -28,6 +28,10 @@
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
 
+/**
+ * 
+ * @deprecated No longer used
+ */
 public class XMLTreeExtension extends TreeExtension {
 
 	public final static String STRUCTURE_PROPERTY = XMLEditorMessages.XMLTreeExtension_0;
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AbstractNodeActionManager.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AbstractNodeActionManager.java
index d2cb515..be7e202 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AbstractNodeActionManager.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/AbstractNodeActionManager.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2008 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -157,14 +157,16 @@
 
 
 		public void run() {
-			beginNodeAction(this);
-			if (cmnode != null) {
-				addNodeForCMNode();
+			if (validateEdit(getModel(), getWorkbenchWindowShell())) {
+				beginNodeAction(this);
+				if (cmnode != null) {
+					addNodeForCMNode();
+				}
+				else {
+					addNodeForNodeType();
+				}
+				endNodeAction(this);
 			}
-			else {
-				addNodeForNodeType();
-			}
-			endNodeAction(this);
 		}
 	}
 
@@ -191,27 +193,29 @@
 		}
 
 		public void run() {
-			beginNodeAction(this);
-
-			for (Iterator i = list.iterator(); i.hasNext();) {
-				Node node = (Node) i.next();
-				if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
-					Attr attr = (Attr) node;
-					attr.getOwnerElement().removeAttributeNode(attr);
-				}
-				else {
-					Node parent = node.getParentNode();
-					if (parent != null) {
-						Node previousSibling = node.getPreviousSibling();
-						if ((previousSibling != null) && isWhitespaceTextNode(previousSibling)) {
-							parent.removeChild(previousSibling);
+			if (validateEdit(getModel(), getWorkbenchWindowShell())) {
+				beginNodeAction(this);
+	
+				for (Iterator i = list.iterator(); i.hasNext();) {
+					Node node = (Node) i.next();
+					if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
+						Attr attr = (Attr) node;
+						attr.getOwnerElement().removeAttributeNode(attr);
+					}
+					else {
+						Node parent = node.getParentNode();
+						if (parent != null) {
+							Node previousSibling = node.getPreviousSibling();
+							if ((previousSibling != null) && isWhitespaceTextNode(previousSibling)) {
+								parent.removeChild(previousSibling);
+							}
+							parent.removeChild(node);
 						}
-						parent.removeChild(node);
 					}
 				}
-			}
 
-			endNodeAction(this);
+				endNodeAction(this);
+			}
 		}
 	}
 
@@ -335,38 +339,40 @@
 		}
 
 		public void run() {
-			beginNodeAction(this);
-
-			Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
-			Node newChildNode = null;
-			boolean format = true;
-			switch (nodeType) {
-				case Node.COMMENT_NODE : {
-					newChildNode = document.createComment(XMLUIMessages._UI_COMMENT_VALUE);
-					break;
+			if (validateEdit(getModel(), getWorkbenchWindowShell())) {
+				beginNodeAction(this);
+	
+				Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+				Node newChildNode = null;
+				boolean format = true;
+				switch (nodeType) {
+					case Node.COMMENT_NODE : {
+						newChildNode = document.createComment(XMLUIMessages._UI_COMMENT_VALUE);
+						break;
+					}
+					case Node.PROCESSING_INSTRUCTION_NODE : {
+						newChildNode = document.createProcessingInstruction(XMLUIMessages._UI_PI_TARGET_VALUE, XMLUIMessages._UI_PI_DATA_VALUE);
+						break;
+					}
+					case Node.CDATA_SECTION_NODE : {
+						newChildNode = document.createCDATASection(""); //$NON-NLS-1$
+						break;
+					}
+					case Node.TEXT_NODE : {
+						format = false;
+						newChildNode = document.createTextNode(parent.getNodeName());
+						break;
+					}
 				}
-				case Node.PROCESSING_INSTRUCTION_NODE : {
-					newChildNode = document.createProcessingInstruction(XMLUIMessages._UI_PI_TARGET_VALUE, XMLUIMessages._UI_PI_DATA_VALUE);
-					break;
+	
+				if (newChildNode != null) {
+					List list = new Vector(1);
+					list.add(newChildNode);
+					insertNodesAtIndex(parent, list, index, format);
 				}
-				case Node.CDATA_SECTION_NODE : {
-					newChildNode = document.createCDATASection(""); //$NON-NLS-1$
-					break;
-				}
-				case Node.TEXT_NODE : {
-					format = false;
-					newChildNode = document.createTextNode(parent.getNodeName());
-					break;
-				}
+	
+				endNodeAction(this);
 			}
-
-			if (newChildNode != null) {
-				List list = new Vector(1);
-				list.add(newChildNode);
-				insertNodesAtIndex(parent, list, index, format);
-			}
-
-			endNodeAction(this);
 		}
 	}
 
@@ -399,13 +405,15 @@
 		}
 
 		public void run() {
-			beginNodeAction(this);
-
-			if ((parent != null) && (cmnode != null)) {
-				remove(parent, startIndex, endIndex);
-				insert(parent, cmnode, startIndex);
+			if (validateEdit(getModel(), getWorkbenchWindowShell())) {
+				beginNodeAction(this);
+	
+				if ((parent != null) && (cmnode != null)) {
+					remove(parent, startIndex, endIndex);
+					insert(parent, cmnode, startIndex);
+				}
+				endNodeAction(this);
 			}
-			endNodeAction(this);
 		}
 	}
 
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditAttributeAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditAttributeAction.java
index 3da8aa7..0cdc771 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditAttributeAction.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditAttributeAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -56,24 +56,26 @@
 	}
 
 	public void run() {
-		manager.beginNodeAction(this);
 		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
-		EditAttributeDialog dialog = new EditAttributeDialog(shell, ownerElement, attr);
-		dialog.create();
-		dialog.getShell().setText(title);
-		dialog.setBlockOnOpen(true);
-		dialog.open();
-
-		if (dialog.getReturnCode() == Window.OK) {
-			if (attr != null) {
-				ownerElement.removeAttributeNode(attr);
+		if (validateEdit(manager.getModel(), shell)) {
+			manager.beginNodeAction(this);
+			EditAttributeDialog dialog = new EditAttributeDialog(shell, ownerElement, attr);
+			dialog.create();
+			dialog.getShell().setText(title);
+			dialog.setBlockOnOpen(true);
+			dialog.open();
+	
+			if (dialog.getReturnCode() == Window.OK) {
+				if (attr != null) {
+					ownerElement.removeAttributeNode(attr);
+				}
+				Document document = ownerElement.getOwnerDocument();
+				Attr newAttribute = document.createAttribute(dialog.getAttributeName());
+				newAttribute.setValue(dialog.getAttributeValue());
+				ownerElement.setAttributeNode(newAttribute);
+				manager.setViewerSelection(newAttribute);
 			}
-			Document document = ownerElement.getOwnerDocument();
-			Attr newAttribute = document.createAttribute(dialog.getAttributeName());
-			newAttribute.setValue(dialog.getAttributeValue());
-			ownerElement.setAttributeNode(newAttribute);
-			manager.setViewerSelection(newAttribute);
+			manager.endNodeAction(this);
 		}
-		manager.endNodeAction(this);
 	}
 }
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditDoctypeAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditDoctypeAction.java
index 6330044..4ce515c 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditDoctypeAction.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditDoctypeAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -13,7 +13,6 @@
 package org.eclipse.wst.xml.ui.internal.actions;
 
 import org.eclipse.core.runtime.Path;
-import org.eclipse.jface.action.Action;
 import org.eclipse.jface.window.Window;
 import org.eclipse.swt.widgets.Display;
 import org.eclipse.swt.widgets.Shell;
@@ -33,7 +32,7 @@
 /**
  * EditDoctypeAction
  */
-public class EditDoctypeAction extends Action {
+public class EditDoctypeAction extends NodeAction {
 	protected DocumentType doctype;
 	protected Document document;
 	protected IStructuredModel model;
@@ -120,24 +119,26 @@
 	}
 
 	public void run() {
-		model.beginRecording(this, getUndoDescription());
-		// Shell shell =
-		// XMLCommonUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
 		Shell shell = getDisplay().getActiveShell();
-		EditDoctypeDialog dialog = showEditDoctypeDialog(shell);
-
-		if (dialog.getReturnCode() == Window.OK) {
-			if (doctype != null) {
-				updateDoctype(dialog, doctype);
-			}
-			else if (document != null) {
-				DocumentType doctype = createDoctype(dialog, document);
+		if (validateEdit(model, shell)) {
+			model.beginRecording(this, getUndoDescription());
+			// Shell shell =
+			// XMLCommonUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+			EditDoctypeDialog dialog = showEditDoctypeDialog(shell);
+	
+			if (dialog.getReturnCode() == Window.OK) {
 				if (doctype != null) {
-					insertDoctype(doctype, document);
+					updateDoctype(dialog, doctype);
+				}
+				else if (document != null) {
+					DocumentType doctype = createDoctype(dialog, document);
+					if (doctype != null) {
+						insertDoctype(doctype, document);
+					}
 				}
 			}
+			model.endRecording(this);
 		}
-		model.endRecording(this);
 	}
 
 	protected EditDoctypeDialog showEditDoctypeDialog(Shell shell) {
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditElementAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditElementAction.java
index b944268..21b55fe 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditElementAction.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditElementAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -69,39 +69,41 @@
 	}
 
 	public void run() {
-		manager.beginNodeAction(this);
 		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
-		EditElementDialog dialog = new EditElementDialog(shell, element);
-		dialog.create();
-		dialog.getShell().setText(title);
-		dialog.setBlockOnOpen(true);
-		dialog.open();
-
-		if (dialog.getReturnCode() == Window.OK) {
-			Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
-			if (element != null) {
-				// here we need to do a rename... which seems to be quite hard
-				// to do :-(
-				if (element instanceof IDOMElement) {
-					IDOMElement elementImpl = (IDOMElement) element;
-					IDOMModel model = elementImpl.getModel();
-					String oldName = elementImpl.getNodeName();
-					String newName = dialog.getElementName();
-					setStructuredDocumentRegionElementName(model, elementImpl.getStartStructuredDocumentRegion(), oldName, newName);
-					setStructuredDocumentRegionElementName(model, elementImpl.getEndStructuredDocumentRegion(), oldName, newName);
+		if (validateEdit(manager.getModel(), shell)) {
+			manager.beginNodeAction(this);
+			EditElementDialog dialog = new EditElementDialog(shell, element);
+			dialog.create();
+			dialog.getShell().setText(title);
+			dialog.setBlockOnOpen(true);
+			dialog.open();
+	
+			if (dialog.getReturnCode() == Window.OK) {
+				Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+				if (element != null) {
+					// here we need to do a rename... which seems to be quite hard
+					// to do :-(
+					if (element instanceof IDOMElement) {
+						IDOMElement elementImpl = (IDOMElement) element;
+						IDOMModel model = elementImpl.getModel();
+						String oldName = elementImpl.getNodeName();
+						String newName = dialog.getElementName();
+						setStructuredDocumentRegionElementName(model, elementImpl.getStartStructuredDocumentRegion(), oldName, newName);
+						setStructuredDocumentRegionElementName(model, elementImpl.getEndStructuredDocumentRegion(), oldName, newName);
+					}
+				}
+				else {
+					Element newElement = document.createElement(dialog.getElementName());
+					NodeList nodeList = parent.getChildNodes();
+					int nodeListLength = nodeList.getLength();
+					Node refChild = (insertionIndex < nodeListLength) && (insertionIndex >= 0) ? nodeList.item(insertionIndex) : null;
+					parent.insertBefore(newElement, refChild);
+					manager.reformat(newElement, false);
+					manager.setViewerSelection(newElement);
 				}
 			}
-			else {
-				Element newElement = document.createElement(dialog.getElementName());
-				NodeList nodeList = parent.getChildNodes();
-				int nodeListLength = nodeList.getLength();
-				Node refChild = (insertionIndex < nodeListLength) && (insertionIndex >= 0) ? nodeList.item(insertionIndex) : null;
-				parent.insertBefore(newElement, refChild);
-				manager.reformat(newElement, false);
-				manager.setViewerSelection(newElement);
-			}
+			manager.endNodeAction(this);
 		}
-		manager.endNodeAction(this);
 	}
 
 	protected void setStructuredDocumentRegionElementName(IDOMModel model, IStructuredDocumentRegion flatNode, String oldName, String newName) {
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditProcessingInstructionAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditProcessingInstructionAction.java
index 9dec301..5578cf2 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditProcessingInstructionAction.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditProcessingInstructionAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -58,38 +58,41 @@
 	}
 
 	public void run() {
-		manager.beginNodeAction(this);
 		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
-
-		EditProcessingInstructionDialog dialog = null;
-		if (pi != null) {
-			dialog = new EditProcessingInstructionDialog(shell, pi);
-		}
-		else {
-			dialog = new EditProcessingInstructionDialog(shell, XMLUIMessages._UI_PI_TARGET_VALUE, XMLUIMessages._UI_PI_DATA_VALUE);
-		}
-
-		dialog.create();
-		dialog.getShell().setText(title);
-		dialog.setBlockOnOpen(true);
-		dialog.open();
-
-		if (dialog.getReturnCode() == Window.OK) {
+		if (validateEdit(manager.getModel(), shell)) {
+			manager.beginNodeAction(this);
+			
+	
+			EditProcessingInstructionDialog dialog = null;
 			if (pi != null) {
-				childRef = pi;
+				dialog = new EditProcessingInstructionDialog(shell, pi);
 			}
-
-			Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
-			Node newNode = document.createProcessingInstruction(dialog.getTarget(), dialog.getData());
-			parent.insertBefore(newNode, childRef);
-
-			if (pi != null) {
-				parent.removeChild(pi);
+			else {
+				dialog = new EditProcessingInstructionDialog(shell, XMLUIMessages._UI_PI_TARGET_VALUE, XMLUIMessages._UI_PI_DATA_VALUE);
 			}
-
-			manager.reformat(newNode, false);
-			manager.setViewerSelection(newNode);
+	
+			dialog.create();
+			dialog.getShell().setText(title);
+			dialog.setBlockOnOpen(true);
+			dialog.open();
+	
+			if (dialog.getReturnCode() == Window.OK) {
+				if (pi != null) {
+					childRef = pi;
+				}
+	
+				Document document = parent.getNodeType() == Node.DOCUMENT_NODE ? (Document) parent : parent.getOwnerDocument();
+				Node newNode = document.createProcessingInstruction(dialog.getTarget(), dialog.getData());
+				parent.insertBefore(newNode, childRef);
+	
+				if (pi != null) {
+					parent.removeChild(pi);
+				}
+	
+				manager.reformat(newNode, false);
+				manager.setViewerSelection(newNode);
+			}
+			manager.endNodeAction(this);
 		}
-		manager.endNodeAction(this);
 	}
 }
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditSchemaInfoAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditSchemaInfoAction.java
index 699492c..92433cc 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditSchemaInfoAction.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/EditSchemaInfoAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2006 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -114,53 +114,55 @@
 	}
 
 	public void run() {
-		manager.beginNodeAction(this);
-
-		// todo... change constructor to take an element
-		Element element = getElement(node);
-		if (element != null) {
-			Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
-			EditSchemaInfoDialog dialog = new EditSchemaInfoDialog(shell, new Path(resourceLocation));
-
-			List namespaceInfoList = namespaceInfoManager.getNamespaceInfoList(element);
-			List oldNamespaceInfoList = NamespaceInfo.cloneNamespaceInfoList(namespaceInfoList);
-
-			// here we store a copy of the old info for each NamespaceInfo
-			// this info will be used in createPrefixMapping() to figure out
-			// how to update the document
-			// in response to these changes
-			for (Iterator i = namespaceInfoList.iterator(); i.hasNext();) {
-				NamespaceInfo info = (NamespaceInfo) i.next();
-				NamespaceInfo oldCopy = new NamespaceInfo(info);
-				info.setProperty("oldCopy", oldCopy); //$NON-NLS-1$
-			}
-
-			dialog.setNamespaceInfoList(namespaceInfoList);
-			dialog.create();
-			// dialog.getShell().setSize(500, 300);
-			dialog.getShell().setText(XMLUIMessages._UI_MENU_EDIT_SCHEMA_INFORMATION_TITLE);
-			dialog.setBlockOnOpen(true);
-			dialog.open();
-
-			if (dialog.getReturnCode() == Window.OK) {
-				List newInfoList = dialog.getNamespaceInfoList();
-				namespaceInfoManager.removeNamespaceInfo(element);
-				namespaceInfoManager.addNamespaceInfo(element, newInfoList, true);
-
-				// see if we need to rename any prefixes
-				Map prefixMapping = createPrefixMapping(oldNamespaceInfoList, namespaceInfoList);
-				if (prefixMapping.size() > 0) {
-					try {
-						manager.getModel().aboutToChangeModel();
-						ReplacePrefixAction replacePrefixAction = new ReplacePrefixAction(manager, element, prefixMapping);
-						replacePrefixAction.run();
-					}
-					finally {
-						manager.getModel().changedModel();
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		if (validateEdit(manager.getModel(), shell)) {
+			manager.beginNodeAction(this);
+	
+			// todo... change constructor to take an element
+			Element element = getElement(node);
+			if (element != null) {
+				EditSchemaInfoDialog dialog = new EditSchemaInfoDialog(shell, new Path(resourceLocation));
+	
+				List namespaceInfoList = namespaceInfoManager.getNamespaceInfoList(element);
+				List oldNamespaceInfoList = NamespaceInfo.cloneNamespaceInfoList(namespaceInfoList);
+	
+				// here we store a copy of the old info for each NamespaceInfo
+				// this info will be used in createPrefixMapping() to figure out
+				// how to update the document
+				// in response to these changes
+				for (Iterator i = namespaceInfoList.iterator(); i.hasNext();) {
+					NamespaceInfo info = (NamespaceInfo) i.next();
+					NamespaceInfo oldCopy = new NamespaceInfo(info);
+					info.setProperty("oldCopy", oldCopy); //$NON-NLS-1$
+				}
+	
+				dialog.setNamespaceInfoList(namespaceInfoList);
+				dialog.create();
+				// dialog.getShell().setSize(500, 300);
+				dialog.getShell().setText(XMLUIMessages._UI_MENU_EDIT_SCHEMA_INFORMATION_TITLE);
+				dialog.setBlockOnOpen(true);
+				dialog.open();
+	
+				if (dialog.getReturnCode() == Window.OK) {
+					List newInfoList = dialog.getNamespaceInfoList();
+					namespaceInfoManager.removeNamespaceInfo(element);
+					namespaceInfoManager.addNamespaceInfo(element, newInfoList, true);
+	
+					// see if we need to rename any prefixes
+					Map prefixMapping = createPrefixMapping(oldNamespaceInfoList, namespaceInfoList);
+					if (prefixMapping.size() > 0) {
+						try {
+							manager.getModel().aboutToChangeModel();
+							ReplacePrefixAction replacePrefixAction = new ReplacePrefixAction(manager, element, prefixMapping);
+							replacePrefixAction.run();
+						}
+						finally {
+							manager.getModel().changedModel();
+						}
 					}
 				}
 			}
+			manager.endNodeAction(this);
 		}
-		manager.endNodeAction(this);
 	}
 }
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/NodeAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/NodeAction.java
index 0974e8f..1ce764a 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/NodeAction.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/NodeAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -14,7 +14,12 @@
 
 package org.eclipse.wst.xml.ui.internal.actions;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.jface.action.Action;
+import org.eclipse.swt.widgets.Shell;
+import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
 
 public abstract class NodeAction extends Action {
 
@@ -22,5 +27,22 @@
 		return null;
 	}
 
+	/**
+	 * Checks that the resource backing the model is writeable utilizing <code>validateEdit</code>
+	 * on a given <tt>IWorkspace</tt>.
+	 * 
+	 * @param model the model to be checked
+	 * @param context the shell context for which <code>validateEdit</code> will be run
+	 * @return boolean result of checking <code>validateEdit</code>. If the resource is unwriteable, <code>status.isOK()</code>
+	 * will return true; otherwise, false.
+	 */
+	protected final boolean validateEdit(IStructuredModel model, Shell context) {
+		if (model != null && model.getBaseLocation() != null) {
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(model.getBaseLocation()));
+			return !file.isAccessible() || ResourcesPlugin.getWorkspace().validateEdit(new IFile[] {file}, context).isOK();
+		}
+		return false; //$NON-NLS-1$
+	}
+
 	public abstract String getUndoDescription();
 }
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ReplacePrefixAction.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ReplacePrefixAction.java
index e5719a9..18599bd 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ReplacePrefixAction.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/actions/ReplacePrefixAction.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2005 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -18,7 +18,9 @@
 import java.util.Vector;
 
 import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.swt.widgets.Shell;
 import org.eclipse.wst.xml.core.internal.contentmodel.util.DOMVisitor;
+import org.eclipse.wst.xml.ui.internal.XMLUIPlugin;
 import org.w3c.dom.Attr;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;
@@ -65,14 +67,17 @@
 	}
 
 	public void run() {
-		NodeCollectingDOMVisitor visitor = new NodeCollectingDOMVisitor();
-		visitor.visitNode(element);
-		for (Iterator i = visitor.list.iterator(); i.hasNext();) {
-			Node node = (Node) i.next();
-			String key = node.getPrefix() != null ? node.getPrefix() : ""; //$NON-NLS-1$
-			String newPrefix = (String) prefixMapping.get(key);
-			if (newPrefix != null) {
-				node.setPrefix(newPrefix);
+		Shell shell = XMLUIPlugin.getInstance().getWorkbench().getActiveWorkbenchWindow().getShell();
+		if (validateEdit(manager.getModel(), shell)) {
+			NodeCollectingDOMVisitor visitor = new NodeCollectingDOMVisitor();
+			visitor.visitNode(element);
+			for (Iterator i = visitor.list.iterator(); i.hasNext();) {
+				Node node = (Node) i.next();
+				String key = node.getPrefix() != null ? node.getPrefix() : ""; //$NON-NLS-1$
+				String newPrefix = (String) prefixMapping.get(key);
+				if (newPrefix != null) {
+					node.setPrefix(newPrefix);
+				}
 			}
 		}
 	}
diff --git a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dnd/DragNodeCommand.java b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dnd/DragNodeCommand.java
index 3f5c66f..bb8a76c 100644
--- a/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dnd/DragNodeCommand.java
+++ b/bundles/org.eclipse.wst.xml.ui/src/org/eclipse/wst/xml/ui/internal/dnd/DragNodeCommand.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2001, 2007 IBM Corporation and others.
+ * Copyright (c) 2001, 2009 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
@@ -19,9 +19,13 @@
 import java.util.List;
 import java.util.Vector;
 
+import org.eclipse.core.resources.IFile;
+import org.eclipse.core.resources.ResourcesPlugin;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.jface.viewers.StructuredSelection;
 import org.eclipse.jface.viewers.TreeViewer;
 import org.eclipse.swt.dnd.DND;
+import org.eclipse.swt.widgets.Shell;
 import org.eclipse.wst.common.ui.internal.dnd.DefaultDragAndDropCommand;
 import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
 import org.eclipse.wst.xml.core.internal.provisional.document.IDOMNode;
@@ -160,6 +164,9 @@
 		boolean result = true;
 		if (target instanceof Node) {
 			Node targetNode = (Node) target;
+			if (!testOnly && fTreeViewer != null && !validateEdit(getStructuredModel(targetNode), fTreeViewer.getControl().getShell()))
+				return false;
+
 			Node parentNode = getParentForDropPosition(targetNode);
 			Node refChild = getRefChild(targetNode);
 
@@ -196,6 +203,22 @@
 		return result;
 	}
 
+	/**
+	 * Checks that the resource backing the model is writeable utilizing <code>validateEdit</code>
+	 * on a given <tt>IWorkspace</tt>.
+	 * 
+	 * @param model the model to be checked
+	 * @param context the shell context for which <code>validateEdit</code> will be run
+	 * @return boolean result of checking <code>validateEdit</code>. If the resource is unwriteable, <code>status.isOK()</code>
+	 * will return true; otherwise, false.
+	 */
+	private boolean validateEdit(IStructuredModel model, Shell context) {
+		if (model != null && model.getBaseLocation() != null) {
+			IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(model.getBaseLocation()));
+			return !file.isAccessible() || ResourcesPlugin.getWorkspace().validateEdit(new IFile[] {file}, context).isOK();
+		}
+		return false; //$NON-NLS-1$
+	}
 
 	public int getFeedback() {
 		int result = DND.FEEDBACK_SELECT;