pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 1 | package org.eclipse.wst.html.validation; |
| 2 | |
| 3 | import java.io.IOException; |
| 4 | import java.io.UnsupportedEncodingException; |
| 5 | |
| 6 | import org.eclipse.core.resources.IContainer; |
| 7 | import org.eclipse.core.resources.IFile; |
| 8 | import org.eclipse.core.resources.IProject; |
| 9 | import org.eclipse.core.resources.IResource; |
| 10 | import org.eclipse.core.resources.ResourcesPlugin; |
| 11 | import org.eclipse.core.runtime.CoreException; |
| 12 | import org.eclipse.core.runtime.NullProgressMonitor; |
| 13 | import org.eclipse.core.runtime.OperationCanceledException; |
| 14 | import org.eclipse.core.runtime.Path; |
| 15 | import org.eclipse.wst.html.core.validate.HTMLValidationAdapterFactory; |
david_williams | d36efd9 | 2005-03-29 03:39:23 +0000 | [diff] [blame] | 16 | import org.eclipse.wst.sse.core.IAdapterFactory; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 17 | import org.eclipse.wst.sse.core.IModelManager; |
| 18 | import org.eclipse.wst.sse.core.IStructuredModel; |
| 19 | import org.eclipse.wst.sse.core.StructuredModelManager; |
| 20 | import org.eclipse.wst.sse.core.util.URIResolver; |
| 21 | import org.eclipse.wst.sse.core.validate.ValidationAdapter; |
| 22 | import org.eclipse.wst.validation.core.IFileDelta; |
nitind | 86040ef | 2005-03-11 22:06:40 +0000 | [diff] [blame] | 23 | import org.eclipse.wst.validation.core.IMessage; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 24 | import org.eclipse.wst.validation.core.IReporter; |
david_williams | 4327167 | 2005-04-01 05:19:26 +0000 | [diff] [blame] | 25 | import org.eclipse.wst.validation.core.IValidationContext; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 26 | import org.eclipse.wst.validation.core.IValidator; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 27 | import org.eclipse.wst.validation.internal.operations.IWorkbenchHelper; |
| 28 | import org.eclipse.wst.validation.internal.operations.WorkbenchReporter; |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame^] | 29 | import org.eclipse.wst.xml.core.document.IDOMDocument; |
| 30 | import org.eclipse.wst.xml.core.document.IDOMModel; |
david_williams | 646a5e2 | 2005-04-02 07:16:27 +0000 | [diff] [blame] | 31 | import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter; |
nitind | 86040ef | 2005-03-11 22:06:40 +0000 | [diff] [blame] | 32 | import org.eclispe.wst.validation.internal.core.Message; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 33 | |
| 34 | public class HTMLValidator implements IValidator { |
| 35 | /** |
| 36 | */ |
| 37 | public HTMLValidator() { |
| 38 | super(); |
| 39 | } |
| 40 | |
| 41 | /** |
| 42 | */ |
| 43 | public void cleanup(IReporter reporter) { |
| 44 | // nothing to do |
| 45 | } |
| 46 | |
| 47 | /** |
| 48 | */ |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame^] | 49 | protected IDOMModel getModel(IProject project, IFile file) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 50 | if (project == null || file == null) |
| 51 | return null; |
| 52 | if (!file.exists()) |
| 53 | return null; |
| 54 | if (!canHandle(file)) |
| 55 | return null; |
| 56 | |
| 57 | IStructuredModel model = null; |
| 58 | IModelManager manager = StructuredModelManager.getModelManager(); |
| 59 | |
| 60 | try { |
| 61 | try { |
| 62 | model = manager.getModelForRead(file); |
| 63 | } |
| 64 | catch (UnsupportedEncodingException ex) { |
| 65 | // retry ignoring META charset for invalid META charset specification |
| 66 | // recreate input stream, because it is already partially read |
| 67 | model = manager.getModelForRead(file, new String(), null); |
| 68 | } |
| 69 | } |
| 70 | catch (UnsupportedEncodingException ex) { |
| 71 | } |
| 72 | catch (IOException ex) { |
| 73 | } |
| 74 | catch (CoreException ex) { |
| 75 | } |
| 76 | |
| 77 | if (model == null) |
| 78 | return null; |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame^] | 79 | if (!(model instanceof IDOMModel)) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 80 | releaseModel(model); |
| 81 | return null; |
| 82 | } |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame^] | 83 | return (IDOMModel) model; |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | /** |
| 87 | */ |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame^] | 88 | protected HTMLValidationReporter getReporter(IReporter reporter, IFile file, IDOMModel model) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 89 | return new HTMLValidationReporter(this, reporter, file, model); |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Check file extension to validate |
| 94 | */ |
| 95 | private boolean canHandle(IFile file) { |
| 96 | if (file == null) |
| 97 | return false; |
| 98 | String name = file.getFullPath().toString(); |
| 99 | if (name == null) |
| 100 | return false; |
| 101 | int index = name.lastIndexOf('.'); |
| 102 | if (index < 0) |
| 103 | return false; |
| 104 | String ext = name.substring(index + 1); |
| 105 | if (ext == null || ext.length() == 0) |
| 106 | return false; |
| 107 | ext = ext.toLowerCase(); |
| 108 | return (ext.startsWith("htm") || //$NON-NLS-1$ |
| 109 | ext.startsWith("jsp") || //$NON-NLS-1$ |
| 110 | ext.equals("jsf") || //$NON-NLS-1$ |
| 111 | ext.startsWith("xht") || //$NON-NLS-1$ |
| 112 | ext.startsWith("shtm") || //$NON-NLS-1$ |
| 113 | ext.startsWith("wml") || //$NON-NLS-1$ |
| 114 | ext.equals("jhtml"));//$NON-NLS-1$ |
| 115 | } |
| 116 | |
| 117 | /** |
| 118 | */ |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame^] | 119 | private boolean hasHTMLFeature(IDOMDocument document) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 120 | DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class); |
| 121 | if (adapter == null) |
| 122 | return false; |
| 123 | return adapter.hasFeature("HTML");//$NON-NLS-1$ |
| 124 | } |
| 125 | |
| 126 | /** |
| 127 | */ |
| 128 | protected void releaseModel(IStructuredModel model) { |
| 129 | if (model != null) |
| 130 | model.releaseFromRead(); |
| 131 | } |
| 132 | |
| 133 | /** |
| 134 | */ |
david_williams | 4327167 | 2005-04-01 05:19:26 +0000 | [diff] [blame] | 135 | public void validate(IValidationContext helper, IReporter reporter, IFileDelta[] deltaArray) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 136 | if (helper == null) |
| 137 | return; |
| 138 | if ((reporter != null) && (reporter.isCancelled() == true)) { |
| 139 | throw new OperationCanceledException(); |
| 140 | } |
| 141 | if (deltaArray != null && deltaArray.length > 0) { |
| 142 | validateDelta(helper, reporter, deltaArray); |
| 143 | } |
| 144 | else { |
| 145 | validateFull(helper, reporter, deltaArray); |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | /** |
| 150 | */ |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame^] | 151 | protected HTMLValidationResult validate(IDOMModel model, IFile file) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 152 | IProject prj = null; |
| 153 | if (file != null) { |
| 154 | prj = file.getProject(); |
| 155 | } |
| 156 | if ((prj == null) && (model != null)){ |
| 157 | URIResolver res = model.getResolver(); |
| 158 | if (res != null) { |
| 159 | prj = res.getProject(); |
| 160 | } |
| 161 | } |
| 162 | final WorkbenchReporter reporter = new WorkbenchReporter(prj, new NullProgressMonitor()); |
| 163 | return validate( reporter, file, model); |
| 164 | } |
| 165 | |
| 166 | /** |
| 167 | */ |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame^] | 168 | private HTMLValidationResult validate(IReporter reporter, IFile file, IDOMModel model) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 169 | if (file == null || model == null) |
| 170 | return null; // error |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame^] | 171 | IDOMDocument document = model.getDocument(); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 172 | if (document == null) |
| 173 | return null; // error |
| 174 | if (!hasHTMLFeature(document)) |
| 175 | return null; // ignore |
| 176 | |
david_williams | d36efd9 | 2005-03-29 03:39:23 +0000 | [diff] [blame] | 177 | IAdapterFactory factory = HTMLValidationAdapterFactory.getInstance(); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 178 | ValidationAdapter adapter = (ValidationAdapter) factory.adapt(document); |
| 179 | if (adapter == null) |
| 180 | return null; // error |
| 181 | |
| 182 | HTMLValidationReporter rep = getReporter(reporter, file, model); |
| 183 | rep.clear(); |
| 184 | adapter.setReporter(rep); |
| 185 | if (reporter != null) { |
| 186 | String args[] = new String[]{file.getFullPath().toString()}; |
| 187 | |
| 188 | // Message mess = new Message("HTMLValidation", //$NON-NLS-1$ |
| 189 | // SeverityEnum.LOW_SEVERITY, "MESSAGE_HTML_VALIDATION_MESSAGE_UI_", //$NON-NLS-1$ |
| 190 | // args); |
nitind | 86040ef | 2005-03-11 22:06:40 +0000 | [diff] [blame] | 191 | Message mess = new LocalizedMessage(IMessage.LOW_SEVERITY, "MESSAGE_HTML_VALIDATION_MESSAGE_UI_"); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 192 | mess.setParams(args); |
| 193 | reporter.displaySubtask(this, mess); |
| 194 | } |
| 195 | adapter.validate(document); |
| 196 | return rep.getResult(); |
| 197 | } |
| 198 | |
| 199 | /** |
| 200 | */ |
david_williams | 4327167 | 2005-04-01 05:19:26 +0000 | [diff] [blame] | 201 | private void validateContainer(IValidationContext helper, IReporter reporter, IContainer container) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 202 | try { |
| 203 | IResource[] resourceArray = container.members(false); |
| 204 | for (int i = 0; i < resourceArray.length; i++) { |
| 205 | IResource resource = resourceArray[i]; |
| 206 | if (resource == null) |
| 207 | continue; |
| 208 | if (resource instanceof IFile) { |
| 209 | validateFile(helper, reporter, (IFile) resource); |
| 210 | } |
| 211 | else if (resource instanceof IContainer) { |
| 212 | validateContainer(helper, reporter, (IContainer) resource); |
| 213 | } |
| 214 | } |
| 215 | } |
| 216 | catch (CoreException ex) { |
| 217 | } |
| 218 | } |
| 219 | |
| 220 | /** |
| 221 | */ |
david_williams | 4327167 | 2005-04-01 05:19:26 +0000 | [diff] [blame] | 222 | private void validateDelta(IValidationContext helper, IReporter reporter, IFileDelta[] deltaArray) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 223 | for (int i = 0; i < deltaArray.length; i++) { |
| 224 | IFileDelta delta = deltaArray[i]; |
| 225 | if (delta == null || delta.getDeltaType() == IFileDelta.DELETED) |
| 226 | continue; |
| 227 | IResource resource = getResource(delta); |
| 228 | if (resource == null || !(resource instanceof IFile)) |
| 229 | continue; |
| 230 | validateFile(helper, reporter, (IFile) resource); |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | /** |
| 235 | */ |
david_williams | 4327167 | 2005-04-01 05:19:26 +0000 | [diff] [blame] | 236 | private void validateFile(IValidationContext helper, IReporter reporter, IFile file) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 237 | if ((reporter != null) && (reporter.isCancelled() == true)) { |
| 238 | throw new OperationCanceledException(); |
| 239 | } |
david_williams | c39caaf | 2005-04-05 06:07:16 +0000 | [diff] [blame^] | 240 | IDOMModel model = getModel(file.getProject(), file); |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 241 | if (model == null) |
| 242 | return; |
| 243 | |
| 244 | try { |
| 245 | validate(reporter, file, model); |
| 246 | } |
| 247 | finally { |
| 248 | releaseModel(model); |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | /** |
| 253 | */ |
david_williams | 4327167 | 2005-04-01 05:19:26 +0000 | [diff] [blame] | 254 | private void validateFull(IValidationContext helper, IReporter reporter, IFileDelta[] fileDelta) { |
pavery | e6107e6 | 2005-02-23 18:01:10 +0000 | [diff] [blame] | 255 | IProject project = null; |
| 256 | if(helper instanceof IWorkbenchHelper) { |
| 257 | IWorkbenchHelper wbHelper = (IWorkbenchHelper)helper; |
| 258 | project = wbHelper.getProject(); |
| 259 | } |
| 260 | else { |
| 261 | // won't work for project validation (b/c nothing in file delta) |
| 262 | project = getResource(fileDelta[0]).getProject(); |
| 263 | } |
| 264 | if (project == null) |
| 265 | return; |
| 266 | validateContainer(helper, reporter, project); |
| 267 | } |
| 268 | |
| 269 | /* |
| 270 | * added to get rid or dependency on IWorkbenchHelper |
| 271 | * @see com.ibm.sse.editor.extensions.validator.IWorkbenchHelper#getResource(com.ibm.sse.editor.extensions.validator.IFileDelta) |
| 272 | */ |
| 273 | public IResource getResource(IFileDelta delta) { |
| 274 | IResource res = null; |
| 275 | if (delta instanceof IResource) |
| 276 | res = (IResource) delta; |
| 277 | else |
| 278 | res = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(delta.getFileName())); |
| 279 | return res; |
| 280 | } |
| 281 | } |