This Bugzilla instance is deprecated, and most Eclipse projects now use GitHub or Eclipse GitLab. Please see the deprecation plan for details.
Bug 262331 - [eclipse] EclipseTouchpoint requires publisher
Summary: [eclipse] EclipseTouchpoint requires publisher
Status: RESOLVED FIXED
Alias: None
Product: Equinox
Classification: Eclipse Project
Component: p2 (show other bugs)
Version: 3.5   Edit
Hardware: PC Windows Vista
: P3 minor (vote)
Target Milestone: 3.5 M7   Edit
Assignee: Simon Kaegi CLA
QA Contact:
URL:
Whiteboard:
Keywords:
: 267246 (view as bug list)
Depends on:
Blocks:
 
Reported: 2009-01-25 21:58 EST by Jeff McAffer CLA
Modified: 2009-04-03 09:54 EDT (History)
6 users (show)

See Also:


Attachments
a patch to illustrate the solution (5.96 KB, patch)
2009-01-25 21:58 EST, Jeff McAffer CLA
no flags Details | Diff
Possible fix. (2.79 KB, patch)
2009-02-20 17:04 EST, John Arthorne CLA
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Jeff McAffer CLA 2009-01-25 21:58:25 EST
Created attachment 123700 [details]
a patch to illustrate the solution

The touchpoint.eclipse bundle has optional requirements on some publisher classes.  It seems however that these classes are in fact hard requirements.  Two issues
- the referenced classes are mentioned in a method of a class (EclipseTouchpoint) that must be loaded for p2 to function effectively.  This may well cause NoClassDeFoundErrors when loadind EclipseTouchpoint in the absence of the publisher.  I always get the behaviour of the verifier at classload time wrong but it is likely that that createBundleIU method (the one that contains all the references to the publisher) should be put out in a separate class that is not run/called unless we know we have the publisher installed.

- the method prepareIU has the following code 
			c = Class.forName("org.eclipse.equinox.p2.publisher.eclipse.BundlesAction"); //$NON-NLS-1$
			if (c != null)
				c = Class.forName("org.eclipse.osgi.service.resolver.PlatformAdmin"); //$NON-NLS-1$
		} catch (ClassNotFoundException e) {
			throw new IllegalStateException(NLS.bind(Messages.generator_not_available, e.getMessage()));
		}
So basically if the publisher class is not found an ISE is thrown.  The caller of this method is not setup in any way to catch this exception so we end up unwinding all the way up.  Probably here we should be returning null.
Comment 1 Simon Kaegi CLA 2009-01-25 22:43:17 EST
Ideally the eclipse touchpoint should have no dependency on the publisher as it would be better to handle the partial IU expansion earlier. With that said, the current code looks ok to me from a runtime verifier perspective. The publisher classes are not exposed in fields, statics or method signatures so should only attempt to load if we detect a partial IU (normally from an old-style update site) and call createBundleIU. 

An ISE maybe heavy handed however the reason it throws it is to avoid installing a partial IU into the profile. If we log and return null my concern is that the IU will get installed and we'll be in a bad shape in terms of resolving future metadata and potentially our configured runtime state. As is the call fails and the transaction rollsback which in this case is the intent.
Comment 2 Jeff McAffer CLA 2009-01-26 22:14:27 EST
Indeed you are rigth wrt the class loading.  I setup a test case of an agent without the publisher and was able to install stuff.  I recall a case that Oleg pointed out where this sort of structure was insufficient isolation.  Go figure.

As for the ISE, the desire to avoid installing a partial IU makes sense.  However, the only caller of prepareIU is initializeOperand() and it does
  IInstallableUnit preparedIU = prepareIU(iu, profile);
    if (preparedIU == null)
      return Util.createError(NLS.bind(Messages.failed_prepareIU, iu));

So it really ought not happen.

BTW, why is prepareIU public?  It is called by a test but that is not really a great reason to make things public.
Comment 3 Simon Kaegi CLA 2009-01-26 23:05:09 EST
Yep. I see what you're saying wrt returning null now and also agree there is no need to make the method public. The test can just as easily run the same logic via initializeOperand.
Comment 4 Jeff McAffer CLA 2009-02-12 14:10:12 EST
What is the thinking on this?  put it in?  This is the only thing directly requiring that hte publisher be shipped as part of an "agent".

Note that bug 262332 is affected as it would normally not include the publisher.
Comment 5 John Arthorne CLA 2009-02-20 16:28:49 EST
The installer is currently also broken because of this:

java.lang.NoClassDefFoundError: org/eclipse/equinox/p2/publisher/IPublisherAdvice
	at java.lang.Class.getDeclaredConstructors0(Native Method)
	at java.lang.Class.privateGetDeclaredConstructors(Unknown Source)
	at java.lang.Class.getConstructor0(Unknown Source)
	at java.lang.Class.newInstance0(Unknown Source)
	at java.lang.Class.newInstance(Unknown Source)
	at org.eclipse.core.internal.registry.osgi.RegistryStrategyOSGI.createExecutableExtension(RegistryStrategyOSGI.java:170)
	at org.eclipse.core.internal.registry.ExtensionRegistry.createExecutableExtension(ExtensionRegistry.java:874)
	at org.eclipse.core.internal.registry.ConfigurationElement.createExecutableExtension(ConfigurationElement.java:243)
	at org.eclipse.core.internal.registry.ConfigurationElementHandle.createExecutableExtension(ConfigurationElementHandle.java:51)
	at org.eclipse.equinox.internal.p2.engine.TouchpointManager$TouchpointEntry.getTouchpoint(TouchpointManager.java:46)
	at org.eclipse.equinox.internal.p2.engine.TouchpointManager.getTouchpoint(TouchpointManager.java:119)
	at org.eclipse.equinox.internal.p2.engine.TouchpointManager.getTouchpoint(TouchpointManager.java:99)
Comment 6 John Arthorne CLA 2009-02-20 17:04:18 EST
Created attachment 126353 [details]
Possible fix.

(not tested)
Comment 7 John Arthorne CLA 2009-02-20 17:53:09 EST
(That fix didn't work)
Comment 8 John Arthorne CLA 2009-03-05 14:37:43 EST
*** Bug 267246 has been marked as a duplicate of this bug. ***
Comment 9 Simon Kaegi CLA 2009-03-10 23:33:45 EDT
I spent a bit of time on this bug tonight trying to understand when the VM will link in classes. What I found was that static references to a class inside the body of a method will not force early linking however use of a constructor will. 

So, in prepareIU the call to BundlesAction.createBundleIU does not cause BundleAction to be linked until the last moment. On the other hand the calls to new PublisherInfo and new AdviceFileAction will force the immediate linking of the classes from the Publisher (and trigger the CND error).

What this means is that we should do something like Jeff originally suggested and isolate the use of the publisher in a separate support class.
Comment 10 Simon Kaegi CLA 2009-03-12 22:13:34 EDT
Thanks Jeff. Fixed in HEAD.
Comment 11 Jeff McAffer CLA 2009-04-03 09:54:42 EDT
cool.  thanks