blob: c7675dcbfd86b621f928552311c8b4a82a99be00 [file] [log] [blame]
david_williams49d24fb2005-04-08 21:16:59 +00001/*******************************************************************************
2 * Copyright (c) 2001, 2004 IBM Corporation and others.
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 *******************************************************************************/
paverye6107e62005-02-23 18:01:10 +000011package org.eclipse.wst.html.validation;
12
13import java.io.IOException;
14import java.io.UnsupportedEncodingException;
15
16import org.eclipse.core.resources.IContainer;
17import org.eclipse.core.resources.IFile;
18import org.eclipse.core.resources.IProject;
19import org.eclipse.core.resources.IResource;
20import org.eclipse.core.resources.ResourcesPlugin;
21import org.eclipse.core.runtime.CoreException;
22import org.eclipse.core.runtime.NullProgressMonitor;
23import org.eclipse.core.runtime.OperationCanceledException;
24import org.eclipse.core.runtime.Path;
25import org.eclipse.wst.html.core.validate.HTMLValidationAdapterFactory;
david_williams285ee2d2005-04-10 18:21:21 +000026import org.eclipse.wst.sse.core.INodeAdapterFactory;
paverye6107e62005-02-23 18:01:10 +000027import org.eclipse.wst.sse.core.IModelManager;
28import org.eclipse.wst.sse.core.IStructuredModel;
29import org.eclipse.wst.sse.core.StructuredModelManager;
30import org.eclipse.wst.sse.core.util.URIResolver;
31import org.eclipse.wst.sse.core.validate.ValidationAdapter;
paverye6107e62005-02-23 18:01:10 +000032import org.eclipse.wst.validation.internal.operations.IWorkbenchHelper;
33import org.eclipse.wst.validation.internal.operations.WorkbenchReporter;
david_williams49d24fb2005-04-08 21:16:59 +000034import org.eclipse.wst.validation.internal.provisional.core.IFileDelta;
35import org.eclipse.wst.validation.internal.provisional.core.IMessage;
36import org.eclipse.wst.validation.internal.provisional.core.IReporter;
37import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
38import org.eclipse.wst.validation.internal.provisional.core.IValidator;
david_williamsc39caaf2005-04-05 06:07:16 +000039import org.eclipse.wst.xml.core.document.IDOMDocument;
40import org.eclipse.wst.xml.core.document.IDOMModel;
david_williams646a5e22005-04-02 07:16:27 +000041import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
nitind86040ef2005-03-11 22:06:40 +000042import org.eclispe.wst.validation.internal.core.Message;
paverye6107e62005-02-23 18:01:10 +000043
44public class HTMLValidator implements IValidator {
45 /**
46 */
47 public HTMLValidator() {
48 super();
49 }
50
51 /**
52 */
53 public void cleanup(IReporter reporter) {
54 // nothing to do
55 }
56
57 /**
58 */
david_williamsc39caaf2005-04-05 06:07:16 +000059 protected IDOMModel getModel(IProject project, IFile file) {
paverye6107e62005-02-23 18:01:10 +000060 if (project == null || file == null)
61 return null;
62 if (!file.exists())
63 return null;
64 if (!canHandle(file))
65 return null;
66
67 IStructuredModel model = null;
68 IModelManager manager = StructuredModelManager.getModelManager();
69
70 try {
71 try {
72 model = manager.getModelForRead(file);
73 }
74 catch (UnsupportedEncodingException ex) {
david_williams49d24fb2005-04-08 21:16:59 +000075 // retry ignoring META charset for invalid META charset
76 // specification
paverye6107e62005-02-23 18:01:10 +000077 // recreate input stream, because it is already partially read
78 model = manager.getModelForRead(file, new String(), null);
79 }
80 }
81 catch (UnsupportedEncodingException ex) {
82 }
83 catch (IOException ex) {
84 }
85 catch (CoreException ex) {
86 }
87
88 if (model == null)
89 return null;
david_williamsc39caaf2005-04-05 06:07:16 +000090 if (!(model instanceof IDOMModel)) {
paverye6107e62005-02-23 18:01:10 +000091 releaseModel(model);
92 return null;
93 }
david_williamsc39caaf2005-04-05 06:07:16 +000094 return (IDOMModel) model;
paverye6107e62005-02-23 18:01:10 +000095 }
96
97 /**
98 */
david_williamsc39caaf2005-04-05 06:07:16 +000099 protected HTMLValidationReporter getReporter(IReporter reporter, IFile file, IDOMModel model) {
paverye6107e62005-02-23 18:01:10 +0000100 return new HTMLValidationReporter(this, reporter, file, model);
101 }
102
103 /**
104 * Check file extension to validate
105 */
106 private boolean canHandle(IFile file) {
107 if (file == null)
108 return false;
109 String name = file.getFullPath().toString();
110 if (name == null)
111 return false;
112 int index = name.lastIndexOf('.');
113 if (index < 0)
114 return false;
115 String ext = name.substring(index + 1);
116 if (ext == null || ext.length() == 0)
117 return false;
118 ext = ext.toLowerCase();
119 return (ext.startsWith("htm") || //$NON-NLS-1$
120 ext.startsWith("jsp") || //$NON-NLS-1$
121 ext.equals("jsf") || //$NON-NLS-1$
122 ext.startsWith("xht") || //$NON-NLS-1$
123 ext.startsWith("shtm") || //$NON-NLS-1$
124 ext.startsWith("wml") || //$NON-NLS-1$
125 ext.equals("jhtml"));//$NON-NLS-1$
126 }
127
128 /**
129 */
david_williamsc39caaf2005-04-05 06:07:16 +0000130 private boolean hasHTMLFeature(IDOMDocument document) {
paverye6107e62005-02-23 18:01:10 +0000131 DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class);
132 if (adapter == null)
133 return false;
134 return adapter.hasFeature("HTML");//$NON-NLS-1$
135 }
136
137 /**
138 */
139 protected void releaseModel(IStructuredModel model) {
140 if (model != null)
141 model.releaseFromRead();
142 }
143
144 /**
145 */
david_williams43271672005-04-01 05:19:26 +0000146 public void validate(IValidationContext helper, IReporter reporter, IFileDelta[] deltaArray) {
paverye6107e62005-02-23 18:01:10 +0000147 if (helper == null)
148 return;
149 if ((reporter != null) && (reporter.isCancelled() == true)) {
150 throw new OperationCanceledException();
151 }
152 if (deltaArray != null && deltaArray.length > 0) {
153 validateDelta(helper, reporter, deltaArray);
154 }
155 else {
156 validateFull(helper, reporter, deltaArray);
157 }
158 }
159
160 /**
161 */
david_williamsc39caaf2005-04-05 06:07:16 +0000162 protected HTMLValidationResult validate(IDOMModel model, IFile file) {
paverye6107e62005-02-23 18:01:10 +0000163 IProject prj = null;
164 if (file != null) {
165 prj = file.getProject();
166 }
david_williams49d24fb2005-04-08 21:16:59 +0000167 if ((prj == null) && (model != null)) {
paverye6107e62005-02-23 18:01:10 +0000168 URIResolver res = model.getResolver();
169 if (res != null) {
170 prj = res.getProject();
171 }
172 }
173 final WorkbenchReporter reporter = new WorkbenchReporter(prj, new NullProgressMonitor());
david_williams49d24fb2005-04-08 21:16:59 +0000174 return validate(reporter, file, model);
paverye6107e62005-02-23 18:01:10 +0000175 }
176
177 /**
178 */
david_williamsc39caaf2005-04-05 06:07:16 +0000179 private HTMLValidationResult validate(IReporter reporter, IFile file, IDOMModel model) {
paverye6107e62005-02-23 18:01:10 +0000180 if (file == null || model == null)
181 return null; // error
david_williamsc39caaf2005-04-05 06:07:16 +0000182 IDOMDocument document = model.getDocument();
paverye6107e62005-02-23 18:01:10 +0000183 if (document == null)
184 return null; // error
185 if (!hasHTMLFeature(document))
186 return null; // ignore
187
david_williams285ee2d2005-04-10 18:21:21 +0000188 INodeAdapterFactory factory = HTMLValidationAdapterFactory.getInstance();
paverye6107e62005-02-23 18:01:10 +0000189 ValidationAdapter adapter = (ValidationAdapter) factory.adapt(document);
190 if (adapter == null)
191 return null; // error
192
193 HTMLValidationReporter rep = getReporter(reporter, file, model);
194 rep.clear();
195 adapter.setReporter(rep);
196 if (reporter != null) {
197 String args[] = new String[]{file.getFullPath().toString()};
david_williams49d24fb2005-04-08 21:16:59 +0000198
199 // Message mess = new Message("HTMLValidation", //$NON-NLS-1$
200 // SeverityEnum.LOW_SEVERITY,
201 // "MESSAGE_HTML_VALIDATION_MESSAGE_UI_", //$NON-NLS-1$
202 // args);
nitind86040ef2005-03-11 22:06:40 +0000203 Message mess = new LocalizedMessage(IMessage.LOW_SEVERITY, "MESSAGE_HTML_VALIDATION_MESSAGE_UI_");
paverye6107e62005-02-23 18:01:10 +0000204 mess.setParams(args);
205 reporter.displaySubtask(this, mess);
206 }
207 adapter.validate(document);
208 return rep.getResult();
209 }
210
211 /**
212 */
david_williams43271672005-04-01 05:19:26 +0000213 private void validateContainer(IValidationContext helper, IReporter reporter, IContainer container) {
paverye6107e62005-02-23 18:01:10 +0000214 try {
215 IResource[] resourceArray = container.members(false);
216 for (int i = 0; i < resourceArray.length; i++) {
217 IResource resource = resourceArray[i];
218 if (resource == null)
219 continue;
220 if (resource instanceof IFile) {
221 validateFile(helper, reporter, (IFile) resource);
222 }
223 else if (resource instanceof IContainer) {
224 validateContainer(helper, reporter, (IContainer) resource);
225 }
226 }
227 }
228 catch (CoreException ex) {
229 }
230 }
231
232 /**
233 */
david_williams43271672005-04-01 05:19:26 +0000234 private void validateDelta(IValidationContext helper, IReporter reporter, IFileDelta[] deltaArray) {
paverye6107e62005-02-23 18:01:10 +0000235 for (int i = 0; i < deltaArray.length; i++) {
236 IFileDelta delta = deltaArray[i];
237 if (delta == null || delta.getDeltaType() == IFileDelta.DELETED)
238 continue;
239 IResource resource = getResource(delta);
240 if (resource == null || !(resource instanceof IFile))
241 continue;
242 validateFile(helper, reporter, (IFile) resource);
243 }
244 }
245
246 /**
247 */
david_williams43271672005-04-01 05:19:26 +0000248 private void validateFile(IValidationContext helper, IReporter reporter, IFile file) {
paverye6107e62005-02-23 18:01:10 +0000249 if ((reporter != null) && (reporter.isCancelled() == true)) {
250 throw new OperationCanceledException();
251 }
david_williamsc39caaf2005-04-05 06:07:16 +0000252 IDOMModel model = getModel(file.getProject(), file);
paverye6107e62005-02-23 18:01:10 +0000253 if (model == null)
254 return;
255
256 try {
257 validate(reporter, file, model);
258 }
259 finally {
260 releaseModel(model);
261 }
262 }
263
264 /**
265 */
david_williams43271672005-04-01 05:19:26 +0000266 private void validateFull(IValidationContext helper, IReporter reporter, IFileDelta[] fileDelta) {
paverye6107e62005-02-23 18:01:10 +0000267 IProject project = null;
david_williams49d24fb2005-04-08 21:16:59 +0000268 if (helper instanceof IWorkbenchHelper) {
269 IWorkbenchHelper wbHelper = (IWorkbenchHelper) helper;
paverye6107e62005-02-23 18:01:10 +0000270 project = wbHelper.getProject();
271 }
272 else {
273 // won't work for project validation (b/c nothing in file delta)
274 project = getResource(fileDelta[0]).getProject();
275 }
276 if (project == null)
277 return;
278 validateContainer(helper, reporter, project);
279 }
280
david_williams49d24fb2005-04-08 21:16:59 +0000281 /*
paverye6107e62005-02-23 18:01:10 +0000282 * added to get rid or dependency on IWorkbenchHelper
david_williams49d24fb2005-04-08 21:16:59 +0000283 *
paverye6107e62005-02-23 18:01:10 +0000284 * @see com.ibm.sse.editor.extensions.validator.IWorkbenchHelper#getResource(com.ibm.sse.editor.extensions.validator.IFileDelta)
285 */
286 public IResource getResource(IFileDelta delta) {
287 IResource res = null;
288 if (delta instanceof IResource)
289 res = (IResource) delta;
290 else
291 res = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(delta.getFileName()));
292 return res;
293 }
294}