Monday, August 20, 2007

Semantic-aware component provisioning: "pencils off" status report

I want to recap my summer of code so far, before the final evaluation starts. Here's what I accomplished so far. It was a lot of work, and a huge fun as well, hope to catch your interest and get some feedback on future developments! :)

GUI CONTRIBUTIONS

global_view

  • new component submission view (drag and drop support from the repository explorer to add dependencies easily :) )

  • repository explorer view

  • preference page (set repository URL)


IMPLEMENTED FEATURES

  • submit a new component

  • usual search features (name, version, tags)

  • search components providing a set of tasks

  • search components providing all the tasks of the selected ones

  • "smart" search of components functionally equivalent to the selected one (reasoning here)

  • search components depending on the selected one

  • assert functional equivalence between components


HANDS-ON

Let's take a test drive. I submit a new component, in this case (just as an example) the "last-gsoc-demo" one. I fill in some data, and press submit. I can just drag-and-drop dependencies from the repository explorer to the dependencies viewer.

submit drag drop

I previously submitted some sample components. Now since all jdbc drivers implement the same specification, to some extent it is correct to consider them "functionally equivalent", and I push this statement in the knowledge base.

find-eq

For sake of brevity I ask you to trust me without further shots, what I did is just assert all jdbc drivers in the repository (besides the "dummy-jdbc" one) "functionally equivalent" to the postgresql one, and then assert the "dummy- jdbc" only equivalent to "mysql-jdbc". I can ask now the repository to give me components "functionally equivalent" to the selected one ("dummy-jdbc"), just clicking on the context menu item:
assert-eq

Here's what I obtain:

inference-rulez

You might notice that the selected item is still there, which makes sense since everything is of course functionally equivalent to itself. ;) Furthermore, it is worthwhile to note I only said the "dummy-jdbc" was equivalent to "mysql-jdbc", full stop! The rest is just the result of the reasoning process.

Now, I can also describe a component in terms of the "tasks" it carries out. Let's suppose - just as an example - I have two components, one for "dom-parsing" and the other for "sax-parsing".

tasks

Suppose now I was not on earth in the last years and I want to know if there exists a single component doing the two things.

union-tasks task-union-found

I can select both of them, click on the shown item and I'll get xerces-j actually does both things. I might decide to use it if it fits my needs, since a single dependency is better than two, in most cases.

I also could want to know if other components rely on mine, or for instance how many components actually use one, which usually means it has great reputation. Remember the "last-gsoc-demo" component? I put "mysql-jdbc" as a dependency there. I just right click on the component, and find the components depending on the selected one. :)

search-clients client

CLIENT-SERVER ARCHITECTURAL VIEW (after latest modifications)

architecture

KNOWN BUGS

  • troubles with SPARQL queries involving literals: searching against id and tasks is ok, versions and tags are not (yet the http://repo.url/tag/{tag} resource works fine... i had no time to investigate further befor pencils were off)

  • dangling dependencies (i.e. after a delete operation) are not handled yet.


COMING SOON (random order)

  • rest (not in the soa-ish meaning)

  • enable license and license-style search criteria on the plugin

  • associate a new perspective with the provided views

  • improve repository explorer (i don't like that tree very much)

  • bundled repository exploiting the eclipse embedded jetty server

  • import existing metadata from maven POM or OSGi manifest (URL drag and drop from web browser?)

  • address repository data access layer performance issues

  • setup an update site somewhere on the globe


CHEERS
That's all for now, I really enjoyed the work, and I am confident this both- side fruitful collaboration will go on. A lot of things remain to be done on this project, and I won't let it down after Google Summer of Code stops.

I want to thank Philippe Ombredanne for mentoring me, and all the guys @ #eclipse-soc for supporting me and other students day after day. It was an invaluable experience to work with you guys.

See you online,

cheers,

Savino Sguera.

Saturday, August 18, 2007

Status: Improving Eclipse Search

My greatest fear ( getting sick ) for SoC has become true this summer and it forced me to sleep / lie down doing nothing for about a week. However, I have another small addition for Find/Replace facilities.

This enhancement is Emacs style "Case Sensitive Replace". Here's the bug:

Retain Caps When Replacing - https://bugs.eclipse.org/bugs/show_bug.cgi?id=28949

It's waiting for code review.

About "Highlight All": I've received feedback from Daniel and I believe I'll complete the patch with a final blow. I should say that as a user, I find these two enhancements quite handy.

About lightweight Find/Replace: I've seen that the area below the editor is not sufficient for displaying the bar completely. It looks good under the editor when resized but the area below the editor is small in width in a vanilla Eclipse install.

To overcome this, I think that it's best to form the bar as a Trim contribution (top/bottom). This way, we'll have a pretty good amount of width and the users that want to use the bar in some other place will also be satisfied.

However we need to resolve bugs like https://bugs.eclipse.org/bugs/show_bug.cgi?id=195776 first. We need to have a bottom trim that can resize itself when contributions do not fit. I discussed the issue with Eric Moffatt and he said that we'll have TrimLayout improvements in M3 and M4. In this case, I'm thinking of creating this "lightweight Find/Replace" as a trim contribution and use the coolbar (which wraps and resizes correctly) for now. When we have Eric's improvements, we can carry it to the bottom trim as in Firefox.

Feel free to comment (especially on this last paragraph). :)

Have a nice weekend,

Parts, drugs and Fullscreen

Fullscreen is often an eyecatcher - isn't it? ;)
But I didn't wrote that to annoy you but to tell that the SWT team (especially Kevin Barnes) just committed fullscreen support for SWT shells. I'm really happy that my patches - which were part of my Google Summer of Code project - found their new home in the Eclipse CVS.
If you're one of the lucky ones working with SWT HEAD or any of the upcoming N-builds you can do something like this in order to turn your shells into real fullscreen windows:

Display display = new Display();
final Shell shell = new Shell(display, SWT.SHELL_TRIM);

Button bFullscreen = new Button(shell, SWT.PUSH);
bFullscreen.setText("switch fullscreen");
bFullscreen.addSelectionListener(new SelectionAdapter() {
public void widgetSelected(SelectionEvent e) {
shell.setFullScreen(!shell.getFullScreen());
}
}


When running this little application and clicking the button, you'll get a fullscreen shell which covers the the whole space of your active screen.
As this a really nice-to-have feature of Eclipse, I'm currently working on a new command/handler/keybinding for the workbench to allow the user to switch the IDE into a fullscreen application.

Besides this there is another major task planned for my SoC project - Detached Windows. Sometimes hated, sometimes loved. I've to say that I really love them...but only my patched version which can hold serveral ViewStacks (folders of views) in one window. It could look like the on on the right.


As I really follow the term "eat your own dogfood", I'm working on my SoC project with two screens:
Screen 1: Eclipse IDE in fullscreen mode which covers everything else on that screen
Screen 2: a detached Window which allows me to arrange my views and folder just like the workbench window itself
Interested? Here is a picture of my current desktop (caution: ~400kb, 3360px*1050px):

Wednesday, August 8, 2007

Groovy Plug-ins: Bundle Activation and Extension Point Processing

I faced an issue with the bundle activation last week. Namely, a bundle activator will not be started if the given bundle doesn't contain any classes. I.e. a bundle activator is provided by my plug-in and the contributor should use this class to enable scripting for the activation routines.

I reported this issue to Eclipse Equinox newsgroup, and the feedback was quite positive in sense of the solutions. Tom Watson purposed some options:

  • Have ScriptExtensionProxy activate the contributing bundle using a transient flag when it creates a proxy (i.e. call Bundle.start(Bundle.START_TRANSIENT)). This would take extra work for ScriptExtensionProxy because it should probably read the Eclipse-LazyStart and/or the new Bundle-ActivationPolicy from OSGi R4.1 specification to verify the bundle is actually lazy activated.

  • Make ScriptExtensionProxy abstract and force contributing groovy bundles to extend it with a real class which exists in the contributing bundle. Then when the extension is constructed it will automatically activate the bundle if it has a lazy activation policy.

The 1st option worked, but it smells like a hack. I think that the contributor should never call the Bundle#start() on its own... FWIW, this method could be available only to the framework and not to the user.
I've sticked to the 2nd option, but instead of making the ScriptExtensionProxy abstract I will leave it as it is, so that user may just declare it in plugin.xml if there's no need for activation.
ScriptBundleActivator is just a facade for calling the activation script, which I presume to be called activator.groovy for now. The start() method call just delegates the work to the start() method of the expando object in the script.

The activator would be useful if the contributing plug-in will have the need for extension point processing, as the INVITATION RULE says: whenever possible, let others contribute to your contributions.

Here's the draft Groovy code for extension point processing in the activator:

import org.eclipse.core.runtime.Platform

def expando = new groovy.util.Expando()

expando.start = { bundleContext ->
def registry = Platform.getPluginRegistry()
def extensionPoint =
registry.getExtensionPoint(
"org.eclipse.soc.scripting.contributor.listeners")

def extensions = extensionPoint.getExtensions()
extensions.each( { extension ->
extension.getConfigurationElements().each({
element ->
def object = element.createExecutableExtension("class")
//do something with the object
})
} )
}
expando // this is the script returning object

While shaping the code above I realized what is the real power of such scripting: NO CASTING! Truly, I didn't think about it before.
Now I have the following:

  1. A proxy for declaring the extensions: read here and here

  2. A bundle activator facade.

This is the basic functionality which may be used for groovy plug-in creation (with some limitations). Currently I'm preparing a demo which could demonstrate how these base classes could be used.
Next, I would like to provide some usability enhancements to the core plug-in: it would be cool to modify the script even if it is already packed and deployed.
P.S. I have also blogged about the progress in my own blog.