Java tutorial
/* * Copyright 2004-2009 the Seasar Foundation and the Others. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, * either express or implied. See the License for the specific language * governing permissions and limitations under the License. */ package org.seasar.s2jsfplugin.validater; import java.io.InputStream; import java.io.StringReader; import jp.aonir.fuzzyxml.FuzzyXMLAttribute; import jp.aonir.fuzzyxml.FuzzyXMLDocument; import jp.aonir.fuzzyxml.FuzzyXMLElement; import jp.aonir.fuzzyxml.FuzzyXMLNode; import jp.aonir.fuzzyxml.FuzzyXMLParser; import jp.aonir.fuzzyxml.XPath; import jp.aonir.fuzzyxml.event.FuzzyXMLErrorEvent; import jp.aonir.fuzzyxml.event.FuzzyXMLErrorListener; import org.apache.commons.el.parser.ELParser; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.CoreException; import org.seasar.s2jsfplugin.S2JSFPlugin; import org.seasar.s2jsfplugin.Util; import org.seasar.s2jsfplugin.assist.HTMLAssistProcessor; import org.seasar.s2jsfplugin.assist.JSFTagDefinition; import org.seasar.s2jsfplugin.assist.S2JSFSelecterMap; import org.seasar.s2jsfplugin.model.AttributeInfo; import org.seasar.s2jsfplugin.model.ManagedBean; import org.seasar.s2jsfplugin.model.S2JSFProject; import org.seasar.s2jsfplugin.model.TLDInfo; import org.seasar.s2jsfplugin.model.TagInfo; import org.seasar.s2jsfplugin.model.Taglib; import org.seasar.s2jsfplugin.pref.S2JSFProjectParams; /** * S2JSFHTMLof?[V?s?B * * @author Naoki Takezoe */ public class S2JSFHTMLValidator extends AbstractS2JSFValidator { private ManagedBean initBean = null; /** * RXgN^ * * @param project S2JSFv?WFNg * @param file ??t@CIuWFNg */ public S2JSFHTMLValidator(S2JSFProject project, IFile file) { super(project, file); } /** * of?[V?s?B */ public void doValidate() { try { Util.removeMakers(getFile()); S2JSFProjectParams params = getS2JSFProjectParams(); InputStream in = getFile().getContents(); FuzzyXMLParser parser = new FuzzyXMLParser(true); if (params.getValidateCloseTag()) { parser.addErrorListener(new FuzzyXMLErrorListenerImpl()); } FuzzyXMLDocument doc = parser.parse(in); if (doc == null) { return; } FuzzyXMLElement root = doc.getDocumentElement(); FuzzyXMLElement html = (FuzzyXMLElement) XPath.selectSingleNode(root, "*"); if (html != null) { initBean = Util.getInitBean(getS2JSFProject(), html); validateElement(html); } } catch (Exception ex) { Util.logException(ex); } } /** G?gof?[V?s?B */ private void validateElement(FuzzyXMLElement element) throws CoreException { // Oof?[V if (element.getName().indexOf(":") > 0) { // ^Oof?[V String[] dim = element.getName().split(":"); if (dim.length > 1 && Util.getPrefixURI(element, dim[0]) == null) { Util.createErrorMarker(getFile(), element.getOffset() + 1, element.getOffset() + dim[0].length() + 2, getLineAtOffset(element.getOffset()), createMessage(ValidationMessages.NS_NOT_DEFINED, dim[0])); return; } } // ?of?[V FuzzyXMLAttribute[] attrs = element.getAttributes(); for (int i = 0; i < attrs.length; i++) { if (attrs[i].getName().indexOf(":") > 0 && !attrs[i].getName().startsWith("xmlns:")) { String[] dim = attrs[i].getName().split(":"); if (dim.length > 1 && !dim[0].equals("xml") && Util.getPrefixURI(element, dim[0]) == null) { Util.createErrorMarker(getFile(), attrs[i].getOffset() + 1, attrs[i].getOffset() + dim[0].length() + 2, getLineAtOffset(attrs[i].getOffset() + 1), createMessage(ValidationMessages.NS_NOT_DEFINED, dim[0])); } } } String mayaPrefix = Util.getMayaPrefix(element); if (mayaPrefix != null) { FuzzyXMLAttribute attr = element.getAttributeNode(mayaPrefix + ":inject"); if (attr != null) { // m:injectCWFNVJX^^Oof?[V validateTaglib(attr, element); } else { // O String[] jsfTagName = S2JSFSelecterMap.getTagName(getS2JSFProject(), element, mayaPrefix); if (jsfTagName != null) { // JSFJX^^Oof?[V validateJSFTaglib(jsfTagName[1], element); } else if (element.getName().equalsIgnoreCase("html")) { // HTML^Oof?[V validateHTMLTag(element); } } } // qvfof?[V FuzzyXMLNode[] children = element.getChildren(); for (int i = 0; i < children.length; i++) { if (children[i] instanceof FuzzyXMLElement) { validateElement((FuzzyXMLElement) children[i]); } } } /** m:injectwJX^^Oof?[V?s?B */ private void validateTaglib(FuzzyXMLAttribute injectAttr, FuzzyXMLElement element) throws CoreException { String mayaPrefix = Util.getMayaPrefix(element); if (mayaPrefix == null) { return; } String inject = injectAttr.getValue(); // m:inject?l if (inject.equals("")) { createAttributeValueMarker(injectAttr, createMessage(ValidationMessages.INJECT_EMPTY, mayaPrefix)); return; } // vtBbNXw if (inject.indexOf(":") <= 0) { createAttributeValueMarker(injectAttr, createMessage(ValidationMessages.INJECT_PREFIX, mayaPrefix)); return; } // JX^^O? String[] dim = inject.split(":"); Taglib taglib = getS2JSFProject().getTaglib(dim[0]); if (taglib == null) { createAttributeValueMarker(injectAttr, createMessage(ValidationMessages.PREFIX_NOT_EXIST, dim[0])); return; } TLDInfo tld = getS2JSFProject().getTLDInfo(taglib.getUri()); if (tld == null) { createAttributeValueMarker(injectAttr, createMessage(ValidationMessages.TLD_NOT_FOUND, taglib.getUri())); return; } TagInfo tag = tld.getTagInfo(dim[1]); if (tag == null) { createAttributeValueMarker(injectAttr, createMessage(ValidationMessages.TAGLIB_NOT_EXIST, inject)); return; } // JSF^OA^O?? if (JSFTagDefinition.hasTagInfo(dim[1]) && taglib.getUri().equals(S2JSFPlugin.S2JSF_URI)) { validateJSFTaglib(dim[1], element); } // K?{?`FbN AttributeInfo[] attrs = tag.getAttributeInfo(); for (int i = 0; i < attrs.length; i++) { if (attrs[i].isRequired() && element.getAttributeNode(mayaPrefix + ":" + attrs[i].getAttributeName()) == null) { Util.createErrorMarker(getFile(), element.getOffset(), element.getOffset() + element.getLength(), getLineAtOffset(element.getOffset()), createMessage(ValidationMessages.ATTR_REQUIRED, mayaPrefix + ":" + attrs[i].getAttributeName())); return; } } } /** HTML^Oof?[V */ private void validateHTMLTag(FuzzyXMLElement element) throws CoreException { String mayaPrefix = Util.getMayaPrefix(element); if (mayaPrefix == null) { return; } FuzzyXMLAttribute[] attrs = element.getAttributes(); for (int i = 0; i < attrs.length; i++) { if (attrs[i].getName().startsWith(mayaPrefix + ":action")) { String value = processExpression(attrs[i], attrs[i].getValue()); if (value == null) { continue; } String[] dim = value.split("\\."); ManagedBean bean = getS2JSFProject().getManagedBean(dim[0]); if (attrs[i].getValue().indexOf('.') > 0 && dim.length == 1) { createAttributeValueMarker(attrs[i], S2JSFPlugin.getResourceString(ValidationMessages.NOT_SPECIFIED)); continue; } if (dim.length == 1 || bean == null) { continue; } if (!bean.hasActionMethod(dim[1])) { createAttributeValueMarker(attrs[i], createMessage(ValidationMessages.NOT_DEFINED, value)); continue; } } if (attrs[i].getName().startsWith(mayaPrefix + ":extends")) { // String value = attrs[i].getValue(); // TODO extends?of?[V // if(project.existsFile(value)){ // // } } } } /** JSFJX^^Oof?[V?s?B */ private void validateJSFTaglib(String jsfTagName, FuzzyXMLElement element) throws CoreException { String mayaPrefix = Util.getMayaPrefix(element); if (mayaPrefix == null) { return; } // UIR|?[lgK?{??H // // K?{?`FbN // TLDInfo tld = project.getTLDInfo(S2JSFPlugin.HTML_URI); // TagInfo tag = tld.getTagInfo(jsfTagName); // if(tld!=null){ // AttributeInfo[] attrs = tag.getAttributeInfo(); // for(int i=0;i<attrs.length;i++){ // if(attrs[i].isRequired() && element.getAttributeNode(mayaPrefix + ":" + attrs[i].getAttributeName())==null){ // createMarker(file,element.getOffset(),element.getOffset()+element.getLength(), // widget.getLineAtOffset(element.getOffset()), // mayaPrefix + ":" + attrs[i].getAttributeName() + "?K?{?B"); // return; // } // } // } // ?l`FbN FuzzyXMLAttribute[] attrs = element.getAttributes(); for (int i = 0; i < attrs.length; i++) { String attrName = attrs[i].getName(); String attrValue = attrs[i].getValue(); if (attrName.indexOf(":") <= 0) { continue; } String[] attrDim = attrName.split(":"); if (!attrDim[0].equals(mayaPrefix)) { continue; } String type = JSFTagDefinition.getAttributeInfo(jsfTagName, attrDim[1]); if (type == null) { continue; } attrValue = processExpression(attrs[i], attrValue); if (attrValue == null) { continue; } if (type == JSFTagDefinition.VALUE) { type = JSFTagDefinition.PROPERTY; } // ELV^bNXG?[m String el = attrs[i].getValue(); el = el.replaceFirst("^#", "\\$"); try { ELParser parser = new ELParser(new StringReader(el)); parser.ExpressionString(); } catch (Exception ex) { createAttributeValueMarker(attrs[i], createMessage(ValidationMessages.INVALID_EL, attrValue)); continue; } // V^bNXG?[BeanL?q?? StringBuffer sb = new StringBuffer(); boolean errorFlag = true; for (int j = 0; j < attrValue.length(); j++) { char c = attrValue.charAt(j); if (Character.isJavaIdentifierPart(c) || c == '.') { sb.append(c); } else { errorFlag = validateBinding(element, attrs[i], sb.toString(), type); sb.setLength(0); if (errorFlag == false) { break; } if (c == '[') { errorFlag = false; break; } } } if (errorFlag == true && sb.length() > 0) { validateBinding(element, attrs[i], sb.toString(), type); } } } /** * BeanL?qof?[V?s?B * G?[??true?A??false?B */ private boolean validateBinding(FuzzyXMLElement element, FuzzyXMLAttribute attr, String value, String type) throws CoreException { String[] dim = Util.splitManagedBean(value); ManagedBean bean = Util.evalPropertyBinding(dim, getS2JSFProject(), initBean); if (value.indexOf('.') > 0 && dim.length == 1) { createAttributeValueMarker(attr, S2JSFPlugin.getResourceString(ValidationMessages.NOT_SPECIFIED)); return false; } if (bean == null && !hasVariable(dim[0], element) && value.indexOf('.') > 0) { createAttributeValueMarker(attr, createMessage(ValidationMessages.NOT_DEFINED, value)); return false; } if (dim.length == 1 || bean == null) { return true; } if (type == JSFTagDefinition.ACTION) { if (!bean.hasActionMethod(dim[dim.length - 1])) { createAttributeValueMarker(attr, createMessage(ValidationMessages.NOT_DEFINED, value)); return false; } } else if (type == JSFTagDefinition.ACTION_LISTENER) { if (!bean.hasActionListenerMethod(dim[dim.length - 1])) { createAttributeValueMarker(attr, createMessage(ValidationMessages.NOT_DEFINED, value)); return false; } } else if (type == JSFTagDefinition.CHANGE_LISTENER) { if (!bean.hasValueChangeListenerMethod(dim[dim.length - 1])) { createAttributeValueMarker(attr, createMessage(ValidationMessages.NOT_DEFINED, value)); return false; } } else if (type == JSFTagDefinition.VALIDATER) { if (!bean.hasValidaterMethod(dim[dim.length - 1])) { createAttributeValueMarker(attr, createMessage(ValidationMessages.NOT_DEFINED, value)); return false; } } else if (type == JSFTagDefinition.PROPERTY) { if (!bean.hasProperty(dim[dim.length - 1])) { createAttributeValueMarker(attr, createMessage(ValidationMessages.NOT_DEFINED, value)); return false; } } return true; } /** * EL #{ } ??o?B */ private String processExpression(FuzzyXMLAttribute attr, String value) throws CoreException { if (!value.startsWith("#{")) { return null; } value = value.replaceFirst("^#\\{", ""); if (!value.endsWith("}")) { createAttributeValueMarker(attr, createMessage(ValidationMessages.REQUIRE_CLOSE, attr.getName())); return null; } value = value.replaceFirst("\\}$", ""); value = value.trim(); // IuWFNg?? for (int i = 0; i < HTMLAssistProcessor.IMPLICIT_OBJECTS.length; i++) { if (value.startsWith(HTMLAssistProcessor.IMPLICIT_OBJECTS[i])) { return null; } } return value; } /** ?lG?[}?[J???B */ private void createAttributeValueMarker(FuzzyXMLAttribute attr, String message) throws CoreException { Util.createErrorMarker(getFile(), getAttrValueOffset(attr.getOffset() + 1), attr.getOffset() + attr.getLength(), getLineAtOffset(attr.getOffset() + 1), message); } /** * ^OReLXg???iK?j?B */ private boolean hasVariable(String var, FuzzyXMLElement element) { if (element.getParentNode() == null) { return false; } String mayaPrefix = Util.getMayaPrefix(element); if (mayaPrefix == null) { return false; } FuzzyXMLElement parent = (FuzzyXMLElement) element.getParentNode(); FuzzyXMLAttribute attr = parent.getAttributeNode(mayaPrefix + ":var"); if (attr != null && attr.getValue().equals(var)) { return true; } return hasVariable(var, parent); } /** FuzzyXMLp?[XG?[??Xi */ private class FuzzyXMLErrorListenerImpl implements FuzzyXMLErrorListener { public void error(FuzzyXMLErrorEvent evt) { try { FuzzyXMLNode node = evt.getNode(); if (node instanceof FuzzyXMLElement) { FuzzyXMLElement element = (FuzzyXMLElement) node; String name = element.getName(); // ^OOK^Ox?? if (name.equalsIgnoreCase("p") || name.equalsIgnoreCase("br") || name.equalsIgnoreCase("img") || name.equalsIgnoreCase("link") || name.equalsIgnoreCase("meta") || name.equalsIgnoreCase("input") || name.equalsIgnoreCase("hr")) { return; } } Util.createWarnMarker(getFile(), evt.getOffset(), evt.getOffset() + evt.getLength(), getLineAtOffset(evt.getOffset()), evt.getMessage()); } catch (Exception ex) { Util.logException(ex); } } } }