Fixes bug 423254 - There is no way to tell if a project's factory path
is different from the workspace default

Change-Id: Ia28cb895a17c327299920d56c65f1db6410218d7
Signed-off-by: Harry Terkelsen <het@google.com>
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FactoryPath.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FactoryPath.java
index 9943db1..224d480 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FactoryPath.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/internal/util/FactoryPath.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2007 BEA Systems, Inc.
+ * Copyright (c) 2005, 2014 BEA Systems, Inc.
  * 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
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *   wharley@bea.com - initial API and implementation
+ *   het@google.com - Bug 423254 - There is no way to tell if a project's factory path is different from the workspace default
  *******************************************************************************/
 
 package org.eclipse.jdt.apt.core.internal.util;
@@ -244,5 +245,22 @@
 		}
 		return map;
 	}
-
+	
+	/**
+	 * A word of warning: this equals() method does not canonicalize factory
+	 * paths before comparing factory path entries. It's possible that two
+	 * factory paths actually refer to the same jar files and this method would
+	 * return that the paths are not equal.
+	 */
+	@Override
+	public boolean equals(Object o) {
+		if (this == o) {
+			return true;
+		}
+		if (!(o instanceof FactoryPath)) {
+			return false;
+		}
+		FactoryPath other = (FactoryPath) o;
+		return _path.equals(other._path);
+	}
 }
diff --git a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java
index 88b4e1d..2f6af8c 100644
--- a/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java
+++ b/org.eclipse.jdt.apt.core/src/org/eclipse/jdt/apt/core/util/AptConfig.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2011 BEA Systems, Inc. 
+ * Copyright (c) 2005, 2014 BEA Systems, Inc. 
  * 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
@@ -7,7 +7,7 @@
  *
  * Contributors:
  *    jgarms@bea.com, wharley@bea.com - initial API and implementation
- *    
+ *    het@google.com - Bug 423254 - There is no way to tell if a project's factory path is different from the workspace default
  *******************************************************************************/
 package org.eclipse.jdt.apt.core.util;
 
@@ -827,16 +827,18 @@
 	}
 	
 	/**
-	 * Has an explicit factory path been set for the specified project, or
-	 * is it just defaulting to the workspace settings? 
+	 * Does this project have a factory path that is different from the
+	 * workspace default?
+	 * 
 	 * @return true if there is a project-specific factory path.
 	 */
 	public static boolean hasProjectSpecificFactoryPath(IJavaProject jproj) {
 		if (null == jproj) {
-			// say no, even if workspace-level factory path does exist. 
+			// say no, even if workspace-level factory path does exist.
 			return false;
 		}
-		return FactoryPathUtil.doesFactoryPathFileExist(jproj);
+		return FactoryPathUtil.doesFactoryPathFileExist(jproj)
+				&& !getFactoryPath(jproj).equals(getDefaultFactoryPath(jproj));
 	}
 
 	/**
diff --git a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/RegressionTests.java b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/RegressionTests.java
index 24327cf..6b968ad 100644
--- a/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/RegressionTests.java
+++ b/org.eclipse.jdt.apt.tests/src/org/eclipse/jdt/apt/tests/RegressionTests.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2005, 2008 BEA Systems, Inc.
+ * Copyright (c) 2005, 2014 BEA Systems, Inc.
  * 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
@@ -7,6 +7,7 @@
  *
  * Contributors:
  *   wharley@bea.com - initial API and implementation
+ *   het@google.com - Bug 423254 - There is no way to tell if a project's factory path is different from the workspace default
  *******************************************************************************/
 
 package org.eclipse.jdt.apt.tests;
@@ -19,7 +20,9 @@
 import org.eclipse.core.resources.IResource;
 import org.eclipse.core.resources.ResourcesPlugin;
 import org.eclipse.core.runtime.IPath;
+import org.eclipse.core.runtime.Path;
 import org.eclipse.jdt.apt.core.util.AptConfig;
+import org.eclipse.jdt.apt.core.util.IFactoryPath;
 import org.eclipse.jdt.core.IJavaProject;
 import org.eclipse.jdt.core.tests.util.Util;
 
@@ -285,5 +288,36 @@
 				}
 		);
     }
-	
+
+	/**
+	 * Tests that a
+	 * {@link AptConfig#hasProjectSpecificFactoryPath(IJavaProject)} checks if
+	 * the project's factory path is equivalent to the default factory path, not
+	 * just that it has created a factory path.
+	 *
+	 * @throws Exception
+	 */
+	public void testBugzilla423254() throws Exception {
+		final String projName = RegressionTests.class.getName()
+				+ "423254.Project"; //$NON-NLS-1$
+		IPath projectPath = env.addProject(projName, "1.5"); //$NON-NLS-1$
+		env.addExternalJars(projectPath, Util.getJavaClassLibs());
+
+		env.removePackageFragmentRoot(projectPath, ""); //$NON-NLS-1$
+		env.addPackageFragmentRoot(projectPath, "src"); //$NON-NLS-1$
+		env.setOutputFolder(projectPath, "bin"); //$NON-NLS-1$
+
+		IJavaProject jproj = env.getJavaProject(projName);
+		assertFalse(AptConfig.hasProjectSpecificFactoryPath(jproj));
+
+		IFactoryPath fp = AptConfig.getFactoryPath(jproj);
+		fp.addVarJar(Path.fromOSString("/some_phony.jar"));
+		AptConfig.setFactoryPath(jproj, fp);
+		assertTrue(AptConfig.hasProjectSpecificFactoryPath(jproj));
+
+		fp = AptConfig.getFactoryPath(jproj);
+		fp.removeVarJar(Path.fromOSString("/some_phony.jar"));
+		AptConfig.setFactoryPath(jproj, fp);
+		assertFalse(AptConfig.hasProjectSpecificFactoryPath(jproj));
+	}
 }