*/
private void checkXmlAttributes(Node.CustomTag n,
Node.JspAttribute[] jspAttrs, Hashtable<String, Object> tagDataAttrs)
throws JasperException {
TagInfo tagInfo = n.getTagInfo();
if (tagInfo == null) {
err.jspError(n, "jsp.error.missing.tagInfo", n.getQName());
}
TagAttributeInfo[] tldAttrs = tagInfo.getAttributes();
Attributes attrs = n.getAttributes();
boolean checkDeferred = !pageInfo.isDeferredSyntaxAllowedAsLiteral()
&& !(tagInfo.getTagLibrary().getRequiredVersion().equals("2.0")
|| tagInfo.getTagLibrary().getRequiredVersion().equals("1.2"));
for (int i = 0; attrs != null && i < attrs.getLength(); i++) {
boolean found = false;
boolean runtimeExpression = ((n.getRoot().isXmlSyntax() && attrs.getValue(i).startsWith("%="))
|| (!n.getRoot().isXmlSyntax() && attrs.getValue(i).startsWith("<%=")));
boolean elExpression = false;
boolean deferred = false;
boolean deferredValueIsLiteral = false;
ELNode.Nodes el = null;
if (!runtimeExpression) {
el = ELParser.parse(attrs.getValue(i));
Iterator<ELNode> nodes = el.iterator();
while (nodes.hasNext()) {
ELNode node = nodes.next();
if (node instanceof ELNode.Root) {
if (((ELNode.Root) node).getType() == '$') {
elExpression = true;
} else if (checkDeferred && ((ELNode.Root) node).getType() == '#') {
elExpression = true;
deferred = true;
if (pageInfo.isELIgnored()) {
deferredValueIsLiteral = true;
}
}
}
}
}
boolean expression = runtimeExpression || (elExpression && !pageInfo.isELIgnored());
for (int j = 0; tldAttrs != null && j < tldAttrs.length; j++) {
if (attrs.getLocalName(i).equals(tldAttrs[j].getName())
&& (attrs.getURI(i) == null
|| attrs.getURI(i).length() == 0 || attrs
.getURI(i).equals(n.getURI()))) {
if (tldAttrs[j].canBeRequestTime()
|| tldAttrs[j].isDeferredMethod() || tldAttrs[j].isDeferredValue()) { // JSP 2.1
if (!expression) {
if (deferredValueIsLiteral && !pageInfo.isDeferredSyntaxAllowedAsLiteral()) {
err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr",
tldAttrs[j].getName());
}
String expectedType = null;
if (tldAttrs[j].isDeferredMethod()) {
// The String litteral must be castable to what is declared as type
// for the attribute
String m = tldAttrs[j].getMethodSignature();
if (m != null) {
int rti = m.trim().indexOf(' ');
if (rti > 0) {
expectedType = m.substring(0, rti).trim();
}
} else {
expectedType = "java.lang.Object";
}
}
if (tldAttrs[j].isDeferredValue()) {
// The String litteral must be castable to what is declared as type
// for the attribute
expectedType = tldAttrs[j].getExpectedTypeName();
}
if (expectedType != null) {
Class expectedClass = String.class;
try {
expectedClass = JspUtil.toClass(expectedType, loader);
} catch (ClassNotFoundException e) {
err.jspError
(n, "jsp.error.unknown_attribute_type",
tldAttrs[j].getName(), expectedType);
}
// Check casting
try {
ELSupport.checkType(attrs.getValue(i), expectedClass);
} catch (Exception e) {
err.jspError
(n, "jsp.error.coerce_to_type",
tldAttrs[j].getName(), expectedType, attrs.getValue(i));
}
}
jspAttrs[i] = new Node.JspAttribute(tldAttrs[j],
attrs.getQName(i), attrs.getURI(i), attrs
.getLocalName(i),
attrs.getValue(i), false, null, false);
} else {
if (deferred && !tldAttrs[j].isDeferredMethod() && !tldAttrs[j].isDeferredValue()) {
// No deferred expressions allowed for this attribute
err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr",
tldAttrs[j].getName());
}
if (!deferred && !tldAttrs[j].canBeRequestTime()) {
// Only deferred expressions are allowed for this attribute
err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr",
tldAttrs[j].getName());
}
Class expectedType = String.class;
try {
String typeStr = tldAttrs[j].getTypeName();
if (tldAttrs[j].isFragment()) {
expectedType = JspFragment.class;
} else if (typeStr != null) {
expectedType = JspUtil.toClass(typeStr,
loader);
}
jspAttrs[i] = getJspAttribute(tldAttrs[j],
attrs.getQName(i), attrs.getURI(i),
attrs.getLocalName(i), attrs
.getValue(i), expectedType, n,
false);
} catch (ClassNotFoundException e) {
err.jspError
(n, "jsp.error.unknown_attribute_type",
tldAttrs[j].getName(), tldAttrs[j].getTypeName());
}
}
} else {
// Attribute does not accept any expressions.
// Make sure its value does not contain any.
if (expression) {
err.jspError(n, "jsp.error.attribute.custom.non_rt_with_expr",
tldAttrs[j].getName());
}
jspAttrs[i] = new Node.JspAttribute(tldAttrs[j],
attrs.getQName(i), attrs.getURI(i), attrs
.getLocalName(i),
attrs.getValue(i), false, null, false);
}
if (jspAttrs[i].isExpression()) {
tagDataAttrs.put(attrs.getQName(i),
TagData.REQUEST_TIME_VALUE);
} else {
tagDataAttrs.put(attrs.getQName(i), attrs
.getValue(i));
}
found = true;
break;
}
}
if (!found) {
if (tagInfo.hasDynamicAttributes()) {
jspAttrs[i] = getJspAttribute(null, attrs.getQName(i),
attrs.getURI(i), attrs.getLocalName(i), attrs
.getValue(i), java.lang.Object.class,
n, true);
} else {