changeset 3357:4487f6f98252

8043186: javac test langtools/tools/javac/util/StringUtilsTest.java fails Summary: The result of String.toLowerCase.indexOf does not always point at the start of the given string in the non-lowercased text. Reviewed-by: jjg, bpatel
author jlahoda
date Fri, 16 May 2014 10:52:07 +0200
parents d488132dbea7
children 51f48a6ab5f7 2a096f5666fd
files src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java src/share/classes/com/sun/tools/javac/util/StringUtils.java test/com/sun/javadoc/testRelativeLinks/TestRelativeLinks.java test/com/sun/javadoc/testRelativeLinks/pkg/C.java test/com/sun/javadoc/testTopOption/TestTopOption.java test/tools/javac/util/StringUtilsTest.java
diffstat 7 files changed, 76 insertions(+), 55 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java	Mon May 12 17:09:26 2014 +0100
+++ b/src/share/classes/com/sun/tools/doclets/formats/html/HtmlDocletWriter.java	Fri May 16 10:52:07 2014 +0200
@@ -28,6 +28,8 @@
 import java.io.*;
 import java.text.SimpleDateFormat;
 import java.util.*;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import com.sun.javadoc.*;
 import com.sun.tools.doclets.formats.html.markup.*;
@@ -139,42 +141,37 @@
         if (index < 0) {
             return htmlstr;
         }
-        String lowerHtml = StringUtils.toLowerCase(htmlstr);
-        final String docroot = "{@docroot}";
-        // Return index of first occurrence of {@docroot}
-        // Note: {@docRoot} is not case sensitive when passed in w/command line option
-        index = lowerHtml.indexOf(docroot, index);
-        if (index < 0) {
+        Matcher docrootMatcher = docrootPattern.matcher(htmlstr);
+        if (!docrootMatcher.find()) {
             return htmlstr;
         }
         StringBuilder buf = new StringBuilder();
-        int previndex = 0;
-        while (true) {
-            // Search for lowercase version of {@docRoot}
-            index = lowerHtml.indexOf(docroot, previndex);
-            // If next {@docRoot} tag not found, append rest of htmlstr and exit loop
-            if (index < 0) {
-                buf.append(htmlstr.substring(previndex));
-                break;
-            }
-            // If next {@docroot} tag found, append htmlstr up to start of tag
-            buf.append(htmlstr.substring(previndex, index));
-            previndex = index + docroot.length();
-            if (configuration.docrootparent.length() > 0 && htmlstr.startsWith("/..", previndex)) {
+        int prevEnd = 0;
+        do {
+            int match = docrootMatcher.start();
+            // append htmlstr up to start of next {@docroot}
+            buf.append(htmlstr.substring(prevEnd, match));
+            prevEnd = docrootMatcher.end();
+            if (configuration.docrootparent.length() > 0 && htmlstr.startsWith("/..", prevEnd)) {
                 // Insert the absolute link if {@docRoot} is followed by "/..".
                 buf.append(configuration.docrootparent);
-                previndex += 3;
+                prevEnd += 3;
             } else {
                 // Insert relative path where {@docRoot} was located
                 buf.append(pathToRoot.isEmpty() ? "." : pathToRoot.getPath());
             }
             // Append slash if next character is not a slash
-            if (previndex < htmlstr.length() && htmlstr.charAt(previndex) != '/') {
+            if (prevEnd < htmlstr.length() && htmlstr.charAt(prevEnd) != '/') {
                 buf.append('/');
             }
-        }
+        } while (docrootMatcher.find());
+        buf.append(htmlstr.substring(prevEnd));
         return buf.toString();
     }
+    //where:
+        // Note: {@docRoot} is not case sensitive when passed in w/command line option:
+        private static final Pattern docrootPattern =
+                Pattern.compile(Pattern.quote("{@docroot}"), Pattern.CASE_INSENSITIVE);
 
     /**
      * Get the script to show or hide the All classes link.
@@ -1690,13 +1687,13 @@
         }
 
         //Redirect all relative links.
-        int end, begin = StringUtils.toLowerCase(text).indexOf("<a");
+        int end, begin = StringUtils.indexOfIgnoreCase(text, "<a");
         if(begin >= 0){
             StringBuilder textBuff = new StringBuilder(text);
 
             while(begin >=0){
                 if (textBuff.length() > begin + 2 && ! Character.isWhitespace(textBuff.charAt(begin+2))) {
-                    begin = StringUtils.toLowerCase(textBuff.toString()).indexOf("<a", begin + 1);
+                    begin = StringUtils.indexOfIgnoreCase(textBuff.toString(), "<a", begin + 1);
                     continue;
                 }
 
@@ -1736,7 +1733,7 @@
                         + redirectPathFromRoot.resolve(relativeLink).getPath();
                     textBuff.replace(begin, end, relativeLink);
                 }
-                begin = StringUtils.toLowerCase(textBuff.toString()).indexOf("<a", begin + 1);
+                begin = StringUtils.indexOfIgnoreCase(textBuff.toString(), "<a", begin + 1);
             }
             return textBuff.toString();
         }
--- a/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java	Mon May 12 17:09:26 2014 +0100
+++ b/src/share/classes/com/sun/tools/doclets/formats/html/MethodWriterImpl.java	Fri May 16 10:52:07 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -332,24 +332,6 @@
     }
 
     /**
-     * Parse the &lt;Code&gt; tag and return the text.
-     */
-    protected String parseCodeTag(String tag){
-        if(tag == null){
-            return "";
-        }
-
-        String lc = StringUtils.toLowerCase(tag);
-        int begin = lc.indexOf("<code>");
-        int end = lc.indexOf("</code>");
-        if(begin == -1 || end == -1 || end <= begin){
-            return tag;
-        } else {
-            return tag.substring(begin + 6, end);
-        }
-    }
-
-    /**
      * {@inheritDoc}
      */
     protected static void addImplementsInfo(HtmlDocletWriter writer,
--- a/src/share/classes/com/sun/tools/javac/util/StringUtils.java	Mon May 12 17:09:26 2014 +0100
+++ b/src/share/classes/com/sun/tools/javac/util/StringUtils.java	Fri May 16 10:52:07 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -26,6 +26,8 @@
 package com.sun.tools.javac.util;
 
 import java.util.Locale;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /** A collection of utilities for String manipulation.
  *
@@ -50,4 +52,19 @@
         return source.toUpperCase(Locale.US);
     }
 
+    /**Case insensitive version of {@link String#indexOf(java.lang.String)}. Equivalent to
+     * {@code text.indexOf(str)}, except the matching is case insensitive.
+     */
+    public static int indexOfIgnoreCase(String text, String str) {
+        return indexOfIgnoreCase(text, str, 0);
+    }
+
+    /**Case insensitive version of {@link String#indexOf(java.lang.String, int)}. Equivalent to
+     * {@code text.indexOf(str, startIndex)}, except the matching is case insensitive.
+     */
+    public static int indexOfIgnoreCase(String text, String str, int startIndex) {
+        Matcher m = Pattern.compile(Pattern.quote(str), Pattern.CASE_INSENSITIVE).matcher(text);
+        return m.find(startIndex) ? m.start() : -1;
+    }
+
 }
--- a/test/com/sun/javadoc/testRelativeLinks/TestRelativeLinks.java	Mon May 12 17:09:26 2014 +0100
+++ b/test/com/sun/javadoc/testRelativeLinks/TestRelativeLinks.java	Fri May 16 10:52:07 2014 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug      4460354 8014636
+ * @bug      4460354 8014636 8043186
  * @summary  Test to make sure that relative paths are redirected in the
  *           output so that they are not broken.
  * @author   jamieh
--- a/test/com/sun/javadoc/testRelativeLinks/pkg/C.java	Mon May 12 17:09:26 2014 +0100
+++ b/test/com/sun/javadoc/testRelativeLinks/pkg/C.java	Fri May 16 10:52:07 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -30,7 +30,7 @@
 public class C {
 
     /**
-     * Here is a relative link in a field:
+     * Here is a relative link in a field:\u0130
      * <a href="relative-field-link.html">relative field link</a>.
      */
     public C field = null;
--- a/test/com/sun/javadoc/testTopOption/TestTopOption.java	Mon May 12 17:09:26 2014 +0100
+++ b/test/com/sun/javadoc/testTopOption/TestTopOption.java	Fri May 16 10:52:07 2014 +0200
@@ -23,7 +23,7 @@
 
 /*
  * @test
- * @bug      6227616
+ * @bug      6227616 8043186
  * @summary  Test the new -top option.
  * @author   jamieh
  * @library  ../lib
@@ -43,7 +43,30 @@
         javadoc("-overview", testSrc("overview.html"),
                 "-use",
                 "-top", "TOP TEXT",
-                "-d", "out",
+                "-d", "out-1",
+                "-sourcepath", testSrc,
+                "pkg");
+        checkExit(Exit.OK);
+
+        checkTopText(
+                "pkg/AnnotationType.html",
+                "pkg/class-use/AnnotationType.html",
+                "pkg/Cl.html",
+                "pkg/class-use/Cl.html",
+                "pkg/package-summary.html",
+                "pkg/package-use.html",
+                "overview-summary.html",
+                "overview-tree.html",
+                "constant-values.html",
+                "help-doc.html");
+    }
+
+    @Test
+    void testDocRootRewrite() {
+        javadoc("-overview", testSrc("overview.html"),
+                "-use",
+                "-top", "\u0130{@docroot}TOP TEXT",
+                "-d", "out-2",
                 "-sourcepath", testSrc,
                 "pkg");
         checkExit(Exit.OK);
--- a/test/tools/javac/util/StringUtilsTest.java	Mon May 12 17:09:26 2014 +0100
+++ b/test/tools/javac/util/StringUtilsTest.java	Fri May 16 10:52:07 2014 +0200
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -23,7 +23,7 @@
 
 /**
  * @test
- * @bug 8029800
+ * @bug 8029800 8043186
  * @summary Unit test StringUtils
  * @run main StringUtilsTest
  */
@@ -44,12 +44,14 @@
         assertEquals("\u0131", "I".toLowerCase());
         assertEquals("\u0130", "i".toUpperCase());
 
-        //verify the StringUtils does what it should
+        //verify the StringUtils.toLowerCase/toUpperCase do what they should:
         assertEquals("i", StringUtils.toLowerCase("I"));
         assertEquals("I", StringUtils.toUpperCase("i"));
 
-        //verify we can use index from indexOf of toLowerCase String in the original:
-        assertEquals(2, StringUtils.toLowerCase("\u0130\u0130lookFor").indexOf("lookfor"));
+        //verify StringUtils.caseInsensitiveIndexOf works:
+        assertEquals(2, StringUtils.indexOfIgnoreCase("  lookFor", "lookfor"));
+        assertEquals(11, StringUtils.indexOfIgnoreCase("  lookFor  LOOKfor", "lookfor", 11));
+        assertEquals(2, StringUtils.indexOfIgnoreCase("\u0130\u0130lookFor", "lookfor"));
     }
 
     void assertEquals(String expected, String actual) {