Ganymede fejlesztés Java 6-tal OSX-en

Elég sok időt töltöttem már azzal, hogy Java 6 alapú fejlesztést lehessen végezni [intlink id=”570″ type=”post”]Eclipse-szel és OSX-szel[/intlink].

Az alapprobléma az volt, hogy egyszerre kellett 32 (az SWT Carbon API-ja kötelezően 32 bites) és 64 biten dolgozni (mert a Java 6 kötelezően 64 bites). Szerencsére ezt a fejlesztők is belátták, és elkészítették az SWT Cocoa portját (ami mellesleg nem lett rossz, de ez nem ennek az írásnak a témája).

Eredmény: némi varázslás után 3.5-ös Eclipse-szel lehetett Java6-ra fejleszteni (a varázslás nem ártott, de erről szintén nem most írok). De ez bizonyos esetekben nem elég. Például, ha az ember kénytelen 3.4-es Eclipse-szel is kompatibilis maradni, és ezt még ellenőrizni is szeretné.

Ez, és az apróbb problémák a 64 bites Java 6-tal győztek meg végül arról, hogy kb. egy hónappal a megjelenés után frissítsek Snow Leopardra. Elvégre abban van 32 bites Java 6 is, ezért elvileg mennie kellene a dolognak. Sőt, csak Java 6 van a rendszerben, szóval ez még jobb.

Na, Ganymede indul, szépen megy is. Összegyűjtöm a tesztelendő projekteket, és indítanám a runtime workbenchet, mire közli velem, hogy a Carbon SWT nem működik a 64 bites JVM-en. No comment.

A szokásos trükkjeimet ilyen esetekre végigpróbáltam, eredmény teljes kudarc, mígnem  az ESE konferenciáról beszámoló blogbejegyzés kommentjében Kevin Barnes leírja a megoldást: a VM-nek a -d32 paramétert átadva 32 bites JVM-et indít.

És ez tökéletesen működött. Szuper.

PS.: jellemző Eclipse probléma, hogy a megoldás triviális, csak megtalálni nehézkes. De legalább most már tudom, hogyan lehet 32 bitre force-olni a JVM-et.

Eclipse Trivia: ListDialog

Némi bugfixing kapcsán eljutottam egy Eclipse plug-in belsejében a JFace ListDialog osztályhoz.

A dolog lényege, hogy egy definiált listát megjelenít, és lehetővé teszi a felhasználó számára az elemek kiválasztását egy dialógusban. Az ötlet jó, hiszen viszonylag gyakran szükséges feladat.

Ugyanakkor egy érdekes adalék a működéséhez: működik az a hasznos (és elvárt) funkció, hogy a lista elemei dupla kattintással történő kiválasztása működik. Feltéve, hogy a Mégsem gomb is engedélyezve van… 😀 No comment. (Ld. még Bug 292576).

Mi a hiba a kódban?

Volt ma egy szép debug köröm. Nagyon nem értettem, miért nem működik egy kód – ami ráaásul régebben (július végén) szépen ment, és azóta nem nyúltam hozzá, és elvileg a kapcsolódó libekben sem volt lényegi változás azóta.

Úgy gondolom, bemutatom a kódot, és felteszem a kérdést, látja-e más is a hibát benne.

[ccw_java]private ICoreNotificationObject notificationObject;

public void actionPerformed(ICoreNotificationObject notification) {
this.notificationObject = notification;
Display.getDefault().aSyncExec(new Runnable() {

public void run() {
String action = notificationObject.getActionType();
if (isOneOf(action, new String[] {
ICoreNotificationObject.TA_TRANSACTION_END,
ICoreNotificationObject.TA_UNDO_END,
ICoreNotificationObject.TA_SUBTRANSACTION_END})) {
updateGraph();
transactions.pop();
} else if (isOneOf(action, new String[] {…}){
//…
}
});[/ccw_java]

Még némi információ a kód működéséről: a kód egy eseményfigyelő osztály belsejében van, és a Runnable adatváltozásokat próbál követni, amely tranzakciókba van szervezve, ill. a tranzakciók során visszavonás események is érkezhetnek.

Na, kinek van tippje, mi lehet a hiba? Ha nincs tipp véges időn belül (előre nem specifikálnám), akkor majd megosztom a helyes megfejtést. Annyit mondok előre, hogy fejet falbaverős hiba 😀 .

Update: először is helyesbítettem a kódot, mert sikeresen a javított változatot töltöttem fel.

A problémát az okozta, hogy az asyncExec() hívás indított egy új jobot, amit valamikor majd végrehajt. Csak közben visszaadja a vezérlést, és ezzel lehetővé teszi a rendszer számára, hogy felülírja a run() metóduson belül is használt notificationObject változót.

Az asyncExec() hívás syncExec()-re cserélése megoldotta a problémát, ugyanis az megvárja, hogy visszatérjen a meghívott thread.

Ez a hiba kifejezetten mocskos dolog, mert eredetileg működött, míg a környezet refactoringja előhozta a bugot…

LPG generálás OSX-en Eclipse-ből

Megnyertem egy parser frissítésének és karbantartásának feladatát. Igen, ez remekül hangzik. Ahogy az is.

A parser az LPG parser generátorral készült, méghozzá annak az 1.0-s változatával. Most már van 2-es is, ami természetesen nem kompatibilis a régivel (legalábbis generált kód szintjén semmiképp sem – többek között más java package-et használ). Miután nem sokkal release előtt kaptam meg, frissíteni most biztos nem lehet (később meg valószínűleg úgyis kellene).

Na, tehát ott tartottam, hogy 1-es verzió. Minden nagyon szép, minden nagyon jó, mindennel meg vagyok elégedve, úgyhogy módosítottam a grammar fájlt. Na, ideje újragenerálni a kódot. És itt jön a feketeleves: az LPG parser generátor régi verziójához csak egy Windows-os exe fájl van, azzal lehet futtatni. Természetesen forráskód is van, de még a makefile is a Visual C++ fordítóra van kihegyezve. Szóval lefordítani macerás.

Nem is kezdem el, mert feltehetőleg csak ideiglenes megoldás kell (max. 1-2 év 😀 ). Ugyanakkor cél, hogy a megoldás integrálódjon az Eclipse-be, azaz néhány klikkeléssel sikerüljön a programot elindítani. A lehetőségeim: wine vagy VMware.

Az utóbbi nem tetszene, mert relatíve sok erőforrást eszik, ráadásul egyszerűen csak a VMware alatt futó Eclipse példánnyal lehetne összekapcsolni, amelynek a gyorsbillentyűi teljesen mások, mint a natív Mac-es példányé.

Szóval lehet reménykedni, hogy a wine-osok jó munkát végeztek. És szerencsém van, mert az lpg.exe gond nélkül futtatható vele.

Most már csak az Eclipse integráció van hátra. Ennek remek eszköze az External Tools eszköz (megjegyzés: natív Windows-on is csak így lehet futtatni az lpg.exe-t Eclipse-ből – nincs jobb támogatás) a Run menüben.

Létrehozhatunk egy saját eszközt, amelynek felparaméterezéséhez használhatjuk az Eclipse különböző változóit. Számunkra ehhez kettőre van szükség:

  • [cci]${resource_loc}[/cci]: az aktuálisan kijelölt erőforrás elérhetősége a fájlrendszerben (nem workspace-relatív módon!)
  • [cci]${container_loc}[/cci]: az aktuális erőforrást tartalmazó mappa elérhetősége (szintén nem workspace-relatív módon)

Az LPG parser generátor számára fontos a munkakönyvtár beállítása, ide fogja generálni a fájlokat. A többi adat kitöltése magától értetődő, ezért csak egy képernyőfotót illesztek be róla.

LPG futtatása Wine segítségével az aktuális fájlra
LPG futtatása Wine segítségével az aktuális fájlra

Az LPG futásához három dologra van szükség: a nyelvtan fájlra vagy fájlokra, az include fájlokra és a template fájlokra. Ezek lehetnek mind a munkakönyvtárban (ez a helyzet, ha saját sablonokat használunk), vagy pedig környezeti változók által kijelölt mappában, esetleg paraméterként is át lehet adni.

Szerintem a legtisztább a környezeti változók használata, ezért az Environment fülön felvettem az [cci]LPG_INCLUDE[/cci] és az [cci]LPG_TEMPLATE[/cci] környezeti változókat, azokat a megfelelő mappákra irányítva.

Ezután a futtatás gombra kattintva jött a varázslat: a wine az OSX-es útvonalakat lefordítja a Windows-os program számára érthető formátumra (megfigyelhetőek az Y:\ kezdetű útvonalak a szöveges kimeneten – amik természetesen megjelennek az Eclipse Console view-ban), és az ugyanilyen formátumban készülő fájlok megjelennek az OSX-es mappában. Sőt, a környezeti változókra is igaz ez. Nagyon cool.

A technológiával két kisebb gondom van: nem tudom az LPG-t így a .g fájl jobb gombos menüjéből futtatni (nincs ott külső eszköz futtatásához lehetőség), és nem működik a megoldás, ha nem a Navigator view aktív a Run external tool használatakor (természetesen akkor sem, ha nem a .g fájl van kijelölve, de ez természetes :D). Van ezekre valakinek valami ötlete?

Kiválasztás átvitele eclipse nézetek között

Érdekes problémákba ütközik az ember, ha eclipse környékén fejleszt. Ezek nagyrészét ugyan már megoldották, de a megoldást külön művészet megtalálni a tengernyi dokumentációban. Mindenesetre legalább dokumentálták. A probléma, amiben pár napja az örömömet leltem, az az, hogy hogyan lehet egy nézet által kiválasztott elemeket átadni egy másik nézetnek, ami természetesen hasonló modell felett dolgozik. Konkrétan a Debug Visualisation projektem által definiált nézetet akartam összekötni a Variables View-vel és vice-versa.

Érdekes problémákba ütközik az ember, ha eclipse környékén fejleszt. Ezek nagyrészét ugyan már megoldották, de a megoldást külön művészet megtalálni a tengernyi dokumentációban. Mindenesetre legalább dokumentálták. A probléma, amiben pár napja az örömömet leltem, az az, hogy hogyan lehet egy nézet által kiválasztott elemeket átadni egy másik nézetnek, ami természetesen hasonló modell felett dolgozik. Konkrétan a Debug Visualisation projektem által definiált nézetet akartam összekötni a Variables View-vel és vice-versa.

Pár óra keresgélés és javadoc olvasgatás után rábukkantam a megoldásra: Minden view-t tartalmazó IWorkbenchPartSite lehetőséget biztosít egy ISelectionProvider regisztrálására, amely interfészt ad kiválasztási információk kinyerésére és átadására, továbbá listener-ek regisztrálására. A másik, csatlakoztatni kívánt view által megadott ISelectionProvider-nek az általunk generált kiválasztási eseményeket át lehet adni, illetve figyelni lehet az általa generált ilyen eseményeket.

A problémát csak az okoz, hogy egy adott view által generált és elfogadott kiválasztandó elemek az adott view modelljéből kerül ki, tehát ugyanezen modell elemeit kell neki átadni. Ha az általunk írt view más modellen, vagy ugyanazon modell felett máshogy definiálja a kiválasztást, akkor a kiválasztást konvertálni kell a modellek között. Ez természetesen csak akkor oldható meg, ha egyáltalán értelmezhető a közös kiválasztás.

Mindehhez persze az első lépés az, hogy megtaláljuk a csatlakoztatni kivánt view-t, amit az azonosítójának ismeretében tehetünk meg a következő módon:


PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().findView(viewID).getSite().getSelectionProvider();

ahol a [cci_java]viewID[/cci_java] helyére a keresett view szöveges azonosítóját kell megadni. A Variables View azonosítóját az org.eclipse.debug.ui plugin egy [cci_java]IDebugUIConstants[/cci_java] nevű publikus interfész elérhetővé teszi.

Mint az eclipse esetében általában erre problémára is egy jól kitalált megoldás létezik, ami megfelelően egyszerű ahhoz, hogy a módszer ismeretében könnyű legyen implementálni, a nehézséget csak a módszer megtalálása jelenti.