Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||||||
ClayTagValidator |
|
| 4.0;4 |
1 | /* |
|
2 | * Licensed to the Apache Software Foundation (ASF) under one or more |
|
3 | * contributor license agreements. See the NOTICE file distributed with |
|
4 | * this work for additional information regarding copyright ownership. |
|
5 | * The ASF licenses this file to you under the Apache License, Version 2.0 |
|
6 | * (the "License"); you may not use this file except in compliance with |
|
7 | * the License. You may obtain a copy of the License at |
|
8 | * |
|
9 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
10 | * |
|
11 | * Unless required by applicable law or agreed to in writing, software |
|
12 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 | * See the License for the specific language governing permissions and |
|
15 | * limitations under the License. |
|
16 | */ |
|
17 | ||
18 | /* |
|
19 | * $Id: ClayTagValidator.java 464373 2006-10-16 04:21:54Z rahul $ |
|
20 | */ |
|
21 | package org.apache.shale.clay.taglib; |
|
22 | ||
23 | import java.io.IOException; |
|
24 | import java.io.InputStream; |
|
25 | import java.util.ArrayList; |
|
26 | import java.util.List; |
|
27 | ||
28 | import javax.servlet.jsp.tagext.PageData; |
|
29 | import javax.servlet.jsp.tagext.TagLibraryValidator; |
|
30 | import javax.servlet.jsp.tagext.ValidationMessage; |
|
31 | ||
32 | import org.apache.shale.clay.parser.Node; |
|
33 | import org.apache.shale.clay.parser.Parser; |
|
34 | import org.apache.shale.util.Messages; |
|
35 | ||
36 | /** |
|
37 | * <p>Validates the JSP page for the clay namespace, |
|
38 | * "http://shale.apache.org/shale/clay-plugin". This tag |
|
39 | * validator checks to make sure that there are not any nested |
|
40 | * tags under the {@link ClayTag} with the exception of the |
|
41 | * {@link SymbolTag}.</p> |
|
42 | */ |
|
43 | 0 | public class ClayTagValidator extends TagLibraryValidator { |
44 | ||
45 | /** |
|
46 | * <p>URI Namespace for the clay tag lib.</p> |
|
47 | */ |
|
48 | private static final String CLAY_URI_NAMESPACE = "http://shale.apache.org/clay"; |
|
49 | ||
50 | /** |
|
51 | * <p>Message resources for this class.</p> |
|
52 | */ |
|
53 | 0 | private static Messages messages = new Messages("org.apache.shale.clay.Bundle", |
54 | 0 | ClayTagValidator.class.getClassLoader()); |
55 | ||
56 | /** |
|
57 | * <p>Loads the <code>page</code> content into a <code>StringBuffer</code>.</p> |
|
58 | * |
|
59 | * @param page tag page data |
|
60 | * @return document in a string buffer |
|
61 | * @exception IOException error reading page data |
|
62 | */ |
|
63 | protected StringBuffer loadTemplate(PageData page) throws IOException { |
|
64 | ||
65 | ||
66 | 0 | StringBuffer buff = new StringBuffer(); |
67 | 0 | InputStream inputStream = page.getInputStream(); |
68 | ||
69 | 0 | int c = 0; |
70 | done: while (true) { |
|
71 | 0 | c = inputStream.read(); |
72 | 0 | if (c > -1) { |
73 | 0 | buff.append((char) c); |
74 | } else { |
|
75 | break done; |
|
76 | } |
|
77 | ||
78 | } |
|
79 | ||
80 | 0 | return buff; |
81 | ||
82 | } |
|
83 | ||
84 | /** |
|
85 | * <p>Creates a <code>ValidationMessage</code> for a {@link ClayTag} containing |
|
86 | * a child of anything other than the {@link SymbolTag}.</p> |
|
87 | * |
|
88 | * @param prefix qname |
|
89 | * @param clayNode markup |
|
90 | * @param childNode child markup |
|
91 | * |
|
92 | * @return message for the JSP compiler |
|
93 | */ |
|
94 | private ValidationMessage getMessage(String prefix, Node clayNode, Node childNode) { |
|
95 | 0 | Object[] args = {clayNode.getToken().getRawText(), |
96 | childNode.getToken().getRawText(), |
|
97 | prefix}; |
|
98 | 0 | String jspid = (String) childNode.getAttributes().get("jsp:id"); |
99 | 0 | String message = messages.getMessage("invalid.nested.tag", args); |
100 | 0 | return new ValidationMessage(jspid, message); |
101 | } |
|
102 | ||
103 | ||
104 | /** |
|
105 | * <p>Checks the child nodes of the <code>clayNode</code> verifying that |
|
106 | * only the symbol node is present.</p> |
|
107 | * |
|
108 | * @param prefix qname |
|
109 | * @param clayNode markup |
|
110 | * @param messages error messages |
|
111 | */ |
|
112 | private void checkForInvalidNestedTags(String prefix, Node clayNode, List messages) { |
|
113 | 0 | List children = clayNode.getChildren(); |
114 | 0 | next: for (int i = 0; i < children.size(); i++) { |
115 | 0 | Node child = (Node) children.get(i); |
116 | 0 | if ((!child.isComment() && !child.isCdata()) && child.isWellFormed()) { |
117 | 0 | if (child.getQname() != null && child.getName() != null) { |
118 | ||
119 | 0 | if (child.getQname().equals("jsp") && child.getName().equals("text")) { |
120 | 0 | continue next; |
121 | 0 | } else if (!child.getName().equals("symbol") || !prefix.equals(child.getQname())) { |
122 | 0 | messages.add(getMessage(prefix, clayNode, child)); |
123 | } |
|
124 | } |
|
125 | ||
126 | } |
|
127 | } |
|
128 | 0 | } |
129 | ||
130 | /** |
|
131 | * <p>Recursively walks the parsed document looking for clay component nodes. The children |
|
132 | * are checked to make sure the symbol tag is the only valid child tag.</p> |
|
133 | * |
|
134 | * @param prefix qname |
|
135 | * @param node markup |
|
136 | * @param messages list of errors |
|
137 | */ |
|
138 | private void validateClayTags(String prefix, Node node, List messages) { |
|
139 | 0 | if ((!node.isComment() && !node.isCdata()) && node.isWellFormed() |
140 | && node.getName() != null && node.getName().equals("clay") |
|
141 | && node.getQname() != null && node.getQname().equals(prefix)) { |
|
142 | ||
143 | 0 | checkForInvalidNestedTags(prefix, node, messages); |
144 | 0 | return; |
145 | } |
|
146 | ||
147 | 0 | List children = node.getChildren(); |
148 | 0 | for (int i = 0; i < children.size(); i++) { |
149 | 0 | Node child = (Node) children.get(i); |
150 | 0 | validateClayTags(prefix, child, messages); |
151 | } |
|
152 | ||
153 | 0 | } |
154 | ||
155 | /** |
|
156 | * <p>Validates the page for a directive with a uri of |
|
157 | * "<strong>http://shale.apache.org/shale/clay-plugin</strong>". |
|
158 | * |
|
159 | * @param prefix namespace |
|
160 | * @param uri namespace |
|
161 | * @param page normalized jsp page into XML |
|
162 | * @return error messages |
|
163 | */ |
|
164 | public ValidationMessage[] validate(String prefix, String uri, PageData page) { |
|
165 | 0 | List messages = new ArrayList(); |
166 | ||
167 | 0 | if (uri != null && CLAY_URI_NAMESPACE.equals(uri)) { |
168 | try { |
|
169 | 0 | StringBuffer buff = loadTemplate(page); |
170 | 0 | Parser p = new Parser(); |
171 | 0 | List roots = p.parse(buff); |
172 | ||
173 | 0 | for (int i = 0; i < roots.size(); i++) { |
174 | 0 | Node node = (Node) roots.get(i); |
175 | 0 | validateClayTags(prefix, node, messages); |
176 | } |
|
177 | ||
178 | 0 | } catch (IOException e) { |
179 | 0 | messages.add(new ValidationMessage(null, e.getMessage())); |
180 | 0 | } |
181 | } |
|
182 | ||
183 | 0 | if (messages.isEmpty()) { |
184 | 0 | return null; |
185 | } else { |
|
186 | 0 | ValidationMessage[] validationMessages = new ValidationMessage[messages.size()]; |
187 | 0 | messages.toArray(validationMessages); |
188 | 0 | return validationMessages; |
189 | } |
|
190 | ||
191 | } |
|
192 | ||
193 | } |