blob: 5edd04ed623a59398a059089bae8dd44ba7ace99 [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 *******************************************************************************/
david_williams96643dd2005-04-13 04:35:24 +000011package org.eclipse.wst.html.internal.validation;
paverye6107e62005-02-23 18:01:10 +000012
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;
david_williamse6ed7322005-10-10 17:32:24 +000022import org.eclipse.core.runtime.IPath;
paverye6107e62005-02-23 18:01:10 +000023import org.eclipse.core.runtime.NullProgressMonitor;
24import org.eclipse.core.runtime.OperationCanceledException;
25import org.eclipse.core.runtime.Path;
david_williamse6ed7322005-10-10 17:32:24 +000026import org.eclipse.core.runtime.Platform;
27import org.eclipse.core.runtime.content.IContentType;
28import org.eclipse.core.runtime.content.IContentTypeManager;
nitinde83b1a42005-06-22 21:22:20 +000029import org.eclipse.osgi.util.NLS;
david_williams56777022005-04-11 06:21:55 +000030import org.eclipse.wst.html.core.internal.validate.HTMLValidationAdapterFactory;
david_williams3a2ab2d2005-04-11 16:32:45 +000031import org.eclipse.wst.html.ui.internal.HTMLUIMessages;
david_williams4ad020f2005-04-18 08:00:30 +000032import org.eclipse.wst.sse.core.internal.provisional.IModelManager;
33import org.eclipse.wst.sse.core.internal.provisional.INodeAdapterFactory;
34import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
35import org.eclipse.wst.sse.core.internal.provisional.StructuredModelManager;
david_williams2aecf082005-04-13 05:03:21 +000036import org.eclipse.wst.sse.core.internal.util.URIResolver;
david_williams3bcfe392005-04-13 04:49:36 +000037import org.eclipse.wst.sse.core.internal.validate.ValidationAdapter;
vbhadrir0b14da32005-04-18 15:40:15 +000038import org.eclipse.wst.validation.internal.core.Message;
vbhadrir271d28a2005-04-12 19:36:05 +000039import org.eclipse.wst.validation.internal.operations.IWorkbenchContext;
paverye6107e62005-02-23 18:01:10 +000040import org.eclipse.wst.validation.internal.operations.WorkbenchReporter;
david_williams49d24fb2005-04-08 21:16:59 +000041import org.eclipse.wst.validation.internal.provisional.core.IMessage;
42import org.eclipse.wst.validation.internal.provisional.core.IReporter;
43import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
44import org.eclipse.wst.validation.internal.provisional.core.IValidator;
david_williams646a5e22005-04-02 07:16:27 +000045import org.eclipse.wst.xml.core.internal.document.DocumentTypeAdapter;
david_williams4ad020f2005-04-18 08:00:30 +000046import org.eclipse.wst.xml.core.internal.provisional.document.IDOMDocument;
47import org.eclipse.wst.xml.core.internal.provisional.document.IDOMModel;
paverye6107e62005-02-23 18:01:10 +000048
49public class HTMLValidator implements IValidator {
david_williamse6ed7322005-10-10 17:32:24 +000050 private static final String ORG_ECLIPSE_JST_JSP_CORE_JSPSOURCE = "org.eclipse.jst.jsp.core.jspsource";
51 private static final String ORG_ECLIPSE_WST_HTML_CORE_HTMLSOURCE = "org.eclipse.wst.html.core.htmlsource";
52
nitind165498a2005-07-12 18:47:49 +000053 static boolean shouldValidate(IFile file) {
54 IResource resource = file;
55 do {
56 if (resource.isDerived() || resource.isTeamPrivateMember() || !resource.isAccessible() || (resource.getName().charAt(0) == '.' && resource.getType() == IResource.FOLDER)) {
57 return false;
58 }
59 resource = resource.getParent();
60 }
61 while ((resource.getType() & IResource.PROJECT) == 0);
62 return true;
63 }
64
paverye6107e62005-02-23 18:01:10 +000065 public HTMLValidator() {
66 super();
67 }
68
69 /**
70 */
71 public void cleanup(IReporter reporter) {
72 // nothing to do
73 }
74
75 /**
76 */
david_williamsc39caaf2005-04-05 06:07:16 +000077 protected IDOMModel getModel(IProject project, IFile file) {
paverye6107e62005-02-23 18:01:10 +000078 if (project == null || file == null)
79 return null;
80 if (!file.exists())
81 return null;
82 if (!canHandle(file))
83 return null;
84
85 IStructuredModel model = null;
86 IModelManager manager = StructuredModelManager.getModelManager();
87
88 try {
89 try {
90 model = manager.getModelForRead(file);
91 }
92 catch (UnsupportedEncodingException ex) {
david_williams49d24fb2005-04-08 21:16:59 +000093 // retry ignoring META charset for invalid META charset
94 // specification
paverye6107e62005-02-23 18:01:10 +000095 // recreate input stream, because it is already partially read
96 model = manager.getModelForRead(file, new String(), null);
97 }
98 }
99 catch (UnsupportedEncodingException ex) {
100 }
101 catch (IOException ex) {
102 }
103 catch (CoreException ex) {
104 }
105
106 if (model == null)
107 return null;
david_williamsc39caaf2005-04-05 06:07:16 +0000108 if (!(model instanceof IDOMModel)) {
paverye6107e62005-02-23 18:01:10 +0000109 releaseModel(model);
110 return null;
111 }
david_williamsc39caaf2005-04-05 06:07:16 +0000112 return (IDOMModel) model;
paverye6107e62005-02-23 18:01:10 +0000113 }
114
115 /**
116 */
david_williamsc39caaf2005-04-05 06:07:16 +0000117 protected HTMLValidationReporter getReporter(IReporter reporter, IFile file, IDOMModel model) {
paverye6107e62005-02-23 18:01:10 +0000118 return new HTMLValidationReporter(this, reporter, file, model);
119 }
120
121 /**
122 * Check file extension to validate
123 */
124 private boolean canHandle(IFile file) {
david_williamse6ed7322005-10-10 17:32:24 +0000125 boolean result = false;
126 if (file != null) {
127 try {
128 IContentTypeManager contentTypeManager = Platform.getContentTypeManager();
129
130 IContentType fileContentType = file.getContentDescription().getContentType();
131
132 IContentType htmlContentType = contentTypeManager.getContentType(ORG_ECLIPSE_WST_HTML_CORE_HTMLSOURCE);
133 if (htmlContentType != null) {
134 if (fileContentType.isKindOf(htmlContentType)) {
135 result = true;
136 }
137 else {
138 // ISSUE: here's a little "backwards" dependancy.
139 // there should be a "JSPEMBEDDEDHTML validator"
140 // contributed by JSP plugin.
141 IContentType jspContentType = contentTypeManager.getContentType(ORG_ECLIPSE_JST_JSP_CORE_JSPSOURCE);
142 if (jspContentType != null) {
143 result = fileContentType.isKindOf(jspContentType);
144 }
145 }
146 }
147 }
148 catch (CoreException e) {
149 // should be rare, but will ignore to avoid logging "encoding
150 // exceptions" and the like here.
151 // Logger.logException(e);
152 }
153 }
154 return result;
paverye6107e62005-02-23 18:01:10 +0000155 }
156
157 /**
158 */
david_williamsc39caaf2005-04-05 06:07:16 +0000159 private boolean hasHTMLFeature(IDOMDocument document) {
paverye6107e62005-02-23 18:01:10 +0000160 DocumentTypeAdapter adapter = (DocumentTypeAdapter) document.getAdapterFor(DocumentTypeAdapter.class);
161 if (adapter == null)
162 return false;
163 return adapter.hasFeature("HTML");//$NON-NLS-1$
164 }
165
166 /**
167 */
168 protected void releaseModel(IStructuredModel model) {
169 if (model != null)
170 model.releaseFromRead();
171 }
172
173 /**
174 */
vbhadrir271d28a2005-04-12 19:36:05 +0000175 public void validate(IValidationContext helper, IReporter reporter) {
paverye6107e62005-02-23 18:01:10 +0000176 if (helper == null)
177 return;
178 if ((reporter != null) && (reporter.isCancelled() == true)) {
179 throw new OperationCanceledException();
180 }
vbhadrir271d28a2005-04-12 19:36:05 +0000181 String[] deltaArray = helper.getURIs();
paverye6107e62005-02-23 18:01:10 +0000182 if (deltaArray != null && deltaArray.length > 0) {
vbhadrir271d28a2005-04-12 19:36:05 +0000183 validateDelta(helper, reporter);
paverye6107e62005-02-23 18:01:10 +0000184 }
185 else {
vbhadrir271d28a2005-04-12 19:36:05 +0000186 validateFull(helper, reporter);
paverye6107e62005-02-23 18:01:10 +0000187 }
188 }
189
190 /**
191 */
david_williamsc39caaf2005-04-05 06:07:16 +0000192 protected HTMLValidationResult validate(IDOMModel model, IFile file) {
paverye6107e62005-02-23 18:01:10 +0000193 IProject prj = null;
194 if (file != null) {
195 prj = file.getProject();
196 }
david_williams49d24fb2005-04-08 21:16:59 +0000197 if ((prj == null) && (model != null)) {
paverye6107e62005-02-23 18:01:10 +0000198 URIResolver res = model.getResolver();
199 if (res != null) {
200 prj = res.getProject();
201 }
202 }
203 final WorkbenchReporter reporter = new WorkbenchReporter(prj, new NullProgressMonitor());
david_williams49d24fb2005-04-08 21:16:59 +0000204 return validate(reporter, file, model);
paverye6107e62005-02-23 18:01:10 +0000205 }
206
207 /**
208 */
david_williamsc39caaf2005-04-05 06:07:16 +0000209 private HTMLValidationResult validate(IReporter reporter, IFile file, IDOMModel model) {
paverye6107e62005-02-23 18:01:10 +0000210 if (file == null || model == null)
211 return null; // error
david_williamsc39caaf2005-04-05 06:07:16 +0000212 IDOMDocument document = model.getDocument();
paverye6107e62005-02-23 18:01:10 +0000213 if (document == null)
214 return null; // error
215 if (!hasHTMLFeature(document))
216 return null; // ignore
217
david_williams285ee2d2005-04-10 18:21:21 +0000218 INodeAdapterFactory factory = HTMLValidationAdapterFactory.getInstance();
paverye6107e62005-02-23 18:01:10 +0000219 ValidationAdapter adapter = (ValidationAdapter) factory.adapt(document);
220 if (adapter == null)
221 return null; // error
222
223 HTMLValidationReporter rep = getReporter(reporter, file, model);
224 rep.clear();
225 adapter.setReporter(rep);
226 if (reporter != null) {
david_williamse6ed7322005-10-10 17:32:24 +0000227 String fileName = "";
228 IPath filePath = file.getFullPath();
229 if (filePath != null) {
230 fileName = filePath.toString();
231 }
232 String args[] = new String[]{fileName};
david_williams49d24fb2005-04-08 21:16:59 +0000233
234 // Message mess = new Message("HTMLValidation", //$NON-NLS-1$
235 // SeverityEnum.LOW_SEVERITY,
236 // "MESSAGE_HTML_VALIDATION_MESSAGE_UI_", //$NON-NLS-1$
237 // args);
nitinde83b1a42005-06-22 21:22:20 +0000238 Message mess = new LocalizedMessage(IMessage.LOW_SEVERITY, NLS.bind(HTMLUIMessages.MESSAGE_HTML_VALIDATION_MESSAGE_UI_, args));
paverye6107e62005-02-23 18:01:10 +0000239 mess.setParams(args);
240 reporter.displaySubtask(this, mess);
241 }
242 adapter.validate(document);
243 return rep.getResult();
244 }
245
246 /**
247 */
david_williams43271672005-04-01 05:19:26 +0000248 private void validateContainer(IValidationContext helper, IReporter reporter, IContainer container) {
paverye6107e62005-02-23 18:01:10 +0000249 try {
250 IResource[] resourceArray = container.members(false);
251 for (int i = 0; i < resourceArray.length; i++) {
252 IResource resource = resourceArray[i];
253 if (resource == null)
254 continue;
255 if (resource instanceof IFile) {
256 validateFile(helper, reporter, (IFile) resource);
257 }
258 else if (resource instanceof IContainer) {
259 validateContainer(helper, reporter, (IContainer) resource);
260 }
261 }
262 }
263 catch (CoreException ex) {
264 }
265 }
266
267 /**
268 */
vbhadrir271d28a2005-04-12 19:36:05 +0000269 private void validateDelta(IValidationContext helper, IReporter reporter) {
270 String[] deltaArray = helper.getURIs();
paverye6107e62005-02-23 18:01:10 +0000271 for (int i = 0; i < deltaArray.length; i++) {
vbhadrir271d28a2005-04-12 19:36:05 +0000272 String delta = deltaArray[i];
273 if (delta == null)
paverye6107e62005-02-23 18:01:10 +0000274 continue;
275 IResource resource = getResource(delta);
276 if (resource == null || !(resource instanceof IFile))
277 continue;
278 validateFile(helper, reporter, (IFile) resource);
279 }
280 }
281
282 /**
283 */
david_williams43271672005-04-01 05:19:26 +0000284 private void validateFile(IValidationContext helper, IReporter reporter, IFile file) {
paverye6107e62005-02-23 18:01:10 +0000285 if ((reporter != null) && (reporter.isCancelled() == true)) {
286 throw new OperationCanceledException();
287 }
nitind165498a2005-07-12 18:47:49 +0000288 if (!shouldValidate(file)) {
289 return;
290 }
david_williamsc39caaf2005-04-05 06:07:16 +0000291 IDOMModel model = getModel(file.getProject(), file);
paverye6107e62005-02-23 18:01:10 +0000292 if (model == null)
293 return;
294
295 try {
296 validate(reporter, file, model);
297 }
298 finally {
299 releaseModel(model);
300 }
301 }
302
303 /**
304 */
vbhadrir271d28a2005-04-12 19:36:05 +0000305 private void validateFull(IValidationContext helper, IReporter reporter) {
paverye6107e62005-02-23 18:01:10 +0000306 IProject project = null;
vbhadrir271d28a2005-04-12 19:36:05 +0000307 String[] fileDelta = helper.getURIs();
308 if (helper instanceof IWorkbenchContext) {
309 IWorkbenchContext wbHelper = (IWorkbenchContext) helper;
paverye6107e62005-02-23 18:01:10 +0000310 project = wbHelper.getProject();
311 }
312 else {
313 // won't work for project validation (b/c nothing in file delta)
314 project = getResource(fileDelta[0]).getProject();
315 }
316 if (project == null)
317 return;
318 validateContainer(helper, reporter, project);
319 }
320
david_williams49d24fb2005-04-08 21:16:59 +0000321 /*
paverye6107e62005-02-23 18:01:10 +0000322 * added to get rid or dependency on IWorkbenchHelper
david_williams49d24fb2005-04-08 21:16:59 +0000323 *
paverye6107e62005-02-23 18:01:10 +0000324 */
vbhadrir271d28a2005-04-12 19:36:05 +0000325 public IResource getResource(String delta) {
david_williamse6ed7322005-10-10 17:32:24 +0000326 return ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(delta));
paverye6107e62005-02-23 18:01:10 +0000327 }
328}