| Summary: | Make public APIs for accessing PDE model | ||||||
|---|---|---|---|---|---|---|---|
| Product: | [Eclipse Project] PDE | Reporter: | Julien Canches <julien.canches> | ||||
| Component: | UI | Assignee: | PDE-UI-Inbox <pde-ui-inbox> | ||||
| Status: | RESOLVED FIXED | QA Contact: | |||||
| Severity: | enhancement | ||||||
| Priority: | P3 | CC: | jerome.gout, mgoyal, paulslau, popescu | ||||
| Version: | 3.2 | ||||||
| Target Milestone: | 3.3 M5 | ||||||
| Hardware: | All | ||||||
| OS: | All | ||||||
| Whiteboard: | |||||||
| Bug Depends on: | |||||||
| Bug Blocks: | 126575 | ||||||
| Attachments: |
|
||||||
|
Description
Julien Canches
past API freeze already Hi, Are there any plans to provide public APIs that are equivalent to the internal methods listed above? TPTP is currently using these methods, we are trying to get rid of internal dependencies. I'll be happy to discuss with a PDE member if you think that there is an alternate way to get the features provided by these methods, without requiring the PDE team to provide these APIs. Regards, Julien Canches -- TPTP Commiter Please increase the priority of this defect to P1 since it is required to resolve a blocking TPTP defect (https://bugs.eclipse.org/bugs/show_bug.cgi?id=126575). Hi Julien, We need to better understand why the TPTP profiler needs access to all these PDE models to do its job. I doubt that all this info is required by the profiler, and it is very possible that the problem lies elsewhere as was the case for bug 127197. In that bug, the TPTP code was refactored in a way that got rid of its internal dependencies on PDE without making a single PDE model class API. To help us resolve this issue, the first step would be for you to go back to your code, examine where/why you are making references to these internal PDE classes, ensure it is done for a good reason and report back your findings. At that point, we can advise if there are better alternatives or if there is something less drastic that can be done (e.g. make the PDE launchers less monolithic, etc.) Paul, given our current knowledge/assessment of the situation, the current priority/severity of this bug report are appropriate. Thanks. Hi Wassim, I'm afraid there might be a confusion between the different TPTP projects. TPTP is made of four projects (Platform, Monitoring Tools, Testing Tools, Tracing and Profiling Tools). This request originates from the "Testing Tools" project, which aims at providing a generic testing framework. In this testing framework, we provide five test implementations: JUnit, JUnit Plug-in, Manual, URL and Automated GUI Recording. When I first implemented JUnit Plug-in, I decided to use PDE internal APIs, because they perfectly matched my needs. I know this is wrong, but this was a long ago, and at that time I didn't see this as a big issue as it is today. Basically, the JUnit Plug-in testing feature consists in: (1) a synchronization mechanism between JUnit code and TPTP models (based on UML2.0 Testing Profile) (2) a deployment model for specifying JUnit Plug-in test deployment (for details such as which host? which eclipse? which product/application? VM/program arguments? which plugins?) (3) an editor for the deployment model (4) a deployment mechanism that transfers the necessary bits to a remote host and creates an ad-hoc configuration area on the remote host (5) a remote launcher that launches eclipse with the appropriate classpath / command line (6) a remote agent (running as an eclipse plugin) that sends back test results to the local eclipse The main difference with PDE JUnit plug-in tests is that TPTP supports deployment and execution of these tests to a remote host. There is a general requirement to the user, that the remote eclipse instance must be identical to the target platform defined in PDE preferences (same plugins, same versions). We currently rely on PDE for (2), (3) and (4), but this is for different reasons: (2) We don't require the user to create a deployment model from scratch. We always provide him with a default deployment model, and this default is basically the target platform, as defined in PDE preferences. So we need the following information about the target platform: - The target eclipse location - The target details (OS, architecture, windowing system, locale) - The default product and application The first item is something that only PDE can provide us with. There may be alternatives for us to determine the remaining information, once we know the target platform's location. (3) The editor enables the user to change the deployment details. The user can select an application or a product from a list, he can select which plugins must be active on the target platform. So we need the following information about the target platform: - the list of available products - the list of available applications - the list of available plugins (4) requires that we generate (a) a temporary MANIFEST.MF or plugin.xml file (b) a configuration area, and (c) a command line. (a) Before deploying, we need to slightly modify the MANIFEST.MF or plugin.xml file of the project that contains the deployed JUnit test, to add the project's output directory to the plugin classpath. We use PDE to modify the plugin.xml's content. (We don't use PDE for modifying the MANIFEST.MF). (b) The configuration area is first generated to a local temporary directory, and then transferred to the remote host. In the local phase, we use these pieces of information: - The plugins available in the workspace - If the user has picked the option "All plugins" in the editor (3), the plugins available on the target platform. Once this information is collected, the configuration area (the "config" directory) must be generated. We call the following method to do that: TargetPlatform.createPlatformConfigurationArea(pluginMap, area, brandingPlugin); The output of this method is then slightly modified to translate paths of the local host to paths of the remote host. I hope these details help you better understand why we are using these APIs. As a summary, here's the list of internal APIs we are using, annotated with the feature for which they are used. I've also added priorities (P1=we can't implement it ourselves, P2=there may be a work-around that involves code duplication, P3=there is a work-around with limited code duplication), but maybe you can provide us with guidance and we may lower the priority or remove the request. 1) PDE Model access: - PDECore.getDefault().getModelManager().getWorkspaceModels() (4b) [P1] Goal: get the list of plugins defined in the workspace by plugin projects. - PDECore.getDefault().getModelManager().getExternalModels() (3)(4) [P1] Goal: get the list of plugins available on the target platform. - PDECore.getDefault().getModelManager().findModel(IProject) (4a) [P3] Goal: retrieve the plugin model associated to a plugin project. - PDECore.getDefault().getModelManager().getPlugins() (4b) [P3] Goal: get a mixed list of workspace and external plugin models. (In this list of APIs, there may be "conveniency" methods whose return value can be computed from the return value of a "core" method. The goal is to publish "core" methods only.) 2) plugin.xml-based models saving - ability to test whether a IPluginModelBase instance is a bundle-based or plugin-based plugin model (this is currently done by checking model instanceof BundlePluginModelBase or model instanceof WorkspacePluginModelBase) (4a) [P2] - ability to save a WorkspacePluginModelBase to a PrintWriter object (4a) [P2] Goal: write to a temporary location a modified copy of an existing plugin model. The modification usually consists in adding the "bin/" folder to the plugin's classpath. The reason why we do this is that we deploy plugin projects to the remote host as is, but since we don't compile them into jars, their output directories must be added to the plugin classpath. 3) Target platform access: ExternalModelManager.getEclipseHome() (2)(4) [P1] Goal: get the location of the target platform. TargetPlatform.getOS() (2) [P2] Goal: get the OS attribute of the target platform. TargetPlatform.getOSArch() (2) [P2] Goal: get the arch attribute of the target platform. TargetPlatform.getWS() (2) [P2] Goal: get the ws attribute of the target platform. TargetPlatform.getNL() (2) [P2] Goal: get the nl attribute of the target platform. TargetPlatform.getApplicationNames() (3) [P2] Goal: present to the user the list of applications declared in the target platform so he can pick one. TargetPlatform.getProductNames() (3) [P2] Goal: present to the user the list of products declared in the target platform so he can pick one. TargetPlatform.getDefaultProduct() (2) [P2] Goal: get the default product that our default deployment will use (so the user does not have to edit the default generated deployment before launching). 4) Runtime configuration directory setup: TargetPlatform.createPlatformConfigurationArea(Map, File, String) (4b) [P2] Goal: create a "config" directory, for a given set of plugins, in the specified directory. This is necessary to launch eclipse on the remote host. TargetPlatform.getConfigIniProperties(String) (4b) [P3] Goal: read the target platform's config.ini file. Thanks, Julien Hi Julien, thanks for the clarification. This is indeed a very ambitious API request that puts us in an unpleasant situation. But we are where we are, so let's see what we can do here to help you out: 1) PDE Model Access It will be very hard for you to get this info without PDE's help. I am not sure what the APIs would look like here yet, but we will figure something out. 2) Saving models This is non-negotiable NO. We cannot open up these model classes as that will start a big chain reaction. There are easy workarounds however: If you want to test if a plug-in is a bundle or not, simply check if the project corresponding to the plug-in has a META-INF/MANIFEST.MF file or not. If you want to modify the manifest.mf to add a bin/, you could easily use the jar.util.Manifest class to do this. If you want to modify a plugin.xml, you can read it into a DOM and write it back out. 3) Target Platform access: re: ExternalModelManager#getEclipseHome() You don't need to directly call PDE code for this. You can just get the value of the ECLIPSE_HOME Java variable (eg. JavaCore.getClasspathVariable(ECLIPSE_HOME) As for the rest of the calls to Target Platform to query for os, ws, arch, ... we could provide APIs for that. These are non-controversial with 'String' return values. 4) Runtime Configuration directory setup I suggest you copy these methods. they are only a handful and very self-contained. Created attachment 52975 [details]
Resolution plan
Comment on attachment 52975 [details]
Resolution plan
Please disregard this attachment, I added it to the wrong bugzilla. Sorry for the confusion.
Thanks Wassim, It seems we have a fair solution to each of the requests I have made, either be it the intent of publishing an API, or a work-around. I will now review all of my code to check if there are any issue, such as an additional dependency that would be introduced by copying bits of PDE code. I'll keep you informed. I am using PDE public api to save the Plugin Model as shown below, and it seems that the bundle manifest.mf is not supported. If PDE doesn't intend to support saving of models, why is the interface IEditable implemented by BundlePluginModel.
IPluginBase base = something;
if(base.getModel() instanceof IEditable) {
StringWriter s = new StringWriter();
PrintWriter myWriter = new PrintWriter(s);
((IEditable) base.getModel()).save(myWriter);
myWriter.flush();
IResource resource = base.getModel().getUnderlyingResource();
if (resource instanceof IFile) {
IFile file = (IFile) resource;
ByteArrayInputStream stream = null;
try {
stream = new ByteArrayInputStream(s.toString().getBytes("UTF8"));
file.setContents(stream, true, true, new NullProgressMonitor());
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
re comment 10: if you can find a way to write pde models by casting to IEditable, that is fine. My point was that we do not plan on making the implementation of BundlePluginModel and friends public. Note however that BundlePluginModel is a wrapper that represents two files, not just one: the manifest.mf and the plugin.xml. It may not make sense for it to implement IEditable. We need to change that if it does, since if you a pass a printwriter to the model, which of the two files is it supposed to be writing? You need access to the individual files. In 3.3, we have implemented WorkspaceBundlePluginModelBase#save() to transparently write both manifest.mf and plugin.xml files. Done. re comment 0: Request #1: There are static methods on org.eclipse.pde.core.plugin.PluginRegistry that will give you access to the models you need. Request #2: you will do on your own, as agreed upon above. Request #3: There is a new TargetPlatform class in an API pacakge now, which will give you access to all the methods you outline. A couple of methods changed names, but the mapping from old to new should be obvious. Request #4: I decided to give you public access to TargetPlatform.createPlatformConfiguration(...) since copying it won't be trivial for you. Note the slight change in the method name and the arguments it takes. As for TargetPlatform.getConfigIniProperties(String), all we are doing here is reading a properties file. There is nothing special here that requires API. This officially concludes the TPTP API saga. (In reply to comment #12) Wassim, on behalf of TPTP and the Test Project, I want to thank you for you and your Team's efforts to resolve this defect. Thanks! you're welcome, Paul. Glad to help. Hi Wassim, I am terribly sorry but, it seems that Julien has forgotten to request an API for TargetPlatform.getBundleList() which has not been exposed in the new PluginRegistry class. I hope it would be possible to get this API in PluginRegistry ? Thanks in advance. Best regards, Jerome (continuing the Julien's work) Jerome, The code in question can easily be copied into your code base without the need for API. However, it may get stale pretty quickly since this is one area of the runtime that keeps changing. So to shield you from any future runtime changes that would break your launcher, I will provide API for that. |