Fix for issues:
388 -
https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=388
410 -
https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=410
411 -
https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=411
413 -
https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=413
415 -
https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=415
417 -
https://javaserverfaces.dev.java.net/issues/show_bug.cgi?id=417
SECTION: Modified Files
----------------------------
FIX FOR 410
==============================================
M jsf-api/src/javax/faces/webapp/UIComponentClassicTagBase.java
- modified setJspId() implementation to augment the container
provided ID with i<include count> when we're part of a
RequestDispatcher include. This ensures that the UNIQUE_ID_PREFIX
is only added to IDs when we in a loop instead of either a loop
or an include. Doing this allows the augmentID logic in HtmlBasicRenderer
to continue to work in all cases.
M jsf-ri/systest/web/forEach03.jsp
M jsf-ri/systest/web/golden/interweaving06.txt
M jsf-ri/systest/web/golden/interweaving07.txt
M jsf-ri/systest/web/golden/subview05.txt
M jsf-ri/systest/web/golden/subview06.txt
M jsf-ri/systest/src/com/sun/faces/jsptest/IdRefTestCase.java
A jsf-ri/systest/web/forEach03Include.jsp
- tests to ensure the following works:
h:message in an include not within a loop
h:message in an include within a loop
==============================================
FIX FOR 388, 411
==============================================
M jsf-ri/systest/src/com/sun/faces/systest/render/CustomResponseWriter.java
M jsf-ri/src/com/sun/faces/renderkit/html_basic/HtmlResponseWriter.java
- reflect change in HtmlUtils.validateEncoding()
M jsf-ri/src/com/sun/faces/renderkit/RenderKitUtils.java
- added utility method to return a boolean flagging whether
or not the content type is XML-based
M jsf-ri/src/com/sun/faces/util/HtmlUtils.java
- updated the implementation of validateEncoding() return
a boolean based on the result of Charset.isSupported()
instead of allocating a String each time this method is called
- Added logic to ensure we don't double escape entities
that are already escaped (i.e. © -> &amp;copy)
- Updated existing logic on encoding any & in the query
string when the content type is xml-based.
M jsf-ri/test/com/sun/faces/util/TestHtmlUtils.java
- updated test with correct inputs/outputs
==============================================
FIX FOR 417
==============================================
M jsf-ri/src/com/sun/faces/application/ApplicationAssociate.java
- ensure the String argument provided to getResourceBundle()
is a known key before attempting any additional work
==============================================
FIX FOR 415
==============================================
M jsf-ri/src/com/sun/faces/application/ConverterPropertyEditorFactory.java
- update the logic in generateClassNameFor to take array
types into account.
==============================================
FIX FOR 413
==============================================
M jsf-ri/src/com/sun/faces/application/ViewHandlerImpl.java
- call the appropriate ExternalContext.encode* method
in the ViewHandler's getActionURL and
getResourceURL to ensure the URLs are encoded with
session info if necessary
M jsf-ri/test/com/sun/faces/application/TestViewHandlerImpl.java
- updated associated test
==============================================
SECTION: Diffs
----------------------------
Index: jsf-api/src/javax/faces/webapp/UIComponentClassicTagBase.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-api/src/javax/faces/webapp/UIComponentClassicTagBase.java,v
retrieving revision 1.25
diff -u -r1.25 UIComponentClassicTagBase.java
--- jsf-api/src/javax/faces/webapp/UIComponentClassicTagBase.java 25 Aug 2006 09:50:18 -0000 1.25
+++ jsf-api/src/javax/faces/webapp/UIComponentClassicTagBase.java 3 Oct 2006 15:21:51 -0000
@@ -34,6 +34,7 @@
import javax.faces.component.UIComponent;
import javax.faces.component.UIOutput;
import javax.faces.component.UIViewRoot;
+import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.render.ResponseStateManager;
import javax.servlet.jsp.JspException;
@@ -201,6 +202,13 @@
*/
private static final String PREVIOUS_JSP_ID_SET =
"javax.faces.webapp.PREVIOUS_JSP_ID_SET";
+
+ /**
+ * Used to store information about dynamic include
+ * sources.
+ */
+ private static final String JAVAX_FACES_INCLUDE_LIST =
+ "javax.faces.webapp.INCLUDE_LIST";
// ------------------------------------------------------ Instance Variables
/**
@@ -1394,12 +1402,12 @@
if (null == facesJspId) {
if (null != jspId) {
facesJspId = UNIQUE_ID_PREFIX + jspId;
- // if this tag happens to be nested within <c:forEach> or we're
- // the target of an include, jspId will be the same for each
- // iteration. So it is transformed into a unique "id" by
- // appending a counter which gets stored in request scope
- // with jspId as the key for use during the next iteration.
- if (isDuplicateId(facesJspId) || isIncludedOrForwarded()) {
+ // if this tag happens to be nested within <c:forEach>,
+ // jspId will be the same for each iteration. So it is
+ // transformed into a unique "id" by appending a counter which
+ // gets stored in request scope with jspId as the key for use
+ // during the next iteration.
+ if (isDuplicateId(facesJspId)) {
facesJspId = generateIncrementedId(facesJspId);
}
} else {
@@ -1534,15 +1542,45 @@
* <p>Defined on {_at_link JspIdConsumer}. This method is called by
* the container before {_at_link #doStartTag}. The argument is
* guaranteed to be unique within the page.</p>
+ *
+ * <p>IMPLEMENTATION NOTE: This method will detect where we
+ * are in an include and assign a unique ID for each include
+ * in a particular 'logical page'. This allows us to avoid
+ * possible duplicate ID situations for included pages that
+ * have components without explicit IDs.</p>
*
* @param id the container generated id for this tag, guaranteed to
* be unique within the page.
*/
public void setJspId(String id) {
- facesJspId = null;
- updatePreviousJspIdAndIteratorStatus(id);
- jspId = id;
+ if (isIncluded()) {
+ StringBuilder builder = new StringBuilder(id.length() + 3);
+ builder.append(id);
+ ExternalContext extContext = context.getExternalContext();
+ Map<String,Object> reqMap = extContext.getRequestMap();
+ List<String> includeList =
+ TypedCollections.dynamicallyCastList(
+ ((List) reqMap.get(JAVAX_FACES_INCLUDE_LIST)),
+ String.class);
+ if (includeList == null) {
+ includeList = new IdentityArrayList<String>(6);
+ reqMap.put(JAVAX_FACES_INCLUDE_LIST, includeList);
+ }
+ String key = (String) reqMap.get("javax.servlet.include.request_uri");
+ int idx = includeList.indexOf(key);
+ if (idx != -1) {
+ builder.append('i').append(idx);
+ } else {
+ includeList.add(key);
+ builder.append('i').append(includeList.size() - 1);
+ }
+ jspId = builder.toString();
+ } else {
+ jspId = id;
+ }
+ facesJspId = null;
+ updatePreviousJspIdAndIteratorStatus(jspId);
}
/**
@@ -1574,7 +1612,7 @@
}
assert(null != previousJspIdSet);
// detect the iterator case
- if (previousJspIdSet.contains(id) && !isIncludedOrForwarded()) {
+ if (previousJspIdSet.contains(id)) {
if (log.isLoggable(Level.FINEST)) {
log.log(Level.FINEST, "Id " + id +
" is nested within an iterating tag.");
@@ -1587,7 +1625,7 @@
}
}
- private boolean isIncludedOrForwarded() {
+ private boolean isIncluded() {
return (getFacesContext().getExternalContext().getRequestMap().
containsKey("javax.servlet.include.request_uri"));
}
@@ -1794,4 +1832,39 @@
return null;
}
+
+ // ----------------------------------------------------------- Inner Classes
+
+
+ private static class IdentityArrayList<E> extends ArrayList<E> {
+
+ IdentityArrayList() {
+ super(16);
+ }
+
+ IdentityArrayList(int initialcapacity) {
+ super(initialcapacity);
+ }
+
+
+ /**
+ * Searches for the first occurence of the given argument, testing
+ * for identity equality using the <tt>==</tt>.
+ *
+ * @param elem an object.
+ *
+ * @return the index of the first occurrence of the argument in this
+ * list; returns <tt>-1</tt> if the object is not found.
+ */
+ @Override public int indexOf(Object elem) {
+ int idx = 0;
+ for (Object o : this) {
+ if (o == elem) {
+ return idx;
+ }
+ idx++;
+ }
+ return -1;
+ }
+ }
}
Index: jsf-ri/src/com/sun/faces/application/ApplicationAssociate.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/application/ApplicationAssociate.java,v
retrieving revision 1.34
diff -u -r1.34 ApplicationAssociate.java
--- jsf-ri/src/com/sun/faces/application/ApplicationAssociate.java 14 Sep 2006 22:38:39 -0000 1.34
+++ jsf-ri/src/com/sun/faces/application/ApplicationAssociate.java 3 Oct 2006 15:21:51 -0000
@@ -359,6 +359,9 @@
public ResourceBundle getResourceBundle(FacesContext context,
String var) {
+ if (!resourceBundles.containsKey(var)) {
+ return null;
+ }
UIViewRoot root = null;
// Start out with the default locale
Locale locale = null, defaultLocale = Locale.getDefault();
Index: jsf-ri/src/com/sun/faces/application/ConverterPropertyEditorFactory.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/application/ConverterPropertyEditorFactory.java,v
retrieving revision 1.4
diff -u -r1.4 ConverterPropertyEditorFactory.java
--- jsf-ri/src/com/sun/faces/application/ConverterPropertyEditorFactory.java 26 Sep 2006 02:39:27 -0000 1.4
+++ jsf-ri/src/com/sun/faces/application/ConverterPropertyEditorFactory.java 3 Oct 2006 15:21:51 -0000
@@ -36,6 +36,7 @@
import java.util.Map;
import java.util.TreeSet;
import java.util.WeakHashMap;
+import java.util.HashMap;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
@@ -305,6 +306,18 @@
public String generateClassNameFor(Class<?> targetClass,
boolean vmFormat) {
String name = targetClass.getName();
+ if (targetClass.isArray()) {
+ int idx = name.lastIndexOf('[');
+ int bracketCount = idx + 1;
+ if (name.indexOf(';') == -1) {
+ // primitive array
+ name = PRIM_MAP.get(name.charAt(idx + 1));
+ } else {
+ // Object array
+ name = name.substring(idx + 2, name.indexOf(';'));
+ }
+ name += "Array" + bracketCount + 'd';
+ }
Matcher m = UnderscorePattern.matcher(name);
// Replace existing underscores with one extra underscore.
name = m.replaceAll("$0_");
@@ -487,6 +500,19 @@
private ClassTemplateInfo templateInfo;
// Cache of DisposableClassLoaders keyed on the class loader of the target.
private Map<ClassLoader, WeakReference<DisposableClassLoader>> classLoaderCache;
+
+ private static final Map<Character,String> PRIM_MAP =
+ new HashMap<Character,String>(8, 1.0f);
+ static {
+ PRIM_MAP.put('B', "byte");
+ PRIM_MAP.put('C', "char");
+ PRIM_MAP.put('S', "short");
+ PRIM_MAP.put('I', "int");
+ PRIM_MAP.put('F', "float");
+ PRIM_MAP.put('J', "long");
+ PRIM_MAP.put('D', "double");
+ PRIM_MAP.put('Z', "boolean");
+ }
/**
* Create a <code>ConverterPropertyEditorFactory</code> that uses the
Index: jsf-ri/src/com/sun/faces/application/ViewHandlerImpl.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/application/ViewHandlerImpl.java,v
retrieving revision 1.86
diff -u -r1.86 ViewHandlerImpl.java
--- jsf-ri/src/com/sun/faces/application/ViewHandlerImpl.java 20 Sep 2006 19:37:46 -0000 1.86
+++ jsf-ri/src/com/sun/faces/application/ViewHandlerImpl.java 3 Oct 2006 15:21:51 -0000
@@ -645,45 +645,49 @@
}
// Acquire the context path, which we will prefix on all results
- String contextPath =
- context.getExternalContext().getRequestContextPath();
+ ExternalContext extContext = context.getExternalContext();
+ String contextPath = extContext.getRequestContextPath();
// Acquire the mapping used to execute this request (if any)
String mapping = Util.getFacesMapping(context);
// If no mapping can be identified, just return a server-relative path
if (mapping == null) {
- return contextPath + viewId;
+ return extContext.encodeActionURL(contextPath + viewId);
}
// Deal with prefix mapping
if (Util.isPrefixMapped(mapping)) {
if (mapping.equals("/*")) {
- return contextPath + viewId;
+ return extContext.encodeActionURL(contextPath + viewId);
} else {
- return contextPath + mapping + viewId;
+ return extContext
+ .encodeActionURL(contextPath + mapping + viewId);
}
}
// Deal with extension mapping
int period = viewId.lastIndexOf(".");
if (period < 0) {
- return contextPath + viewId + mapping;
+ return extContext.encodeActionURL(contextPath + viewId + mapping);
} else if (!viewId.endsWith(mapping)) {
- return contextPath + viewId.substring(0, period) + mapping;
+ return extContext.encodeActionURL(contextPath
+ + viewId.substring(0, period)
+ + mapping);
} else {
- return contextPath + viewId;
+ return extContext.encodeActionURL(contextPath + viewId);
}
}
public String getResourceURL(FacesContext context, String path) {
-
+ ExternalContext extContext = context.getExternalContext();
if (path.startsWith("/")) {
- return context.getExternalContext().getRequestContextPath() + path;
+ return extContext
+ .encodeResourceURL(extContext.getRequestContextPath() + path);
} else {
- return (path);
+ return extContext.encodeResourceURL(path);
}
}
Index: jsf-ri/src/com/sun/faces/renderkit/RenderKitUtils.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/renderkit/RenderKitUtils.java,v
retrieving revision 1.27
diff -u -r1.27 RenderKitUtils.java
--- jsf-ri/src/com/sun/faces/renderkit/RenderKitUtils.java 15 Sep 2006 17:45:54 -0000 1.27
+++ jsf-ri/src/com/sun/faces/renderkit/RenderKitUtils.java 3 Oct 2006 15:21:51 -0000
@@ -962,6 +962,18 @@
/**
+ * @param contentType the content type in question
+ * @return <code>true</code> if the content type is a known XML-based
+ * content type, otherwise, <code>false</code>
+ */
+ public static boolean isXml(String contentType) {
+ return (RIConstants.XHTML_CONTENT_TYPE.equals(contentType)
+ || RIConstants.APPLICATION_XML_CONTENT_TYPE.equals(contentType)
+ || RIConstants.TEXT_XML_CONTENT_TYPE.equals(contentType));
+ }
+
+
+ /**
* <p>This is a utility method for compressing multi-lined javascript.
* In the case of {_at_link #SUN_JSF_JS} it offers about a 47% decrease
* in length.</p>
Index: jsf-ri/src/com/sun/faces/renderkit/html_basic/HtmlResponseWriter.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/renderkit/html_basic/HtmlResponseWriter.java,v
retrieving revision 1.31
diff -u -r1.31 HtmlResponseWriter.java
--- jsf-ri/src/com/sun/faces/renderkit/html_basic/HtmlResponseWriter.java 1 Sep 2006 17:30:54 -0000 1.31
+++ jsf-ri/src/com/sun/faces/renderkit/html_basic/HtmlResponseWriter.java 3 Oct 2006 15:21:51 -0000
@@ -34,7 +34,6 @@
import javax.faces.context.ResponseWriter;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import java.io.Writer;
import com.sun.faces.util.HtmlUtils;
@@ -106,13 +105,10 @@
this.encoding = encoding;
// Check the character encoding
- try {
- HtmlUtils.validateEncoding(encoding);
- } catch (UnsupportedEncodingException e) {
+ if (!HtmlUtils.validateEncoding(encoding)) {
throw new IllegalArgumentException(MessageUtils.getExceptionMessageString(
- MessageUtils.ENCODING_ERROR_MESSAGE_ID));
- }
-
+ MessageUtils.ENCODING_ERROR_MESSAGE_ID));
+ }
}
// -------------------------------------------------- Methods From Closeable
Index: jsf-ri/src/com/sun/faces/util/HtmlUtils.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/src/com/sun/faces/util/HtmlUtils.java,v
retrieving revision 1.11
diff -u -r1.11 HtmlUtils.java
--- jsf-ri/src/com/sun/faces/util/HtmlUtils.java 24 Aug 2006 19:25:01 -0000 1.11
+++ jsf-ri/src/com/sun/faces/util/HtmlUtils.java 3 Oct 2006 15:21:52 -0000
@@ -35,12 +35,17 @@
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
-import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
import java.util.BitSet;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
-import com.sun.faces.RIConstants;
+import com.sun.faces.renderkit.RenderKitUtils;
/**
* Utility class for HTML.
@@ -103,7 +108,10 @@
} else {
if (ch == '&') {
buffIndex = flushBuffer(out, buff, buffIndex);
-
+ if (((i + 1) < length) && isEscaped(text, i + 1)) {
+ out.write(ch);
+ continue;
+ }
out.write("&");
} else {
buffIndex = addToBuffer(out, buff, buffIndex,
@@ -171,7 +179,10 @@
} else {
if (ch == '&') {
buffIndex = flushBuffer(out, buff, buffIndex);
-
+ if (((i + 1) < length) && isEscaped(text, i + 1)) {
+ out.write(ch);
+ continue;
+ }
out.write("&");
} else {
buffIndex = addToBuffer(out, buff, buffIndex,
@@ -225,12 +236,12 @@
// If between "'" and ";", no escaping is needed
if (ch < 0x3c) {
buffIndex = addToBuffer(out, buff, buffIndex,
- buffLength, ch);
- // Note - "<" isn't escaped in attributes, as per
- // HTML spec
+ buffLength, ch);
+ } else if (ch == '<') {
+ buffIndex = flushBuffer(out, buff, buffIndex);
+ out.write("<");
} else if (ch == '>') {
buffIndex = flushBuffer(out, buff, buffIndex);
-
out.write(">");
} else {
buffIndex = addToBuffer(out, buff, buffIndex,
@@ -239,7 +250,10 @@
} else {
if (ch == '&') {
buffIndex = flushBuffer(out, buff, buffIndex);
-
+ if (((i + 1) < length) && isEscaped(text, i + 1)) {
+ out.write(ch);
+ continue;
+ }
// HTML 4.0, section B.7.1: ampersands followed by
// an open brace don't get escaped
if ((i + 1 < length) && (text.charAt(i + 1) == '{'))
@@ -313,10 +327,11 @@
// If between "'" and ";", no escaping is needed
buffIndex = addToBuffer(out, buff, buffIndex,
buffLength, ch);
- // Note - "<" isn't escaped in attributes, as per HTML spec
+ } else if (ch == '<') {
+ buffIndex = flushBuffer(out, buff, buffIndex);
+ out.write("<");
} else if (ch == '>') {
buffIndex = flushBuffer(out, buff, buffIndex);
-
out.write(">");
} else {
buffIndex = addToBuffer(out, buff, buffIndex,
@@ -325,7 +340,10 @@
} else {
if (ch == '&') {
buffIndex = flushBuffer(out, buff, buffIndex);
-
+ if (((i + 1) < length) && isEscaped(text, i + 1)) {
+ out.write(ch);
+ continue;
+ }
// HTML 4.0, section B.7.1: ampersands followed by
// an open brace don't get escaped
if ((i + 1 < end) && (text[i + 1] == '{'))
@@ -450,6 +468,107 @@
return 0;
}
+
+
+ private static final int MAX_ESCAPE_LENGTH = 7;
+
+ /**
+ * Check if a & is the beginning of an escape seqence or not.
+ */
+ private static boolean isEscaped(char[] buff, int offset) {
+ int idx = 0;
+ int maxLen = offset + MAX_ESCAPE_LENGTH;
+ int bufLen = buff.length;
+ if (maxLen > bufLen) {
+ maxLen = bufLen;
+ }
+ boolean found = false;
+ for (int i = offset; i < maxLen; i++, idx++) {
+ if (buff[i] == ';') {
+ found = true;
+ break;
+ }
+ // found another '&' before a ';' - not escaped
+ if (buff[i] == '&') {
+ return false;
+ }
+ }
+ if (found && idx >= 2) {
+ char[][] escapes = ISO8859_ENTITY_MAP.get(buff[offset]);
+ if (escapes != null) {
+ for (int i = 0; i < escapes.length; i++) {
+ boolean equal = true;
+ char[] ent = escapes[i];
+ if (ent == null) {
+ return false;
+ }
+ if (ent.length != idx) {
+ continue;
+ }
+ for (int j = 0; j < escapes[i].length; j++) {
+ if (buff[offset + j] != ent[j]) {
+ equal = false;
+ break;
+ }
+ }
+ if (equal) {
+ return equal;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Check if a & is the beginning of an escape seqence or not.
+ */
+ private static boolean isEscaped(String buff, int offset) {
+ int idx = 0;
+ int maxLen = offset + MAX_ESCAPE_LENGTH;
+ int bufLen = buff.length();
+ if (offset + MAX_ESCAPE_LENGTH > bufLen) {
+ maxLen = bufLen;
+ }
+ boolean found = false;
+ for (int i = offset; i < maxLen; i++, idx++) {
+ if (buff.charAt(i) == ';') {
+ found = true;
+ break;
+ }
+ // found another '&' before a ';' - not escaped
+ if (buff.charAt(i) == '&') {
+ return false;
+ }
+ }
+ if (found && idx >= 2) {
+ char[][] escapes = ISO8859_ENTITY_MAP.get(buff.charAt(offset));
+ if (escapes != null) {
+ for (int i = 0; i < escapes.length; i++) {
+ boolean equal = true;
+ char[] ent = escapes[i];
+ if (ent == null) {
+ return false;
+ }
+ if (ent.length != idx) {
+ continue;
+ }
+ for (int j = 0; j < escapes[i].length; j++) {
+ if (buff.charAt(offset + j) != ent[j]) {
+ equal = false;
+ break;
+ }
+ }
+ if (equal) {
+ return equal;
+ }
+ }
+ }
+ }
+
+ return false;
+ }
private HtmlUtils() {
@@ -520,27 +639,12 @@
// as if it were in the request's character set. So use
// the real encoding for those!
else if (ch == '?') {
- out.write('?');
- //If the content type is an XML file use standard attribute rules.
- if (RIConstants.XHTML_CONTENT_TYPE.equals(contentType) ||
- RIConstants.APPLICATION_XML_CONTENT_TYPE.equals(contentType) ||
- RIConstants.TEXT_XML_CONTENT_TYPE.equals(contentType)) {
- String encodedURL = encodeURIString(text, queryEncoding, i + 1);
- //Convert all & to & and all &%3B to &
- char[] encodedURLArray = encodedURL.toCharArray();
- for(int loop = 0;loop < encodedURLArray.length;loop++) {
- if(encodedURLArray[loop] != '&') {
- out.write(encodedURLArray[loop]);
- } else if(loop+7 <= encodedURLArray.length && encodedURL.substring(loop, loop+7).equals("&%3B")) {
- out.write("&");
- loop += 6;
- } else {
- out.write("&");
- }
- }
- } else {
- out.write(encodeURIString(text, queryEncoding, i + 1));
- }
+ out.write('?');
+ encodeURIString(out,
+ text,
+ queryEncoding,
+ RenderKitUtils.isXml(contentType),
+ i + 1);
return;
} else {
out.write(ch);
@@ -551,12 +655,13 @@
// Encode a String into URI-encoded form. This code will
// appear rather (ahem) similar to java.net.URLEncoder
- static private String encodeURIString(String text,
+ static private void encodeURIString(Writer out,
+ String text,
String encoding,
+ boolean isXml,
int start)
- throws IOException, UnsupportedEncodingException {
- Writer out = new StringWriter(text.length());
- ByteArrayOutputStream buf = null;
+ throws IOException, UnsupportedEncodingException {
+ MyByteArrayOutputStream buf = null;
OutputStreamWriter writer = null;
char[] charArray = null;
@@ -564,10 +669,18 @@
for (int i = start; i < length; i++) {
char ch = text.charAt(i);
if (DONT_ENCODE_SET.get(ch)) {
- out.write(ch);
+ if (isXml && ch == '&') {
+ if (((i + 1) < length) && isEscaped(text, i + 1)) {
+ out.write(ch);
+ continue;
+ }
+ out.write(AMP_CHARS);
+ } else {
+ out.write(ch);
+ }
} else {
if (buf == null) {
- buf = new ByteArrayOutputStream(MAX_BYTES_PER_CHAR);
+ buf = new MyByteArrayOutputStream(MAX_BYTES_PER_CHAR);
if (encoding != null) {
writer = new OutputStreamWriter(buf, encoding);
} else {
@@ -589,15 +702,14 @@
continue;
}
- byte[] ba = buf.toByteArray();
- for (int j = 0; j < ba.length; j++) {
+ byte[] ba = buf.getBuf();
+ for (int j = 0, size = buf.size(); j < size; j++) {
writeURIDoubleHex(out, ba[j] + 256);
}
buf.reset();
}
- }
- return out.toString();
+ }
}
@@ -621,7 +733,7 @@
static private final BitSet DONT_ENCODE_SET = new BitSet(256);
- // See:
http://www.ietf.org/rfc/rfc2396.txt
+ // See:
http://www.ietf.org/rfc/rfc3986.txt
// We're not fully along for that ride either, but we do encode
// ' ' as '%20', and don't bother encoding '~' or '/'
static {
@@ -642,6 +754,10 @@
// Ditto for '+', which is an encoded space
DONT_ENCODE_SET.set('+');
+ // Reserved characters from RFC 3986
+ // If a developer needs these to be available
+ // in the data set, they'll need to percent encode
+ // them manually
DONT_ENCODE_SET.set('#');
DONT_ENCODE_SET.set('&');
DONT_ENCODE_SET.set('=');
@@ -655,6 +771,7 @@
DONT_ENCODE_SET.set('!');
DONT_ENCODE_SET.set('(');
DONT_ENCODE_SET.set(')');
+ DONT_ENCODE_SET.set(';');
}
@@ -759,24 +876,60 @@
"thorn",
"yuml"
};
+
+ private static final Map<Character,char[][]> ISO8859_ENTITY_MAP =
+ new HashMap<Character,char[][]>();
+ static {
+ List<String> list = new ArrayList<String>();
+ list.add("amp");
+ list.add("gt");
+ list.add("lt");
+ list.add("quot");
+ list.addAll(Arrays.asList(sISO8859_1_Entities));
+ String[] entities = list.toArray(new String[list.size()]);
+ for (int i = 'a'; i <= 'z'; i++) {
+ List<char[]> l = new ArrayList<char[]>();
+ for (int e = 0; e < entities.length; e++) {
+ if (entities[e].charAt(0) == (char) i) {
+ l.add(entities[e].toCharArray());
+ }
+ }
+ if (l.size() > 0) {
+ ISO8859_ENTITY_MAP.put((char) i,
+ l.toArray(new char[l.size()][]));
+ }
+ }
+ for (int i = 'A'; i <= 'Z'; i++) {
+ List<char[]> l = new ArrayList<char[]>();
+ for (int e = 0; e < entities.length; e++) {
+ if (entities[e].charAt(0) == (char) i) {
+ l.add(entities[e].toCharArray());
+ }
+ }
+ if (l.size() > 0) {
+ ISO8859_ENTITY_MAP.put((char) i,
+ l.toArray(new char[l.size()][]));
+ }
+ }
+ }
+
//----------------------------------------------------------
// The following is used to verify encodings
//----------------------------------------------------------
//
- static public void validateEncoding(String encoding)
- throws UnsupportedEncodingException {
+ static public boolean validateEncoding(String encoding) {
if (encoding != null) {
- // Try creating a string off of the default encoding
- new String(encodingTestBytes, encoding);
+ return Charset.isSupported(encoding);
}
- }
-
- // Private array used simply to verify character encodings
- static private final byte[] encodingTestBytes = new byte[]{(byte) 65};
+ // return true if encoding is null to be compatible with the
+ // previous implementation
+ return true;
+ }
+
//----------------------------------------------------------
// The following is used to verify "empty" Html elements.
// "Empty" Html elements are those that do not require an
@@ -843,7 +996,9 @@
static private String[] pNames = new String[]{
"param",
- };
+ };
+
+ private static final char[] AMP_CHARS = "&".toCharArray();
static {
@@ -865,5 +1020,29 @@
emptyElementArr['M'] = mNames;
emptyElementArr['p'] = pNames;
emptyElementArr['P'] = pNames;
+ }
+
+
+ // ----------------------------------------------------------- Inner Classes
+
+
+ /**
+ * <p>Private implementation of ByteArrayOutputStream.</p>
+ */
+ private static class MyByteArrayOutputStream extends ByteArrayOutputStream {
+
+
+ public MyByteArrayOutputStream(int initialCapacity) {
+ super(initialCapacity);
+ }
+ /**
+ * Obtain access to the underlying byte array to prevent
+ * unecessary temp object creation.
+ * @return <code>buf</code>
+ */
+ public byte[] getBuf() {
+ return buf;
+ }
+
}
}
Index: jsf-ri/systest/src/com/sun/faces/jsptest/IdRefTestCase.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/systest/src/com/sun/faces/jsptest/IdRefTestCase.java,v
retrieving revision 1.1
diff -u -r1.1 IdRefTestCase.java
--- jsf-ri/systest/src/com/sun/faces/jsptest/IdRefTestCase.java 27 Jul 2006 22:03:41 -0000 1.1
+++ jsf-ri/systest/src/com/sun/faces/jsptest/IdRefTestCase.java 3 Oct 2006 15:21:52 -0000
@@ -147,5 +147,55 @@
assertTrue("All cleared inputs have messages", messageMap.keySet()
.containsAll(Arrays.asList(testIds)));
}
+
+ public void testIncludedLoopIdRefs() throws Exception {
+ HtmlPage page = getPage("/faces/forEach03.jsp");
+ Map inputTagsById = mapElementsByAttribute(page.getDocumentElement(),
+ "input", "id", "type", "text");
+ String[] testIds = {
+ "myform:inputId11",
+ "myform:inputId11j_id_1",
+ "myform:inputId11j_id_2"
+ };
+ for (int i = 0; i < testIds.length; i++) {
+ HtmlTextInput input = (HtmlTextInput) inputTagsById.get(testIds[i]);
+ input.setValueAttribute("");
+ }
+ List list = getAllElementsOfGivenClass(page, null,
+ HtmlSubmitInput.class);
+ HtmlSubmitInput button = (HtmlSubmitInput) list.get(0);
+ page = (HtmlPage) button.click();
+ Map messageMap = mapMessagesById(page.getDocumentElement());
+ assertEquals("One 'value required' message for each cleared input",
+ testIds.length, messageMap.size());
+ assertTrue("Only cleared inputs have messages", Arrays.asList(testIds)
+ .containsAll(messageMap.keySet()));
+ assertTrue("All cleared inputs have messages", messageMap.keySet()
+ .containsAll(Arrays.asList(testIds)));
+ }
+
+ public void testIncludeNoLoopIdRef() throws Exception {
+ HtmlPage page = getPage("/faces/forEach03.jsp");
+ Map inputTagsById = mapElementsByAttribute(page.getDocumentElement(),
+ "input", "id", "type", "text");
+ String[] testIds = {
+ "myform:Short11",
+ };
+ for (int i = 0; i < testIds.length; i++) {
+ HtmlTextInput input = (HtmlTextInput) inputTagsById.get(testIds[i]);
+ input.setValueAttribute("");
+ }
+ List list = getAllElementsOfGivenClass(page, null,
+ HtmlSubmitInput.class);
+ HtmlSubmitInput button = (HtmlSubmitInput) list.get(0);
+ page = (HtmlPage) button.click();
+ Map messageMap = mapMessagesById(page.getDocumentElement());
+ assertEquals("One 'value required' message for each cleared input",
+ testIds.length, messageMap.size());
+ assertTrue("Only cleared inputs have messages", Arrays.asList(testIds)
+ .containsAll(messageMap.keySet()));
+ assertTrue("All cleared inputs have messages", messageMap.keySet()
+ .containsAll(Arrays.asList(testIds)));
+ }
}
Index: jsf-ri/systest/src/com/sun/faces/systest/render/CustomResponseWriter.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/systest/src/com/sun/faces/systest/render/CustomResponseWriter.java,v
retrieving revision 1.8
diff -u -r1.8 CustomResponseWriter.java
--- jsf-ri/systest/src/com/sun/faces/systest/render/CustomResponseWriter.java 24 Aug 2006 19:57:10 -0000 1.8
+++ jsf-ri/systest/src/com/sun/faces/systest/render/CustomResponseWriter.java 3 Oct 2006 15:21:52 -0000
@@ -29,17 +29,16 @@
package com.sun.faces.systest.render;
-import com.sun.faces.util.HtmlUtils;
-import com.sun.faces.util.MessageUtils;
-
import javax.faces.FacesException;
import javax.faces.component.UIComponent;
import javax.faces.context.ResponseWriter;
import java.io.IOException;
-import java.io.UnsupportedEncodingException;
import java.io.Writer;
+import com.sun.faces.util.HtmlUtils;
+import com.sun.faces.util.MessageUtils;
+
/**
* <p><strong>CustomResponseWriter</strong> is an Html specific implementation
@@ -95,12 +94,11 @@
this.encoding = encoding;
// Check the character encoding
- try {
- HtmlUtils.validateEncoding(encoding);
- } catch (UnsupportedEncodingException e) {
+ // Check the character encoding
+ if (!HtmlUtils.validateEncoding(encoding)) {
throw new IllegalArgumentException(MessageUtils.getExceptionMessageString(
- MessageUtils.ENCODING_ERROR_MESSAGE_ID));
- }
+ MessageUtils.ENCODING_ERROR_MESSAGE_ID));
+ }
}
@@ -283,7 +281,7 @@
writer.write("=\"");
// write the attribute value
- HtmlUtils.writeAttribute(writer, buffer, value.toString());
+ HtmlUtils.writeText(writer, buffer, value.toString());
//PENDING (horwat) using String as a result of Tomcat char
// writer ArrayIndexOutOfBoundsException (3584)
writer.write("\"");
@@ -331,7 +329,7 @@
// Javascript URLs should not be URL-encoded
if (stringValue.startsWith("javascript:")) {
- HtmlUtils.writeAttribute(writer, buffer, stringValue);
+ HtmlUtils.writeText(writer, buffer, stringValue);
} else {
HtmlUtils.writeURL(writer, stringValue, encoding, getContentType());
}
Index: jsf-ri/systest/web/forEach03.jsp
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/systest/web/forEach03.jsp,v
retrieving revision 1.1
diff -u -r1.1 forEach03.jsp
--- jsf-ri/systest/web/forEach03.jsp 27 Jul 2006 22:03:41 -0000 1.1
+++ jsf-ri/systest/web/forEach03.jsp 3 Oct 2006 15:21:52 -0000
@@ -130,6 +130,8 @@
</h:panelGrid>
</h:panelGroup>
</h:panelGrid>
+
+ <jsp:include page="forEach03Include.jsp" />
<h:commandButton id="submit" value="Submit" />
</h:form>
Index: jsf-ri/systest/web/golden/interweaving06.txt
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/systest/web/golden/interweaving06.txt,v
retrieving revision 1.4
diff -u -r1.4 interweaving06.txt
--- jsf-ri/systest/web/golden/interweaving06.txt 28 Aug 2006 14:17:32 -0000 1.4
+++ jsf-ri/systest/web/golden/interweaving06.txt 3 Oct 2006 15:21:52 -0000
@@ -29,19 +29,19 @@
Array[0]:
This component has no ID <br>
- <input id="j_id_id15j_id_1" type="text" name="j_id_id15j_id_1" value="This component has no ID " /><br>
+ <input id="j_id_id15i0" type="text" name="j_id_id15i0" value="This component has no ID " /><br>
Array[1]:
This component has no ID <br>
- <input id="j_id_id15j_id_2" type="text" name="j_id_id15j_id_2" value="This component has no ID " /><br>
+ <input id="j_id_id15i0j_id_1" type="text" name="j_id_id15i0j_id_1" value="This component has no ID " /><br>
Array[2]:
This component has no ID <br>
- <input id="j_id_id15j_id_3" type="text" name="j_id_id15j_id_3" value="This component has no ID " /><br>
+ <input id="j_id_id15i0j_id_2" type="text" name="j_id_id15i0j_id_2" value="This component has no ID " /><br>
Array[3]:
This component has no ID <br>
- <input id="j_id_id15j_id_4" type="text" name="j_id_id15j_id_4" value="This component has no ID " /><br>
+ <input id="j_id_id15i0j_id_3" type="text" name="j_id_id15i0j_id_3" value="This component has no ID " /><br>
</p>
Index: jsf-ri/systest/web/golden/interweaving07.txt
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/systest/web/golden/interweaving07.txt,v
retrieving revision 1.4
diff -u -r1.4 interweaving07.txt
--- jsf-ri/systest/web/golden/interweaving07.txt 28 Aug 2006 14:17:33 -0000 1.4
+++ jsf-ri/systest/web/golden/interweaving07.txt 3 Oct 2006 15:21:52 -0000
@@ -29,19 +29,19 @@
Array[0]:
This component has no ID <br>
- <input id="j_id_id15j_id_1" type="text" name="j_id_id15j_id_1" value="This component has no ID " /><br>
+ <input id="j_id_id15i0" type="text" name="j_id_id15i0" value="This component has no ID " /><br>
Array[1]:
This component has no ID <br>
- <input id="j_id_id15j_id_2" type="text" name="j_id_id15j_id_2" value="This component has no ID " /><br>
+ <input id="j_id_id15i0j_id_1" type="text" name="j_id_id15i0j_id_1" value="This component has no ID " /><br>
Array[2]:
This component has no ID <br>
- <input id="j_id_id15j_id_3" type="text" name="j_id_id15j_id_3" value="This component has no ID " /><br>
+ <input id="j_id_id15i0j_id_2" type="text" name="j_id_id15i0j_id_2" value="This component has no ID " /><br>
Array[3]:
This component has no ID <br>
- <input id="j_id_id15j_id_4" type="text" name="j_id_id15j_id_4" value="This component has no ID " /><br>
+ <input id="j_id_id15i0j_id_3" type="text" name="j_id_id15i0j_id_3" value="This component has no ID " /><br>
</p>
Index: jsf-ri/systest/web/golden/subview05.txt
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/systest/web/golden/subview05.txt,v
retrieving revision 1.8
diff -u -r1.8 subview05.txt
--- jsf-ri/systest/web/golden/subview05.txt 28 Aug 2006 14:17:33 -0000 1.8
+++ jsf-ri/systest/web/golden/subview05.txt 3 Oct 2006 15:21:52 -0000
@@ -30,19 +30,19 @@
Array[0]:
This component has no ID <br>
- <input id="subviewInner:j_id_id17j_id_1" type="text" name="subviewInner:j_id_id17j_id_1" value="This component has no ID " /><br>
+ <input id="subviewInner:j_id_id17i0" type="text" name="subviewInner:j_id_id17i0" value="This component has no ID " /><br>
Array[1]:
This component has no ID <br>
- <input id="subviewInner:j_id_id17j_id_2" type="text" name="subviewInner:j_id_id17j_id_2" value="This component has no ID " /><br>
+ <input id="subviewInner:j_id_id17i0j_id_1" type="text" name="subviewInner:j_id_id17i0j_id_1" value="This component has no ID " /><br>
Array[2]:
This component has no ID <br>
- <input id="subviewInner:j_id_id17j_id_3" type="text" name="subviewInner:j_id_id17j_id_3" value="This component has no ID " /><br>
+ <input id="subviewInner:j_id_id17i0j_id_2" type="text" name="subviewInner:j_id_id17i0j_id_2" value="This component has no ID " /><br>
Array[3]:
This component has no ID <br>
- <input id="subviewInner:j_id_id17j_id_4" type="text" name="subviewInner:j_id_id17j_id_4" value="This component has no ID " /><br>
+ <input id="subviewInner:j_id_id17i0j_id_3" type="text" name="subviewInner:j_id_id17i0j_id_3" value="This component has no ID " /><br>
Index: jsf-ri/systest/web/golden/subview06.txt
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/systest/web/golden/subview06.txt,v
retrieving revision 1.10
diff -u -r1.10 subview06.txt
--- jsf-ri/systest/web/golden/subview06.txt 28 Aug 2006 14:17:33 -0000 1.10
+++ jsf-ri/systest/web/golden/subview06.txt 3 Oct 2006 15:21:52 -0000
@@ -31,19 +31,19 @@
Array[0]:
This component has no ID <br>
- <input id="subviewOuter:subviewInner:j_id_id17j_id_1" type="text" name="subviewOuter:subviewInner:j_id_id17j_id_1" value="This component has no ID " /><br>
+ <input id="subviewOuter:subviewInner:j_id_id17i0" type="text" name="subviewOuter:subviewInner:j_id_id17i0" value="This component has no ID " /><br>
Array[1]:
This component has no ID <br>
- <input id="subviewOuter:subviewInner:j_id_id17j_id_2" type="text" name="subviewOuter:subviewInner:j_id_id17j_id_2" value="This component has no ID " /><br>
+ <input id="subviewOuter:subviewInner:j_id_id17i0j_id_1" type="text" name="subviewOuter:subviewInner:j_id_id17i0j_id_1" value="This component has no ID " /><br>
Array[2]:
This component has no ID <br>
- <input id="subviewOuter:subviewInner:j_id_id17j_id_3" type="text" name="subviewOuter:subviewInner:j_id_id17j_id_3" value="This component has no ID " /><br>
+ <input id="subviewOuter:subviewInner:j_id_id17i0j_id_2" type="text" name="subviewOuter:subviewInner:j_id_id17i0j_id_2" value="This component has no ID " /><br>
Array[3]:
This component has no ID <br>
- <input id="subviewOuter:subviewInner:j_id_id17j_id_4" type="text" name="subviewOuter:subviewInner:j_id_id17j_id_4" value="This component has no ID " /><br>
+ <input id="subviewOuter:subviewInner:j_id_id17i0j_id_3" type="text" name="subviewOuter:subviewInner:j_id_id17i0j_id_3" value="This component has no ID " /><br>
Index: jsf-ri/test/com/sun/faces/application/TestViewHandlerImpl.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/test/com/sun/faces/application/TestViewHandlerImpl.java,v
retrieving revision 1.34
diff -u -r1.34 TestViewHandlerImpl.java
--- jsf-ri/test/com/sun/faces/application/TestViewHandlerImpl.java 15 Aug 2006 17:19:05 -0000 1.34
+++ jsf-ri/test/com/sun/faces/application/TestViewHandlerImpl.java 3 Oct 2006 15:21:52 -0000
@@ -235,7 +235,7 @@
testRequest.setAttribute("com.sun.faces.INVOCATION_PATH", null);
String path = handler.getActionURL(facesContext, "/path/test.jsp");
System.out.println("VIEW ID PATH 2: " + path);
- assertEquals(contextPath + "/faces/path/test.jsp", path);
+ assertEquals(contextPath + "/faces/path/test.jsp", path.substring(0, path.indexOf(";j")));
// if getServletPath() returns a path indicating extension mapping
@@ -246,7 +246,7 @@
testRequest.setAttribute("com.sun.faces.INVOCATION_PATH", null);
path = handler.getActionURL(facesContext, "/path/test");
System.out.println("VIEW ID PATH 3: " + path);
- assertEquals(contextPath + "/path/test.jsf", path);
+ assertEquals(contextPath + "/path/test.jsf", path.substring(0, path.indexOf(";j")));
// if getServletPath() returns a path indicating extension mapping
// and the viewId passed has an extension, replace the extension with
@@ -256,7 +256,7 @@
testRequest.setAttribute("com.sun.faces.INVOCATION_PATH", null);
path = handler.getActionURL(facesContext, "/path/t.est.jsp");
System.out.println("VIEW ID PATH 4: " + path);
- assertEquals(contextPath + "/path/t.est.jsf", path);
+ assertEquals(contextPath + "/path/t.est.jsf", path.substring(0, path.indexOf(";j")));
// if path info is null, the impl must check to see if
// there is an exact match on the servlet path, if so, return
@@ -266,7 +266,7 @@
testRequest.setAttribute("com.sun.faces.INVOCATION_PATH", null);
path = handler.getActionURL(facesContext, "/path/t.est");
System.out.println("VIEW ID PATH 5: " + path);
- assertEquals(contextPath + "/faces/path/t.est", path);
+ assertEquals(contextPath + "/faces/path/t.est", path.substring(0, path.indexOf(";j")));
}
@@ -313,12 +313,14 @@
new FacesContextImpl(extContext, lifecycle);
// Validate correct calculations
+ String path = Util.getViewHandler(getFacesContext()).
+ getResourceURL(context, "/index.jsp");
assertEquals(request.getContextPath() + "/index.jsp",
- Util.getViewHandler(getFacesContext()).
- getResourceURL(context, "/index.jsp"));
+ path.substring(0, path.indexOf(";j")));
+ path = Util.getViewHandler(getFacesContext()).
+ getResourceURL(context, "index.jsp");
assertEquals("index.jsp",
- Util.getViewHandler(getFacesContext()).
- getResourceURL(context, "index.jsp"));
+ path.substring(0, path.indexOf(";j")));
}
Index: jsf-ri/test/com/sun/faces/util/TestHtmlUtils.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-ri/test/com/sun/faces/util/TestHtmlUtils.java,v
retrieving revision 1.2
diff -u -r1.2 TestHtmlUtils.java
--- jsf-ri/test/com/sun/faces/util/TestHtmlUtils.java 24 Aug 2006 19:25:01 -0000 1.2
+++ jsf-ri/test/com/sun/faces/util/TestHtmlUtils.java 3 Oct 2006 15:21:52 -0000
@@ -53,24 +53,24 @@
//Test URL with two params
testURLEncoding("
http://www.google.com?joe=10&fred=20", "
http://www.google.com?joe=10&fred=20", "
http://www.google.com?joe=10&fred=20");
//Test URL with & entity encoded
- testURLEncoding("/index.jsf?joe=10&fred=20", "/index.jsf?joe=10&%3Bfred=20", "/index.jsf?joe=10&fred=20");
+ testURLEncoding("/index.jsf?joe=10&fred=20", "/index.jsf?joe=10&fred=20", "/index.jsf?joe=10&fred=20");
//Test URL with two params and second & close to end of string
testURLEncoding("/index.jsf?joe=10&f=20", "/index.jsf?joe=10&f=20", "/index.jsf?joe=10&f=20");
//Test URL with misplaced & expected behavior but not necissarily right.
testURLEncoding("/index.jsf?joe=10&f=20&", "/index.jsf?joe=10&f=20&", "/index.jsf?joe=10&f=20&");
//Test URL with encoded entity at end of URL expected behavior but not necissarily right.
- testURLEncoding("/index.jsf?joe=10&f=20&", "/index.jsf?joe=10&f=20&%3B", "/index.jsf?joe=10&f=20&");
+ testURLEncoding("/index.jsf?joe=10&f=20&", "/index.jsf?joe=10&f=20&", "/index.jsf?joe=10&f=20&");
}
private void testURLEncoding(String urlToEncode, String expectedHTML, String expectedXML) throws UnsupportedEncodingException, IOException {
char[] buffer = new char[1024];
StringWriter xmlWriter = new StringWriter();
HtmlUtils.writeURL(xmlWriter, urlToEncode, "UTF-8", RIConstants.XHTML_CONTENT_TYPE);
-// System.out.println(xmlWriter.toString());
+ System.out.println("XML: " + xmlWriter.toString());
assertEquals(xmlWriter.toString(), expectedXML);
StringWriter htmlWriter = new StringWriter();
HtmlUtils.writeURL(htmlWriter, urlToEncode, "UTF-8", RIConstants.HTML_CONTENT_TYPE);
-// System.out.println(htmlWriter.toString());
+ System.out.println("HTML: " +htmlWriter.toString());
assertEquals(htmlWriter.toString(), expectedHTML);
}
Index: jsf-tools/template-src/TypedCollections.java
===================================================================
RCS file: /cvs/javaserverfaces-sources/jsf-tools/template-src/TypedCollections.java,v
retrieving revision 1.1
diff -u -r1.1 TypedCollections.java
--- jsf-tools/template-src/TypedCollections.java 25 Aug 2006 09:50:19 -0000 1.1
+++ jsf-tools/template-src/TypedCollections.java 3 Oct 2006 15:21:52 -0000
@@ -48,16 +48,14 @@
*/
@SuppressWarnings("unchecked")
@protection@ static <E,TypedC extends Collection<E>> TypedC dynamicallyCastCollection(Collection<?> c,
- Class<E> type, Class<TypedC> collectionType) {
- if (c == null)
+ Class<E> type,
+ Class<TypedC> collectionType) {
+ if (c == null)
return null;
if (!collectionType.isInstance(c))
throw new ClassCastException(c.getClass().getName());
- for (Object element : c) {
- if (element != null && !type.isInstance(element))
- throw new ClassCastException(element.getClass().getName());
- }
- return collectionType.cast(c);
+
+ return collectionType.cast(c);
}
/**
@@ -75,7 +73,7 @@
*/
@SuppressWarnings("unchecked")
@protection@ static <E> List<E> dynamicallyCastList(List<?> list, Class<E> type) {
- return dynamicallyCastCollection(list, type, List.class);
+ return dynamicallyCastCollection(list, type, List.class);
}
/**
@@ -92,8 +90,9 @@
* @throws java.lang.ClassCastException
*/
@SuppressWarnings("unchecked")
- @protection@ static <E> Set<E> dynamicallyCastSet(Set<?> set, Class<E> type) {
- return dynamicallyCastCollection(set, type, Set.class);
+ @protection@ static <E> Set<E> dynamicallyCastSet(Set<?> set,
+ Class<E> type) {
+ return dynamicallyCastCollection(set, type, Set.class);
}
/**
@@ -115,16 +114,11 @@
*/
@SuppressWarnings("unchecked")
@protection@ static <K, V> Map<K, V> dynamicallyCastMap(Map<?, ?> map,
- Class<K> keyType, Class<V> valueType) {
- if (map != null) {
- for (Map.Entry<?, ?> entry : map.entrySet()) {
- if (entry.getKey() != null && !keyType.isInstance(entry.getKey()))
- throw new ClassCastException(entry.getKey().getClass().getName());
- if (entry.getValue() != null
- && !valueType.isInstance(entry.getValue()))
- throw new ClassCastException(entry.getValue().getClass().getName());
- }
- }
- return (Map<K, V>) map;
+ Class<K> keyType,
+ Class<V> valueType) {
+ if (map == null) {
+ return null;
+ }
+ return (Map<K, V>) map;
}
}
SECTION: New Files
----------------------------
SEE ATTACHMENTS