Bug 499196 - Javadoc Location support for doclava federated
documentation

Change-Id: I07996096363cce7b1b3ce33cfbb8461923b910ea
Signed-off-by: Jay Arthanareeswaran <jarthana@in.ibm.com>
diff --git a/org.eclipse.jdt.core.tests.compiler/endorsed/lib1.jar b/org.eclipse.jdt.core.tests.compiler/endorsed/lib1.jar
new file mode 100644
index 0000000..15cb0ec
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.compiler/endorsed/lib1.jar
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachedJavadocTests.java b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachedJavadocTests.java
index 9376aa6..203b2bc 100644
--- a/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachedJavadocTests.java
+++ b/org.eclipse.jdt.core.tests.model/src/org/eclipse/jdt/core/tests/model/AttachedJavadocTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2015 IBM Corporation and others.
+ * Copyright (c) 2000, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -260,20 +260,7 @@
 		try {
 			IClasspathEntry[] entries = this.project.getRawClasspath();
 			savedEntries = entries.clone();
-			IResource resource = this.project.getProject().findMember("/doc.zip"); //$NON-NLS-1$
-			assertNotNull("doc folder cannot be null", resource); //$NON-NLS-1$
-			URI locationURI = resource.getLocationURI();
-			assertNotNull("doc folder cannot be null", locationURI); //$NON-NLS-1$
-			URL docUrl = null;
-			try {
-				docUrl = locationURI.toURL();
-			} catch (MalformedURLException e) {
-				assertTrue("Should not happen", false); //$NON-NLS-1$
-			} catch(IllegalArgumentException e) {
-				assertTrue("Should not happen", false); //$NON-NLS-1$
-			}
-			final String path = "jar:" + docUrl.toExternalForm() + "!/doc"; //$NON-NLS-1$ //$NON-NLS-2$
-			//final String path = "jar:" + "platform:/resource/AttachedJavadocProject/doc.zip" + "!/doc";
+			final String path = "jar:" + "platform:/resource/AttachedJavadocProject/doc.zip" + "!/doc";
 			IClasspathAttribute attribute = JavaCore.newClasspathAttribute(IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME, path);
 			for (int i = 0, max = entries.length; i < max; i++) {
 				final IClasspathEntry entry = entries[i];
@@ -1315,5 +1302,27 @@
 			assertTrue("Should not happen", false);
 		}
 	}
+	public void testBug499196() throws JavaModelException {
+		try {
+			IClasspathAttribute attribute =
+					JavaCore.newClasspathAttribute(
+							IClasspathAttribute.JAVADOC_LOCATION_ATTRIBUTE_NAME,
+							"jar:platform:/resource/AttachedJavadocProject/bug499196_doc.zip!/");
+			IClasspathEntry newEntry = JavaCore.newLibraryEntry(new Path("/AttachedJavadocProject/bug499196.jar"), null, null, null, new IClasspathAttribute[] {attribute}, true);
+			this.project.setRawClasspath(new IClasspathEntry[]{newEntry}, null);
+			this.project.getResolvedClasspath(false);
+
+			IPackageFragmentRoot jarRoot = this.project.getPackageFragmentRoot(getFile("/AttachedJavadocProject/bug499196.jar"));
+			final IType type = jarRoot.getPackageFragment("p1.p2").getClassFile("Bug499196.class").getType();
+			assertNotNull(type);
+			IMethod method = type.getMethod("Bug499196", new String[] {}); //$NON-NLS-1$
+			assertNotNull("Constructor should not be null", method);
+			assertTrue(method.exists());
+			String javadoc = method.getAttachedJavadoc(new NullProgressMonitor()); //$NON-NLS-1$
+			assertNotNull("Should have a javadoc", javadoc); //$NON-NLS-1$
+		} catch (IndexOutOfBoundsException e) {
+			assertTrue("Should not happen", false);
+		}
+	}
 }
 
diff --git a/org.eclipse.jdt.core.tests.model/workspace/AttachedJavadocProject/bug499196.jar b/org.eclipse.jdt.core.tests.model/workspace/AttachedJavadocProject/bug499196.jar
new file mode 100644
index 0000000..16eb723
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/AttachedJavadocProject/bug499196.jar
Binary files differ
diff --git a/org.eclipse.jdt.core.tests.model/workspace/AttachedJavadocProject/bug499196_doc.zip b/org.eclipse.jdt.core.tests.model/workspace/AttachedJavadocProject/bug499196_doc.zip
new file mode 100644
index 0000000..197c047
--- /dev/null
+++ b/org.eclipse.jdt.core.tests.model/workspace/AttachedJavadocProject/bug499196_doc.zip
Binary files differ
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java
index ed53500..e52d2e1 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocConstants.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2014 IBM Corporation and others.
+ * Copyright (c) 2005, 2016 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -14,7 +14,9 @@
 
 	String ANCHOR_PREFIX_END = "\""; //$NON-NLS-1$
 	char[] ANCHOR_PREFIX_START = "<A NAME=\"".toCharArray(); //$NON-NLS-1$
-	int ANCHOR_PREFIX_START_LENGHT = ANCHOR_PREFIX_START.length;
+	char[] ANCHOR_PREFIX_START_2 = "<A ID=\"".toCharArray(); //$NON-NLS-1$
+	int ANCHOR_PREFIX_START_LENGTH = ANCHOR_PREFIX_START.length;
+	int ANCHOR_PREFIX_START2_LENGTH = ANCHOR_PREFIX_START_2.length;
 	char[] ANCHOR_SUFFIX = "</A>".toCharArray(); //$NON-NLS-1$
 	int ANCHOR_SUFFIX_LENGTH = JavadocConstants.ANCHOR_SUFFIX.length;
 	char[] CONSTRUCTOR_DETAIL = "<!-- ========= CONSTRUCTOR DETAIL ======== -->".toCharArray(); //$NON-NLS-1$
diff --git a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java
index 02341d5..e29b96d 100644
--- a/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java
+++ b/org.eclipse.jdt.core/model/org/eclipse/jdt/internal/core/JavadocContents.java
@@ -185,14 +185,15 @@
 		}
 		
 		int fromIndex = this.tempLastAnchorFoundIndex;
-		int index;
+		int[] index;
 		
 		// check each next unknown anchor locations
-		while ((index = CharOperation.indexOf(JavadocConstants.ANCHOR_PREFIX_START, this.content, false, fromIndex)) != -1 && (index < indexOfSectionBottom || indexOfSectionBottom == -1)) {
-			fromIndex = index + 1;
-			
-			int anchorEndStart = index + JavadocConstants.ANCHOR_PREFIX_START_LENGHT;
-			
+		index = getAnchorIndex(fromIndex);
+		while (index[0] != -1 && (index[0] < indexOfSectionBottom || indexOfSectionBottom == -1)) {
+			fromIndex = index[0] + 1;
+
+			int anchorEndStart = index[0] + index[1];
+
 			this.tempLastAnchorFoundIndex = anchorEndStart;
 			
 			if (CharOperation.prefixEquals(anchor, this.content, false, anchorEndStart)) {
@@ -204,11 +205,25 @@
 				
 				this.tempAnchorIndexes[this.tempAnchorIndexesCount++] = anchorEndStart;
 			}
+			index = getAnchorIndex(fromIndex);
 		}
 		
 		return null;
 	}
-	
+	private int[] getAnchorIndex(int fromIndex) {
+		int index = CharOperation.indexOf(JavadocConstants.ANCHOR_PREFIX_START, this.content, false, fromIndex);
+		if (index != -1) {
+			return new int[]{index, JavadocConstants.ANCHOR_PREFIX_START_LENGTH};
+		}
+		if (index == -1) {
+			index = CharOperation.indexOf(JavadocConstants.ANCHOR_PREFIX_START_2, this.content, false, fromIndex);
+		}
+		if (index == -1) {
+			return new int[]{-1, -1};
+		} else {
+			return new int[]{index, JavadocConstants.ANCHOR_PREFIX_START2_LENGTH};
+		}
+	}
 	private int[] computeChildRange(int anchorEndStart, char[] anchor, int indexOfBottom) {
 		int[] range = null;
 				
@@ -218,7 +233,7 @@
 			int indexOfEndLink = CharOperation.indexOf(JavadocConstants.ANCHOR_SUFFIX, this.content, false, anchorEndStart + anchor.length);
 			if (indexOfEndLink != -1) {
 				// try to find the next anchor
-				int indexOfNextElement = CharOperation.indexOf(JavadocConstants.ANCHOR_PREFIX_START, this.content, false, indexOfEndLink);
+				int indexOfNextElement = getAnchorIndex(indexOfEndLink)[0];
 				
 				int javadocStart = indexOfEndLink + JavadocConstants.ANCHOR_SUFFIX_LENGTH;
 				int javadocEnd = indexOfNextElement == -1 ? indexOfBottom : Math.min(indexOfNextElement, indexOfBottom);