blob: b3df14855dd717829e87a419554e42304b237182 [file] [log] [blame]
package org.eclipse.jst.jsf.facelet.ui.internal.validation;
import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.Set;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.core.runtime.content.IContentTypeManager;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.jst.jsf.common.runtime.internal.view.model.common.Namespace;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IDOMContextResolver;
import org.eclipse.jst.jsf.context.resolver.structureddocument.IStructuredDocumentContextResolverFactory;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContext;
import org.eclipse.jst.jsf.context.structureddocument.IStructuredDocumentContextFactory;
import org.eclipse.jst.jsf.core.internal.JSFCorePlugin;
import org.eclipse.jst.jsf.designtime.internal.view.model.ITagRegistry;
import org.eclipse.jst.jsf.facelet.core.internal.util.ViewUtil;
import org.eclipse.jst.jsf.facelet.ui.internal.FaceletUiPlugin;
import org.eclipse.jst.jsf.validation.internal.IJSFViewValidator;
import org.eclipse.jst.jsf.validation.internal.JSFValidatorFactory;
import org.eclipse.jst.jsf.validation.internal.ValidationPreferences;
import org.eclipse.jst.jsf.validation.internal.facelet.FaceletDiagnosticFactory;
import org.eclipse.wst.sse.core.StructuredModelManager;
import org.eclipse.wst.sse.core.internal.provisional.IStructuredModel;
import org.eclipse.wst.sse.core.internal.provisional.text.IStructuredDocument;
import org.eclipse.wst.validation.AbstractValidator;
import org.eclipse.wst.validation.ValidationResult;
import org.eclipse.wst.validation.ValidationState;
import org.eclipse.wst.validation.internal.core.ValidationException;
import org.eclipse.wst.validation.internal.operations.LocalizedMessage;
import org.eclipse.wst.validation.internal.provisional.core.IMessage;
import org.eclipse.wst.validation.internal.provisional.core.IReporter;
import org.eclipse.wst.validation.internal.provisional.core.IValidationContext;
import org.eclipse.wst.validation.internal.provisional.core.IValidator;
import org.eclipse.wst.xml.core.internal.provisional.document.IDOMAttr;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
/**
* The Facelet HTML file validator.
*
* @author cbateman
*
*/
public class HTMLValidator extends AbstractValidator implements IValidator
{
private FaceletDiagnosticFactory _diagnosticFactory = new FaceletDiagnosticFactory();
/**
* @param helper
* @return no rule, null
*/
public ISchedulingRule getSchedulingRule(final IValidationContext helper)
{
// no rule...
return null;
}
/**
* @param helper
* @param reporter
* @return status of this validation
* @throws ValidationException
*/
public IStatus validateInJob(final IValidationContext helper,
final IReporter reporter) throws ValidationException
{
IStatus status = Status.OK_STATUS;
try
{
validate(helper, reporter);
}
catch (final ValidationException e)
{
status = new Status(IStatus.ERROR, FaceletUiPlugin.PLUGIN_ID,
IStatus.ERROR, e.getLocalizedMessage(), e);
}
return status;
}
public void cleanup(final IReporter reporter)
{
// do nothing
}
@Override
public ValidationResult validate(IResource resource, int kind, ValidationState state, IProgressMonitor monitor){
ValidationResult vr = new ValidationResult();
if (resource == null || !(resource instanceof IFile)) {
return vr;
}
IFile currentFile = (IFile) resource;
if (shouldValidate(currentFile)) {
validateFile(currentFile, vr.getReporter(monitor));
}
return vr;
}
public void validate(final IValidationContext helper,
final IReporter reporter) throws ValidationException
{
final String[] uris = helper.getURIs();
final IWorkspaceRoot wsRoot = ResourcesPlugin.getWorkspace().getRoot();
if (uris.length > 0)
{
IFile currentFile = null;
for (int i = 0; i < uris.length && !reporter.isCancelled(); i++)
{
currentFile = wsRoot.getFile(new Path(uris[i]));
if (currentFile != null && currentFile.exists())
{
if (shouldValidate(currentFile))
{
final int percent = (i * 100) / uris.length + 1;
final IMessage message = new LocalizedMessage(
IMessage.LOW_SEVERITY, percent + "% " + uris[i]);
reporter.displaySubtask(this, message);
validateFile(currentFile, reporter);
}
}
}
}
}
private void validateFile(final IFile file, final IReporter reporter)
{
final IJSFViewValidator validator = JSFValidatorFactory
.createDefaultXMLValidator();
final ValidationPreferences prefs = new ValidationPreferences(
JSFCorePlugin.getDefault().getPreferenceStore());
prefs.load();
IStructuredModel model = null;
try
{
model = StructuredModelManager.getModelManager().getModelForRead(
file);
final ValidationReporter jsfReporter = new ValidationReporter(this,
reporter, file, prefs, model);
validator.validateView(file, jsfReporter);
// TODO: break off into composite strategies
validateFaceletHtml(file, jsfReporter);
}
catch (final CoreException e)
{
JSFCorePlugin.log("Error validating JSF", e);
}
catch (final IOException e)
{
JSFCorePlugin.log("Error validating JSF", e);
}
finally
{
if (null != model)
{
model.releaseFromRead();
}
}
}
private void validateFaceletHtml(final IFile file,
final ValidationReporter reporter)
{
IStructuredModel model = null;
try
{
model = StructuredModelManager.getModelManager().getModelForRead(
file);
final IStructuredDocument structuredDoc = model
.getStructuredDocument();
validateDocument(structuredDoc, reporter, file.getProject());
}
catch (final CoreException e)
{
JSFCorePlugin.log("Error validating JSF", e);
}
catch (final IOException e)
{
JSFCorePlugin.log("Error validating JSF", e);
}
finally
{
if (null != model)
{
model.releaseFromRead();
}
}
}
private void validateDocument(IStructuredDocument structuredDoc,
final ValidationReporter reporter, IProject project)
{
validateRoot(structuredDoc, reporter, project);
}
private void validateRoot(IStructuredDocument structuredDoc,
ValidationReporter reporter, IProject project)
{
final IStructuredDocumentContext context = IStructuredDocumentContextFactory.INSTANCE
.getContext(structuredDoc, -1);
final IDOMContextResolver resolver = IStructuredDocumentContextResolverFactory.INSTANCE
.getDOMContextResolver(context);
final Document document = resolver.getDOMDocument();
Element rootElement = document.getDocumentElement();
if ("html".equals(rootElement.getNodeName()))
{
final Set<Attr> declaredNamespaces = ViewUtil
.getDeclaredNamespaces(rootElement.getAttributes());
final ITagRegistry tagRegistry = ViewUtil
.getHtmlTagRegistry(project);
final Collection<? extends Namespace> namespaces;
if (tagRegistry != null)
{
namespaces = tagRegistry.getAllTagLibraries();
}
else
{
// unexpected
namespaces = Collections.EMPTY_SET;
JSFCorePlugin.log(IStatus.ERROR, "Program Error: HTML tag registry not found"); //$NON-NLS-1$
}
for (final Attr attr : declaredNamespaces)
{
// only validate prefix declarations
if (attr.getPrefix() != null && attr instanceof IDOMAttr)
{
final String declaredUri = attr.getValue();
String findUri = null;
SEARCH_NAMESPACES: for (final Namespace ns : namespaces)
{
if (ns.getNSUri().equals(declaredUri))
{
findUri = ns.getNSUri();
break SEARCH_NAMESPACES;
}
}
if (findUri == null)
{
final Diagnostic diag = _diagnosticFactory.create_CANNOT_FIND_FACELET_TAGLIB(declaredUri);
final IDOMAttr domAttr = (IDOMAttr) attr;
reporter.report(diag, domAttr.getValueRegionStartOffset(), domAttr
.getValue().length());
}
}
}
}
}
private boolean shouldValidate(final IFile model)
{
final IContentTypeManager manager = Platform.getContentTypeManager();
final IContentType contentType = manager
.getContentType("org.eclipse.wst.html.core.htmlsource");
return (contentType.isAssociatedWith(model.getName()))
&& ViewUtil.isFaceletVDLFile(model);
}
}