Archívum

A(z) ‘Tech’ kategória archívuma

Samsung Galaxy Spica frissítése Android 2.2-re (Froyo-ra)

október 14th, 2011 17 hozzászólás

Mindenek előtt köszönet Maczák Balázsnak, aki felhívta a figyelmem az új firmware verzióra. Nélküle nem készült volna el ez a bejegyzés.

No de miért is érdemes firmware-t frissíteni? A Galaxy Spica egy jó ár/érték arányú Androidos belépő telefon. Annak idején, mikor még én vettem az enyémet, olyan 60 000 Ft körül lehetett megkapni (jelenleg olyan 30 000-40 000 Ft körül lehet) 1.5-ös Android firmware-el. Időközben aztán az ember kinövi. Jó lenne magasabb verziós Android, lehetne kicsit gyorsabb, hiányzik a multitouch támogatás, vagy a programok sd kártyára helyezésének lehetősége (nekem ez utóbbi kettő hiányzott leginkább). Ilyenkor az ember első gondolata, hogy cseréljük le a jó öreg Spica-t valami újabb modellre. Pedig sokan nem tudják, milyen tartalékok vannak ebben a kis eszközben. Kis bátorsággal körülbelül fél óra alatt a fenti feature-ök közül mind elérhetővé tehető a telefonon. Igen, a multitouch is! Régebben úgy gondoltam, hogy a Spica-n hardver okokból nem elérhető ez a lehetőség, de egy sima szoftver frissítés után ez is remekül működik. Nézzük hát, mi a frissítés folyamata.

Elsőként root-olni kell a telefont, amihez itt (http://www.addictivetips.com/mobile/root-samsung-galaxy-spica-i5700-with-leshaks-kernel/) megtalálhatunk minden szükséges kelléket.

  1. Mielőtt bármihez kezdenénk, az sd kártya root könyvtárába másoljuk fel az  LK2-02-1_update.zip állományt.
  2. Töltsük le az Odin-t innen (cloud.addictivetips.com/wp-content/uploads/android/samsung/galaxy-spica/Odin_v4_03.zip).
  3. Kapcsoljuk ki a telefont, majd a hangerő szabályzó gombot lefelé nyomva és a fényképező gombot nyomva tartva nyomjuk meg hosszan a hívás bontás gombot. Így bekapcsolva a telefont az download módba kerül.
  4. Az Odin-ban nyomjuk meg a Reset files gombot, majd az ops részbe tallózzuk be a spica_jc3.ops fájlt (ezt az Odin-hoz csomagolva megtaláljuk).
  5. Bontsuk ki a i5700_LK2-02_PDA.zip állományt, és a tartalmát tallózzuk be a PDA részhez.
  6. Nyomjuk meg a Start gombot. Ekkor az Odin feltölti a telefonra az új loadert.
  7. Ha az Odin végzett, a telefonon megjelenik egy menü, ahol az ‘Apply any zip from SD’ opcióval kiválaszthatjuk az előzőleg oda másolt zip-et.
  8. Újraindítás után van egy root-olt telefonunk, tehát félig megvagyunk.

Root-olást követően már könnyedén telepíthetünk új ROM-ot. A Samdroid ROM 2.2-es változatát innen (http://forum.samdroid.net/f53/samdroidmod-2-2-1-a9-froyo-aosp-i5700-3017/) tölthetjük le, de a Wikipedia-n találhatunk néhány hasznos linket más ROM-okra. A ROM telepítéséhez végezzük el a következő néhány lépést:

  1. Másoljuk fel a ROM állományt az sd kártyára.
  2. Indítsuk el a telefont recovery módban a hangerő szabályzót lefelé nyomva, valamint a hívás fogadás és bontás gombokat egyszerre nyomva tartva. Ilyenkor előjön a boot menü, amivel már találkoztunk.
  3. Ha akarunk, itt készíthetünk backupot a jelenlegi rendszerről, de mivel jó esetben a címlista, a naptár bejegyzések, és a többi hasznos dolog a Google szervereire is le van szinkronizálva, erre sokszor nincs is szükség.
  4. Van egy Wipe data & cache menüpont, ezzel tisztára törölhetjük a telefon memóriát.
  5. Válasszuk ki a ROM zip-et az sd kártyáról az Apply menüpont használatával.
  6. A frissítés utáni reboot, és néhány percnyi várakozás után (4-5x újra fog indulni a telefon, addig hagyjuk békén, ellesz magában) a szépséges új 2.2-es Android UI fogad minket.

Ennyi az egész. Az egész procedúra körülbelül 15 percig tart, és a végén egy megújult telefon fogad minket. Telepíthetünk alkalmazásokat SD kártyára, használhatjuk a 2 ujjas nagyítást, és a 2.2-es Android virtuális gépébe bekerült JIT-nek köszönhetően sok alkalmazásunk is gyorsabban fog futni (2-3x-os gyorsulás is tapasztalható bizonyos alkalmazások esetén). Szerintem mindenképp megéri …

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

HgEclipse – Mercurial az Eclipse-ben

Nemrégiben írtam egy rövid bejegyzést a Mercurial elosztott verziókezelő rendszerről. Ott a TortoiseHg-n keresztül mutattam be a rendszer lehetőségeit dióhéjban. Mivel azonban elsősorban a fejlesztésekhez használok verziókezelő rendszereket, szükségem volt egy Eclipse pluginre. Nagyon rövid keresés után rá is találtam a HgEclipse kiegészítőre. A kiegészítő telepítése nagyon egyszerű: a szokásos módon a honlapon található update URL-t kell megadni az eclipse-nek, ahonnan a rendszer lehúzza a kiegészítőt, és folyamatosan követi is annak frissítéseit. A HgEclipse nagyon jól integrálódik az Eclipse általános verziókezelő moduljába. Tehát a funkciókat a Team menüpont alatt fogjuk megtalálni, itt hozhatunk létre tárolót, innen commit-olhatunk, stb. Az egész annyira kézre áll, hogy ha lehet ilyet mondani, még kényelmesebb is a használata, mint a TortoiseHg-nek (pedig ahhoz sem kell atomfizikus diploma).  Nézzük is meg dióhéjban, hogy működik.

Első körben hozzunk létre egy Java projektet, mondjuk MercurialTest néven. Eztán a szokásos jobb gomb -> Team/Share project …/Mercurial módszerrel hozzuk is létre a tárolót. Ahogyan az előző bejegyzésben már írtam, maga a tároló nem több, mint néhány speciális rejtett fájl a verziókezelt mappában, így nincs más dolgunk, mint nyomni egy finish-t, és kész is a tároló. Nem kell megadnunk szervert, stb. Ha megvagyunk, hozzunk is létre egy állományt, mondjuk egy szokásos HelloWorld.java programot. Ha ez is megvan, akkor az SVN-ből már megszokott Team/Commit módszerrel rögzíthetjük a változásokat. Ilyenkor kell adnunk valami rövid leírást az adott verzióhoz (igen, kell, nem lehet elhagyni, ami nem is feltétlen baj), kiválasztjuk a fájlokat, és már kész is a verzió. Tehát a dolog ugyanúgy megy, mint SVN esetén, csak nem kell hozzá szerver. E helyett minden a projekt könyvtárában lévő lokális tárolóba kerül. A Team/Show history-val láthatjuk az egyes verziókban történ változásokat, összehasonlíthatjuk, hogy hol mi változott, tehát mindent megtehetünk, amit SVN-ben. Ahogyan az előző bejegyzésben már írtam, az elosztott verziókezelőknél a fejlesztő a lokális tárolóba dolgozik mindaddig, amíg nem végez egy feladattal. Ha a feladat elkészült (letesztelte, jól működik a programrész, stb.), csak akkor tolja fel a változásokat a központi tárolóba. Ezt a Team/Push… menüpont segítségével tehetjük meg. Itt értelem szerűen megadhatjuk a távoli tároló címét, ahová betoljuk a változásokat. Ez felel meg kb. az SVN commit-nak. (Mivel a Mercurial lokális tárolója valójában néhány fájlból áll, ezért elvileg megtehető az is, hogy valaki Mercurial-t használ lokális verziókezelésre, majd ha elkészült, a változásokat a régi SVN tárolójába tolja be. Ilyesmivel nem próbálkoztam, és nem is tudom mennyire lehet hatékony, de ha valaki nagyon ragaszkodik az SVN-hez, az próbálkozhat ilyesmivel. Így esetleg fájdalommentesebb lehet az átállás egyik rendszerről a másikra.) Próbaképp készítsünk néhány lokális változatot, majd térjünk rá az elosztott verziókezelés egyik legnagyobb előnyére, és klónozzunk.

A klónozás kicsit trükkös Eclipse-ben, ugyanis nem a Team, hanem az Import menüpontban találjuk a Mercurial/Clone repository menüpont alatt (ami utólag végiggondolva végül is logikus). A klónozásra kiválaszthatunk távoli tárolót (ez felel meg kb. az SVN checkout-nak), vagy lokális tárolót. Próbaképp válasszuk ki a fájlrendszerből az eredeti (azóta Mercurial tárolóvá tett) eclipse projektet. Ha elkészült a klón, itt is csináljunk néhány változatot, és az eredeti projektben is commit-oljunk néhányat, lehetőleg úgy, hogy a kétféle változtatás üsse egymást (így tesztelhetjük majd a merge-öt). Ha készen vagyunk, próbáljuk visszafésülni az eredeti projektbe az újonnan létrehozott változatokat. Ehhez az eredeti tárolón használjuk a Team/Pull menüpontot. (Az előző bejegyzésben már írtam arról, hogy a változásokat vagy tolni [push], vagy húzni [pull] lehet egyik tárolóból a másikba.) Itt válasszuk ki a második lokális tárolót (természetesen használhatnánk távoli tárolót is), és húzzuk át a változásokat. Ekkor az eredeti tárolóban létrejön egy másik ág, és a HgEclipse rögtön rá is kérdez, hogy összefésülje-e a két ágat. Ezt ugye érdemes megtenni, úgyhogy válasszuk a merg-öt. Ha jól dolgoztunk, a rendszer nem fogja tudni simán összefésülni a két ágat, és néhány állomány conflict-es lesz. Ez ismerős lehet SVN-ből is, hiszen ott is előfordulhat, hogy a szerveren lévő változatot nem lehet automatikusan összefésülni a lokális változattal. Mondjuk az SVN ilyenkor televágja minden krix-krax-al a fájlt, és létrehoz egy állományt a lokális, egyet pedig a szerveren lévő változatnak. A Mercurial ennél szebben jár el, hiszen ott csak egy kis jelet látunk a fájl mellet, hogy conflict van, de nem rontja el az eredeti tartalmat, alul pedig megjelenik egy Mercurial Merge ablak, ahol látszik a conflict-es fájlok listája. Itt ha jobb gombbal rákattintunk egy állományra, a legelső menüpont az Open in Merge Editor. Itt szépen egymás mellett látjuk a két változatot, és kézzel kijavíthatjuk a hibákat. Elég kényelmes kis eszköz. Ha készen vagyunk a kézi merge-öléssel, újra nyomjunk jobb gombbal a fájlra, és az SVN-ből már megszokott “mark resolved” menüponttal fogadjuk el a változásokat. Ha megvagyunk a javításokkal, az eredményt kitolhatjuk a szerveren tárolt közös tárolóba, stb. Dióhéjban körülbelül ennyi lenne.

Véleményem szerint a HgEclipse egy nagyon jól sikerült kis eszköz, és önmagában a HgEclipse is, és a Mercurial mint verziókezelő is jóval többet ad nekünk, mint a hagyományos SVN tárolók. Az én jóslatom, hogy egyre többen fogják felismerni az ebben rejlő lehetőségeket, és néhány éven belül mindenhol át fognak térni valamilyen elosztott verziókezelő (Git, Mercurial, stb.) használatára.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

Mercurial – első tapasztalatok egy elosztott verziókezelővel

május 7th, 2011 8 hozzászólás

Már régóta szemezek az elosztott verzió kezelő rendszerekkel. Egyfelől azért, mert úgy látom ez a trend (néhány év múlva az elosztott verzió kezelők fogják átvenni az  SVN helyét, úgy ahogyan annak idején az SVN került az akkoriban elterjedt CVS helyére), másfelől magam is szembesültem már az SVN néhány hátrányával, amiken az elosztott verziókezelő rendszerek felülemelkednek. No de mi is az az elosztott verzió kezelő rendszer?

Feltételezem, hogy az olvasó találkozott már  központi (centralizált) verziókezelő rendszerrel. Ilyen például a hagyományos SVN, vagy a CVS. Központi verziókezelő esetén ugye van egy központi szerver (pl. SVN szerver), a felhasználók pedig innen húzzák le, illetve ide tolják fel a saját változtatásaikat. Minden feltöltést egy letöltésnek kell megelőznie, ami az adott felhasználó gépén összefésüli a szerveren lévő és a lokális változatot. Ha az összefésülés automatikusan megoldható (általában megoldható), akkor azt a rendszer el is végzi, ha nem, akkor kézzel kell összefésülnünk a változatokat, majd az eredményt feltöltjük, és onnantól az lesz az aktuális változat. Az egyes változatokat vissza lehet keresni, egy egy állományt vissza lehet állítani a régi állapotra, és változatonként pontosan nyomon követhetjük, hogy hol mi változott. Nagyon röviden valami ilyesmiről szól egy központi verziókezelő.

Elosztott (decentralizált) verziókezelő esetén más a helyzet. Ott egyetlen központi tároló (repository) helyett minden felhasználónak van egy saját külön tárolója a gépén. A külön tárolónak külön verziókezelése van, tehát nem kell minden egyes változást a központi szerverre tölteni. Itt rögtön látszik is az elosztott verziókezelők egyik nagy előnye az SVN-el szemben. SVN esetén ha valami nagy feladaton dolgozunk, és a feladat megoldása közben menteni szeretnénk egy egy mérföldkövet, azt csak az egyetlen központi tárolóba menthetjük. Így választhatunk, hogy vagy félkész dolgokat mentegetünk a központi tárolóba (ezzel esetleg működésképtelen vagy hibás verziókat hozva létre), vagy mindaddig nem készítünk verziót, amíg el nem készültünk a feladattal (így viszont a feladat ideje alatt elveszítjük a verziókezelésből eredő előnyöket). Mindkét megoldás rossz, de mindenki saját szája íze szerint választhat, hogy melyik a kisebbik. Elosztott verziókezelés esetén nincs ilyen gond, hiszen a saját lokális tárolójába mindenki olyan verziókat hoz létre, amilyet akar (lehetnek ezek között működésképtelen, félkész állapotok is), és csak akkor tölti fel az egészet a központi tárolóba, ha kész van a feladattal (esetleg le is tesztelte, stb.). Így a központi tárolóban mindig egy stabil, használható változat van. Ez már önmagában nagy előny, de mint látni fogjuk, ez csak egyetlen a sok közül. Tehát egy központi tároló helyett itt több tároló van, és mivel nincs is olyan fogalom, hogy “központi” tároló, ezekből a lokális tárolókból tetszőleges hierarchiák kialakíthatóak. Tehát pl. egy projekt 2 nagyobb feladatra osztható, és mindkét feladaton dolgozik 2-2 fejlesztő. Ebben az esetben a két fejlesztőnek van 1-1 saját tárolója, ezekből mindig az adott feladat tárolójába szinkronizálnak, és ha az adott feladat elkészül, akkor tolják ki az egészet a “központi”, stabil tárolóba. De hasonló módon akár az is megoldható, hogy 2 “központi” tárolót tartunk fenn. Az első egy “testing”, a második egy “stabil” változat. Ha elkészül egy feladat, akkor az a “testing” rendszerbe kerül. Itt valaki leteszteli, és ha megfelelőnek találja, kihelyezi a stabil tárolóba. Ez csak néhány példa a teljesség igénye nélkül, de sok más elrendezés is elképzelhető. Például ami nekem nagyon tetszett, hogy nyílt forrású projektek esetén ha a forráskód tárolására SVN-t használnak, akkor két módon lehet beszállni a fejlesztésbe. Az egyik, hogy elérési jogot kérünk a tárolóhoz. Itt ugye az a dolog veszélye, hogy akinek ilyen jogot adunk, abban nagyon meg kell bízni, hisz kontrollálatlanul telepakolhatja a kódot mindenfélével. A másik eset, hogy a felhasználó elvégzi a módosítást, majd generál egy patch-t, amit elküldhet a projekt vezetőjének, aki átnézi azt, és kézzel befésüli az SVN-be. Ez viszont elég kényelmetlen. Elosztott verziókezelő esetén a dolog igen gördülékenyen megy, mivel a felhasználó csinál egy másolatot (klónt) a központi kódbázisról, elvégzi a változtatásokat (itt használhatja a lokális változatának saját verziókezelését), majd ha elkészült, értesíti a projekt gazdáját, hogy húzza át a módosítást a fő kódbázisba. Ez tulajdonképpen olyan mint mikor az ember patch-et küld egy SVN-es projekthez, de sokkal egyszerűbb, és gördülékenyebb.

A legismertebb ilyen elosztott verziókezelő a Git. Ezt a linux kernel fejlesztéséhez hozták létre, de mostanra már sokan mások is használják. Git-ben tárolják pl. az Android forráskódját, a Diaspora-t, az Appcelerator forráskódját, a Facebook is ezt használja a nyílt forrású projektjeihez, és még több ezer projekt, amiket jellemzően a GitHub-on hosztolnak. (A GitHub egy Git alapú code hosting szolgáltatás, olyan mint a Google Code Hosting, vagy a Sourceforge, bár sok szempontból sokkal fejlettebb.) A Git után szorosan második helyen áll a Mercurial. Nem kell szégyenkeznia a Git mellett, hisz olyan projektek használják, mint a Mozilla böngésző, Python programozási nyelv, OpenJDK, Netbeans, stb. Ráadásul a Google Code Hosting-on is használhatjuk az SVN alternatívájaként. Valójában nekem is szimpatikusabb a Mercurial, mint a Git, mivel a Git egy scriptekből és programokból összelapátolt valami, míg a Mercurial tulajdonképpen egy Python program, így ha kell, ebbe jobban bele lehet nyúlni (pl. plugint fejleszteni hozzá), ráadásul az egész valahogy jobban egyben van. Van még néhány elosztott verziókezelő (pl. Bazaar, amit az Ubuntu Linux használ), de mind közül nekem a Mercurial tetszett legjobban, így erről fogok írni.

Akit mélyebben érdekel a Mercurial, a http://hginit.com/ címen találhat egy nagyon jó angol nyelvű összefoglalót, de én is írok róla néhány sort.  Ha ki szeretnénk próbálni ennek a verziókezelő rendszernek a képességeit, legegyszerűbb, ha letöltjük a TortoiseHg klienst. Ez beépül a Windows jobb gombos menüjébe, így a fájlkezelőben könnyen adminisztrálgathatjuk a tárolóinkat. A kísérletezéshez hozzunk létre egy tárolót. Ehhez a TortoiseHg-ban van egy “Create repository here” menüpont. Az első dolog, amit észrevehetünk, hogy maga a tároló egy egyszerű könyvtár néhány speciális fájlal, tehát alapvetően nincs szükség szerverre a működéshez. Ez már önmagában is hasznos lehet. Ha kész a tároló, hozzunk is létre benne néhány fájlt. Eztán ha a tároló könyvtárán jobb gombot nyomunk, feltűnik az ismerős commit parancs. Ezzel az SVN-hez hasonlóan rögzíthetjük a változásokat, és létrehozhatunk egy verziót, ami az SVN-el ellentétben nem egy szerveren, hanem a könyvtárban lévő egyik mappában jön létre. Készítsünk még 1-2 verziót. Van egy Hg Workbench menüpont is, amivel szépen fában látjuk a változatokat, megnézhetjük a különbségeket, stb. Eztán jöhet a trükk, ami az elosztott verziókezelők legnagyobb előnye.  A menüben találunk egy “Clone” parancsot. Ezzel a teljes tárolót lemásolhatjuk még egy példányban, verzió történettel, mindennel együtt. A clone után mér két tárolónk van (két sima könyvtár néhány speciális fájlal és mappával). Most csináljunk néhány verziót az egyik, majd néhány verziót a másik tárolóban. Ez jelképezi a több fejlesztési ágat. A gyakorlatban ez úgy néz ki, hogy minden egyes fejlesztő klónozza magának a tárolót, és abba dolgozik. Szóval csináljunk néhány verziót mindkét tárolóban. Ha ezzel megvagyunk, akkor jön az, hogy a másodlagos (pl. fejlesztési) tárolót fésüljük vissza az elsődleges tárolóba. Ezt két módon tehetjük meg. Vagy a cél tárolóba húzzuk (pull) a változásokat a forrás tárolóból, vagy a forrás tárolóból nyomjuk (push) a cél tárolóba a dolgokat. Mindkét módozatnak van értelme. A push-ra jó példa, amikor mondjuk egy fejlesztő befejezett egy feladatot a saját lokális tárolójában, és ezt betolja a központi fejlesztői tárolóba (kb. az SVN commitnak felel meg). A pull használata pedig például akkor lehet hasznos, ha a stabil szál felelőse áthúzza a változásokat a fejlesztői szálból. Például GitHubon (ez Git alapú, de a mechanizmus ugyanaz) úgy szállhatunk be egy nyílt forrású projekt fejlesztésébe, hogy klónozzuk a projekt tárolóját, megcsináljuk a változtatásokat (ehhez semmilyen interakció nem kell ugye a projekt gazdájával), majd ha megvagyunk, küldünk egy pull request-et (ez kb. egy üzenet, hogy “kérlek, húzd át a változásokat az én tárolómból”) a projekt gazdájának, aki átnézi, hogy mit változtattunk, és ha mindent rendben talál, áthúzza a változásokat a projekt fő tárolójába. Ez nagyon gördülékeny módja a nyílt forrású projekthez való hozzájárulásnak, sokkal kényelmesebb, mint SVN hozzáférést kunyerálni, vagy patch-eket küldeni. A példa kedvéért tehát nyissuk meg az elsődleges tárolónkat a Hg Workbench-ben, és húzzuk át a változásokat a másodlagosból. Ha ez megvan, láthatjuk a Workbench-ben, hogy a másodlagos tároló történettel, mindennel együtt egy új ágként megjelent a mi tárolónk történetében (magyarul látszik, hogy ott ketté vált a fa). Ez már majdnem jó, már csak egyesíteni kell a két ágat. Ehhez van a workbench-ben egy merge művelet. Ez igazából ugyanúgy megy, mint SVN-ben a merge-ölés, ha lehet, automatikusan merge-öl a rendszer, ha nem, akkor kézzel kell ezt megtenni. (Elvileg a Mercurial mindenféle metaadatot gyűjt a merge segítésére, de ezt a részét annyira nem próbáltam.) Ha megvan a Merge, jöhet egy commit, és rögtön egy szálon megy tovább az egész. Tehát ha a fejlesztés végén ránézünk a fára, lépten-nyomon kis elágazásokat és visszacsatolásokat fogunk látni, amik az egyes fejlesztések.

Úgy nagyon dióhéjban ennyi lenne a Mercurial bemutatása. Feltűnhetett, hogy minden műveletet a fájlrendszerben végeztünk, de ahogyan SVN esetén, természetesen itt is megvan a lehetősége annak, hogy egy repository-t egy szerveren tároljunk, amit HTTP-n, HTTPS-en, vagy SSH-n keresztül lehet elérni. A dolgok mechanizmusán ez nem sokat változtat, egyszerűen az ilyen tároló nem a fájlrendszerben van, hanem egy távoli szerveren, de ugyanúgy lehet klónozni, lehúzni (pull) róla a változásokat (ami az SVN update-hez hasonló), vagy felnyomni (push) oda a változásokat (ami az SVN commit-hoz hasonló). Célszerűen csak a fejlesztő lokális tárolóját érdemes a fájlrendszerben tartani, minden olyan tárolót, amit többen használnak (közös fejlesztési ág, stabil ág, stb.), szerveren érdemes tartani.

Remélem ezzel a kis ismertetővel sikerült kicsit kedvet csinálni az elosztott verzió kezelő rendszerek, azon belül is a Mercurial használatához.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

JSONP és Cross-Site Scripting

január 10th, 2011 Nincsenek hozzászólások

Aki próbált már JavaScript-ből idegen szerverrel kommunikálni, az valószínűleg belefutott már a Cross-Site Scripting problémakörbe. Röviden arról van szó, hogy biztonsági okokból egy oldalon lévő JavaScript csak az oldalt tartalmazó domain-el képes kommunikálni (onnan bármit letölteni, vagy küldeni oda). Ez bizonyára sok gonoszságtól megvéd minket, mégis vannak helyzetek, mikor jól jönne, ha idegen domainről tudnánk adatokat letölteni. Például RSS feed-et szeretnénk olvasni JavaScript-ből, vagy valami távoli szolgáltatást szeretnénk valami API-n keresztül elérni. A napokban én is egy hasonló problémával találtam szemben magam. Nevezetesen volt két oldalam (mondjuk foo.com és bar.com). Az egyiken leraktam egy cookie-t, amit a másik oldalon szerettem volna kiolvasni, és mindezt JavaScript-ből. Mivel a bar.com oldal nem láthatja a foo.com oldal cookie-jait, ezért ezt csak úgy lehet megoldani, hogy a foo.com kiolvassa a saját cookie-ját, és valahogy átadja ezt a bar.com-nak. A baj csak az, hogy a bar.com-on lévő JavaScript nem tudja semmiképp elérni a foo.com oldalt. Több dologgal próbálkoztam, iframe-el, megpróbáltam a foo.com-ról betölteni a JavaScript-et, stb. de semmi nem vezetett eredményre. Ekkor találtam rá a JSONP-re.

A JSONP igazából egy igen egyszerű kis trükk a fenti probléma megkerülésére. Ha egy ideig szenved vele az ember, valószínűleg egy idő után magától is kitalálja. A JSONP-nek annyi a lényege, hogy úgy adunk át adatokat a foo.com-ról a bar.com-nak, hogy foo.com az átadandó adatokból generál egy JavaScript-et, és ezt a bar.com egy egyszerű script taggal behúzza. Mindebből úgy alakíthatunk ki kétirányú kommunikációt, hogy a kliens URL paramétereket használ az adatok továbbítására, amire a szerver a megfelelő javascript generálásával válaszol. Hogy mindez tisztább legyen, nézzünk egy példát. Tekintsük a fenti problémát, vagyis a foo.com domainről szeretnénk lekérni a cookie megadott nevű mezőjének értékét. Ehhez hozzunk létre egy cookie.php állományt a foo.com domainen, amit a következőképpen paraméterezhetünk: foo.com/cookie.php?cookie_name=<változó neve>&callback=<javascript fv.>. Itt a változó neve ugye egyértelmű, a callback paramétert meg nemsokára megértjük. A cookie.php valahogy így fog kinézni:

<?php
$cookie_name = $_GET['cookie_name'];
$data = array();
$data[$cookie_name] = $_COOKIE[$cookie_name];
echo $_GET['callback'] . '(' . json_encode($data) . ');';
?>

ha a fenti scriptet cookie_name=test és callback=jsonp_callback paraméterrel hívjuk, az eredmény valami ilyesmi lesz:

jsonp_callback({'test': 'Test cookie value.'});

Ez pedig egy teljesen szabványos javascript hívás. Nincs más dolgunk,mint a fenti url-t egy script tag-el behúzni a hívó oldalra:

<script type="text/javascript" src="http://foo.com/cookie.php?cookie_name=test&callback=jsonp_callback"></script>

A script tag tartalmát a böngésző azonnal végrehajtja, ami ugye így azt eredményezi, hogy meghívódik a jsonp_callback függvény a {‘test’: ‘Test cookie value.’} paraméterrel. Nincs más dolgunk, mint definiálni a jsonp_callback fv.-t, és kész is vagyunk:

function jsonp_callback(data) {
alert(data.test);
}

Igazából ennyi az egész. Persze a gyakorlatban általában nem fix paraméterekkel akarunk hívni egy szerver szolgáltatást. A dinamikus paraméterezéshez dinamikusan kell előállítanunk a script tag-eket, ez DOM műveletekkel viszonylag egyszerűen megvalósítható, de van egy még kényelmesebb megoldás, ez pedig a jquery javascript library ajax hívása. Ezzel a megoldással egy egyszerű függvényhívásra van csak szükség, ami valahogy így néz ki:

$.ajax({
dataType: 'jsonp',
data: 'cookie_name=test'
url: 'http://foo.com/cookie.php',
success: function (data) {
alert(data.test);
},
});

Így tehát JQuery használatával, és némi PHP ismerettel már egész kényelmes Cross-Site Scripting megoldást készíthetünk. Akit a JSONP mélyebben érdekel, az utánanézhet a wikipediában.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

lworm (egy pehelysúlyú PHP ORM megoldás)

november 20th, 2010 Nincsenek hozzászólások

Amikor elkezdett foglalkoztatni a gondolat, hogy PHP-ban fejlesszek Google App Engine-re, az egyik legnagyobb problémának az adatbázis elérése tűnt, hiszen PHP-ból általában SQL használunk erre, ami ugye App Engine alatt nem megoldható, hiszen a datastore egy nem relációs adatbázis. Utánanéztem kicsit, hogy mások hogy oldják meg ezt, és igazából két megoldást találtam. Az egyik az App Engine által szolgáltatott JPA vagy JDO réteg használata. Itt ugye az a gond, hogy ezzel elveszítjük a rendszer hordozhatóságát, hiszen egy standard LAMP környezetben már nem állnak rendelkezésre ezek a programkönyvtárak. A másik lehetséges megoldás, hogy valamilyen SQL wrappert használunk, amin keresztül a datastore szabvány SQL adatbázisnak tűnik. Ezzel az volt a gondom, hogy feleslegesnek tűnt, hiszen az SQL réteg felett úgyis valamilyen ORM réteget használnék, és ha már így van, miért ne építsük az ORM réteget közvetlenül a datastore fölé. Így született tehát az elhatározás, hogy saját ORM réteget fejlesszek PHP-hoz, és ha már belefogtam, megpróbáltam belegyúrni az eddigi tapasztalataimat.

Az első szempont az egyszerűség volt. Minimalista megoldást akartam, ami egyszerű, de mégis hatékony. E mellett legyen transzparens, tehát az elkészült PHP alkalmazás egyaránt képes legyen futni egy általános LAMP környezetben, és az AppEngine datastore-ja felett is. Mivel annak idején a Hibernate-el volt némi nézeteltérésem, mindenképp olyan megoldást akartam, ahol az entitások memória objektumok, tehát nincsenek az adatbázishoz kötve (csúnyán mondva nem attach-oltak). Itt most nem térnék ki a részletekre, de a lényeg, hogy ennek köszönhetően az adatbázis objektumokat büntetlenül tárolhatjuk a session-ben, vagy mondjuk JSON formában mozgathatjuk őket két rendszer között. Kb. ezek voltak az előfeltételek, lássuk hát a megvalósítást.

A rendszer használatához elsőként egy YAML állományban le kell írnunk az adatbázis sémát és az entitások kapcsolatrendszerét. Ez a YAML formátum felépítésének köszönhetően nem túl bonyolult, mégis szép és átlátható. A YAML alapján a ModelGenerator osztály használatával legenerálhatjuk az entitás osztályokat. Az entitás objektumok csak egyszerű adattároló szerepet töltenek be, így felépítésük az adatbázis megvalósítástól független. Ha ezzel megvagyunk, a megfelelő Datastore factory hívásával kérhetünk a rendszertől egy datastore példányt, aminek segítségével az adatokkal kitöltött entitás az adatbázisra menthető, illetve onnan felolvasható. Ugyancsak a datastore segítségével generálhatunk lekérdezéseket, aminek segítségével egyenlőre csak szűrni és rendezni lehet az eredményeket. Ennek az az oka, hogy az alacsony szintű datastore API csak ezeket teszi lehetővé. Bár lehet, hogy ez az eszközkészlet kicsit szegényesnek tűnik, de az esetek nagy részében általában elég, vagy némi kódolással kiegészíthető. Az entitás példányok kapcsolatainak kezelésére azt találtam ki, hogy az entitás objektum minden kapcsolatához egy metódust rendeltem, ami paraméterként kapja meg az aktuális datastore-t. A metódus egy kezelő objektumot ad vissza, ami a kapcsolatnak megfelelően karbantartja a kapcsolódó objektumokat. Tehát vegyük például a User (felhasználó) és Role (szerepkör) entitásokat, melyek közt many-to-many (több-több) kapcsolat van. Ebben az esetben a User osztálynak lesz egy getRolesRelation metódusa, ami egy kezelő objektumot ad vissza. Ezen az objektumon keresztül adhatunk hozzá Role-okat az adott felhasználóhoz, ezen keresztül listázhatjuk ki a hozzárendelt szerepköröket, vagy törölhetjük azokat. Mivel ezek a Relation objektumok mindig létrehozáskor kapják meg a szükséges adatbázis kapcsolatot, az entitásnak magának nem kell az adatbázishoz kötődnie, amiről az előzőekben már írtam. Röviden tehát körülbelül ennyi.

Az eredmény tehát egy nagyon kompakt kis ORM rendszer. Jelenleg a MySQL-t és a Google App Engine Datastore-ját támogatja, de nagyon egyszerűen kiterjeszthető. Maga a kód nagyon egyszerű, áttekinthető és könnyen használható. Bár ennek a lehetőségét nem vizsgáltam meg mélyebben, de a csökkentett eszközkészletnek köszönhetően valószínűleg a datastore-on kívül más nem relációs adatbázisokra is alkalmazható lenne a rendszer, pl. MongoDB-re. A későbbiekben talán érdemes ezt az irányt is megvizsgálni. A programkönyvtár másik nagy előnye, hogy nagyon pici, így akár kódméret kritikus rendszerekben is használható lenne. A későbbiekben lehet, hogy készül Java, Python, esetleg C++ változatot, amit például mobiltelefonok programozásához lehetne használni.

A kód és néhány példa elérhető a Google Code-on a http://code.google.com/p/lworm/ címen.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

gae-filestore (Írható/olvasható virtuális fájlrendszer Google AppEngine-re)

november 16th, 2010 Nincsenek hozzászólások

A Google AppEngine egyik elég erős megszorítása, hogy a telepített alkalmazás csak olvasni tudja a fájlrendszert. Új fájlokat nem hozhatunk létre, illetve nem módosíthatjuk a fájlokat. Bármilyen adattárolásra az AppEngine által biztosított adatbázist, a Datastore-t kell használnunk. Igazából ha jobban meggondoljuk, egy webalkalmazás többnyire valóban csak az adatbázist használja, így sokszor tényleg nincs szükség fájlrendszerre, de azért néha jól jön. Egy projektem kapcsán épp ilyesmire volt szükségem, ezért készítettem egy igazán egyszerű virtuális fájlrendszer implementációt Google AppEngine-hez. A rendszer működésének megértéséhez először írnék kicsit a Datastore-ról, annak is az alacsony szintű megvalósításáról.

Az AppEngine Datastore-ja egy BigTable alapú nem relációs adatbázis rendszer. Bár pontosan nem tudom, hogy a Google alkalmazások (GMail, Google Maps, a kereső, stb.) is ezt a megvalósítást használják-e, erről nem találtam konkrét leírást, de mindenesetre ez valami nagyon hasonló dolog kell hogy legyen. A rendszer használatára két lehetőségünk van. Egyfelől kapunk egy szabványos JPA/JDO réteget, így J2EE alkalmazásainkat változtatás nélkül, vagy kisebb változtatásokat követően futtathatjuk AppEngine-en. A másik lehetőség a low-level API használata, ami közvetlen hozzáférést biztosít a DataStore-hoz, így sokkal hatékonyabb, ugyanakkor kicsivel kényelmetlenebb is, mint a szabványos réteg. Én ez utóbbiról írnék kicsit bővebben. A Datastore adattárolásának alapja az Entity. A relációs adatbázis kezelőkhöz hasonlítva az Entity az adatbázis rekordnak felel meg, azzal a különbséggel, hogy az Entity-nek nincs fix szerkezete. Ebből a szempontból az Entity inkább olyan mint egy asszociatív tömb, vagy Java terminológiával élve Map. Egy ilyen Entity-be szabadon helyezhetünk el név-érték párokat. A másik nagyon fontos komponens a Key. A Key az entitás elsődleges azonosítója. A Key 3 féle módon épülhet fel. Generálhatjuk egy string-ből vagy long-ból, ezen felül definiálhatunk egy kulcs típust (kind), ami kb. a tábla megfelelője, és végül definiálhatjuk úgy a kulcsot, hogy ezeken felül egy szülő kulcsot is megadunk. Ez utóbbi megoldással a kulcsok és ezzel az Entity-k hierarchiába szervezhetőek. Ha összeállítottunk egy Entity-t, azt egyetlen metódussal lerakhatjuk a datastore-ra, és onnan a Key segítségével vissza is olvashatjuk. Amennyiben nem a Key alapján szeretnénk visszanyerni az entitást, úgy létre kell hoznunk egy Query-t. A Query segítségével az Entitás bármely értékére szűrhetünk az alapműveletek (kisebb, nagyobb, egyenlő, stb.) használatával. Az ilyen keresések segítésére definiálhatunk indexeket, de erre sincs feltétlenül szükség, hiszen a rendszer a lekérdezések alapján automatikusan legenerálja a szükséges indexeket. Az eredményként kapott entitás listát bármely eleme alapján rendezhetjük is, és nagyjából ennyi. Ha több entitást szeretnénk összekapcsolni (JOIN), VAGY kapcsolatot kialakítani a szűrési feltételekben, vagy bármi hasonlót tenni, amire egy relációs adatbázis amúgy önmagában képes, azt kódból kell megvalósítanunk. Cserébe viszont az egész rendszer masszívan elosztott, sémamentes, flexibilis és gyors. Most hogy megismertük a Datastore-t, lássuk a virtuális fájlrendszer működését.

A virtuális fájlrendszer legfelső szintű eleme a DataStoreFile entitás. Ezek az entitások testesítik meg az állományokat és a könyvtárakat egyaránt. Egy ilyen entitásnak 4 attribútuma van. A fájl típusa (könyvtár v. fájl), az utolsó módosítás ideje, a fájl mérete, és a fájlt tartalmazó útvonal. A fájl entitás egyedi azonosítója annak elérési útja, így ez alapján nagyon könnyen elérhetőek a fájl metaadatai. Mivel a metaadatokra sokszor szükség lehet, ezért a fájl entitás mentésekor és betöltésekor a memcache-ben is tároljuk, így annak további elérése már nagyon gyorsan megy a cache-ből. A fájl tényleges tartalmának tárolása Blob-okban történik. A Blob tulajdonképpen egy byte tömb, aminek mérete maximálisan 1 Mb lehet AppEngine esetén. Én 512 Kb méretű blokkokat használtam, amiket sorszámmal azonosít a rendszer. Az egyes blokkok a fájl entitás alatt helyezkednek el (a blokk kulcsa a fájl entitás kulcsának leszármazottja). Amikor adatokat írunk vagy olvasunk a fájlból, a rendszer a fájlmutató alapján meghatározza a blokk sorszámát ahol az adat van, majd ebben módosítja a megfelelő adatot. Egyszerű kialakítás, mégis kényelmes és hatékony.

A kód szokásos módon a Google Code-on megtalálható a http://code.google.com/p/gae-filestore/ címen.

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

PHP futtatása Googel App Engine-en

november 9th, 2010 Nincsenek hozzászólások

A GAE vagy Google App Engine a Google alkalmazás hoszting szolgáltatása. Nagy előnye, hogy segítségével alkalmazásunka a Google infrastruktúráján futtathatjuk. Nem kell olyan apróságokkal foglalkoznunk, mint a load balanceing, erőforrás allokáció, elosztott session kezelés, stb. hiszen a Google a terheléstől és a kérések helyétől függően optimálisan fogja “szétkenni” az alkalmazásunkat. Adatbázisként egy Google BigTable alapú nem relációs adatbázist kapunk, aminek klaszterezését ugyancsak a rendszer végzi automatikusan. E mellett kapunk még néhány “nyalánkságot”, mint amilyen az elosztott memcache, e-mail, vagy xmpp lehetőség. Amiért azonban igazán vonzó lehet induló startup-ok számára, az az, hogy a rendszer körülbelül havi 1 000 000 lapletöltésig és 500 Gb tárhelyigényig teljesen ingyenes. Ha pedig az embernek sikerült ekkora forgalmat generálnia, akkor már jó eséllyel ki tudja termelni a plusz sávszélesség és tárhely árát is, ami néhány cent gigabájtonként, tehát igen baráti. Persze ezért a nagy kényelemért némi kompromisszumot is kénytelenek vagyunk meghozni. Az egyik ilyen korlát, ami véleményem szerint nagyban gátolja a technológia elterjedését, hogy egyenlőre csak Java és Python nyelven programozható. Az egyik talán leggyakoribb kérés szokott lenni a felhasználók felől, hogy más hoszting szolgáltatókhoz hasonlóan támogassák a PHP nyelvet is. Így megnyílna az út sok népszerű web framework, és PHP fejlesztő előtt. Ezt a dolgot viszont valamiért a Google nem annyira erőlteti. Bár a PHP hivatalosan nem támogatott, mégis viszonylag egyszerű módon futtathatunk PHP scripteket AppEngine felett.

A megoldás kulcsa a Caucho Quercus nevű Java Servlet alapú PHP implementáció, amely az App Engine-en való futtatást is támogatja. A gyakorlati megoldás sem olyan bonyolult. Töltsük le a legújabb resin verziót, és a resin.jar-t másoljuk a WEB-INF/lib könyvtárba. A web.xml-t bővítsük ki a következő bejegyzéssel:

  <servlet>
    <servlet-name>Quercus Servlet</servlet-name>
    <servlet-class>com.caucho.quercus.servlet.GoogleQuercusServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>Quercus Servlet</servlet-name>
    <url-pattern>*.php</url-pattern>
  </servlet-mapping>

Így a .php állományokat a Quercus automatikusan a QuercusServlet-nek továbbítja. Magukat a PHP állományokat a root könyvtárba helyezzük. Ezt követően az appengine-web.xml-hez adjuk hozzá a következő sorokat:

<static-files>
<exclude path="/**.php"/>
</static-files>
<resource-files>
<include path="/**.php"/>
</resource-files>

E nélkül a rendszer a php állományokat statikus fájloknak tekintené, és nem adná át a szervlet motornak. Körülbelül ennyi. Innentől kezdve már PHP-t is futtathatunk a Google App Engine-en. Ezzel a technikával elvileg sikeresen futtattak már Drupal-t, WordPress-t, és néhány hasonló PHP keretrendszert. Persze azért a PHP alkalmazások szállítása nem olyan egyszerű, hiszen ezek többnyire MySQL-t használnak, AppEngine-en viszont ugye nincs relációs adatbázis. Tehát valamilyen szintű módosításra mindenképp szükség van, de ez talán megéri mindazokért az előnyökért cserébe, amit az AppEngine, és eleve maga a Quercus adhat (pl. egyszerű PHP-Java integráció, Java libek használata, stb.).

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

jin-plugin

október 20th, 2010 Nincsenek hozzászólások

Egy projektem kapcsán próbáltam valamilyen általános megoldást keresni beépülő modulok (plugin-ek) kezelésére. Ugye a lényeg röviden annyi, hogy a kész alkalmazáshoz bárki könnyen írhasson kiegészíthetőket, amiket egyszerű módon lehet telepíteni. Rövid keresgélés után rá is találtam az OSGi-re, ami tulajdonképpen minderre a szabványos megoldás. Ezt használja például az Eclipse is. Át is néztem a doksit, de úgy találtam, hogy az én igényeimhez képest ez amolyan ágyúval verébre megoldás. Valami olyan egyszerű megoldást kerestem, amit a leendő plugin fejlesztők néhány perc alatt el tudnak sajátítani. Olyat, amilyet például a PHP CMS-ek is használnak (pl. WordPress, Joomla), ahol a plugin csak néhány függvényből áll. Találtam is egy annotation alapú jspf nevű keretrendszert, ami már nagyon megközelítette azt amire én gondoltam, de ekkor már úgy voltam vele, hogy csak és kizárólag a minimalista megoldás érdekel. Ahogyan a jin-template esetén, itt is arra gondoltam, hogy ha már készítek egy egyszerű megoldást, rögtön elkészítem a PHP implementációt is, amit később más programnyelvekre történő adaptáció követhet, így kvázi megteremtve a “minimális plugin architektúra szabványát”. Ezt valószínűleg már sokan sokféle módon megtették előttem is, de sehol nem láttam publikálva ilyen jellegű különálló programkönyvtárat. Ennek valószínűleg az az oka, hogy a fejlesztők értelmetlennek találták leválasztani a plugin rendszert a kész alkalmazásról (éppen annak egyszerűsége miatt). Erre tipikus példa a PHP CMS-ekben használt plugin rendszer, ahol bár a megoldások nagyon hasonlóak, mégis minden rendszernek saját megoldása van. Így fogant meg hát a jin-plugin rendszer gondolata.

A rendszer felépítése a célnak megfelelően nagyon egyszerű. A plugin manager végignézi a paraméterként megadott könyvtárat, ahol minden pluginhez külön könyvtár tartozik. Minden könyvtárban egy yaml fájl található, ami definiálja a plugin osztályt, valamint az esetleges függőségeket. A plugin manager a függőségeket betartva tölti be a plugineket, és hívja meg a plugin osztály init metódusát. Maga a plugin kód a plugin könyvtárában található. PHP esetén a kódok helye közvetlenül a könyvtár, Java esetén pedig a classes könyvtár. Ez utóbbi esetben lehetőségünk van a program számára szükséges programkönyvtárak csomagolására is, amik a lib könyvtárban kapnak helyet. A pluginnek lehetősége van névvel ellátott szolgáltatások installálására, amiket más pluginek felhasználhatnak. Tulajdonképpen ez minden. Ennyi az a feltétlenül szükséges minimális működés, amire szükségem volt. A plugin installálása egyszerűen a plugin könyvtárba történő könyvtármásolással történik, a pluginek készítésének elsajátítása pedig a rendszer egyszerűségének köszönhetően néhány perc. Ez utóbbi szerintem bíztatólag hat a fejlesztőkre, ami igen fontos, ha azt szeretnénk, hogy minél több kiterjesztés szülessen az alkalmazásunkhoz. Már csak abban kell reménykednem, hogy a megoldásom elterjed, és így talán másokat is sikerül egy kicsit hozzásegítenem sikeres kiterjeszthető alkalmazások fejlesztéséhez.

A rendszer rövid dokumentációja, és a teljes forráskód LGPL licenc alatt megtalálható a Google Code-on:
http://code.google.com/p/jin-plugin/

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

jin-template

október 12th, 2010 Nincsenek hozzászólások

Már több webes projekt van a hátam mögött, de igazából még nem sikerült olyan template rendszert találnom, ami maradéktalanul kielégítené az igényeimet. Az egyik legnagyobb problémát az szokta jelenteni, hogy a HTML designt öcsém készíti el rendszerint Dreamweaver-el, és a későbbi karbantartás miatt meg is kell őriznünk a HTML tisztaságát. A legtöbb template rendszer speciális tag-eket, vagy más extra blokkokat használ, ami rendszerint teljesen tönkreteszi a HTML forrást. Az ilyen tag-ekkel teletűzdelt HTML már nem úgy jelenik meg a böngészőben vagy a szerkesztőben, ahogyan az eredmény, így a vizuális szerkesztés a standard HTML-es eszközökkel (pl. az általunk is használta Dreamwaver) nagyon nehézkes. A problémát általában úgy hidaltam át, hogy a template motornak szóló parancsokat HTML kommentekben helyeztem el, és egy előfeldolgozó után eresztettem rá a template motort. Ez a megoldás egész hatékonynak bizonyult, de még így sem voltam maradéktalanul elégedett. Az a gond ezekkel a template motorokkal, hogy szűkös a tudásuk. Ez a szűkös tudás persze az esetek nagy részében elegendő is, de ha esetleg olyan igényünk van, amit a template rendszer alapból nem támogat, sokszor igen nehézkes kiterjeszteni azt. Smarty plugineket kell gyártanunk, saját taglib-eket, stb. De miért kell ennek ilyen macerásnak lennie? Valójában arról van szó, hogy a template rendszer egy primitív programozási nyelvet definiál, és ezt kell kiterjesztenünk. Innen jött az ötlet, hogy a template rendszer speciális nyelve helyett használjuk a jól megszokott programozási nyelvet, és ezzel tulajdonképpen bontsuk ketté a template-et egy tiszta HTML forrásra, és egy felület generáló kódra (view building logic). Ez volt a jin-template alapötlete.

A rendszer maga nagyon egyszerű, néhány osztályból áll az egész.  A forrás HTML-ben kommentekkel jelölhetünk ki blokkokat, majd a kódból ezen blokkok tartalmát használhatjuk fel, és cserélhetjük ki. Ez alapján tehát egy fórum motor bejegyzéseinek listája úgy áll elő, hogy definiálunk egy bejegyzés konténert, és egy bejegyzés elemet. Ezt követően kódból előszedjük a bejegyzés elemet, feltöltjük a megfelelő adatokkal, majd a bejegyzéseket behelyezzük a bejegyzés konténerbe. Ezzel a módszerrel a HTML forrásokat megtarthatjuk eredeti formájukban (csak néhány komment hozzáadása szükséges), a tartalom generálásához pedig felhasználhatjuk az implemetáló programozási nyelv teljes eszközkészletét.

Az elkészült rendszert feltöltöttem a Google Code-ra, ahol a működést egy egyszerű példán szemléltettem is:
http://code.google.com/p/jin-template/

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags:

Programfejlesztés Android-ra

szeptember 22nd, 2010 1 hozzászólás

Néhány hónapja beszereztem egy Samsung Galaxy Spica-t, azzal a határozott szándékkal, hogy végre megtanulok Android-ot programozni. A jelenlegi tendenciákat figyelve az Android valószínűleg hamarosan a legelterjedtebb mobil platformmá válhat, és az sem elhanyagolandó tény, hogy Java nyelven fejleszthetünk rá, ami (legalábbis szerintem) sokkal barátságosabb, mint a C++ (Symbian), vagy az Objective-C (iPhone). Úgy tervezem, hogy több bejegyzést is írok majd a témában. Ebben a mostaniban azt írom le, hogyan állíthatjuk be a fejlesztőkörnyezetet, és kezdhetjük meg a fejlesztést.

Ha Android fejlesztésre adjuk a fejünket, legjobb választás az Eclipse fejlesztőrendszer használata. Elvileg létezik NetBeans plugin is, de mivel én eddig is Eclipse-et használtam fejlesztésre (még a PHP projektekhez is), ezért soha nem próbáltam. Szóval maradjunk az Eclipse-nél. Én a 3.5-ös Galileo-t telepítettem (a cikk írásakor ez volt a legfrissebb Android plugin által támogatott változat). Az Eclipse telepítése után telepítsük az ADT plugint. Ha ez megvan, még szükségünk van az Android SDK-ra, amit innen tölthetünk le. Ha fent van az SDK, futtassuk az SDK Manager.exe-t (Windows esetén), amivel letölthetjük és telepíthetjük a legfrissebb fejlesztői csomagokat. Ha a fejlesztéshez emulátort használunk, akkor a Virtual Devices fül alatt adjunk hozzá egy virtuális eszközt. Ha ezzel megvagyunk, lépjünk vissza eclipse-be, és Window/Preferences fül alatt keressük ki az Android részt, és állítsuk be az SDK location-t. Ha mindez megvan, rendszerünk készen áll a fejlesztésre.

A Package Explorer-ben adjunk hozzá gy Android projektet, állítsuk be az alkalmazás nevét, a package-t és a célrendszert, és kész is az első Android projektünk. A default Android projekt egy önmagában is futtatható Hello World alkalmazás, így nincs más dolgunk, mint elindítani azt a Debug As Android Application opcióval. Ha nincs csatlakoztatva telefon, a rendszer automatikusan az emulátort indítja el. Ha rögtön telefonon szeretnénk tesztelni (én így szoktam), akkor kapcsoljuk be a telefonon a fejlesztői módot. Nálam ez a Beállítások/Alkalmazások/Fejlesztés alatt kapcsolható be az USB-hibakeresés opcióval. Ha bekapcsoltuk, az adatkábellel kössük össze a telefont a PC-vel. Ilyenkor a PC vagy felismeri a telefont (nálam már valahonnan fent volt egy Samsung ADT driver, ami valószínűleg a gyári szoftverrel települt). Ha nincs fent driver, próbálkozhatunk az SDK-ban lévő usb driverrel, ami az usb_driver könyvtárban található. Ha sikerült csatlakoztatni a telefont, újra indítsuk el az alkalmazást a Debug opcióval, és ha minden jól megy, most már az a telefonon fog elindulni. Ez a módszer szerintem sokkal jobb, mint az emulátor használata, hiszen élő környezetben tesztelhetjük a programot, mégis ugyanúgy tudunk debugolni, mint emulátor esetén. Ráadásul a natív környezetnek köszönhetően sokkal gyorsabban is fut az alkalmazás. Egy dolog van még, amit érdemes megtenni. Az Eclipse Window / Show view menüpontjában található a LogCat view, ahová a programból logolhatunk, és ahová a rendszer a hibaüzeneteket küldi. Ha valami nem megy, érdemes egy pillantást vetni ide.

Ha további infóra lenne szükség a környezet telepítését illetően, az SDK honlapja-án mindent meg lehet találni.

Sok szerencsét minden leendő Android fejlesztőnek!

Digg This
Reddit This
Stumble Now!
Buzz This
Vote on DZone
Share on Facebook
Bookmark this on Delicious
Kick It on DotNetKicks.com
Shout it
Share on LinkedIn
Bookmark this on Technorati
Post on Twitter
Google Buzz (aka. Google Reader)
Categories: Tech Tags: