Bug 367073 - wrong access restriction for directly accessed class in jar file
Summary: wrong access restriction for directly accessed class in jar file
Status: VERIFIED WONTFIX
Alias: None
Product: JDT
Classification: Eclipse Project
Component: Core (show other bugs)
Version: 3.5.2   Edit
Hardware: PC Windows 7
: P3 major (vote)
Target Milestone: 3.8 M5   Edit
Assignee: Jay Arthanareeswaran CLA
QA Contact:
URL:
Whiteboard:
Keywords:
Depends on:
Blocks:
 
Reported: 2011-12-19 08:31 EST by Dimitrij Afonitschkin CLA
Modified: 2012-01-23 08:18 EST (History)
2 users (show)

See Also:


Attachments
example workspace (4.90 KB, application/x-zip-compressed)
2011-12-19 08:31 EST, Dimitrij Afonitschkin CLA
no flags Details

Note You need to log in before you can comment on or make changes to this bug.
Description Dimitrij Afonitschkin CLA 2011-12-19 08:31:57 EST
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
Comment 1 Ayushman Jain CLA 2011-12-19 08:54:32 EST
(In reply to comment #0)
> Is it a bug or is something missed.
Jay, can you please check? Thanks!
Comment 2 Jay Arthanareeswaran CLA 2011-12-19 11:57:00 EST
At first glance, looks like a bug to me. Let me see what's wrong.
Comment 3 Jay Arthanareeswaran CLA 2011-12-20 11:55:15 EST
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.
Comment 4 Jay Arthanareeswaran CLA 2011-12-20 22:55:49 EST
Marking as resolved.
Comment 5 Dimitrij Afonitschkin CLA 2011-12-23 06:38:41 EST
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};
	}
	....
Comment 6 Jay Arthanareeswaran CLA 2012-01-02 10:15:57 EST
(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.
Comment 7 Jay Arthanareeswaran CLA 2012-01-02 23:18:20 EST
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.
Comment 8 Satyam Kandula CLA 2012-01-23 08:18:18 EST
Verified for 3.8M5