| /******************************************************************************* |
| * Copyright (c) 2007, 2011 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.wst.validation.internal.model; |
| |
| import java.util.regex.Pattern; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IAdaptable; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.content.IContentType; |
| import org.eclipse.osgi.util.NLS; |
| import org.eclipse.wst.common.project.facet.core.FacetedProjectFramework; |
| import org.eclipse.wst.validation.internal.ContentTypeWrapper; |
| import org.eclipse.wst.validation.internal.Deserializer; |
| import org.eclipse.wst.validation.internal.ExtensionConstants; |
| import org.eclipse.wst.validation.internal.Serializer; |
| import org.eclipse.wst.validation.internal.Tracing; |
| import org.eclipse.wst.validation.internal.ValMessages; |
| import org.eclipse.wst.validation.internal.plugin.ValidationPlugin; |
| |
| /** |
| * A rule that is used to filter out (or in) validation on a resource. |
| * The concrete classes are all immutable. |
| * @author karasiuk |
| * |
| */ |
| public abstract class FilterRule implements IAdaptable { |
| |
| protected final String _pattern; |
| |
| protected static final String PortableFileDelim = "/"; //$NON-NLS-1$ |
| |
| /** |
| * Create a rule based on a configuration element. |
| * |
| * @param rule |
| * The configuration element, see the extension point for details. |
| * @return null if there is a problem. |
| */ |
| public static FilterRule create(IConfigurationElement rule){ |
| String name = rule.getName(); |
| if (ExtensionConstants.Rule.fileext.equals(name))return new FileExt(rule); |
| if (ExtensionConstants.Rule.projectNature.equals(name))return new ProjectNature(rule); |
| if (ExtensionConstants.Rule.file.equals(name))return File.createFile(rule); |
| if (ExtensionConstants.Rule.contentType.equals(name))return ContentType.createContentType(rule); |
| if (ExtensionConstants.Rule.facet.equals(name))return new Facet(rule); |
| if (ExtensionConstants.Rule.pattern.equals(name))return FilePattern.createFilePattern(rule); |
| return null; |
| } |
| |
| static FilterRule create(Deserializer des) { |
| String type = des.getString(); |
| if (ExtensionConstants.Rule.fileext.equals(type)){ |
| String pattern = des.getString(); |
| boolean caseSensitive = des.getBoolean(); |
| return new FileExt(pattern, caseSensitive); |
| } |
| |
| if (ExtensionConstants.Rule.projectNature.equals(type)){ |
| String pattern = des.getString(); |
| return new ProjectNature(pattern); |
| } |
| |
| if (ExtensionConstants.Rule.file.equals(type)){ |
| String pattern = des.getString(); |
| boolean caseSensitive = des.getBoolean(); |
| int fileType = des.getInt(); |
| return new File(pattern, caseSensitive, fileType); |
| } |
| |
| if (ExtensionConstants.Rule.contentType.equals(type)){ |
| String pattern = des.getString(); |
| boolean exactMatch = des.getBoolean(); |
| return new ContentType(pattern, exactMatch); |
| } |
| |
| if (ExtensionConstants.Rule.facet.equals(type)){ |
| String pattern = des.getString(); |
| return new Facet(pattern, null); |
| } |
| |
| if (ExtensionConstants.Rule.pattern.equals(type)){ |
| String pattern = des.getString(); |
| boolean caseSensitive = des.getBoolean(); |
| return new FilePattern(pattern, caseSensitive); |
| } |
| return null; |
| } |
| |
| |
| public static FilterRule createFile(String pattern, boolean caseSensitive, int type){ |
| return new File(pattern, caseSensitive, type); |
| } |
| |
| public static FilterRule createFileExt(String pattern, boolean caseSensitive){ |
| FileExt ext = new FileExt(pattern, caseSensitive); |
| return ext; |
| } |
| |
| public static FilterRule createFacet(String facetId){ |
| return new Facet(facetId, null); |
| } |
| |
| public static FilterRule createProject(String projectNature){ |
| return new ProjectNature(projectNature); |
| } |
| |
| public static FilterRule createContentType(String contentType, boolean exactMatch){ |
| return new ContentType(contentType, exactMatch); |
| } |
| |
| protected FilterRule(String pattern){ |
| _pattern = pattern; |
| } |
| |
| /** |
| * Answer true if the rule matches the resource, false if it doesn't, and |
| * null if the rule does not apply to resources. |
| * |
| * @param resource the resource that is being validated. |
| */ |
| public Boolean matchesResource(IResource resource, ContentTypeWrapper contentTypeWrapper){ |
| return null; |
| } |
| |
| /** |
| * Answer true if the rule matches the project, false if it doesn't, and null if the |
| * rule does not apply. |
| * |
| * @param project the project that is being validated. |
| */ |
| public Boolean matchesProject(IProject project){ |
| return null; |
| } |
| |
| public String toString() { |
| return getDisplayableType() + ": " + _pattern; //$NON-NLS-1$ |
| } |
| |
| /** Answer a name of the rule, that can be displayed to a user. */ |
| public String getName(){ |
| return toString(); |
| } |
| |
| public String getPattern(){ |
| return _pattern; |
| } |
| |
| /** Answer the type of rule. */ |
| public abstract String getType(); |
| |
| /** Answer a type that can be displayed to an end user. */ |
| public abstract String getDisplayableType(); |
| |
| public static boolean asBoolean(String value, boolean aDefault){ |
| if (value == null)return aDefault; |
| if (value.equals(ExtensionConstants.True))return true; |
| if (value.equals(ExtensionConstants.False))return false; |
| return aDefault; |
| } |
| |
| @SuppressWarnings("unchecked") |
| public Object getAdapter(Class adapter) { |
| return Platform.getAdapterManager().getAdapter(this, adapter); |
| } |
| |
| public static abstract class FilterRuleCaseSensitive extends FilterRule { |
| |
| public FilterRuleCaseSensitive(String pattern, boolean caseSensitive) { |
| super(pattern); |
| _caseSensitive = caseSensitive; |
| } |
| |
| private final boolean _caseSensitive; |
| |
| @Override |
| public int hashCodeForConfig() { |
| int h = super.hashCodeForConfig(); |
| if (_caseSensitive)h += 401; |
| return h; |
| } |
| |
| @Override |
| public void save(Serializer ser) { |
| super.save(ser); |
| ser.put(_caseSensitive); |
| } |
| |
| public boolean isCaseSensitive() { |
| return _caseSensitive; |
| } |
| |
| } |
| |
| public static final class ProjectNature extends FilterRule { |
| |
| private ProjectNature(IConfigurationElement rule) { |
| super(rule.getAttribute(ExtensionConstants.RuleAttrib.id)); |
| |
| } |
| |
| public ProjectNature(String projectNature) { |
| super(projectNature); |
| } |
| |
| public String getDisplayableType() { |
| return ValMessages.RuleProjectNature; |
| } |
| |
| public String getType() { |
| return ExtensionConstants.Rule.projectNature; |
| } |
| |
| public Boolean matchesProject(IProject project) { |
| try { |
| return project.hasNature(_pattern); |
| } |
| catch (CoreException e){ |
| } |
| return Boolean.FALSE; |
| } |
| |
| } |
| |
| public static final class FileExt extends FilterRuleCaseSensitive { |
| |
| private FileExt(IConfigurationElement rule){ |
| super(rule.getAttribute(ExtensionConstants.RuleAttrib.ext), |
| asBoolean(rule.getAttribute(ExtensionConstants.RuleAttrib.caseSensitive), false)); |
| } |
| |
| private FileExt(String pattern, boolean caseSensitive) { |
| super(pattern, caseSensitive); |
| } |
| |
| public String getType() { |
| return ExtensionConstants.Rule.fileext; |
| } |
| |
| public String getDisplayableType() { |
| return ValMessages.RuleFileExt; |
| } |
| |
| public String getName() { |
| return toString(); |
| } |
| |
| public String toString() { |
| if (isCaseSensitive())return NLS.bind(ValMessages.FileExtWithCase, getDisplayableType(), _pattern); |
| return NLS.bind(ValMessages.FileExtWithoutCase, getDisplayableType(), _pattern); |
| } |
| |
| public Boolean matchesResource(IResource resource, ContentTypeWrapper contentTypeWrapper) { |
| String ext = resource.getFileExtension(); |
| if (isCaseSensitive())return _pattern.equals(ext); |
| return _pattern.equalsIgnoreCase(ext); |
| } |
| } |
| |
| /** |
| * A rule that is used to filter based on file or folder names. |
| * @author karasiuk |
| * |
| */ |
| public static final class File extends FilterRuleCaseSensitive { |
| |
| private final String _patternAsLowercase; |
| |
| /** One of the FileTypeXX constants. */ |
| private final int _type; |
| |
| public static final int FileTypeFile = 1; |
| public static final int FileTypeFolder = 2; |
| public static final int FileTypeFull = 3; |
| |
| private static File createFile(IConfigurationElement rule){ |
| String pattern = rule.getAttribute(ExtensionConstants.RuleAttrib.name); |
| if (pattern == null)throw new IllegalStateException(ValMessages.ErrPatternAttrib); |
| String type = rule.getAttribute(ExtensionConstants.RuleAttrib.fileType); |
| if (type == null)throw new IllegalStateException(ValMessages.ErrTypeReq); |
| |
| int myType = -1; |
| if (ExtensionConstants.FileType.file.equals(type))myType = FileTypeFile; |
| else if (ExtensionConstants.FileType.folder.equals(type)){ |
| myType = FileTypeFolder; |
| if (!pattern.endsWith(PortableFileDelim))pattern += PortableFileDelim; |
| } |
| else if (ExtensionConstants.FileType.full.equals(type))myType = FileTypeFull; |
| else { |
| Object[] parms = {type, ExtensionConstants.FileType.file, ExtensionConstants.FileType.folder, |
| ExtensionConstants.FileType.full}; |
| throw new IllegalStateException(NLS.bind(ValMessages.ErrType, parms)); |
| } |
| boolean caseSensitive = asBoolean(rule.getAttribute(ExtensionConstants.RuleAttrib.caseSensitive), false); |
| return new File(pattern, caseSensitive, myType); |
| } |
| |
| private File(String pattern, boolean caseSensitive, int type){ |
| super(pattern, caseSensitive); |
| _type = type; |
| _patternAsLowercase = pattern == null ? null : pattern.toLowerCase(); |
| } |
| |
| public String getType() { |
| return ExtensionConstants.Rule.file; |
| } |
| |
| public String getDisplayableType() { |
| if (_type == FileTypeFolder)return ValMessages.RuleFolder; |
| if (_type == FileTypeFull)return ValMessages.RuleFull; |
| return ValMessages.RuleFile; |
| } |
| |
| public void setData(IConfigurationElement rule) { |
| } |
| |
| public String toString() { |
| if (isCaseSensitive())return NLS.bind(ValMessages.FileExtWithCase, getDisplayableType(), _pattern); |
| return NLS.bind(ValMessages.FileExtWithoutCase, getDisplayableType(), _pattern); |
| } |
| |
| public Boolean matchesResource(IResource resource, ContentTypeWrapper contentTypeWrapper) { |
| String name = null; |
| switch (_type){ |
| case FileTypeFile: |
| name = resource.getName(); |
| break; |
| |
| case FileTypeFolder: |
| name = resource.getProjectRelativePath().removeLastSegments(1).toString() + PortableFileDelim; |
| break; |
| |
| case FileTypeFull: |
| name = resource.getProjectRelativePath().toPortableString(); |
| break; |
| } |
| |
| if (name == null)return Boolean.FALSE; |
| if (isCaseSensitive())return name.startsWith(_pattern); |
| return name.toLowerCase().startsWith(_patternAsLowercase); |
| } |
| |
| @Override |
| public void save(Serializer ser) { |
| super.save(ser); |
| ser.put(_type); |
| } |
| |
| } |
| |
| public static final class Facet extends FilterRule { |
| |
| private final String _versionExpression; |
| |
| private Facet(IConfigurationElement rule){ |
| super(rule.getAttribute(ExtensionConstants.RuleAttrib.id)); |
| _versionExpression = rule.getAttribute(ExtensionConstants.RuleAttrib.version); |
| |
| } |
| |
| public Facet(String facetId, String versionExpression) { |
| super(facetId); |
| _versionExpression = versionExpression; |
| } |
| |
| public String getType() { |
| return ExtensionConstants.Rule.facet; |
| } |
| |
| public String getDisplayableType() { |
| return ValMessages.RuleFacet; |
| } |
| |
| @Override |
| public Boolean matchesProject(IProject project) { |
| try { |
| if (_versionExpression == null)return FacetedProjectFramework.hasProjectFacet(project, _pattern); |
| return FacetedProjectFramework.hasProjectFacet(project, _pattern, _versionExpression); |
| } |
| catch (CoreException e){ |
| if (Tracing.isLogging())ValidationPlugin.getPlugin().handleException(e); |
| } |
| return Boolean.FALSE; |
| } |
| |
| @Override |
| public String toString() { |
| StringBuffer b = new StringBuffer(200); |
| b.append(getDisplayableType()); |
| b.append(": "); //$NON-NLS-1$ |
| b.append(_pattern); |
| |
| if (_versionExpression != null){ |
| b.append(" ("); //$NON-NLS-1$ |
| b.append(_versionExpression); |
| b.append(")"); //$NON-NLS-1$ |
| } |
| return b.toString(); |
| } |
| |
| } |
| |
| public static final class ContentType extends FilterRule { |
| |
| private final IContentType _type; |
| private final boolean _exactMatch; |
| |
| private ContentType(String pattern, boolean exactMatch){ |
| super(pattern); |
| _type = Platform.getContentTypeManager().getContentType(pattern); |
| _exactMatch = exactMatch; |
| } |
| |
| private static ContentType createContentType(IConfigurationElement rule){ |
| String pattern = rule.getAttribute(ExtensionConstants.RuleAttrib.id); |
| boolean exactMatch = true; |
| String exact = rule.getAttribute(ExtensionConstants.RuleAttrib.exactMatch); |
| if (ExtensionConstants.False.equals(exact)) exactMatch = false; |
| |
| return new ContentType(pattern, exactMatch); |
| } |
| |
| public String getType() { |
| return ExtensionConstants.Rule.contentType; |
| } |
| |
| @Override |
| public int hashCodeForConfig() { |
| int h = super.hashCodeForConfig(); |
| if (_exactMatch)h += 301; |
| return h; |
| } |
| |
| public String getDisplayableType() { |
| return ValMessages.RuleContentType; |
| } |
| |
| @Override |
| public void save(Serializer ser) { |
| super.save(ser); |
| ser.put(_exactMatch); |
| } |
| |
| public void setData(IConfigurationElement rule) { |
| } |
| |
| public Boolean matchesResource(IResource resource, ContentTypeWrapper contentTypeWrapper) { |
| if (_type == null)return Boolean.FALSE; |
| if (resource instanceof IFile) { |
| IFile file = (IFile) resource; |
| IContentType ct = contentTypeWrapper.getContentType(file); |
| if (ct == null)return Boolean.FALSE; |
| boolean match = false; |
| if (_exactMatch)match = ct.getId().equals(_type.getId()); |
| else match = ct.isKindOf(_type); |
| |
| if (match && Tracing.isTraceMatches()) |
| Tracing.log("FilterRule-01: ", toString() + " has matched " + resource); //$NON-NLS-1$ //$NON-NLS-2$ |
| return match; |
| } |
| return Boolean.FALSE; |
| } |
| |
| @Override |
| public String toString() { |
| if (_exactMatch)return NLS.bind(ValMessages.ContentTypeExact, getDisplayableType(), _pattern); |
| return NLS.bind(ValMessages.ContentTypeNotExact, getDisplayableType(), _pattern); |
| } |
| |
| } |
| |
| public static final class FilePattern extends FilterRuleCaseSensitive { |
| |
| private final Pattern _compiledPattern; |
| |
| private static FilePattern createFilePattern(IConfigurationElement rule){ |
| String pattern = rule.getAttribute(ExtensionConstants.RuleAttrib.regex); |
| boolean caseSensitive = asBoolean(rule.getAttribute(ExtensionConstants.RuleAttrib.caseSensitive), false); |
| return new FilePattern(pattern, caseSensitive); |
| } |
| |
| private FilePattern(String pattern, boolean caseSensitive){ |
| super(pattern, caseSensitive); |
| int flags = 0; |
| if (caseSensitive)flags = Pattern.CASE_INSENSITIVE; |
| Pattern compiledPattern = Pattern.compile(pattern, flags); |
| _compiledPattern = compiledPattern; |
| } |
| |
| @Override |
| public String getDisplayableType() { |
| return ValMessages.RulePattern; |
| } |
| |
| @Override |
| public String getType() { |
| return ExtensionConstants.Rule.pattern; |
| } |
| |
| @Override |
| public Boolean matchesResource(IResource resource, ContentTypeWrapper wrapper) { |
| String name = PortableFileDelim + resource.getProjectRelativePath().toPortableString(); |
| return _compiledPattern.matcher(name).matches(); |
| } |
| } |
| |
| /** |
| * Save your settings into the serializer. |
| * @param ser |
| */ |
| public void save(Serializer ser) { |
| ser.put(getType()); |
| ser.put(getPattern()); |
| } |
| |
| public int hashCodeForConfig() { |
| int h = getType().hashCode(); |
| if (_pattern != null)h += _pattern.hashCode(); |
| return h; |
| } |
| |
| } |