Community
Participate
Working Groups
Created attachment 208550 [details] example workspace I have following problem: I have to projects a and b. Both projects have reference to external library api.jar(containing class com.sap.test.Libr) - project a exports api.jar. - project b references project a with 2 access rules 1. a/** ACCESSIBLE 2. **/* NON_ACCESSIBLE | IGNORE_IF_BETTER "Combine rules ..." checkbox is active. As result the com.sap.test.Libr class is not accesible from project b. I have attached a workspace with 2 projects and a jar file, where it is reproducable. Is it a bug or is something missed. Best Regards Dimitrij
(In reply to comment #0) > Is it a bug or is something missed. Jay, can you please check? Thanks!
At first glance, looks like a bug to me. Let me see what's wrong.
Actually, nothing is wrong here. With the workspace and set-up provided in comment #0, the particular class is found in two locations and their respective access rules. Classpath jar file C:/work/eclipse_builds/runtime-New_configuration/runtime-New_configuration/api.jar with AccessRuleSet { pattern=a/** (ACCESSIBLE) pattern=**/* (NON ACCESSIBLE | IGNORE IF BETTER) pattern=com/** (ACCESSIBLE) } [classpath entry: C:\work\eclipse_builds\runtime-New_configuration\runtime-New_configuration\api.jar] Binary classpath directory /a/bin with AccessRuleSet { pattern=a/** (ACCESSIBLE) pattern=**/* (NON ACCESSIBLE | IGNORE IF BETTER) } [classpath entry: a] Since we select the combine rules option, the first classpath entry gets the access rules from the imported entry too. And as a net result, we end up with **/* (NON ACCESSIBLE | IGNORE IF BETTER) I initially misunderstood the IGNORE IF BETTER. But after reading the doc, it makes sense now.
Marking as resolved.
Hi, I have investigated the issue much deeper. Project b can access api.jar in two ways 1. throw project a 2. direct library reference 1. Access to classes inside of api.jar is blocked by **/* (NON ACCESSIBLE | IGNORE IF BETTER) by set project reference 2. All classes inside of api.jar should be accessible So from my point of view, com.sap.test.Libr should be accessible from project b throw the way 2. I have debugged the issue and found out, the class DeltaProcessingState in function getRootInfos newRootsMaps get filled with values depending on order in projects array and in classpath. If I change the order of projects to [b,a] the class com.sap.test.Libr can be resolved, because newRoot get the value from direct reference to pai.jar and not from exported reference from project a. E.g. the problem disappears, if I delete the project a without content and then import the project again, to change the order of projects. And I delete project reference from b to a , add it again and define old access rules, to put classpath entry for the reference to the end of class path. If com.sap.test.Libr get resolved depends on order of projects delivered from java model and from order of class path entries in classpath of project b and can be each time different. Do you see any chance to fix the issue? org.eclipse.jdt.internal.core.DeltaProcessingState ... private HashMap[] getRootInfos(boolean usePreviousSession) { HashMap newRoots = new HashMap(); HashMap newOtherRoots = new HashMap(); HashMap newSourceAttachments = new HashMap(); HashMap newProjectDependencies = new HashMap(); IJavaModel model = JavaModelManager.getJavaModelManager().getJavaModel(); IJavaProject[] projects; try { projects = model.getJavaProjects(); } catch (JavaModelException e) { // nothing can be done return null; } for (int i = 0, length = projects.length; i < length; i++) { JavaProject project = (JavaProject) projects[i]; IClasspathEntry[] classpath; ... for (int j= 0, classpathLength = classpath.length; j < classpathLength; j++) { IClasspathEntry entry = classpath[j]; ... // root path IPath path = entry.getPath(); if (newRoots.get(path) == null) { newRoots.put(path, new DeltaProcessor.RootInfo(project, path, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), entry.getEntryKind())); } else { ArrayList rootList = (ArrayList)newOtherRoots.get(path); if (rootList == null) { rootList = new ArrayList(); newOtherRoots.put(path, rootList); } rootList.add(new DeltaProcessor.RootInfo(project, path, ((ClasspathEntry)entry).fullInclusionPatternChars(), ((ClasspathEntry)entry).fullExclusionPatternChars(), entry.getEntryKind())); } .... } } return new HashMap[] {newRoots, newOtherRoots, newSourceAttachments, newProjectDependencies}; } ....
(In reply to comment #5) > Hi, > I have investigated the issue much deeper. Thanks for the input. Now, I see what you mean. Looking at the code, I can say that we don't have any code at all to handle the IGNORE_IF_BETTER when there are two classpath entries, both pointing to the same path, but with different access restrictions. Here is my understanding: 1. Each package fragment root is mapped to one classpath entry after classpath resolution. And in our case, since both classpath entries point to the same library, obviously there would be only one package fragment root. 2. Depending on which classpath entry gets chosen and hence the access rules, the NameLookup is either able to find it or otherwise. This is why, like you mentioned, the order of the classpath entry makes a difference. 3. Even if we were to combine the rules from both the classpath entries, it would not work because, for a particular entry (and package fragment root), we always choose the most restrictive rule. In light of the above points, I don't think we can do much here. I am inclined to close this as WONTFIX.
Closing this as WONTFIX. We can't do much here as we have to pick only one entry among multiple entries pointing to the same path and typically it's the first that appears in the classpath. Also note that we can workaround the problem by changing the order of the classpath entries.
Verified for 3.8M5