BlogKontaktTagcloud

Fertig!

Wie schon angekündigt haben wir am Freitag, wie andere auch (z.B. die oder die), unsere Semesterarbeit abgegeben. Für Interessierte hier schon mal vorab unser Abstract, sobald die Abstracts aller Arbeiten online sind, werde ich sicher nochmals darüber schreiben. Die Qualität der Arbeiten waren in diesem Semester (mit den obligaten Ausnahmen), meiner Meinung nach, einiges höher als im letzten.
Ähnliche Beiträge:
Mein erster Patch
Generische Decorator in Java mit Reflection
Developing Eclipse CDT
PHP 6 is coming
Akregator Konqueror Plugin & Patch
Comments (0)  Permalink

Mein erster Patch

Ich bin gar nicht dazu gekommen zu schreiben das mein erster Patch für ein Open Source Projekt angenommen wurde. Auch wenn es sich dabei nur um ein einziges Break handelt bin ich sehr stolz. Die weiteren Patches werden ja bald folgen.
Ähnliche Beiträge:
Fertig!
Generische Decorator in Java mit Reflection
Developing Eclipse CDT
PHP 6 is coming
Akregator Konqueror Plugin & Patch
Comments (0)  Permalink

Generische Decorator in Java mit Reflection

In unserer Eclipse CDT Semesterarbeit geht es zügig voran. Emanuel schreibt eine Erweiterung für den Abstract Syntax Tree um Kommentare zu speichern. Kommentare sind im AST meist nicht nötig, für Refactorings ist es aber entscheiden das Kommentare nicht einfach auf der Strecke bleiben oder gar verloren gehen.

Um die Kommentare zu Speichern hat Emanuel den Knoten mit der Kommentarinformationen „dekoriert“ und dazu das Decoratorpattern verwendet. Dazu hat er das Interface des entsprechende Knotens implementiert und für die Funktionen des ursprünglichen Knotens einfach einen Wrapper geschrieben der auf die Methoden des „echten“ Knoten zugreift. Dies ist das übliche Vorgehen bei einer solchen Problemstellung. Das kann bei vielen Knoten schnell in einem grossen Programmieraufwand enden. Da wir uns entschieden die Kommentare nur in zwei Knoten zu speichern hielt sich der Aufwand dazu in Grenzen. Trotzdem bemerkten wir auch in diesem Fall dass das Ganze auch sehr fehleranfällig ist. In unserem Dekorator hatte sich trotz kleines Umfanges bereits ein Fehler versteckt, den wir zum Glück beim durchsehen des Codes noch fanden.

Der Vorschlag unseres Professors war nun das Problem generischer mit Reflection zu lösen wie das auch in Ruby oder Smalltalk gehen soll. Eine andere Möglichkeit währe es wohl die Klassen statisch mit einem Script automatisch zu erzeugen. Wir haben letzte Woche nun versucht den Lösungsvorschlag unseres Professors zu implementieren. Dazu verwendeten wir die „dynamic proxies“-Funktionalität von Java wie sie seit Java 1.3 vorhanden ist und unter anderem auch für Java RMI verwendet wird.

Zuerst müssen wir nun eine Factory erstellen welche das Proxy-Objekt erstellt, da dies über einen gewöhnlichen Konstruktor nicht mehr möglich ist. Der Factory übergeben wir den Orginal Knoten der dekoriert werden soll. Das sieht in unserem Beispiel dann so aus:

public static Object invocationFactory(CPPASTNode node) {
CPPASTCommentedInvocationHandler handler = new CPPASTCommentedInvocationHandler(
node);

Class[] interfaces = getAllInterfaces(node);

Object o = Proxy.newProxyInstance(IASTCommentDecorator.class
.getClassLoader(), interfaces, handler);

return o;
}

Zuerst wird der Handler erzeugt der die Zugriffe die auf das Proxy-Objekt erfolgen handhabt. Auf die Funktionalität des Handlers gehe ich später in diesem Text ein. Mit der Methode „getAllInterfaces“ werden danach alle Interfaces des Knoten zurückgegeben und mit dem Interface das die Funktionalität zum Speichern von Knoten bereitstellt ergänzt. Danach wird ein Proxy-Objekt („Proxy.newProxyInstance“) für diese Elemente mit diesen Interfaces und dem Handler erstellt.

private static Class[] getAllInterfaces(CPPASTNode node) {
Class[] interfaces = node.getClass().getInterfaces();
Class[] allInterfaces = new Class[interfaces.length + 1];

for (int i = 0; i < interfaces.length; ++i) {
allInterfaces[i] = interfaces[i];
}

allInterfaces[allInterfaces.length - 1] = IASTCommentDecorator.class;
return allInterfaces;
}

Der Handler ist dann ein relativ einfaches Konstrukt welches das InvocationHandler-Interface implementiert. Welches einzig und allein die invoke Methode verlangt.

public class CPPASTCommentedInvocationHandler implements InvocationHandler 

Im Konstruktor wird der Orginalknoten gespeichert und ein Objekt der Klasse die das Speichern der Kommentare vornimmt angelegt. Die Speicherfunktionalität hätte auch im Handler selbst implementiert werden können, eine eigene Klasse löst aber die Kopplung und erhöht die Wiederverwendbarkeit des Codes.

In der invoke Methode landen nun alle Aufrufe an das Proxy-Objekt. Zuerst werden nun hier die Methoden equals und acceppt abgefangen da sie sowohl mit dem Knoten als auch mit dem Kommentar-Speicher interagieren. und deshalb direkt im Handler behandelt werden.

public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {

if (method.getName().equals("equals") && args.length == 1
&& args[0].getClass().equals(Object.class)) {

return equalsMethodeCall(args[0]);
} else if (method.getName().equals("accept") && args.length == 1
&& ASTVisitor.class.isInstance(args[0]) ){

return acceptMethodeCall((ASTVisitor) args[0]);
} else {
return standardClassCalls(method, args);
}
}

In der Methode „standardClassCalls“ werden nun die übrigen Methodenaufrufe an die beiden Klassen „verteilt“. Alle Methoden die vom IASTCommentDecorator ausgehen werden an das Objekt commentExt, welches die Speicherfunktionen für die Kommentare (also das Interface IASTCommentDecorator) implementiert. Alle anderen Methoden wurden ja von den Interface des konkreten Knotens implementiert und werden deshalb auch an diesen weitergeleitet.

private Object standardClassCalls(Method method, Object[] args)
throws IllegalAccessException, InvocationTargetException {
if (method.getDeclaringClass().equals(IASTCommentDecorator.class)) {
return method.invoke(commentExt, args);
} else {
return method.invoke(node, args);
}
}

Die Implementation auf diese Weise ist sehr flexibel und elegant, auch wenn sie ein wenig schwer zu verstehen ist. Leider kann das Proxy-Objekt nur in die entsprechende Interface, und nicht in eine Knotenklasse, gecastet werden. Da in Eclipse CDT, wie vermutlich in den meisten grösseren Projekten, nicht konsequent gegen Interfaces programmiert würde funktioniert dieser Lösungsansatz bei uns leider nicht.

Ähnliche Beiträge:
Developing Eclipse CDT
Fertig!
Mein erster Patch
Generisches toString in Java mit Reflection
Named parameters in Java (bgl-style)
Comments (0)  Permalink

Developing Eclipse CDT

Meine Links auf del.icio.us haben es bereits angekündigt. Emanuel und ich haben mit unserer nächsten Semesterarbeit begonnen. Diesmal versuchen wir für und mit Peter Sommerlad "CDT AST writability for Eclipse" zu implementieren. Nun sind wir bereits in der zweiten Semester- und Projektwoche.

Diese Projekt hat Emanuel und mir definitiv gezeigt das wir noch nicht alles über Java wissen. Der Code ist kompliziert, weist viele Eigenarten auf (die teilweise die c/c++ Vergangenheit der Entwickler nicht verheimlichen können) und bietet auch aus der Javasicht einige Neuheiten. Mit folgendem Code hätte ich zu Beginn dieser Woche noch nichts anfangen könne.

public static IViewPart openDOMASTView(IEditorPart editor){
...
( (DOMAST)tempView).setContentProvider( (DOMAST)tempView).new
ViewContentProvider(((CEditor)editor).getInputFile()));
...
}

Ja genau der Code instanziert eine innere Klasse aus einem statischen Kontext. Aber so was lernt man wohl in keiner Vorlesung (oder vergisst es schneller wieder als man es gehört hat).

Inzwischen sehen ich aber bereits wieder Licht. Das Codechaos wird langsam durchschaubar, obwohl beim CDT wohl die Grundregel gilt, dass keine Funktion nur einmal existiert und Codeduplizierung zur Tagesordnung zu gehören scheint. Heute bin ich auch über den ersten Fehler im Code gestolpert und habe einen Patch dafür erstellt. Wie es mit dem Projekt weitergeht wird wohl auf meinem Blog oder in unserem Projekt-Wiki stehen.

Ähnliche Beiträge:
Generische Decorator in Java mit Reflection
Fertig!
Mein erster Patch
Named parameters in Java (bgl-style)
SCJP, now!
Comments (0)  Permalink
1-4/4