david_williams | 49d24fb | 2005-04-08 21:16:59 +0000 | [diff] [blame] | 1 | /******************************************************************************* |
amywu | 32bdd41 | 2007-02-14 08:12:56 +0000 | [diff] [blame] | 2 | * Copyright (c) 2001, 2007 IBM Corporation and others. |
david_williams | 49d24fb | 2005-04-08 21:16:59 +0000 | [diff] [blame] | 3 | * All rights reserved. This program and the accompanying materials |
| 4 | * are made available under the terms of the Eclipse Public License v1.0 |
| 5 | * which accompanies this distribution, and is available at |
| 6 | * http://www.eclipse.org/legal/epl-v10.html |
| 7 | * |
| 8 | * Contributors: |
| 9 | * IBM Corporation - initial API and implementation |
| 10 | *******************************************************************************/ |
david_williams | 96643dd | 2005-04-13 04:35:24 +0000 | [diff] [blame] | 11 | package org.eclipse.wst.html.internal.validation; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 12 | |
| 13 | import java.io.IOException; |
| 14 | import java.io.UnsupportedEncodingException; |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 15 | import java.util.ArrayList; |
| 16 | import java.util.List; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 17 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 18 | import org.eclipse.core.filebuffers.ITextFileBuffer; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 19 | import org.eclipse.core.resources.IContainer; |
| 20 | import org.eclipse.core.resources.IFile; |
| 21 | import org.eclipse.core.resources.IProject; |
| 22 | import org.eclipse.core.resources.IResource; |
| 23 | import org.eclipse.core.resources.ResourcesPlugin; |
| 24 | import org.eclipse.core.runtime.CoreException; |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 25 | import org.eclipse.core.runtime.IConfigurationElement; |
| 26 | import org.eclipse.core.runtime.IExecutableExtension; |
nitind | 7780ed6 | 2007-12-18 04:45:17 +0000 | [diff] [blame] | 27 | import org.eclipse.core.runtime.IPath; |
nitind | 3b1ac31 | 2008-04-21 20:41:30 +0000 | [diff] [blame] | 28 | import org.eclipse.core.runtime.IProgressMonitor; |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 29 | import org.eclipse.core.runtime.IStatus; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 30 | import org.eclipse.core.runtime.NullProgressMonitor; |
| 31 | import org.eclipse.core.runtime.OperationCanceledException; |
| 32 | import org.eclipse.core.runtime.Path; |
david_williams | e6ed732 | 2005-10-10 17:32:24 +0000 | [diff] [blame] | 33 | import org.eclipse.core.runtime.Platform; |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 34 | import org.eclipse.core.runtime.Status; |
nitind | a06daf8 | 2005-11-01 22:42:33 +0000 | [diff] [blame] | 35 | import org.eclipse.core.runtime.content.IContentDescription; |
david_williams | e6ed732 | 2005-10-10 17:32:24 +0000 | [diff] [blame] | 36 | import org.eclipse.core.runtime.content.IContentType; |
| 37 | import org.eclipse.core.runtime.content.IContentTypeManager; |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 38 | import org.eclipse.core.runtime.jobs.ISchedulingRule; |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 39 | import org.eclipse.jface.text.IDocument; |
| 40 | import org.eclipse.jface.text.IRegion; |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 41 | import org.eclipse.wst.html.core.internal.document.HTMLDocumentTypeConstants; |
david_williams | 5677702 | 2005-04-11 06:21:55 +0000 | [diff] [blame] | 42 | import org.eclipse.wst.html.core.internal.validate.HTMLValidationAdapterFactory; |
nitind | de5d5aa | 2007-02-14 22:58:32 +0000 | [diff] [blame] | 43 | import org.eclipse.wst.html.ui.internal.Logger; |
david_williams | b5d0563 | 2006-02-27 09:24:00 +0000 | [diff] [blame] | 44 | import org.eclipse.wst.sse.core.StructuredModelManager; |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 45 | import org.eclipse.wst.sse.core.internal.FileBufferModelManager; |
david_williams | 4ad020f | 2005-04-18 08:00:30 +0000 | [diff] [blame] | 46 | import org.eclipse.wst.sse.core.internal.provisional.IModelManager; |
| 47 | import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory; |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 48 | import org.eclipse.wst.sse.core.internal.provisional.INodeNotifier; |
david_williams | 4ad020f | 2005-04-18 08:00:30 +0000 | [diff] [blame] | 49 | import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel; |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 50 | import org.eclipse.wst.sse.core.internal.provisional.IndexedRegion; |
pavery | 99e577e | 2006-03-16 21:28:46 +0000 | [diff] [blame] | 51 | import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument; |
| 52 | import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocumentRegion; |
david_williams | 2aecf08 | 2005-04-13 05:03:21 +0000 | [diff] [blame] | 53 | import org.eclipse.wst.sse.core.internal.util.URIResolver; |
david_williams | 3bcfe39 | 2005-04-13 04:49:36 +0000 | [diff] [blame] | 54 | import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter; |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 55 | import org.eclipse.wst.sse.core.utils.StringUtils; |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 56 | import org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator; |
nitind | 3b1ac31 | 2008-04-21 20:41:30 +0000 | [diff] [blame] | 57 | import org.eclipse.wst.validation.AbstractValidator; |
| 58 | import org.eclipse.wst.validation.ValidationResult; |
| 59 | import org.eclipse.wst.validation.ValidationState; |
vbhadrir | 0b14da3 | 2005-04-18 15:40:15 +0000 | [diff] [blame] | 60 | import org.eclipse.wst.validation.internal.core.Message; |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 61 | import org.eclipse.wst.validation.internal.core.ValidationException; |
vbhadrir | 271d28a | 2005-04-12 19:36:05 +0000 | [diff] [blame] | 62 | import org.eclipse.wst.validation.internal.operations.IWorkbenchContext; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 63 | import org.eclipse.wst.validation.internal.operations.WorkbenchReporter; |
david_williams | 49d24fb | 2005-04-08 21:16:59 +0000 | [diff] [blame] | 64 | import org.eclipse.wst.validation.internal.provisional.core.IMessage; |
| 65 | import org.eclipse.wst.validation.internal.provisional.core.IReporter; |
| 66 | import org.eclipse.wst.validation.internal.provisional.core.IValidationContext; |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 67 | import org.eclipse.wst.validation.internal.provisional.core.IValidatorJob; |
david_williams | 646a5e2 | 2005-04-02 07:16:27 +0000 | [diff] [blame] | 68 | import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter; |
david_williams | 4ad020f | 2005-04-18 08:00:30 +0000 | [diff] [blame] | 69 | import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument; |
| 70 | import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel; |
pavery | dc8b306 | 2005-10-24 20:43:42 +0000 | [diff] [blame] | 71 | import org.w3c.dom.Text; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 72 | |
nitind | 3b1ac31 | 2008-04-21 20:41:30 +0000 | [diff] [blame] | 73 | public class HTMLValidator extends AbstractValidator implements IValidatorJob, ISourceValidator, IExecutableExtension { |
nitind | 73e7641 | 2005-11-10 01:50:19 +0000 | [diff] [blame] | 74 | private static final String ORG_ECLIPSE_WST_HTML_CORE_HTMLSOURCE = "org.eclipse.wst.html.core.htmlsource"; //$NON-NLS-1$ |
david_williams | e6ed732 | 2005-10-10 17:32:24 +0000 | [diff] [blame] | 75 | |
nitind | 165498a | 2005-07-12 18:47:49 +0000 | [diff] [blame] | 76 | static boolean shouldValidate(IFile file) { |
| 77 | IResource resource = file; |
| 78 | do { |
| 79 | if (resource.isDerived() || resource.isTeamPrivateMember() || !resource.isAccessible() || (resource.getName().charAt(0) == '.' && resource.getType() == IResource.FOLDER)) { |
| 80 | return false; |
| 81 | } |
| 82 | resource = resource.getParent(); |
| 83 | } |
| 84 | while ((resource.getType() & IResource.PROJECT) == 0); |
| 85 | return true; |
| 86 | } |
| 87 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 88 | private IDocument fDocument; |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 89 | private IContentTypeManager fContentTypeManager; |
| 90 | private IContentType[] fOtherSupportedContentTypes = null; |
| 91 | private String[] fAdditionalContentTypesIDs = null; |
| 92 | private IContentType fHTMLContentType; |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 93 | |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 94 | public HTMLValidator() { |
| 95 | super(); |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 96 | fContentTypeManager = Platform.getContentTypeManager(); |
| 97 | fHTMLContentType = fContentTypeManager.getContentType(ORG_ECLIPSE_WST_HTML_CORE_HTMLSOURCE); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 98 | } |
| 99 | |
| 100 | /** |
| 101 | */ |
| 102 | public void cleanup(IReporter reporter) { |
| 103 | // nothing to do |
| 104 | } |
| 105 | |
| 106 | /** |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 107 | * Gets list of content types this validator is interested in |
| 108 | * |
| 109 | * @return All HTML-related content types |
| 110 | */ |
| 111 | private IContentType[] getOtherSupportedContentTypes() { |
| 112 | if (fOtherSupportedContentTypes == null) { |
| 113 | List contentTypes = new ArrayList(3); |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 114 | if (fAdditionalContentTypesIDs != null) { |
| 115 | for (int i = 0; i < fAdditionalContentTypesIDs.length; i++) { |
| 116 | IContentType type = Platform.getContentTypeManager().getContentType(fAdditionalContentTypesIDs[i]); |
| 117 | if (type != null) { |
| 118 | contentTypes.add(type); |
| 119 | } |
| 120 | } |
| 121 | } |
| 122 | fOtherSupportedContentTypes = (IContentType[]) contentTypes.toArray(new IContentType[contentTypes.size()]); |
| 123 | } |
| 124 | return fOtherSupportedContentTypes; |
| 125 | } |
| 126 | |
| 127 | |
| 128 | /** |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 129 | */ |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame] | 130 | protected IDOMModel getModel(IProject project, IFile file) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 131 | if (project == null || file == null) |
| 132 | return null; |
| 133 | if (!file.exists()) |
| 134 | return null; |
| 135 | if (!canHandle(file)) |
| 136 | return null; |
| 137 | |
| 138 | IStructuredModel model = null; |
| 139 | IModelManager manager = StructuredModelManager.getModelManager(); |
nitind | de5d5aa | 2007-02-14 22:58:32 +0000 | [diff] [blame] | 140 | try { |
| 141 | file.refreshLocal(IResource.DEPTH_ZERO, new NullProgressMonitor()); |
| 142 | } |
| 143 | catch (CoreException e) { |
| 144 | Logger.logException(e); |
| 145 | } |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 146 | try { |
| 147 | try { |
| 148 | model = manager.getModelForRead(file); |
| 149 | } |
| 150 | catch (UnsupportedEncodingException ex) { |
david_williams | 49d24fb | 2005-04-08 21:16:59 +0000 | [diff] [blame] | 151 | // retry ignoring META charset for invalid META charset |
| 152 | // specification |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 153 | // recreate input stream, because it is already partially read |
| 154 | model = manager.getModelForRead(file, new String(), null); |
| 155 | } |
| 156 | } |
| 157 | catch (UnsupportedEncodingException ex) { |
| 158 | } |
| 159 | catch (IOException ex) { |
| 160 | } |
nitind | de5d5aa | 2007-02-14 22:58:32 +0000 | [diff] [blame] | 161 | catch (CoreException e) { |
| 162 | Logger.logException(e); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 163 | } |
| 164 | |
| 165 | if (model == null) |
| 166 | return null; |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame] | 167 | if (!(model instanceof IDOMModel)) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 168 | releaseModel(model); |
| 169 | return null; |
| 170 | } |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame] | 171 | return (IDOMModel) model; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 172 | } |
| 173 | |
| 174 | /** |
| 175 | */ |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame] | 176 | protected HTMLValidationReporter getReporter(IReporter reporter, IFile file, IDOMModel model) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 177 | return new HTMLValidationReporter(this, reporter, file, model); |
| 178 | } |
| 179 | |
| 180 | /** |
| 181 | * Check file extension to validate |
| 182 | */ |
| 183 | private boolean canHandle(IFile file) { |
david_williams | e6ed732 | 2005-10-10 17:32:24 +0000 | [diff] [blame] | 184 | boolean result = false; |
| 185 | if (file != null) { |
| 186 | try { |
nitind | a06daf8 | 2005-11-01 22:42:33 +0000 | [diff] [blame] | 187 | IContentDescription contentDescription = file.getContentDescription(); |
nitind | a06daf8 | 2005-11-01 22:42:33 +0000 | [diff] [blame] | 188 | if (contentDescription != null) { |
| 189 | IContentType fileContentType = contentDescription.getContentType(); |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 190 | if (fileContentType.isKindOf(fHTMLContentType)) { |
| 191 | result = true; |
| 192 | } |
| 193 | else { |
| 194 | IContentType[] otherTypes = getOtherSupportedContentTypes(); |
| 195 | for (int i = 0; i < otherTypes.length; i++) { |
| 196 | result = result || fileContentType.isKindOf(otherTypes[i]); |
david_williams | e6ed732 | 2005-10-10 17:32:24 +0000 | [diff] [blame] | 197 | } |
| 198 | } |
| 199 | } |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 200 | else if (fHTMLContentType != null) { |
| 201 | result = fHTMLContentType.isAssociatedWith(file.getName()); |
nitind | a06daf8 | 2005-11-01 22:42:33 +0000 | [diff] [blame] | 202 | } |
david_williams | e6ed732 | 2005-10-10 17:32:24 +0000 | [diff] [blame] | 203 | } |
| 204 | catch (CoreException e) { |
| 205 | // should be rare, but will ignore to avoid logging "encoding |
| 206 | // exceptions" and the like here. |
| 207 | // Logger.logException(e); |
| 208 | } |
| 209 | } |
| 210 | return result; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 211 | } |
| 212 | |
| 213 | /** |
| 214 | */ |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame] | 215 | private boolean hasHTMLFeature(IDOMDocument document) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 216 | DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class); |
| 217 | if (adapter == null) |
| 218 | return false; |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 219 | return adapter.hasFeature(HTMLDocumentTypeConstants.HTML); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 220 | } |
| 221 | |
| 222 | /** |
| 223 | */ |
| 224 | protected void releaseModel(IStructuredModel model) { |
| 225 | if (model != null) |
| 226 | model.releaseFromRead(); |
| 227 | } |
| 228 | |
| 229 | /** |
| 230 | */ |
vbhadrir | 271d28a | 2005-04-12 19:36:05 +0000 | [diff] [blame] | 231 | public void validate(IValidationContext helper, IReporter reporter) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 232 | if (helper == null) |
| 233 | return; |
| 234 | if ((reporter != null) && (reporter.isCancelled() == true)) { |
| 235 | throw new OperationCanceledException(); |
| 236 | } |
vbhadrir | 271d28a | 2005-04-12 19:36:05 +0000 | [diff] [blame] | 237 | String[] deltaArray = helper.getURIs(); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 238 | if (deltaArray != null && deltaArray.length > 0) { |
vbhadrir | 271d28a | 2005-04-12 19:36:05 +0000 | [diff] [blame] | 239 | validateDelta(helper, reporter); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 240 | } |
| 241 | else { |
vbhadrir | 271d28a | 2005-04-12 19:36:05 +0000 | [diff] [blame] | 242 | validateFull(helper, reporter); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 243 | } |
| 244 | } |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 245 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 246 | /** |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 247 | * This validate call is for the ISourceValidator partial document |
| 248 | * validation approach |
| 249 | * |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 250 | * @param dirtyRegion |
| 251 | * @param helper |
| 252 | * @param reporter |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 253 | * @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 254 | */ |
| 255 | public void validate(IRegion dirtyRegion, IValidationContext helper, IReporter reporter) { |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 256 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 257 | if (helper == null || fDocument == null) |
| 258 | return; |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 259 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 260 | if ((reporter != null) && (reporter.isCancelled() == true)) { |
| 261 | throw new OperationCanceledException(); |
| 262 | } |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 263 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 264 | IStructuredModel model = StructuredModelManager.getModelManager().getExistingModelForRead(fDocument); |
| 265 | if (model == null) |
| 266 | return; // error |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 267 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 268 | try { |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 269 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 270 | IDOMDocument document = null; |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 271 | if (model instanceof IDOMModel) { |
| 272 | document = ((IDOMModel) model).getDocument(); |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 273 | } |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 274 | |
nitind | 7780ed6 | 2007-12-18 04:45:17 +0000 | [diff] [blame] | 275 | if (document == null || !hasHTMLFeature(document)) { |
| 276 | model.releaseFromRead(); |
| 277 | return; //ignore |
| 278 | } |
| 279 | |
| 280 | IPath filePath = null; |
| 281 | IFile file = null; |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 282 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 283 | ITextFileBuffer fb = FileBufferModelManager.getInstance().getBuffer(fDocument); |
nitind | 7780ed6 | 2007-12-18 04:45:17 +0000 | [diff] [blame] | 284 | if (fb != null) { |
| 285 | filePath = fb.getLocation(); |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 286 | |
nitind | 7780ed6 | 2007-12-18 04:45:17 +0000 | [diff] [blame] | 287 | if (filePath.segmentCount() > 1) { |
| 288 | file = ResourcesPlugin.getWorkspace().getRoot().getFile(filePath); |
| 289 | if (!file.isAccessible()) { |
| 290 | file = null; |
| 291 | } |
| 292 | } |
| 293 | } |
| 294 | else { |
| 295 | filePath = new Path(model.getId()); |
| 296 | } |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 297 | |
pavery | dc8b306 | 2005-10-24 20:43:42 +0000 | [diff] [blame] | 298 | // this will be the wrong region if it's Text (instead of Element) |
| 299 | // we don't know how to validate Text |
pavery | 99e577e | 2006-03-16 21:28:46 +0000 | [diff] [blame] | 300 | IndexedRegion ir = getCoveringNode(dirtyRegion); // model.getIndexedRegion(dirtyRegion.getOffset()); |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 301 | if (ir instanceof Text) { |
| 302 | while (ir != null && ir instanceof Text) { |
pavery | dc8b306 | 2005-10-24 20:43:42 +0000 | [diff] [blame] | 303 | // it's assumed that this gets the IndexedRegion to |
| 304 | // the right of the end offset |
| 305 | ir = model.getIndexedRegion(ir.getEndOffset()); |
| 306 | } |
| 307 | } |
pavery | 99e577e | 2006-03-16 21:28:46 +0000 | [diff] [blame] | 308 | |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 309 | if (ir instanceof INodeNotifier) { |
| 310 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 311 | INodeAdapterFactory factory = HTMLValidationAdapterFactory.getInstance(); |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 312 | ValidationAdapter adapter = (ValidationAdapter) factory.adapt((INodeNotifier) ir); |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 313 | if (adapter == null) |
| 314 | return; // error |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 315 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 316 | if (reporter != null) { |
| 317 | HTMLValidationReporter rep = null; |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 318 | rep = getReporter(reporter, file, (IDOMModel) model); |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 319 | rep.clear(); |
| 320 | adapter.setReporter(rep); |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 321 | |
nitind | 7780ed6 | 2007-12-18 04:45:17 +0000 | [diff] [blame] | 322 | Message mess = new LocalizedMessage(IMessage.LOW_SEVERITY, filePath.toString().substring(1)); |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 323 | reporter.displaySubtask(this, mess); |
| 324 | } |
| 325 | adapter.validate(ir); |
| 326 | } |
| 327 | } |
| 328 | finally { |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 329 | if (model != null) |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 330 | model.releaseFromRead(); |
| 331 | } |
| 332 | } |
| 333 | |
pavery | 99e577e | 2006-03-16 21:28:46 +0000 | [diff] [blame] | 334 | private IndexedRegion getCoveringNode(IRegion dirtyRegion) { |
| 335 | |
| 336 | IndexedRegion largestRegion = null; |
| 337 | if(fDocument instanceof IStructuredDocument) { |
nitind | d7870fd | 2006-09-13 01:57:38 +0000 | [diff] [blame] | 338 | IStructuredDocumentRegion[] regions = ((IStructuredDocument) fDocument).getStructuredDocumentRegions(dirtyRegion.getOffset(), dirtyRegion.getLength()); |
| 339 | largestRegion = getLargest(regions); |
pavery | 99e577e | 2006-03-16 21:28:46 +0000 | [diff] [blame] | 340 | } |
| 341 | return largestRegion; |
| 342 | } |
| 343 | protected IndexedRegion getLargest(IStructuredDocumentRegion[] sdRegions) { |
| 344 | |
| 345 | if(sdRegions == null || sdRegions.length == 0) |
| 346 | return null; |
| 347 | |
| 348 | IndexedRegion currentLargest = getCorrespondingNode(sdRegions[0]); |
| 349 | for (int i = 0; i < sdRegions.length; i++) { |
| 350 | if(!sdRegions[i].isDeleted()) { |
| 351 | IndexedRegion corresponding = getCorrespondingNode(sdRegions[i]); |
| 352 | |
| 353 | if(currentLargest instanceof Text) |
| 354 | currentLargest = corresponding; |
| 355 | |
| 356 | if(corresponding != null) { |
| 357 | if(!(corresponding instanceof Text)) { |
| 358 | if (corresponding.getStartOffset() <= currentLargest.getStartOffset() |
| 359 | && corresponding.getEndOffset() >= currentLargest.getEndOffset() ) |
| 360 | currentLargest = corresponding; |
| 361 | } |
| 362 | } |
| 363 | |
| 364 | } |
| 365 | } |
| 366 | return currentLargest; |
| 367 | } |
| 368 | protected IndexedRegion getCorrespondingNode(IStructuredDocumentRegion sdRegion) { |
| 369 | IStructuredModel sModel = StructuredModelManager.getModelManager().getExistingModelForRead(fDocument); |
| 370 | IndexedRegion indexedRegion = null; |
| 371 | try { |
| 372 | if (sModel != null) |
| 373 | indexedRegion = sModel.getIndexedRegion(sdRegion.getStart()); |
| 374 | } finally { |
| 375 | if (sModel != null) |
| 376 | sModel.releaseFromRead(); |
| 377 | } |
| 378 | return indexedRegion; |
| 379 | } |
| 380 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 381 | /** |
| 382 | * @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator |
| 383 | */ |
| 384 | public void connect(IDocument document) { |
| 385 | fDocument = document; |
| 386 | } |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 387 | |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 388 | /** |
| 389 | * @see org.eclipse.wst.sse.ui.internal.reconcile.validator.ISourceValidator |
| 390 | */ |
| 391 | public void disconnect(IDocument document) { |
nitind | d7870fd | 2006-09-13 01:57:38 +0000 | [diff] [blame] | 392 | fDocument = null; |
pavery | a0e2eae | 2005-10-20 20:24:29 +0000 | [diff] [blame] | 393 | } |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 394 | |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 395 | /** |
| 396 | */ |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame] | 397 | protected HTMLValidationResult validate(IDOMModel model, IFile file) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 398 | IProject prj = null; |
| 399 | if (file != null) { |
| 400 | prj = file.getProject(); |
| 401 | } |
david_williams | 49d24fb | 2005-04-08 21:16:59 +0000 | [diff] [blame] | 402 | if ((prj == null) && (model != null)) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 403 | URIResolver res = model.getResolver(); |
| 404 | if (res != null) { |
| 405 | prj = res.getProject(); |
| 406 | } |
| 407 | } |
| 408 | final WorkbenchReporter reporter = new WorkbenchReporter(prj, new NullProgressMonitor()); |
david_williams | 49d24fb | 2005-04-08 21:16:59 +0000 | [diff] [blame] | 409 | return validate(reporter, file, model); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 410 | } |
| 411 | |
| 412 | /** |
| 413 | */ |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame] | 414 | private HTMLValidationResult validate(IReporter reporter, IFile file, IDOMModel model) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 415 | if (file == null || model == null) |
| 416 | return null; // error |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame] | 417 | IDOMDocument document = model.getDocument(); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 418 | if (document == null) |
| 419 | return null; // error |
| 420 | if (!hasHTMLFeature(document)) |
| 421 | return null; // ignore |
| 422 | |
david_williams | 285ee2d | 2005-04-10 18:21:21 +0000 | [diff] [blame] | 423 | INodeAdapterFactory factory = HTMLValidationAdapterFactory.getInstance(); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 424 | ValidationAdapter adapter = (ValidationAdapter) factory.adapt(document); |
| 425 | if (adapter == null) |
| 426 | return null; // error |
| 427 | |
| 428 | HTMLValidationReporter rep = getReporter(reporter, file, model); |
| 429 | rep.clear(); |
| 430 | adapter.setReporter(rep); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 431 | adapter.validate(document); |
| 432 | return rep.getResult(); |
| 433 | } |
| 434 | |
| 435 | /** |
| 436 | */ |
david_williams | 4327167 | 2005-04-01 05:19:26 +0000 | [diff] [blame] | 437 | private void validateContainer(IValidationContext helper, IReporter reporter, IContainer container) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 438 | try { |
| 439 | IResource[] resourceArray = container.members(false); |
| 440 | for (int i = 0; i < resourceArray.length; i++) { |
| 441 | IResource resource = resourceArray[i]; |
nitind | bcb8cd0 | 2006-08-15 21:11:35 +0000 | [diff] [blame] | 442 | if (resource == null || reporter.isCancelled()) |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 443 | continue; |
| 444 | if (resource instanceof IFile) { |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 445 | Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, resource.getFullPath().toString().substring(1)); |
| 446 | reporter.displaySubtask(this, message); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 447 | validateFile(helper, reporter, (IFile) resource); |
| 448 | } |
| 449 | else if (resource instanceof IContainer) { |
| 450 | validateContainer(helper, reporter, (IContainer) resource); |
| 451 | } |
| 452 | } |
| 453 | } |
| 454 | catch (CoreException ex) { |
| 455 | } |
| 456 | } |
| 457 | |
| 458 | /** |
| 459 | */ |
vbhadrir | 271d28a | 2005-04-12 19:36:05 +0000 | [diff] [blame] | 460 | private void validateDelta(IValidationContext helper, IReporter reporter) { |
| 461 | String[] deltaArray = helper.getURIs(); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 462 | for (int i = 0; i < deltaArray.length; i++) { |
vbhadrir | 271d28a | 2005-04-12 19:36:05 +0000 | [diff] [blame] | 463 | String delta = deltaArray[i]; |
| 464 | if (delta == null) |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 465 | continue; |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 466 | |
| 467 | if (reporter != null) { |
nitind | 314005a | 2008-03-25 03:31:25 +0000 | [diff] [blame] | 468 | Message message = new LocalizedMessage(IMessage.LOW_SEVERITY, delta.substring(1)); |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 469 | reporter.displaySubtask(this, message); |
| 470 | } |
| 471 | |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 472 | IResource resource = getResource(delta); |
| 473 | if (resource == null || !(resource instanceof IFile)) |
| 474 | continue; |
| 475 | validateFile(helper, reporter, (IFile) resource); |
| 476 | } |
| 477 | } |
| 478 | |
| 479 | /** |
| 480 | */ |
david_williams | 4327167 | 2005-04-01 05:19:26 +0000 | [diff] [blame] | 481 | private void validateFile(IValidationContext helper, IReporter reporter, IFile file) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 482 | if ((reporter != null) && (reporter.isCancelled() == true)) { |
| 483 | throw new OperationCanceledException(); |
| 484 | } |
nitind | 165498a | 2005-07-12 18:47:49 +0000 | [diff] [blame] | 485 | if (!shouldValidate(file)) { |
| 486 | return; |
| 487 | } |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame] | 488 | IDOMModel model = getModel(file.getProject(), file); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 489 | if (model == null) |
| 490 | return; |
| 491 | |
| 492 | try { |
| 493 | validate(reporter, file, model); |
| 494 | } |
| 495 | finally { |
| 496 | releaseModel(model); |
| 497 | } |
| 498 | } |
| 499 | |
| 500 | /** |
| 501 | */ |
vbhadrir | 271d28a | 2005-04-12 19:36:05 +0000 | [diff] [blame] | 502 | private void validateFull(IValidationContext helper, IReporter reporter) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 503 | IProject project = null; |
vbhadrir | 271d28a | 2005-04-12 19:36:05 +0000 | [diff] [blame] | 504 | String[] fileDelta = helper.getURIs(); |
| 505 | if (helper instanceof IWorkbenchContext) { |
| 506 | IWorkbenchContext wbHelper = (IWorkbenchContext) helper; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 507 | project = wbHelper.getProject(); |
| 508 | } |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 509 | else if(fileDelta.length > 0){ |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 510 | // won't work for project validation (b/c nothing in file delta) |
| 511 | project = getResource(fileDelta[0]).getProject(); |
| 512 | } |
| 513 | if (project == null) |
| 514 | return; |
| 515 | validateContainer(helper, reporter, project); |
| 516 | } |
| 517 | |
david_williams | 49d24fb | 2005-04-08 21:16:59 +0000 | [diff] [blame] | 518 | /* |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 519 | * added to get rid or dependency on IWorkbenchHelper |
david_williams | 49d24fb | 2005-04-08 21:16:59 +0000 | [diff] [blame] | 520 | * |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 521 | */ |
vbhadrir | 271d28a | 2005-04-12 19:36:05 +0000 | [diff] [blame] | 522 | public IResource getResource(String delta) { |
david_williams | e6ed732 | 2005-10-10 17:32:24 +0000 | [diff] [blame] | 523 | return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(delta)); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 524 | } |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 525 | |
| 526 | public ISchedulingRule getSchedulingRule(IValidationContext helper) { |
| 527 | return null; |
| 528 | } |
| 529 | |
| 530 | public IStatus validateInJob(IValidationContext helper, IReporter reporter) throws ValidationException { |
david_williams | 2deeabe | 2006-07-30 03:11:20 +0000 | [diff] [blame] | 531 | // Exception catching was removed, see |
| 532 | // https://bugs.eclipse.org/bugs/show_bug.cgi?id=123600 |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 533 | IStatus status = Status.OK_STATUS; |
david_williams | 2deeabe | 2006-07-30 03:11:20 +0000 | [diff] [blame] | 534 | validate(helper, reporter); |
pavery | 9e4a23d | 2006-03-13 20:28:03 +0000 | [diff] [blame] | 535 | return status; |
| 536 | } |
nitind | a9458e5 | 2006-11-02 00:59:27 +0000 | [diff] [blame] | 537 | |
| 538 | /** |
| 539 | * @see org.eclipse.core.runtime.IExecutableExtension#setInitializationData(org.eclipse.core.runtime.IConfigurationElement, |
| 540 | * java.lang.String, java.lang.Object) |
| 541 | */ |
| 542 | public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { |
| 543 | fAdditionalContentTypesIDs = new String[0]; |
| 544 | if (data != null) { |
| 545 | if (data instanceof String && data.toString().length() > 0) { |
| 546 | fAdditionalContentTypesIDs = StringUtils.unpack(data.toString()); |
| 547 | } |
| 548 | } |
| 549 | } |
nitind | 3b1ac31 | 2008-04-21 20:41:30 +0000 | [diff] [blame] | 550 | |
| 551 | public ValidationResult validate(IResource resource, int kind, ValidationState state, IProgressMonitor monitor) { |
| 552 | if (resource.getType() != IResource.FILE) |
| 553 | return null; |
| 554 | ValidationResult result = new ValidationResult(); |
| 555 | IReporter reporter = result.getReporter(monitor); |
| 556 | validateFile(null, reporter, (IFile) resource); |
| 557 | return result; |
| 558 | } |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 559 | } |