SDJ_11_2008_PL_E-Commerce

84

Transcript of SDJ_11_2008_PL_E-Commerce

Page 1: SDJ_11_2008_PL_E-Commerce
Page 2: SDJ_11_2008_PL_E-Commerce
Page 3: SDJ_11_2008_PL_E-Commerce
Page 4: SDJ_11_2008_PL_E-Commerce

4 11/2008 www.sdjournal.org 5

Le périodique hakin9 est publié par Software-Wydawnictwo Sp. z o.o.Bokserska, 02-682 Varsovie, PologneTél. +48 22 887 10 10, Fax. +48 22 887 10 11www.phpsolmag.org

Directeur de la publication : Jarosław Szumski

Imprimerie, photogravure : 101 Studio, Firma Tęgi Ekonomiczna 30/36, 93-426 ŁódźImprimé en Pologne/Printed in Poland

Abonnement (France métropolitaine, DOM/TOM) : 1 an (soit 6 numéros) 38 €

Dépôt légal : à parutionISSN : 1731-7037Distribution : MLP Parc d’activités de Chesnes, 55 bd de la Noirée BP 59 F - 38291 SAINT-QUENTIN-FALLAVIER CEDEX(c) 2005 Software-Wydawnictwo, tous les droits réservés

Miesięcznik Software Developer’s Journal (12 numerów w roku)jest wydawany przez Software-Wydawnictwo Sp. z o.o.

Dyrektor wydawniczy: Sylwia Małecka

Junior Market Manager: Anna Adamczyk

Senior Product Manager: Katarzyna Juszczyńska

Redaktor naczelny: Iwona Chwedoruk [email protected]

Kierownik produkcji: Marta Kurpiewska [email protected]

Projekt okładki: Agnieszka Marchocka

Skład i łamanie: Monika Grotkowska [email protected]

Wyróżnieni betatesterzy: Ł. Lechert, S. Nieszwiec, R. Zacharczyk

Nakład: 6 000 egz.

Adres korespondencyjny:Software-Wydawnictwo Sp. z o.o., ul. Bokserska 1, 02-682 Warszawa, Polskatel. +48 22 427 36 86, fax +48 22 427 36 69www.phpsolmag.org [email protected]

Dział reklamy: [email protected]: Marzena Dmowska [email protected], tel. +48 22 427 36 79; +48 22 427 36 53

Dołączoną do magazynu płytę CD przetestowano programem AntiVirenKit firmy G DATA Software Sp. z o.o.

Redakcja dokłada wszelkich starań, by publikowane w piśmie i na towarzyszących mu nośnikach informacje i programy były poprawne, jednakże nie bierze odpowiedzialności za efekty wykorzystania ich; nie gwarantuje także poprawnego działania programów shareware, freeware i public domain.

Uszkodzone podczas wysyłki płyty wymienia redakcja.

SPIS TREŚCIPROGRAMOWANIE PHP

32 Opensource-owe platformy blogoweLech AlbrzykowskiLech opisuje jak w przeciągu ostatnich lat blogi internetowe zjedna-ły sobie wielką popularność wśród użytkowników internetu. Przestały być tylko i wyłącznie formą pamiętników a stały się miejscem wymia-ny zdań pomiędzy różnymi środowiskami jak choćby programistów.

TESTOWANIE OPROGRAMOWANIA36 SAP GUI Scripting APIRoman GryzowskiRoman opisuje że SAP GUI Scripting API to interfejs pozwalają-cy na emulowanie każdej czynności jaką może wykonać użytkow-nik w środowisku SAP GUI. Dzięki jego użyciu można zautomatyzo-wać czynności powtarzalne, ale również uzyskać dostęp do SAP GUI z poziomu innych aplikacji, np. Windows Scripting Host.

40 IBM Rational Data Architect – pierwsze krokiSzymon GruszewskiWyobraźmy sobie sytuację, w której musimy stworzyć oprogra-mowanie dla biblioteki. Chcąc wywiązać się z zadania musimy zaprojektować system, który będzie spełniał wymagania stawia-ne przez naszego zleceniodawcę. Z pomocą przychodzi nam Ra-tional Data Architect, który jest narzędziem służącym do two-rzenia zarówno prostych, jak i bardzo złożonych modeli bazo-danowych.

44 Bezpieczne partycjonowanie – systemy wielordzeniowe QNX Kerry Johnson, Romain SahaAutorzy opisują że w dzisiejszych czasach praktycznie każdy wbu-dowany system podłączony jest fizycznie lub bezprzewodowo to świata zewnętrznego. Taka łączność sieciowa pozwala użytkow-

06 AKTUALNOŚCIRafał Kocisz

12 OPIS CD

BIBLIOTEKA MIESIĄCA14 Jericho HTMLDavid de RosierDavid opisuje Jericho jako prostą, lekką i darmową bibliotekę uży-teczną dla wszystkich programistów Java przetwarzających bądź generujących kod HTML. Jericho dostarcza klasy umożliwiające ana-lizę i przekształcanie istniejących dokumentów HTML bądź też ge-nerowanie nowych. Wszystko z użyciem minimalnego nakładu pra-cy ze strony programisty.

ECOMMERCE20 Sklep internetowy w PHP i SQLiteGrzegorz HibnerZdaniem Grzegorza gotowych rozwiązań na rynku e-commerce są setki. Znajdziemy gotowe skrypty o funkcjonalności systemów au-kcyjnych, sklepów internetowych oraz systemów barterowych. To najczęściej sprawdzone i tanie rozwiązania, regularnie aktualizowane – dlatego skorzystanie z nich najczęściej bywa bardzo kuszące. Jednak czy zawsze uzasadnione? Najczęściej o wiele lepiej stworzyć własną platformę e-commerce. Nie jest to trudne – zajmie to 60 minut.

28 Wydajny, elastyczny i przyjazny CMSKrystian RajskiKrystian napisał że Textpattern nie jest tak popularny jak np. Joom-la. Nie posiada tak rozbudowanej listy plugin'ów i dodatków. Mniej znany, nie oznacza jednak gorszy czy też mniej wydajny. Stanowi ciekawą alternatywę i chociażby tylko ze względu na to warto po-szerzyć horyzonty i przyjrzeć się rozwiązaniu bliżej. Niniejszy artykuł pełni rolę wprowadzenia.

11/2008 (167)

Page 5: SDJ_11_2008_PL_E-Commerce

4 11/2008 www.sdjournal.org 5

Rédacteur en chef : Marek Bettman [email protected]édacteurs : Aneta Cejmańska [email protected] Dudzic [email protected]éparation du CD : Aurox Core TeamMaquette : Anna Osiecka [email protected] : Agnieszka MarchockaTraduction : Iwona Czarnota, Aneta Lasota, Marie-Laure Perrotey, Grazyna WełnaBêta-testeurs : Thomas Bores, Tony Boucheau, Pascal Foulon, Pascal Miquet, Romain Lévy, Augustin Pascual, Julien Poulalion, Alain Ribault

Les personnes intéressées par la coopération sont priées de nous contacter : [email protected]

Abonnement : [email protected] : Marta Kurpiewska [email protected] : Monika Godlewska [email protected]é : [email protected]

Si vous êtes intéressé par l’achat de licence de publication de revues merci de contacter : Monika Godlewska [email protected] , tél : +48 (22) 887 12 66 fax : +48 (22) 887 10 11

Wszystkie znaki firmowe zawarte w piśmie są własności odpowiednich firm.Zostały użyte wyłącznie w celach informacyjnych.

Redakcja używa systemu automatycznego składu

Osoby zainteresowane współpracą prosimy o kontakt:[email protected]

Druk: ArtDruk

Wysokość nakładu obejmuje również dodruki. Redakcja nie udziela pomocy technicznej w instalowaniu i użytkowaniu programów zamieszczonych na płycie CD-ROM dostarczonej razem z pismem.

Sprzedaż aktualnych lub archiwalnych numerów pisma po innej cenie niż wydrukowana na okładce – bez zgody wydawcy – jest działaniem na jego szkodę i skutkuje odpowiedzialnością sądową.

nikom na zdalne monitorowanie i sterowanie oraz umożliwia sys-temom pobieranie nowych programów i treści wtedy, kiedy jest to konieczne.

48 Joomla 1.5 – nowościStefan WajdaNowe wydanie Joomla! zapewnia użytkownikom i projektantom wygodny i łatwy w użyciu szkielet publikacji treści w witrynach internetowych wszelkiego typu. Stworzenie doskonałej witryny ze wszystkimi funkcjami, jakie sobie wymarzysz, może wymagać czasu i zaangażowania. Ale ze społecznością Joomla!, wsparciem projektantów oraz dzięki licznym rozszerzeniom tworzonym dla Joomla! 1.5, jest to jak najbardziej możliwe. Możesz również two-rzyć własne rozszerzenia i udostępniać je ku uciesze całej spo-łeczności.

XML52 Spring 2 Schema – własne przestrzenie nazw w Spring 2.x Henryk KonsekOsoby intensywnie wykorzystujące Springa w swoich aplika-cjach często narzekają na ogrom konfiguracji XML koniecznej do utworzenia aplikacji o większym stopniu zaawansowania. Autorzy Spring Framework pisząc o dobrym oprogramowaniu promują za-sadę DRY (Don't Repeat Yourself ) – wyraźnie widać to w mecha-nizmie rozszerzania konfiguracji XML kontenera Springa. Ten arty-kuł wprowadzi Cię szybko w podstawowe techniki tworzenia wła-snych przestrzeni nazw XML Schema dla plików konfiguracyjnych Spring IOC.

KASA DLA WEBMASTERA58 LinkLift – koniec z reklamą kontekstowąKrzysztof TrynkiewiczW internecie królują systemy reklamy kontekstowej. W oparciu o treść witryny, wyświetlane są odpowiednie reklamy z takich serwi-sów jak Google AdSense, czy AdKontekst Wirtualnej Polski. Zarob-

ki z takich reklam są jednak stosunkowo niewielkie, stąd istnieje zapotrzebowanie na inne formy reklamy. Gwarantowany zarobek oferuje nowy wchodzący do Polski LinkLift.

NARZĘDZIA PROGRAMISTYCZNE60 Plugin – wielokrotne wykorzystanie sprawdzonych narzędziPiotr PlenikTworzenie aplikacji, składa się zarówno z tych bardziej twórczych, jak i bardziej odtwórczych prac. Mimo wszelkich naszych starań tworzenia wedle zasady DRY (z ang. DRY – Don't Repeat Your-self ), zdarza się, że dla tej samej funkcjonalności powielamy i do-stosowujemy ten sam kod na wielu różnych elementach aplika-cji lub pomiędzy różnymi aplikacjami. Na początek zaprezentuje-my najczęściej wykorzystywane pluginy w Symfony, których jest w chwili obecnej ponad 200. Następnie stworzymy prosty doda-tek do wysyłania maila w symfony bez dodatkowego nakładu na-szej pracy.

PROGRAMOWANIE URZĄDZEŃ MOBILNYCH64 Programowanie gier dla Symbian OS – budujemy grę!Rafał KociszW poprzednim, pierwszym odcinku z serii „Programowanie gier dla Symbian OS” Mieliśmy okazję przebrnąć przez gąszcz stosunkowo zawiłych i miejscami mało interesujących szczegółów dotyczących programowania aplikacji pod Symbiana. W rezultacie powstał pro-sty szkielet gry pod wspomniany system. W niniejszej części cyklu zajmiemy się tematem znacznie ciekawszym – odejdziemy (chwilo-wo) od niskopoziomowych zagadnień systemowych i zrobimy to co Tygrysy lubią najbardziej – zbudujemy grę!

WYWIAD76 Wywiad z Bartoszem Stebnickim – dyrektorem generalnym firmy EMC

Page 6: SDJ_11_2008_PL_E-Commerce

11/2008

Aktualności

6 www.sdjournal.org

Aktualności

7

Windows 7 Beta 1 jeszcze w tym roku?Wygląda na to, że Microsoft dojrzał już, by publicznie i konkretnie mówić o przy-szłej wersji systemu Windows oznaczo-nej kodowo cyfrą 7. Sesje techniczne poświęcone następcy Visty są już zapla-nowane na listopadowej Windows Har-dware Engineering Conference. Nie oznacza to oczywiście, że już wtedy testowe kompilacje będą rozdawane uczestnikom. Niemniej z najnowszych, oczywiście nieoficjalnych informacji wynika, że wersja Beta 1 nowych Okie-nek może zostać wydana szerszej grupie testerów jeszcze w tym roku, a konkret-nie w połowie grudnia. Niewielka grupa wybrańców już bierze udział w pracach nad Windows 7 – dotychczas Microsoft wydał dwie wersje Milestone 1 i Milesto-ne 2 tego systemu, a przygotowania do wydania Milestone 3 właśnie mają się ku końcowi. Wydanie pierwszej Bety 1 już w grudniu sugerowałoby znaczne przy-spieszenie prac i mogłoby rodzić ocze-kiwania co do wydania finalnej wersji produktu jeszcze w 2009 roku. Pytanie zasadnicze brzmi więc – kiedy Micro-soft zdecyduje się na szerszy program beta, a nawet na publiczną betę? Więk-szość obserwatorów uważa, że całkowite otwarcie programu beta nastąpi dopie-ro w momencie, gdy system będzie kom-pletny funkcjonalnie – choć pojawiają się coraz poważniejsze głosy, że Windows 7 będzie wydany publicznie jeszcze wcze-śniej, niż w przypadku Visty (w której przypadku była to faza Beta 2).http://www.techit.pl/

Ile znaczy Google News?Mały błąd Google spowodował, że wła-ściciele linii United Airlines stracili 1,14 miliarda dolarów. W 2002 roku linia lotni-cza United Airlines była bliska bankructwa. Informację o tym zamieściły różne serwisy, w tym także Google News. Google jednak nie ustawiło daty newsa co spowodowało, że pojawił się ponownie – w połowie wrze-śnia 2008 roku. Został on szybko podchwy-cony przez inne serwisy informacyjne, łącz-nie z Bloombergiem. Jak się łatwo domyślić, spowodowało to gwałtowny spadek ceny akcji linii z 12 na 3 dolary, a ich posiadacze stracili łącznie ponad miliard. Na szczęście szybko zauważono pomyłkę i cena akcji znów wzrosła, osiągając poziom ok. 10 dolarów. Jak się później okazało, informa-cja pojawiła się na Google News ponieważ robot Google dostrzegł jej popularność na stronach gazety South Florida Sun-Senti-nel. Przypadek ten pokazuje jak duże jest obecnie uzależnienie globalnego rynku od serwisów firmy Google. Jeszcze niedaw-no ciekawostką były procesy wytaczane w sytuacjach, gdy na skutek zmian w algo-rytmie wyszukiwarki Google czyjaś strona nagle spadała na dalsze miejsca w rankin-gach. Aktualnie, wraz ze wzrostem znacze-nia Google, takich incydentów może poja-wiać się coraz więcej.http://online.wsj.com/

Google Chrome

Google zaprezentowało nową, zbudowa-ną w oparciu o otwarte oprogramowa-nie, przeglądarkę mającą ułatwić użyt-

kownikom na całym świecie korzystanie z Interne-tu. Dostępny w wersji beta w 43 językach, Google Chrome odzwierciedla nowe podejście do przeglą-darek, oparte na prostych i skutecznych rozwiąza-niach, do których przyzwyczajeni są użytkownicy produktów korporacji. Google projektując Chro-me położyło szczególny nacisk na jej lekkość, prze-kładającą na niskie wykorzystanie zasobów sys-temowych. Wykorzystuje ona silnik renderowa-nia stron webKit – framework używany w Safari i iPhone, wraz z autorskimi rozwiązaniami z Mon-tain View, dostarczającymi gamę innowacyjnych rozwiązań. Jednym z nich jest funkcja dynamicz-nych kart, pozwalająca na tworzenie nowych kart poprzez przeciągnięcie jej poza aktywny obszar przeglądarki. Dodatkowo, dzięki Kontroli awarii, każda z nich jest uruchamiana oddzielnie, co spra-wia, iż wskutek zawieszenia się jednej, nie wpłynie to na funkcjonowanie pozostałych. Prócz tego, tryb incognito oferuje możliwość niezapisywania od-wiedzanych witryn w historii. W Chrome znala-zły się także mechanizmy zabezpieczające takie jak Bezpieczne przeglądanie – ostrzegający przed wej-ściem na witryny podejrzewane o phishing czy roz-powszechniającymi złośliwe oprogramowanie, z dwoma aktualizowanymi okresowo blacklistsami. W programie nie zabrakło również opcji impor-tu ustawień, menadżera pobierania plików i pro-cesów. Dostępna jest też możliwość instalacji wty-czek, poszerzających możliwości aplikacji, wspar-cie dla technologii Gears, a rosnące wykorzysta-nie zasobów może być rozkładane na wiele rdzeni procesora. Najnowszą testową wersję Google Chro-me dla systemów Windows można pobrać bezpo-średnio ze strony twórców (http://www.google.com/chrome/index.html). W chwili obecnej, trwają pra-ce na wersjami przeglądarki dla systemów Linuks

i Mac OS X. Co ciekawe, już po trzech dniach od wydania aktualizacji dla przeglądarki Chrome, jej twórcy opisali na łamach oficjalnego blogu aplika-cji zmiany jakie wprowadzono w aplikacji za jej po-średnictwem. Aktualizacja niweluje dwie, poważ-ne luki w zabezpieczeniach, oraz trzy mniej groź-ne. Instalacja aktualizacji odbywa się automatycz-nie u wszystkich użytkowników przeglądarki i nie daje żadnych nowych funkcjonalności. Kolejna cie-kawostka dotycząca przeglądarki rodem z Moun-tain View wiąże się z jej licencją i rzekomo niepo-kojących zapisach znajdujących się w jej treści. Li-cencja Chrome mówi, że Google ma nieograniczo-ne czasowo, ogólnoświatowe, nieodwołalne pra-wo do reprodukcji, adaptacji, modyfikowania, pu-blikowania i tłumaczenia każdej treści, którą użyt-kownik wysyła lub wyświetla za pomocą przeglą-darki. Brzmi to groźne, jednak w rzeczywistości nie jest to nic nowego. Google stosuje podobne wa-runki także przy innych swoich usługach. Stosowa-ne jest to w celu uproszczenia obowiązujących za-sad i może nie zawsze pasować do wszystkich pro-duktów Google. W odpowiedzi na kontrower-sje Google zapowiedziało jednak zmiany w licen-cji Chrome. W przeszłości internetowy gigant po-stąpił tak z licencją Google Docs. Należy przy oka-zji zauważyć, że Chrome jest otwarte i kod wysyła-jący do Google dane użytkownika zostałby szybko zauważony. Ponadto kod Chrome jest objęty licen-cją BSD, która narzuca bardzo małe ograniczenia na programistów chcących modyfikować kod prze-glądarki, np. w celu usunięcia niechcianych funk-cji. Należy się jednak spodziewać, że mało kto zre-zygnuje z funkcjonalności paska adresowo-wyszu-kiwawczego i nadal wszystkie wpisywane tam sło-wa, także adresy odwiedzanych przez internautów stron, będą trafiały do Google wraz z adresami IP użytkowników.http://www.google.com/chrome/index.htmlhttp://dobreprogramy.pl/

Page 7: SDJ_11_2008_PL_E-Commerce

11/2008

Aktualności

6 www.sdjournal.org

Aktualności

7

Luka w DNS poważniejsza niż przewidywanoOd jakiegoś czasu wiele się słyszy o luce w systemie nazw Domian Name Sever (DNS). Wydawać by się mogło, że luka ta została usunięta. Niestety, eksperci są zgodni co do tego, że sprawa jest nadal daleka od pomyślnego zakończenia. Na trop wspo-mnianej usterki wpadła na początku bie-żącego roku firma IOActive, a konkretnie Dan Kaminsky, prowadząc w ten sposób do największego łatania w historii Inter-netu. Wspomniana luka pozwala ataku-jącemu wykorzystać specjalny typ żądań w celu doprowadzenia do przejęcia sesji TCP/IP, a wskutek tego – przekierowania sporej ilości osób na odpowiednio sprepa-rowane witryny. Działanie opracowanych poprawek, bez względu na platformę sys-temową, polega na dodaniu mechanizmu losowania portów co zmniejsza ryzyko wykorzystania luki. Jak pokazują bada-nia po takim zabiegu liczba serwerów podatnych na ataki z ponad 85%, zmalała do około 30. Jednak zdaniem Kamińskie-go i innych ekspertów z branży, opisane wyżej zabiegi nie eliminują w całości luki, a jednie utrudniają napastnikowi przepro-wadzenie pomyślnego ataku. Przewidu-je się więc kolejną porcję poprawek do wprowadzenia w najbliższym czasie. Nie-stety, ze względu na liczne problemy tech-niczne szansa ich równoczesnego wdroże-nia przez administratorów wszystkich śro-dowisk serwerów DNS jest znacznie mniej-sza niż w przypadku poprzednich popra-wek.http://www.techit.pl/

Google skraca czas przechowywania adresów IP w logachPod presją Unii Europejskiej Google poin-formował, że skraca czas, przez jaki w logach serwerów webowych przechowy-wane są informacje o adresach IP pozwa-lające zidentyfikować użytkowników korzystających z wyszukiwarki i pozo-stałych usług firmy. Dotychczas dane te były przechowywane przez 18 miesięcy, po czym adresy IP były z nich usuwane. Teraz czas ten został skrócony o połowę – do 9 miesięcy. Trudno powiedzieć, czy Komisja Europejska będzie zadowolona z takiego kroku – w oficjalnym oświad-czeniu wydanym w kwietniu apelowała do Google, by dane w logach serwerów były neutralizowane już po sześciu mie-siącach. Google broniło się twierdząc, że korzysta z tych danych do opracowywa-nia nowych usług i polepszania jakości już istniejących – oczywiście przy jedno-czesnej odpowiedniej ochronie prywatno-ści użytkowników, których adresy IP wid-nieją w logach. Teraz firma w tonie ubole-wania zapewnia, że choć ma do dyspozy-cji o połowę mniej logów, to jest na dobrej drodze do opracowania nowych metod analizowania przechowywanych danych – bardziej polegających na informacjach innych niż adresy IP. http://www.google.com/

Apache nie daje za wygraną

W przeciągu ostatnich miesięcy da-ło się zaobserwować dynamiczny wzrost udziału usług Internet In-

formation Services w rynku serwerów interne-towych przy jednocześnie słabnącej popularno-ści konkurencyjnego serwera Apache. Z badań firmy Netcraft wynikało wówczas, że IIS wbudo-wany w systemy z rodziny Windows Server konse-kwentnie umacnia swoją pozycję, a oglądając da-ne za październik można było dojść do wniosku, że jeszcze nigdy dotąd obu rozwiązań nie dzieli-ła tak niewielka różnica. Co ciekawe, we wrześniu bieżącego roku nastąpiła zdecydowana zamiana w dynamice tych statystyk. Z wykonanego przez Netcraft sierpniowego badania wynika, że w Sie-ci pojawiło się ponad 1,3 miliona nowych witryn z czego 1,2 mln wykorzystuje serwer Apache zaś pół miliona hostowana jest na rozwiązaniu ofero-wanym przez Google. Z sieci jednocześnie znik-nęło 760 tysięcy witryn obsługiwanych przez IIS. Udział serwera Microsoft w rynku odnotował spadek o 1,74 punktu procentowego (strata bli-sko dwóch milionów witryn), zaś udział Apache wzrósł o 0,33 punktu procentowego. W badaniu łącznie sprawdzono ponad 176 748 506 stron. Po uwzględnieniu tych danych w ogólnej klasyfikacji nadal prowadzi Apache z 46.84% udziałem i 33 milionami witryn. Tuż za nim jest Microsoft IIS wykorzystywany na 34,83% serwerów WWW (24,5 mln stron). Trzecie miejsce zajmuje zmo-

dyfikowana przez Google wersja Apache (Google Front End) z wynikiem ok. 8 miliona witryn, co daje prawie 11-procentowy udział. Na dalszych miejscach plasują się lighttpd, Sun, Zeus, oraz dynamicznie pnący się w górę nginx. Równocze-śnie, jak wynika z najnowszego raportu firmy ana-litycznej IDC, wzrasta także sprzedaż serwerów z Linuksem. W porównaniu z rokiem ubiegłym, kiedy zainteresowanie nimi kształtowało się na poziomie 9,4%, odnotowano wzrost o całe czte-ry punkty procentowe, wskutek czego dzisiaj licz-ba ta wynosi już 13,4%. Sprzedaż maszyn z Unik-sem stanowiła 7,7%, z kolei sprzedaż serwerów z Windows –36,5%. W sumie, w drugim kwarta-le, dochód z pierwszych z nich wyniósł 4,6 miliar-dów dolarów, co jest tylko o pół miliarda dolarów mniej, w porównaniu z maszynami wyposażony-mi w Windows Server. Niezmiennie liderem w ich sprzedaży pozostaje IBM, na drugim miejscu uplasował się HP, trzecie miejsce cały czas zajmu-je Dell, który przewodzi w sprzedaży maszyn 32-bitowych (x86). Analizując dane z przedstawio-nych badań można dojść do wniosku, że, zarówno Apache, jak i IIS idą niemalże łeb w łeb. Pierwszy z nich kroczy niemalże cały czas w granicach 50% udziałów w rynku, drugi natomiast sukcesywnie nadrabia straty. Zanosi się na to, iż taka równowa-ga będzie trwała jeszcze długo, a wojowniczy Apa-che niełatwo da się pokonać.http://netcraft.com/

Apple prezentuje iTunes 8 oraz nowe iPody

Konferencję Let's Rock rozpoczęły ade-kwatne do nazwy, rockowe brzmienia Rolling Stones oraz Jimmiego Hen-

drixa. Muzyka była tematem przewodnim wy-darzenia. Steve Jobs rozpoczął prezentację od iTunes. iTunes Store, według rankingów naj-większy dystrybutor multimediów na świecie, teraz wzbogaci się o filmy HD. Również odcin-ki seriali będzie można ściągnąć w SD lub HD i obejrzeć na komputerze za pomocą nowego iTunes lub na AppleTV. Poza tym, tak jak nio-sły plotki, iTunes posiada teraz możliwość two-rzenia zestawu piosenek o podobnym nastroju (funkcja znana z serwisu Pandora). Ale to nie wszystko. Nowym elementem programu jest Genius Sidebar. Za pomocą tego paska nie tyl-ko stworzymy nastrojową playlistę z własnej ko-lekcji, ale też dowiemy się jakie utwory z iTu-nes Store mogą się spodobać. Propozycje do-bierane są na podstawie statystyk zbieranych przez program oraz ocen użytkownika i wysyła-nych, oczywiście anonimowo, do serwisu. Sam

odtwarzacz iTunes przeszedł prawdziwą meta-morfozę, jeśli chodzi o wygląd. Jobs zaprezen-tował zupełnie nowy sposób przeglądania mu-zyki i filmów. Wizualnie przeglądarka przypo-mina iPhoto i pozwala przeglądać albumy, ar-tystów, kompozytorów, gatunki etc. Co więcej, ten sam mechanizm pozwala przeglądać filmy, na przykład sezony seriali. A wszystko to moż-na kontrolować głosem (voice-over)! Skoro mo-wa o muzyce, nie można pominąć odtwarzacza iPod. Tutaj również Apple przygotowało nie la-da nowość w postaci całej tęczy (czarny, fiole-towy, niebieski, zielony, żółty, pomarańczowy, czerwony, różowy) Nano. Najnowsza wersja jest najcieńsza z wyprodukowanych do tej pory a jednocześnie najbardziej przyjazna środowi-sku. Towarzyszą mu nowe modele słuchawek i większa pojemność (8 i 16GB). iPod Touch również jest teraz cieńszy, ale przede wszyst-kim jego oprogramowanie również zostało wzbogacone o zestaw usług Genius.http://www.apple.com/

Page 8: SDJ_11_2008_PL_E-Commerce

11/2008

Aktualności

8 www.sdjournal.org

Aktualności

9

Microsoft przegrał z Komisją Europejską jednym głosemOkazuje się, że zawarcie ugody z Komi-sją Europejską tuż po kolejnym nieko-rzystnym wyroku z 17 września ubiegłe-go roku mogło być ogromnym błędem Microsoftu. Koncern z Redmond nie wie-dział bowiem wtedy, że przegrał całą sprawę zaledwie... jednym głosem. Gło-sowanie w unijnym sądzie było oczywi-ście tajne, ale teraz na jaw wyszła infor-macja, że Microsoft przegrał stosun-kiem głosów 7 do 6. Źródłem przecieku było dwóch proszących o anonimowość urzędników z bezpośrednią wiedzą na temat procesu. Analitycy są zgodni, że w takiej sytuacji zawarcie ugody nie musia-ło być najlepszą decyzją prawników Microsoftu. Sędziowie unijni byli dalecy od jednomyślności i jak widać, mieli cał-kiem sporo wątpliwości. W kolejnej ape-lacji mogłoby więc okazać się, że Micro-soft wygrałby. Taka wygrana pozwoliła-by uniknąć płacenia rekordowej w histo-rii firmy i w całej historii Unii Europej-skiej kary finansowej, razem z odsetkami i kosztami procesowymi grubo przekra-czającej miliard euro, a przede wszystkim miałaby zupełnie inny wpływ na prze-mysł IT. W tej sytuacji przedstawiciele Microsoftu mogą czuć się mocno rozgo-ryczeni. Według źródeł wewnątrz firmy, prawnicy korporacji dowiedzieli się o stosunku głosów dopiero w maju bieżą-cego roku.http://seattletimes.nwsource.com/

Ubiquity – wykonaj to co napiszęFundacja Mozilla poinformowała o wyda-niu pierwszej wersji nowego rozszerze-nia dla Firefoksa – Ubiquity 0.1. Jest to dosyć nietypowy dodatek, pozwalający na zastąpienie najpopularniejszych czyn-ności wykonywanych podczas korzysta-nia z Internetu słownymi poleceniami. Rozszerzenie Ubiquity pozwala użytkow-nikowi na integrację funkcji wielu aplika-cji sieciowych.

Przykładowo chcąc zaprosić znajo-mych do restauracji wystarczy użyć kilka prostych komend, które np. przekieru-ją użytkownika do usługi Google Maps, bądź zaprezentują mu recenzje danego lokalu z serwisu Yelp. Następnie pozo-staje tylko skopiowanie kodu i wkleje-nie go do wiadomości mailowej, która wyląduje w elektronicznych skrzynkach pocztowych uczestników imprezy. Doda-tek oferuje użytkownikom wiele przydat-nych komend i poleceń, które usprawnią ich pracę w Internecie. Wśród nich zna-leźć można m.in. defi – wywołujący defi-nicję, trans – tłumaczący wskazany tekst, czy np. twit – kopiujący materiał do ser-wisu Twitter. Ponadto każdy zaintereso-wany może w prosty sposób zdefinio-wać własne polecenia. Dodatek Ubiqu-ity pobrać można z oficjalnej strony pro-jektu.http://www.mozilla.org/

OpenGL 3.0 – początek końca?

Grupa Khronos udostępniła ostatecz-ną wersję specyfikacji OpenGL 3.0, będącej otwartym, wieloplatformo-

wym API pozwalającym na sprzętową obsłu-gę grafiki 3D. Firmom rozwijającym opro-gramowanie CAD nowa wersja biblioteki z pewnością się spodoba, stanowi bowiem roz-winięcie wydania 2.1, aczkolwiek wielu de-weloperów otwarcie wyraża frustrację. Ich zdaniem biblioteki są mocno zacofane pod względem możliwości, zwłaszcza w kontek-ście wykorzystania ich jako platformy do roz-woju gier. OpenGL 3.0 pojawił się z ponad rocznym opóźnieniem, półtora roku po pre-mierze DirectX 10, a ciągle jeszcze nie ob-sługuje wszystkich funkcji, jakie dawno te-mu zostały zaimplementowane przez Micro-soft. Jak powszechnie wiadomo OpenGL jest zestawem standardów umożliwiających de-weloperom tworzenie aplikacji graficznych dla Windows, Mac OS oraz Linuksa. Według szacunków, ilość sprzętu zainstalowanego w komputerach i posiadającego wsparcie dla OpenGL 3.0 przekracza 60 milionów. Fir-my takie jak Intel, Advanced Micro Devices czy NVidia znacząco przyczyniły się do roz-woju specyfikacji i dziś wszystkie trzy przy-znają, że w ich intencji leży wprowadzenie obsługi standardu we wszystkich możliwych produktach. Jednak od zapewnień do reali-zacji droga daleka. Ani chipsety Intela, ani ATI (AMD) nie błyszczą, gdy wziąć pod uwa-gę wydajność aplikacji OpenGL w porówna-niu do szybkości przetwarzania w wypadku DirectX. Kiedy opublikowano specyfikację OpenGL 3.0, na forum Khronos Group pod-niósł się lament. Wielu deweloperów uzna-ło, że zapomniano o obietnicach, które rok i dwa lata temu dano programistom. Co cieka-we, a jednocześnie niepokojące, do pełnej ob-sługi OpenGL 3.0 konieczne jest stosowanie kart kompatybilnych z DirectX 10, ale jed-nocześnie sam OpenGL 3.0 nie implemen-tuje wszystkich funkcji dostępnych w DX10. Wśród opinii deweloperów nie brakuje rady-kalnych stwierdzeń – niektórzy z miejsca de-klarują „przesiadkę” na standard Microsoftu. Pojawiły się również opinie, że opublikowa-na właśnie specyfikacja jest zacofana aż o sie-dem lat względem DirectX – a przepaść ma rosnąć z każdą chwilą. Co gorsza, mniej wię-cej w tym samym czasie Gigant z Redmond zapowiedział przypadającą na koniec bieżące-go roku premierę DirectX 11. Nehe, popular-ny serwis poświęcony programowaniu aplika-cji na bazie Open jako największe grzechy no-

wej odsłony OpenGL wymienia następujące kwestie – brak obiecanego obiektowego mo-delu API, zachowanie wstecznej kompaty-bilności (czynniki mocno hamujący rozwój), utrudnienie procesu tworzenia sterowników. W tym samy miejscu podkreślone jest jednak iż nowo wprowadzony kontekst GL3 stanowi rozwiązanie przyszłościowe i otwiera szerokie możliwości dla kolejnych odsłon standardu. Pocieszający może być również fakt, iż wraz z premierą Larrabee i innych GPU ogólnego za-stosowania (GPGPU) wojna na liczbę obsłu-giwanych funkcji przez DirectX i OpenGL powinna stać się przeszłością. Deweloperzy gier nie będą musieli już czekać, aż firma X udostępni chipset implementujący funkcję Y, a następnie wypatrywać API, za pomocą którego ją obsłużą. Zamiast tego sami będą mogli zaprogramować chip do własnych po-trzeb korzystając z klasycznych narzędzi i ję-zyków wykorzystywanych na platformie x86. Co by nie mówić, nowy standard wprowadza pewne nowości. Wśród nowinek wprowadzo-nych w OpenGL 3.0 znalazło się kilka rozsze-rzeń potencjalnie mogących zwiększyć moż-liwości następnej wersji bibliotek. Oprócz te-go API pozwala na obsługę GLSL 1.30, no-wej wersję języka cieniowania oraz posiada wszechstronne wsparcie dla funkcji ofero-wanych przez akceleratory graficzne ostat-niej generacji. Ponadto w bibliotekach poja-wiła się implementacja Vertex Array Objects, funkcja kompaktowania danych pikseli i wer-teksów w celu oszczędzania pamięci i pasma, wsparcie dla 32-bitowego bufora głębi, czte-ry nowe schematy kompresji tekstur, nieblo-kowalny dostęp do obiektów bufora wertek-sów oraz funkcja renderowania warunkowe-go zwiększającego wydajność. Jak potoczą się dalsze losy standardu OpenGL? Trudno prze-widzieć. Teraz kolej na ruch Microsoftu. Jed-no jest niestety pewne – niesmak i niedosyt związane z ogłoszeniem trzeciej odsłony po-zostaną na długo w głowach użytkowników tej – jak by nie patrzeć – istotnej we współ-czesnym świecie informatycznym bibliotece.http://www.idg.pl/http://nehe.gamedev.net/

Page 9: SDJ_11_2008_PL_E-Commerce

11/2008

Aktualności

8 www.sdjournal.org

Aktualności

9

Red Hat kupił KVMaW czerwcu bieżącego roku pojawiły się informacje o pracach Red Hata nad wbu-dowanym linuksowym hypervisorem, który ma być uzupełnieniem, a nie kon-kurencją dla istniejącego już rozwiąza-nia Xen. Fundament nowego hypervi-sora miał stanowić projekt Kernel-based Virtual Machine. Tymczasem korpora-cja oficjalnie poinformowała o kupnie, za kwotę 107 milionów USD jego produ-centa – firmy Qumranet. Zdaniem Paula Cormiera, jednego z prezesów Red Hata, fuzja obu przedsiębiorstw ma wpro-wadzić niespotykane dotąd możliwo-ści wirtualizacyjne w produktach spółki. Ich połączenie może się bowiem przy-czynić do eliminacji kilku problemów. Przede wszystkim, stworzenia własnego silnika wirtualizacyjnego, czego korpo-racja wcześniej nie była w stanie zrobić z Xenem, ze względu na XenSource, który niedawno wykupiony został przez Citriksa. Uzyska za to gotową platformę, cechującą się przede wszystkim elastycz-nością pozwalającą na jej wdrożenie na różnego rodzaju serwerach, kompute-rach stacjonarnych, urządzeniach wbu-dowanych oraz jakichkolwiek innych pracujących pod kontrolą Linuksa. Może to również pomóc w umocnieniu pozy-cji na rynku wirtualizacyjnym, a także lepszej konkurencji z Novellem, kryty-kowanym za współpracę z Microsoftem. Jednym z ciekawszych rozwiązań opra-cowanych przez Qumranet jest oprogra-mowanie o nazwie Virtual Desktop Inter-face (VDI) – połączenie brokera z nową wersję protokołu Remote Desktop. Inną, wartą uwagi technologią jest SolidICE. Pozwala ona – przy wykorzystaniu tech-niki wirtualizacji pulpitów – na urucho-mienie dowolnej liczby maszyn wirtu-alnych, zarówno z Windows, jak i Linuk-sem pod kontrolą KVM, pracującego na centralnym serwerze. Red Hat już teraz zapowiedział wdrożenie w swojej sztan-darowej dystrybucji – Red Hat Enterpri-se Linux – KVM w zastępstwie do tej pory wykorzystywanego Xena oraz otwarcie źródeł SPICE (Simple Protocol for Indepen-dent Computing Enviromentns), z kolei opracowywany przez Red Hata hypervi-sor ma ujrzeć światło dzienne na począt-ku przyszłego roku.http://www.techit.pl/

Java Lightweight UI Toolkit otwartySun otworzył Java Lightweight UI Toolkit, zestaw narzędzi do tworzenia mobilnych aplikacji w języku Java. LWUIT został udo-stępniony na licencji GPLv2 with Classpath Exception jako projekt-inkubator hostowa-ny w ramach serwisu java.net. Bazując na Java Mobile Edition oferuje wiele kompo-nentów graficznych, tematów, czcionek, animacji i efektów przejść, obsługę ekra-nów dotykowych oraz obsługę formatu SVG przy wykorzystaniu Java Specification Request (JSR) 226.http://www.theregister.com/

20 lat Internetu w Polsce

17 sierpnia bieżącego roku Polski In-ternet obchodził 20 urodzimy. Rów-no 20 lat temu, 17 sierpnia 1988 ro-

ku, Polska po raz pierwszy połączyła się z Kopenhagą, za pośrednictwem łącza inter-netowego o prędkości 9600 bitów na sekun-dę (bps). Trzy lata później, dr Rafał Pietrak z Uniwersytetu Warszawskiego nawiązał łącz-ność w oparciu o protokół TCP/IP z pracow-nikiem Uniwersytetu w Kopenhadze, wysy-łając elektroniczną wiadomość pocztową. Wraz ze wzrostem popularności Internetu w Polsce, medium to nabrało zupełnie nowe-go znaczenia. O ile kiedyś Internet był obec-ny na uczelniach technicznych, a jego zna-jomość rozpoczynało się od nauki Uniksa, obecnie, z pojawieniem się pierwszych wer-sji Windows oraz spadkiem cen utrzymania łącz, niemal każdy może mieć go w zasięgu ręki. Dzisiaj Internet jest powszechnie wy-korzystywany głównie do przeglądania wi-tryn WWW, korzystania z Usenetu, czyli po-wstałych w 1979 roku grup dyskusyjnych, czy prowadzenia różnego rodzaju rozmów, realizowanych za pośrednictwem komuni-katorów, czy IRC-a. Dużą popularnością cie-szą się też serwisy umożliwiające udostęp-nianie zdjęć czy filmów wideo. Przy takiej okrągłej rocznicy warto zadać sobie pytanie jaka będzie przyszłość globalnej sieci. W cią-gu najbliższych lat, nasz kraj czeka między innymi przejście na protokół IPv6, oferują-

cy dużo większą liczbę możliwych adresów (teoretycznie nawet 2 do potęgi 128), któ-re nawet przy niezbyt oszczędnym rozdzie-laniu nie powinny się wyczerpać, pozwalając na bezpośrednie podłączenie do sieci prak-tycznie każdego urządzenia. IPv6 wprowa-dza również wiele ulepszeń w zakresie bez-pieczeństwa. Proces migracji na ten protokół wspomaga od niedawna Unia Europejska, a na początku lutego br. ICANN, organizacja zajmująca się między innymi zarządzaniem domenami najwyższego poziomu uaktualni-ła sześć z trzynastu głównych serwerów DNS o adresy IPv6. Przyszłość Internetu to rów-nież nowe techniki tworzenia witryn inter-netowych oraz takie standardy jak Web 2 i 3.0, czy HTML5.http://gazeta.pl/

TinEye – nowa wyszukiwarka plików graficznych

Powstała nowa, ciekawa wyszukiwarka pli-ków graficznych, TinEye. W przeciwień-stwie do tradycyjnych wyszukiwarek, nie

odnajduje ona plików graficznych na podstawie słów, które im towarzyszą na stronach interneto-wych. Nie oczekuje nawet na wpisanie słów klu-czowych. Zamiast tego użytkownik wysyła plik graficzny ze swojego komputera lub podaje adres URL. TinEye wyszukuje wskazany plik w Interne-cie, nawet jeśli jest on w innym formacie, ma inne rozmiary a nawet jeśli obraz został przetworzony z użyciem różnych efektów lub też został włączo-ny do innego zdjęcia/grafiki. Pozwalają na to dosyć zaawansowane algorytmy, które tworzą sygnaturę danego obrazu analizując zawarte w nim kształty i kolory. TinEye jest wyszukiwarką wyjątkową nie tylko dlatego, że nie opiera się w ogóle na tekście, ale przede wszystkim dlatego, że służy do wyszu-kiwania plików, które użytkownicy już posiada-ją. Ma więc inne zastosowania niż zwykła wyszu-

kiwarka. Pozwala ona np. śledzić autorom zdjęć i grafik co się dzieje z ich twórczością, np. czy ich praca nie jest wykorzystywana w sposób nielegal-ny. Może też pomóc w przypadku posiadania pli-ków o których nie wiadomo co przedstawiają lub kto jest ich autorem. Dzięki TinyEye odnaleźć można bowiem strony, które zawierają informa-cje o danym pliku. Wyszukiwarka jest obecnie w fazie beta i ma zaindeksowanych przeszło 700 mi-lionów plików graficznych. Korzystanie z niej wy-maga logowania.http://tineye.com/

Page 10: SDJ_11_2008_PL_E-Commerce

11/2008

Aktualności

10 www.sdjournal.org

Aktualności

11

Milion dolarów za włamanieJak informuje serwis Hacking.pl, firma Per-manent Privacy złożyła hakerom publicz-ną ofertę – jeśli uda im się złamać stwo-rzone przez nich zabezpieczenia, będą mogli odejść z milionem dolarów. Platfor-ma Permanent Privacy bazuje na szyfrowa-niu AES, dodaje natomiast dodatkową war-stwę zabezpieczającą, która, jak twierdzą jej projektanci, jest nie do zdobycia. Ogól-nie rzecz biorąc, pomysł wziął się z zaszyfro-wania fragmentu bezsensownego tekstu. Autorzy zabezpieczenia są tak pewni siły zabezpieczenia, że postanowili wypłacić milion dolarów każdej osobie, która zdoła się włamać do systemu. Peter White, dyrek-tor zarządzający firmy Permanent Priva-cy zapewnia, że użytkownicy mogą teraz wysyłać listy elektroniczne i przechowy-wać dane ze 100-procentową pewnością, iż pozostaną one zabezpieczone. Nawet Pen-tagon nie może odczytać waszych sekre-tów, jeśli nie ma kluczy – dodaje. Być może niedługo ktoś będzie bogatszy o milion...http://hacking.pl/

Keyczar – usługi kryptograficzne od GoogleWłaściwe zastosowanie rozwiązań krypto-graficznych nie jest łatwym zadaniem i nie każdy webmaster potrafi z nim sobie pora-dzić. Ich niewłaściwa implementacja może przyczynić się do występowania poważ-nych luk w bezpieczeństwie. Wielu progra-mistów korzysta też często z przestarzałych algorytmów i pomija istotne aspekty bez-pieczeństwa zapominając choćby o rota-cji kluczy. Wychodząc naprzeciw tym pro-blemom, Google udostępnił nowe narzę-dzie kryptograficzne. Keyczar, bo tak wła-śnie brzmi jego nazwa, jest zestawem narzędzi kryptograficznych, zapewniają-cych wsparcie zarówno dla szyfrowania, jak i uwierzytelniania dla algorytmów syme-trycznych lub kluczy publicznych. Aplika-cja udostępnia proste API i potrafi wska-zywać domyślnie najniebezpieczniejsze miejsca, tagować dane wyjściowe z infor-macjami o wersjach kluczy, a także oferu-je możliwość rotacji kluczy z prostym sys-temem wersjonowania. Prócz tego w pro-gramie znajdziemy opcje związane z auto-matycznym generowaniem wektorów ini-cjalizacyjnych oraz podpisami zaszyfro-wanymi (ang. ciphertextowymi). Korzysta-nie z narzędzia wiąże się z koniecznością zaszyfrowania parametru URL przy użyciu klucza symetrycznego. Dotychczas, dewe-loper musiał zadecydować o wyborze algo-rytmu, długości klucza, trybu działania, jak również sposobu obsługi wektorów inicja-lizacyjnych, rotacji kluczy, czy też cipher-tekstu. Keyczar upraszcza całą sytuację, dzięki czemu interakcja ze strony progra-misty wiąże się z wprowadzeniem zaled-wie dwóch linijek kodu, używając Pythona, Javy, oraz – już niebawem – C++. Keyczar funkcjonuje w ramach usługi Google Code i jest dostępny do pobrania pod adresem http://www.keyczar.org/.http://www.techit.pl/

Układ scalony ma już 50 lat!

Cały przemysł komputery nie byłby tym, czym jest obecnie, gdyby nie technologia, która powstała równo

pół wieku temu. Układy scalone, opracowa-ne przez dwóch naukowców, są dziś obecne w każdym sprzęcie elektronicznym i trudno wy-obrazić sobie życie bez nich. Dwaj inżyniero-wie, którzy zaprezentowali pierwsze na świe-cie układy scalone to Jack Kilby (pracujący wówczas w Texas Instruments) i Robert Noy-ce (zatrudniony w Fairchild Semiconductor, późniejszy współzałożyciel firmy Intel). Noy-ce i Kilby pracowali oddzielnie, ale niemal jed-nocześnie zaprezentowali bardzo podobne do siebie rozwiązania. Z tym, iż Noyce oparł swój wynalazek na krzemie, a Kilby na germanie. Pierwszy mikrochip ujrzał światło dzienne do-kładnie 12 września 1958 r. Ten dziwnie wy-glądający (jak na dzisiejsze czasy) układ scalo-ny miał wielkość 11,1 na 1,58 mm i jego kon-struktorem był Kilby. Obecnie przemysł wy-twarzający układy scalone może się pochwa-lić obrotami rzędu 300 mld USD rocznie. Po-pularne scalaki pełnią w produktach elektro-nicznych rolę mózgu oraz układu nerwowe-go. Są to produkty zawierające miliony tran-zystorów, wytwarzane przy użyciu technolo-gii kilkudziesięciu nanometrów, co oznacza iż poszczególne elementy czy ścieżki są na ta-kim układzie oddalone od siebie np. o 60 nm. A warto pamiętać, że nanometr to jedna mi-liardowa część metra (ludzki włos ma śred-nicę 10 tys. nanometrów). Czterdzieści lat temu superkomputer mający wydajność za-ledwie 1000 dzisiejszych pecetów zajmował kilka dużych pokoi i kosztował bajońskie su-my – ponad 10 mln USD. Wszystko zmieni-ło się właśnie za sprawą układów scalonych. W latach pięćdziesiątych komputery składa-ły się z dziesiątków tysięcy pojedynczych tran-zystorów, diod i rezystorów. To też była swo-ista rewolucja, ponieważ wcześniej stosowa-no lampy. Kilby i Noyce doszli więc do wnio-sku, że tranzystory, rezystory i kondensato-ry można przecież zintegrować ze sobą w ra-mach jednego kawałka np. krzemu czy innego materiału. Jak rewolucyjny to był wynalazek niech świadczy fakt, że Kilby zdobył w 2000 r. nagrodę Nobla w dziedzinie fizyki właśnie za wynalezienie układu scalonego. Noyce ma w tej dziedzinie też duże zasługi, opracowu-jąc układ scalony oparty na krzemie, który to materiał jest stosowany do dzisiaj. Firma Fair-child (w której pracował Noyce) produkowa-ła w latach pięćdziesiątych tranzystory opar-te na krzemie. Stąd pomysł stosowania krze-mu do budowania układów scalonych, a nie germanie, jak to zrobił Kilby. Co ciekawe, do

dyskusji o układach scalonych włączył się wte-dy Moore (wszyscy chyba znamy sformułowa-ne przez niego prawo), twierdząc, że układ opracowany przez Noyce'a (oparty na krze-mie) jest bardziej praktyczny i będzie łatwiej-szy do produkowania niż układ oparty na ger-manie, co okazało się prawdą. Kilby złożył ja-ko pierwszy wniosek o opatentowanie swoje-go wynalazku, jednak pierwszy patent został przyznany rozwiązaniu opracowanemu przez Noyce'a. Następnie po powtórnym rozpatrze-niu całej kwestii związanej z datami sprawę wygrał Kilby, jednak po wieloletnich przepy-chankach sądowych ostatecznie patent po-wrócił do Noyce'a. Na początku nie wszyscy byli przekonani, że układ scalony to dobry po-mysł. Wielu znawców przedmiotu argumen-towało, że proces produkcji układu scalonego jest tak skomplikowany, że będzie to niemoż-liwe albo bardzo drogie i nieopłacalne przed-sięwzięcie. Po latach widać, jak bardzo się my-lili. Tak czy inaczej obie firmy dogadały się w sprawie patentów i po jakimś czasie zaczę-ły produkować układy scalone. Uważa się, że produkcję pierwszego komercyjnego układu scalonego podjęła firma Fairchild. Firma TI uruchomiła natomiast w 1964 roku produk-cję swoich pierwszych kalkulatorów opartych na układach scalonych. Przemysł zbrojeniowy Stanów Zjednoczonych wykorzystał bardzo szybko układy scalone, wprowadzając je do swoich produktów, takich jak np. rakiety ba-listyczne Minuteman. Z kolei NASA stosowa-ła szeroko scalaki podczas realizacji misji czło-wieka na Księżyc (program Apollo). Patrząc w przeszłość i oceniając rolę układów scalo-nych w rozwoju elektroniki, Kilby wypowie-dział znamienne słowa podczas odbierania w 2000 r. nagrody Nobla – To tak jakby bóbr i królik przyglądali się potężnej zaporze przedzie-lającej rzekę i ten pierwszy powiedział do królika – ja jej nie zbudowałem, ale cały pomysł to chyba wzięli ode mnie. Wynalazcy układów scalonych już nie żyją. Noyce zmarł na atak serca w 1990 r. mając 63 lata, a Jack Kilby zmarł na raka w 2005 r. w Dallas (w wieku 81 lat).http://www.itpartner.pl

Page 11: SDJ_11_2008_PL_E-Commerce

11/2008

Aktualności

10 www.sdjournal.org

Aktualności

11

Picasa rozpoznaje twarzeGoogle dodało funkcję rozpoznawania twarzy do swojego serwisu Picasa Web Albums. Dzięki niej użytkownik dostaje zestaw zdjęć, które według algorytmu rozpoznającego przedsta-wiają tą samą osobę i może je łatwo otagować, np. imieniem. Dzięki tagom można przeglądać na bieżąco tworzone albumy zawierające zdję-cia danej osoby. Odnajdywanie twarzy na 3 tysiącach zdjęć zajmuje ok. 20 minut.

Jak można się było spodziewać, nowa funk-cja nie zawsze działa poprawnie. Czasami nie wykryje twarzy na zdjęciu, czasem za twarz uzna coś, co nią nie jest. Wykrywanie działa najlepiej, gdy twarz fotografowanej osoby była skierowana w stronę fotografujące-go oraz nie występują na niej cienie. Ogól-nie jednak mechanizm ten spisuje się bardzo dobrze. Technologię rozpoznawania twarzy Google pozyskało kupując firmę Neven Vision. Serwis Picasa Web Albums wzboga-cił się też o funkcję Explore, która pozwala na przeglądanie wszystkich publicznych zdjęć. Nawigować można na podstawie daty, miej-sca i popularnych tagów. Przy okazji Google planuje także wydanie Bety trzeciej wersji aplikacji Picasa. Pojawią się w niej takie funk-cje jak tworzenie filmów ze zdjęć i muzyki, usuwanie przebarwień skóry oraz efektu czer-wonych oczu, ulepszona funkcja kolażu, prze-glądarka plików graficznych oraz synchroni-zacja z serwisem Picasa Web.http://www.cnet.com/

Microsoft poszerza współpracę z NovellemFirmy Microsoft i Novell poinformowały o poszerzeniu współpracy na rzecz budowa-nia mostów pomiędzy otwartym i zamknię-tym oprogramowaniem. Koncentruje się ona między innymi na umocnieniu oferowa-nego wsparcia technicznego oraz szkoleń, ale przede wszystkim na zwiększeniu inte-roperacyjności pomiędzy systemami z rodzi-ny Microsoft Windows Server i SUSE Linux Enterprise Server. Microsoft zobowiązał się do zakupu certyfikatów o wartości stu milio-nów dolarów, mogących zostać wykorzy-stanych przez klientów korzystających ze wsparcia technicznego produktów Novella. W ramach nawiązanej pierwotnie na pięć lat, w listopadzie 2006 roku, współpracy, gigant z Redmond nabył wówczas certyfikaty warte 240 mln USD. W ciągu kolejnych 18 miesię-cy ponad połowa z nich została wykorzysta-na. Wśród klientów, którzy skorzystali z oferty korporacji znalazły się takie koncerny jak Wal-Mar Stores, Renault, czy BMW. Zdaniem Kevina Turnera z Microsoftu, celem posze-rzonej współpracy jest podołanie wymaga-niem klientów, którzy chcą mieć możliwość uruchamiania równocześnie zarówno Win-dows, jak i Linuksa, a także pomoc w migracji do SUSE Linux Enterprise Server z innych roz-wiązań. Inwestycja ma wejść w życie z dniem 1 listopada 2008. Korporacje już teraz wyrazi-ły chęć kontynuacji innych inicjatyw, w takich dziedzinach jak wirtualizacja, systemy zarzą-dzania, zgodności formatów dokumentów oraz technologia Moonlight.http://www.techit.pl/

Tim Berners-Lee ogłasza powstanie Fundacji WWW

W wywiadzie dla BBC News, Tim Berners-Lee, twórca sieci WWW, poinformował o powsta-

niu Fundacji WWW, której jednym z głów-nych założeń jest opracowanie mechanizmu umożliwiającego oddzielenie miejsc w Inter-necie, gdzie znaleźć można rzetelne informa-cje od tych zawierających plotki. Berners-Lee w trakcie rozmowy z dziennikarzami mówił o zmianach, jakie wprowadzić należy w Sieci, by stała się ona bardziej przyjazna i dostępna dla Internautów. Pośród wszystkich poruszo-nych przez niego aspektów najistotniejszym wydaje się zastosowanie podziału stron i ser-wisów internetowych w taki sposób, by pro-mować tylko te, które zawierają wiarygodne informacje.

Przykładem niepotrzebnej histerii, jaką wy-wołać mogą plotki rozpowszechnione w In-ternecie jest według niego historia Wielkie-go Zderzacza Hadronów. Powołana przez Ber-nersa-Lee do życia Fundacja WWW opraco-wać ma złożony mechanizm oznaczania rze-telnych dostawców informacji w Sieci, umoż-liwiając tym samym wielu organizacjom nada-wanie serwisom różnych etykiet, które świad-czyłyby o wiarygodności treści. Inną kwestią, nad jaką pracować będzie Fundacja WWW jest ułatwienie dostępu do Internetu miesz-kańcom najbiedniejszych rejonów na świecie.

Z czasem Sieć stać się ma bardziej przyja-zna dla wszelakiego rodzaju urządzeń mo-

bilnych, a z racji tego, że większość osób za-mieszkałych wspomniane tereny to analfa-beci, Berners-Lee mówił także o dostarcza-niu treści w sposób niewymagający umiejęt-ności czytania. Ponadto ważnym elementem działalności Fundacji WWW ma być także zapewnianie neutralności każdemu użyt-kownikowi Internetu, tak by mógł swobod-nie wyrażać swoje zdanie i dokonywać wy-borów.http://www.bbc.co.uk/

Najlepsze aplikacje dla Androida wybrane

Firma Google ogłosiła zwycięzców pierw-szego etapu konkursu Android Develo-per Challange, którego głównym zało-

żeniem było napisanie jak najlepszej aplikacji przeznaczonej na platformę Android. Jako naj-ciekawsze aplikacje stworzone przez uczestni-ków konkursu wymienić należy m.in. cab4me, GoCart, czy też TuneWiki. Pierwsza z nich to przydatne rozszerzenie dla telefonów komór-kowych za którego pomocą w łatwy sposób znaleźć można najbliższą taksówkę, nie zna-jąc nawet dokładnej lokalizacji, w której się znajdujemy. Kolejna aplikacja, GoCart, znacz-nie ułatwia zakupy. Rejestrując za pośrednic-twem wbudowanej kamery kod kreskowy da-nego produktu, aplikacja informuje użytkow-nika, gdzie wybrany towar można kupić najta-niej. TuneWiki pozwala na odtwarzanie plików

multimedialnych w oparciu o Social Network, udostępniając tym samym publicznie informa-cje o odtwarzanych aktualnie plikach. Dzięki temu możliwe jest podglądnięcie czego słucha-ją inni użytkownicy Androida w lokalizacji, w której aktualnie się znajdujemy. Ogółem nagro-dzonych zostało 50 zespołów, których projek-ty uznane zostały za najlepsze. Pierwsza dzie-siątka otrzymała po 270 tys. USD, twórcy ko-lejnych 10 aplikacji zostali nagrodzeni sumą 100 tys. USD, z kolei wszyscy pozostali otrzy-mali po 25 tys. USD. Więcej informacji na te-mat wszystkich nagrodzonych w konkursie aplikacji znaleźć można na stronie ADC Galle-ry. Warto dodać, iż wszystkie one dostępne bę-dą do pobrania za darmo w serwisie Android Marketplace.http://osnews.pl/

Page 12: SDJ_11_2008_PL_E-Commerce

11/200812

Opis CD

Acrobat 9 Pro na CDNa dołączonej do tego magazynu płycie znajdziecie ewaluacyj-ną wersję programu Acrobat 9 Pro w angielskiej wersji języko-wej. Dodatkowo, aby ułatwić Wam pracę na tym narzędziu za-mieściliśy na CD wideotutoriale pokazujące jak korzystać z no-wych funkcji i do jakich zastosowań może być przydatna ta aplikacja.

Opis nowości w Acrobat 9W najnowszej, dziewiątej już wersji oprogramowania, po raz pierwszy wprowadzono bezpośrednią obsługę technologii Ado-be Flash, dzięki czemu użytkownicy mogą umieszczać w pliku PDF materiał wideo zgodny z tym popularnym standardem. Od-biorca dokumentu do obejrzenia jego zawartości potrzebuje jedy-nie bezpłatnego oprogramowania Adobe Reader 9.

Acrobat 9 umożliwia także łączenie różnorodnej zawartości w jeden dokument, tzw. pakiet PDF (Portfolio). Pakiety PDF pozwalają na łączenie kilku różnych typów plików multime-dialnych — takich jak dokumenty, materiały filmowe i dźwię-kowe, a nawet obiekty trójwymiarowe — w jeden skompreso-wany plik PDF. Użytkownicy mogą zastosować różne układy stron (lub utworzyć własne), aby zintegrować zawartość, okre-ślić sposób nawigacji oraz całość oprawić w odpowiednią sza-tę graficzną.

W rezultacie takie dokumenty jak oferty handlowe, doku-menty prawne czy materiały informacyjne do produktu, sta-ją się bardziej urozmaicone i dostosowane do specyficznych potrzeb.

Dodatkowo Acrobat 9 umożliwia wspólną pracę w czasie rzeczywistym na dokumencie PDF. Wykorzystywany jest do tego Acrobat.com – nowy zestaw usług udostępnianych w ho-stingu, w chwili obecnej dostępny w postaci publicznej wersji beta. Dzięki niemu kilka osób może w tym samym czasie pra-cować na jednym dokumencie, konsultować zmiany i wprowa-dzać poprawki.

Co więcej, użytkownicy programu Acrobat 9 mogą za pośred-nictwem serwisu Acrobat.com zapisywać i udostępniać pliki, wy-korzystywać go jako centrum przechowywania danych w ramach przetwarzania formularzy, a także zbierać za jego pomocą komen-tarze do udostępnionych dokumentów. Acrobat.com oferuje także inne usługi, takie jak:

• Adobe ConnectNow – osobisty serwis do konferencji interne-towych, pozwalający na współużytkowanie pulpitu, konfe-rencje wideo i audio oraz czat;

• Adobe Buzzword – funkcjonalny, internetowy edytor tekstu, który może być wykorzystywany w celu współtworzenia i współużytkowania dokumentów na potrzeby komentowania i recenzji, zapewniający jednocześnie najwyższej jakości wy-druki.

Dwie wersje programu Acrobat 9 dostępne są też w języku pol-skim. Są to: Acrobat 9 Standard oraz Acrobat 9 Pro.

Ceny i dostępnośćAdobe Acrobat 9 Standard w polskiej bądź angielskiej wersji ję-zykowej kosztuje około 1172 złotych netto. Adobe Acrobat 9 Pro w polskiej bądź angielskiej wersji językowej kosztować bę-dzie około 1878 złotych netto.

Natomiast Acrobat 9 Pro Extended, dostępny jedynie w wersji anglojęzycznej, to wydatek rzędu 2751 złotych netto.

Page 13: SDJ_11_2008_PL_E-Commerce

11/200812

Redakcja nie udziela pomocy technicznej

w instalowaniu i użytkowaniu

programów zamieszczonych na płytach

CD-ROM dostarczonych razem z pismem.

Jeśli nie możesz odczytać zawartości

płyty CD, a nie jest ona uszkodzona

mechanicznie, sprawdź ją na co najmniej

dwóch napędach CD. W razie problemów

z płytą, prosimy pisać pod adres:

[email protected]

Page 14: SDJ_11_2008_PL_E-Commerce

11/200814

Biblioteka miesiącaJericho HTML

www.sdjournal.org 15

Jozue wyruszył na bitwę o Jerycho i mury mia-sta runęły [...] Nie ma to jak stary dobry Jo-zue i bitwa o Jerycho” – płyną słowa ponie-

kąd religijnej pieśni, która równie dobrze mogła-by być żołnierską przyśpiewką, mruczaną pod no-sem podczas ostrzenia mieczy. Pewnie wszyscy zna-my krwawą historię o Jerycho w której mury mia-sta zawaliły się od ryku trąb a potem ludzie Jozu-ego „wyrżnęli do nogi ostrzem miecza wszystko, co było w mieście, mężczyzn i kobiety, młodych i sta-rych, woły, owce i osły (Joz 6,21; BW).

Być może jednak nie wszyscy znamy małą, acz użyteczną bibliotekę Java a tej samej nazwie – Je-richo. Z góry nadmieniam, iż nie jest to oprogra-mowanie służące celom destrukcyjnym lub reli-gijnym krucjatom a zbieżność nazw jest tu taka sama jak w przypadku języka Java i wyspy o iden-tycznej nazwie. No, może nieco większa – twór-ca biblioteki nazywa się Martin Jericho.

Tak więc – wbrew groźnej nazwie – polecam tym razem Czytelnikom bibliotekę łatwą i przy-jemną, a przede wszystkim – nader przyjazną. Nie jest to może ogromny połeć oprogramowa-nia, za to jego przydatność – dość wszechstron-na dla wszystkich programistów aplikacji inter-netowych spod znaku Java. Czym dokładnie jest ta biblioteka? W pierwszej kolejności można by

powiedzieć, iż jest parserem HTML ale ja użyję tu określenia nieco szerszego – Jericho to biblio-teka narzędziowa pozwalająca na łatwe parsowa-nie a także – sformatowane generowanie kodu HTML. Jej wewnętrzne mechanizmy pozwala-ją na wygodną współpracę ze scriptletami innych języków, jak JSP, ASP, PHP. W praktyce narzę-dzie to przyda się programistom na trzech płasz-czyznach – przy analizie struktury kodu HTML, podczas konieczności odfiltrowywania fragmen-tów tekstu z kodu HTML oraz podczas automa-tycznego generowania stron HTML. Jak nieczy-telny lub rozdmuchany jest nierzadko kod automa-tycznie generowanych stron wie każdy programi-sta WWW. Z zarówno estetycznych jak i praktycz-nych powodów (choćby debugowanie), chciałoby się mieć nieco więcej porządku w takim kodzie, co właśnie umożliwia opisana tu biblioteka. Kwestia parsowania HTML może być dla niektórych Czy-telników zagadnieniem bardziej kontrowersyjnym – przecież HTML (zwłaszcza współczesny, opar-ty o XHTML) to podzbiór języka XML, dla które-go narzędzi, w tym parserów, nie brakuje. Czy nie jest to zatem tworzenie dodatkowych bytów? Otóż nie. Przynajmniej dla miłośników rozwiązań pro-stych i czytelnych. Jericho jest biblioteką dedyko-waną i dla swojej dziedziny, znacznie wygodniejszą w użyciu niż bardziej ogólny parser XML.

Pierwsza wersja biblioteki została opubliko-wana w lutym 2004 roku i od tamtego czasu re-gularnie się rozwija. Obecnie na stronie interne-towej projektu znaleźć można wersję 2.6 wyda-ną w czerwcu 2008 roku. W obecnym stadium

biblioteka jest stabilna i z powodzeniem mo-że być wykorzystywana w komercyjnych pro-jektach. Oprogramowanie jest rozpowszechnia-ne na zasadzie licencji EPL (Eclipse Public Licen-se) oraz LGPL (GNU Lesser General Public Licen-se), które pozwalają na jego pełne i nieodpłatne wykorzystywanie w dowolnego typu projektach. Autorzy rozważają wydanie w przyszłości odpo-wiednika biblioteki dla platformy .NET.

Struktura i możliwości bibliotekiJericho jest narzędziem łatwym do opanowania i lekkim. Programiści mogą bez obaw o utratę wy-dajności lub nadmiar zajmowano miejsca dołą-czać ją do swoich aplikacji. Skompilowana biblio-teka zajmuje łącznie około 160kB a na całość skła-da się zaledwie kilkadziesiąt klas. Ponadto do pra-widłowego działania biblioteka nie wymaga uży-cia żadnych niestandardowych klas zewnętrz-nych. Wszystkie klasy Jericho umieszczone są w pakiecie au.id.jericho.lib.html.

W sferze funkcjonalnej bibliotekę można po-dzielić na cztery podstawowe moduły:

• parser – narzędzie samo w sobie oraz baza dla pozostałych modułów – pozwala w ła-twy i intuicyjny sposób nawigować po drze-wiastej strukturze dokumentu HTML;

• renderer – narzędzie pozwalające na wy-odrębnianie elementów tekstowych z do-kumentu HTML, z pominięciem tagów i atrybutów języka. Można tutaj w łatwy spo-sób odnosić się do pojedynczych elementów strony – np. wartości pól formularzy lub wręcz całościowo skonwertować dokument HTML do czytelnej dla człowieka postaci – z zachowaniem definiowalnych przez pro-gramistę reguł formatowania tekstowego;

• formatter – komponent dający wsparcie dla formatowania dokumentu HTML; nie-zwykle użyteczne narzędzie dla wszyst-

Jericho HTML

Jericho to prosta, lekka i darmowa biblioteka użyteczna dla wszystkich programistów Java przetwarzających bądź generujących kod HTML. Jericho dostarcza klasy umożliwiające analizę i przekształcanie istniejących dokumentów HTML bądź też generowanie nowych. Wszystko z użyciem minimalnego nakładu pracy ze strony programisty.

Dowiesz się:• Jak w łatwy sposób, bez używania bezpośred-

nich operacji na łańcuchach znaków, modyfi-

kować, czytać i generować kod HTML z pozio-

mu aplikacji Java.

Powinieneś wiedzieć:• Jak programować w językach Java i HTML na

poziomie podstawowym.

Poziom trudności

Parser i biblioteka narzędziowa HTML

Page 15: SDJ_11_2008_PL_E-Commerce

11/200814

Biblioteka miesiącaJericho HTML

www.sdjournal.org 15

kich programistów generujących dyna-micznie strony WWW, którym zależy na czytelnym kodzie wynikowym;

• kompresor – jak wyżej, narzędzie przy-datne przede wszystkim jako wsparcie dla generowanego kodu HTML; pozwala zmniejszyć jego objętość poprzez usuwa-nie niepotrzebnych znaków (zwykle nad-miarowe białe znaki). Wbrew pozorom taka operacja potrafi czasem zredukować wielkość pliku wynikowego o kilkadzie-siąt procent.

Dużym atutem biblioteki jest umiejętność ra-dzenia sobie z dodatkowymi skryptami umiesz-czonymi wewnątrz kodu. Narzędzie potra-fi ignorować tagi specyficzne dla skryptów JSP, PHP, ASP, PSP i Mason. Ponadto istnieje możli-wość zarejestrowania dodatkowych tagów, które będą akceptowane przez parser biblioteki.

Parser oferowany przez Jericho prezentuje nieco odmienną filozofię niż klasyczne parsery XML i nie operuje bezpośrednio na drzewie ta-gów lub zdarzeniach przejścia przez kolejne ta-gi a przypomina bardziej mechanizm zaawanso-wanego wyszukiwania tekstowego. Dzięki temu plik HTML jest cały czas traktowany jako doku-ment tekstowy o specyficznym (dowolnym) układzie, a nie jako obiektowa struktura danych i atrybutów. Każdy element dokumentu iden-tyfikowany jest poprzez swoje położenie w nim (wiersz i kolumna początku i końca elementu). Taka forma reprezentacji dokumentu HTML nie pozwala na utratę jego tekstowej natury i po-zwala na dowolne a nie tylko globalne operowa-nie wyglądem dokumentu. Dzięki tekstowemu podejściu biblioteka pozwala na pracę z doku-mentami HTML zawierającymi błędy programi-stów (niezamknięte tagi, błędy w strukturze do-kumentu, etc.), co byłoby niemożliwe przy kla-sycznych parserach XML.

Pierwszy programCzas napisać pierwszy program z użyciem biblio-teki. Zaczniemy od niewielkiego przykładu, za to bardzo obrazowego. Zaprezentowany na Listin-gu 1 kod ukazuje filtr HTTP, który wycina nad-miarowe znaki z wyjścia serwletu (np. pliku JSP). W przypadku kodu JSP używającego dużej ilości scriptletów, zazwyczaj generowana jest bardzo duża ilość białych znaków, które w tym wypad-ku zostaną usunięte, zauważalnie redukując roz-miar odpowiedzi z serwera aplikacji. Przykład bę-dzie działał z dowolnym serwletem generującym na wyjściu kod HTML. JSP jest najprostszą formą jego zobrazowania.

Aby nasza aplikacja mogła poprawnie działać, trzeba jeszcze zadeklarować filtr w deskryptorze aplikacji. Zobrazowano to na Listingu 2. Jak wi-dać program bezpośrednio odwołuje się do serw-letów reprezentowanych przez pliki JSP. Uważny Czytelnik z pewnością spostrzegł, że program jest mocno uproszczony i nie rozpatruje sytuacji, kie-dy odpowiedź z serwera jest ciągiem binarnym a

nie tekstowym. Dobrze napisany filtr powinien rozpoznać taką sytuację i wyłączyć kompresję znaków. Pozostawiam to Czytelnikom jako zada-nie domowe.

Większość kodu z Listingu 1 poświęcona jest pobraniu odpowiedzi z serwletu w postaci tekstu. Sama redukcja jego wielkości danych sprowadza się zaledwie do dwóch kluczowych linii kodu:

Source source =

new Source(wrapper.toString());

SourceCompactor compactor =

new SourceCompactor(source);

Klasa Source reprezentuje źródło dokumentu HTML – może to być plik, URL lub strumień danych. Zawsze pracę z biblioteką rozpocznie-my od utworzenia instancji tej klasy. W wie-lu wypadkach będzie to też jedyny obiekt, któ-ry będzie nam potrzebny, gdyż klasa Source to jednocześnie parser HTML. Z użyciem jej me-tod możemy przykładowo łatwo przeszukać wskazany dokument. Opisane zostanie to sze-rzej w dalszej części artykułu.

SourceCompactor to narzędzie, które wyko-nuje za nas całą pracę. Jak widać musimy jedynie wskazać na źródło danych HTML oraz finalnie – wskazać na obiekt Writer, który obsłuży zapis danych wynikowych. W naszym wypadku zapi-szemy dane bezpośrednio do wyjścia z filtra:

compactor.writeTo(

new OutputStreamWriter(out));

SourceCompactor działa na zasadzie czarnej skrzynki, wykonując za nas całą pracę. Może-my tu jedynie wpłynąć na sposób generowa-nia nowych linii – metoda setNewLine (String newLine) przyjmuje jako parametr ciąg znaków reprezentujących nową linię. Jeśli wartość nie zostanie przez nas ustalona, biblioteka użyje identycznej reprezentacji nowych linii jak w da-nych wejściowych (patrz metoda getNewLine() w klasie Source). Ustawiając tę wartość na spa-cję, uzyskamy w wyniku niezbyt czytelny, zapi-sany w jednej długiej linii. W niektórych przy-padkach może to być użyteczne. Powrotu do wartości domyślnych możemy dokonać po-przez wywołanie metody z wartością null.

Praca z parserem HTMLJak wspomniano wcześniej – Jericho nie jest praw-dziwym parserem a bardziej – zaawansowanym mechanizmem wyszukiwania tekstowego, zorien-towanym na składnię HTML. Tym niemniej pro-gramista może odnieść wrażenie, iż (podobnie jak w przypadku DOM) operuje na drzewie obiek-tów reprezentujących strukturę dokumentu. We-wnętrznie jednak biblioteka wykonuje karkołom-ne operacje na łańcuchach znaków – i to z uży-ciem podstawowych mechanizmów standardowej biblioteki Java. Analizując kod biblioteki nie znaj-dziemy operacji z użyciem wyrażeń regularnych lub budowania złożonego modelu obiektowego przed rozpoczęciem przeszukiwania dokumentu. Biblioteka działa zatem bardzo niskopoziomowo, co czyni ją narzędziem dość wydajnym.

Szybki startNajlepiej i najszybciej jest uczyć się na przykładach. Biblioteka dostarczana jest waz ze zbiorem kilkunastu przykładowych klas obrazujących jej działanie w różnych aspektach. Aby je urucho-mić, musimy oczywiście w pierwszej kolejności pobrać bibliotekę ze strony projektu:http://sourceforge.net/projects/jerichohtml/Oprogramowanie dystrybuowane jest postaci pojedynczego pliku ZIP z dokumentacją, źródła-mi i skompilowaną biblioteką wewnątrz. Nas interesować będzie katalog samples/console, zawie-rający zbiór plików .bat uruchamiających wybrane przykłady. Nie pozostaje zatem nic innego jak uruchomić wybrane skrypty a potem przeanalizować wynikowy ekran wraz ze źródłami progra-mów. W tych ostatnich zabrakło niestety komentarzy. Programiści nieużywający systemu Windows będą musieli uruchomić programy bezpośrednio z linii komend, wpisując z poziomu katalogu samples/console:

java -classpath classes:../../lib/jericho-html-2.6.jar -Djava.util.logging.config.file=lo

gging.prop

erties ClassName

gdzie ClassName jest nazwą wybranej aplikacji przykładowej. Z ciekawszych programów, którym warto się przyjrzeć na początku są:

• Encoding – program odczytujący tryb kodowania znaków dla pliku HTML; przy okazji pobie-ra też podstawowe informacje o stronie (np. jej tytuł);

• RenderToText – przekształca plik HTML do sformatowanego pliku tekstowego, czytelnie za-znaczając akapity, listy, etc;

• DisplayAllElements – analizuje plik HTML i wyświetla listę wszystkich jego elementów oraz ich położenie w pliku;

• ConvertStyleSheets – program demonstruje odczyt danych i manipulację na strukturach HTML – wyszukuje zewnętrzne style z plików CSS i osadza je bezpośrednio w pliku HTML (jego zmodyfikowana wersja została przedstawiona na listingu 6 i szerzej opisana w niniejszym artykule).

Wszystkie opisane programy operują na przykładowym pliku HTML dostarczanym wraz z biblioteką. W katalogu samples można również znaleźć inny podkatalog – webapps, zawierający plik .war z przykładową aplikacją internetową, którą przed uruchomieniem należy zainstalować pod wy-branym serwerem aplikacji.

Page 16: SDJ_11_2008_PL_E-Commerce

11/200816

Biblioteka miesiącaJericho HTML

www.sdjournal.org 17

Reprezentacja dokumentu HTMLNajmniejszą częścią dokumentu HTML w rozu-mieniu Jericho jest tag, reprezentowany przez kla-sę o tej samej nazwie. W rzeczywistości biblioteka rozróżnia (dziedziczący po klasie Tag) tag otwie-rający (klasa StartTag) i zamykający (EndTag), dzięki czemu łatwo można nawigować między początkami i końcami poszczególnych elemen-tów strony. Obiekty tego typu zawierają infor-macje jedynie o samym tagu, z pominięciem jego atrybutów i ciała. Dostarczają za to szeregu metod pozwalających zidentyfikować tag lub nawigować pomiędzy związanymi z nim elementami.

Większą jednostką od taga jest Element, któ-ry reprezentuje fragment kodu HTML ograni-czony tagiem otwierającym i zamykającym. Ele-ment umożliwia dostęp do tagów wewnętrz-nych, pozwala no odczyt atrybutów oraz ciał po-szczególnych tagów. Można go przyrównać do obiektów typu Node w DOM. Specyficznym typem elementu jest FormControl, który repre-zentuje pole formularza HTML. Dedykowane metody pozwalają na odczyt lub zapis wartości pól oraz na manipulację ich atrybutami.

Kolejną specyficzną częścią dokumen-tu HTML są znaki specjalne (zapisane z uży-

ciem znaku &). Za operacje na nich odpowia-da klasa CharacterReference a w szczegól-ności – dwie różne klasy dziedziczące po niej – CharacterEntityReference dla znaków po-siadających swą nazwę w standardzie HTML (np. &, €) oraz NumericCharacterReference dla znaków reprezentowanych po-przez ich kod (np. >)

Najbardziej nadrzędną jednostką jest cały dokument reprezentowany przez omawianą już klasę Source. Z punktu widzenia możliwo-ści poruszania się po dokumencie, Source przy-pomina klasę Element. Ponadto zawiera szereg dodatkowych metod, specyficznych dla całego dokumentu HTML.

Wszystkie wymienione wyżej elementy dzie-dziczą po jednej klasie – Segment, która dostar-cza zbioru wspólnych metod służących porusza-niu się po dokumencie. Ponadto większość z klas narzędziowych (jak choćby poznany na początku artykułu SourceCompactor) będzie operowała na obiektach typu Segment, zatem nie będzie miało znaczenia, czy do operacji przedstawimy cały do-kument, czy np. tylko element formularza.

Przeszukiwanie dokumentuSiła tekstowej natury parsera Jericho ujawnia się przy przeszukiwaniu dokumentów HTML. Mo-żemy tutaj bowiem poruszać się zarówno po-między elementami (tagami) dokumentu, jak również dokonywać na nim klasycznych poszu-kiwań zadanych wycinków tekstu. Ilość opcji wyszukiwania jest spora – rozważmy dla przy-kładu różne warianty wyszukań zwracających li-stę wszystkich elementów zgodnych z zadanymi kryteriami dla segmentu nadrzędnego (może to być cały dokument lub tylko jego element):

• findAllElements() – zwraca listę wszyst-kich elementów zawierających się w elemen-cie, dla którego metoda została wywołana;

• findAllElements(String name) – zwraca listę wszystkich elementów oznaczonych tagiem podanym w parametrze metody;

• findAllTags(String name) – jak wyżej ale zwraca listę tagów a nie elementów (opera-cja szybsza i mniej zachłanna w wykorzy-staniu pamięci);

• findAllStartTags(String name) – jak wy-żej ale uwzględnia tylko tagi otwierające;

• findAllElements

(String attributeName, String

value, boolean valueCaseSensitive) – zwraca listę wszystkich elementów pod-rzędnych, których tagi zawierają zadany atrybut i wartość;

• findAllCharacterReferences() – zwraca listę znaków specjalnych w zadanym seg-mencie;

• findFormControls() – zwraca listę elemen-tów formularza HTML w zadanym seg-mencie;

• getChildElements() – zwraca listę bez-pośrednich dzieci zadanego segmentu.

Listing 1. Przykład użycia klasy SourceCompactor na potrzeby filtru HTTP

package org.sdjournal.jericho;

import java.io.*;

import javax.servlet.*;

import javax.servlet.http.*;

import au.id.jericho.lib.html.*;

public class CompactorFilter implements Filter {

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

throws IOException, ServletException {

OutputStream out = response.getOutputStream();

ApplicationResponseWrapper wrapper =

new ApplicationResponseWrapper((HttpServletResponse)response);

chain.doFilter(request, wrapper);

Source source = new Source( wrapper.toString() );

SourceCompactor compactor = new SourceCompactor(source);

compactor.writeTo(new OutputStreamWriter(out));

out.close();

}

public void init(FilterConfig arg0) throws ServletException {

}

public void destroy() {

}

}

class ApplicationResponseWrapper extends HttpServletResponseWrapper {

private ByteArrayOutputStream output;

private CharArrayWriter myOut;

public ApplicationResponseWrapper(HttpServletResponse response) {

super(response);

output = new ByteArrayOutputStream();

this.myOut = new CharArrayWriter();

}

public ServletOutputStream getOutputStream() throws IOException {

return new FilterServletOutputStream(output);

}

public PrintWriter getWriter() throws IOException {

return new PrintWriter(this.myOut);

}

public byte[] getData() {

return output.toByteArray();

}

public String toString() {

return myOut.toString();

}

}

Page 17: SDJ_11_2008_PL_E-Commerce

11/200816

Biblioteka miesiącaJericho HTML

www.sdjournal.org 17

Powyżej przedstawiono jedynie wybrane me-tody przeszukiwania – nie jest to pełna lista.

W przypadku wyszukiwania tekstowego uży-teczne będą następujące podstawowe metody:

• subSequence(int beginIndex, int

endIndex) – zwraca ciąg znaków zawarty pomiędzy wskazanymi indeksami;

• charAt(int index) – zwraca pojedynczy znak z zadanej pozycji;

• getParseText() – zwraca obiekt typu ParseText, który bezpośrednio reprezen-tuje tekst kodu HTML i dostarcza całej ga-my metod przeszukiwania tekstowego.

Zapewne jedną z najczęściej wykonywanych operacji przez programistów będzie przechodze-nie całego segmentu element po elemencie. Aby usprawnić ten proces, klasa Segment dostarcza metodę getNodeIterator(), zwracającą iterator przechodzący po wszystkich tagach segmentu.

Oprócz standardowych mechanizmów wy-szukiwania, otrzymujemy do dyspozycji meto-dy pozwalające na poruszanie się pomiędzy za-leżnymi od siebie elementami – podobne do tych jak ma to miejsce w DOM. Wyżej wspo-mniałem już o metodzie getChildElements, zwracającej listę bezpośrednich potomków ele-mentu. W alternatywie mamy również metodę getParentElement, zwracającą obiekt ojca. Dla tagów odnajdziemy metody typu findNextTag i findPreviousTag. Całość pozwala na bardzo ła-twe i intuicyjne poruszanie się po dokumencie.

PrzykładPrzykładowa aplikacja prezentująca możliwo-ści parsera została zaprezentowana na Listingu 3. Program pobiera kod HTML zadanej stro-ny (wskazanej w parametrze wywołania progra-mu) i wyszukuje w nim nazwy wszystkich uży-tych klas CSS. Program w pierwszej kolejności wyszukuje w dokumencie taga body. Ponieważ nie interesuje nas jego pełna zawartość, a jedynie miejsce w dokumencie, gdzie tag się znajduje, posłużyliśmy się tutaj szybszą metodą wyszuku-jącą obiekt typu StartTag (a nie Element). Na-zwa taga została została podana z użyciem kla-sy HTMLElementName, reprezentującej listę nazw wszystkich elementów HTML ale można tu również posłużyć się zwykłym tekstem.

Dla uproszczenia załóżmy, że pobieramy stro-nę HTML o poprawnej strukturze, tak więc mo-żemy oczekiwać tylko jednego taga body – w tej sy-tuacji skorzystamy z metody findNextStartTag, by pobrać jedynie pierwszy zgodny element a nie całą listę. W rezultacie otrzymaliśmy obiekt typu StartTag, jednak chcemy w jego obrębie poszukiwać obiektów typu Element (metoda findAllElements), która zwróci listę pełnych da-nych na temat każdego elementu wewnątrz ta-ga body. Bezpośrednie odwołanie się do tej meto-dy jest błędną koncepcją – w pierwszej kolejno-ści musimy bowiem pobrać dla elementu typu Tag jego zawartość (Element). Służy do tego uży-

ta dalej metoda getElement. Z użyciem metody getAttributeValue (dostępnej dla obiektów kla-sy Element ale nie Tag), możemy odczytać wartość poszukiwanego atrybutu (class).

Z HTML do tekstuCzęstą praktyką programistyczną jest odfiltro-wywanie części tekstu z wnętrza kodu HTML – choćby na potrzeby kanałów RSS, przedsta-wiania wyników wyszukiwania, etc. Bibliote-ka Jericho daje pełne wsparcie dla tego procesu, dostarczając dwa różne narzędzia:

• TextExtractor – klasa odfiltrowuje z za-danego segmentu wszystkie znaki specjalne i nazwy tagów, pozostawiając czysty tekst;

• Renderer – bardziej złożone narzędzie, które pozwala na sformatowanie wyniko-wego tekstu na podstawie tagów źródłowe-go kodu HTML. Narzędzie będzie głównie przydatne przy transformacji większych części HTML lub całych stron, dając w efekcie tekst czytelny dla człowieka.

TextExtractorSkupmy się w pierwszej kolejności na prost-szym narzędziu – TextExtractor, wyodrębnia-jącym tekst spośród kodu HTML. Jak wszystkie narzędzia Jericho, klasa operuje na danych typu Segment. Nową instancję klasy TextExtractor tworzymy z użyciem operatora new, podając w konstruktorze obiekt segmentu lub... wywołu-

Listing 2. Plik web.xml do przykładu z Listingu 1, który definiuje filtr dla wyjścia z plików JSP

<?xml version="1.0"?>

<!DOCTYPE web-app PUBLIC

'-//Sun Microsystems, Inc.//DTD Web Application 2.2//EN'

'http://java.sun.com/j2ee/dtds/web-app_2_2.dtd'>

<web-app>

<display-name>SDJ - Jericho</display-name>

<filter>

<filter-name>Compactor Filter</filter-name>

<filter-class>org.sdjournal.jericho.CompactorFilter</filter-class>

</filter>

<filter-mapping>

<filter-name>Compactor Filter</filter-name>

<servlet-name>jsp</servlet-name>

</filter-mapping>

</web-app>

Listing 3. Program demonstrujący przeszukiwanie dokumentu HTML. Aplikacja wypisuje nazwy wszystkich klas CSS użytych na stronie wskazanej w parametrze uruchomienia programu

package org.sdjournal.jericho;

import java.net.URL;

import java.util.*;

import au.id.jericho.lib.html.*;

public class ClassFinder {

public static void main(String[] args) {

try {

Source source = new Source(new URL(args[0]));

Iterator it = source

.findNextStartTag(0, HTMLElementName.BODY)

.getElement().findAllElements().iterator();

HashSet classes = new HashSet();

while( it.hasNext() ) {

Element el = (Element)it.next();

String cssClass = el.getAttributeValue("class");

if(cssClass != null && !classes.contains(cssClass)) {

classes.add(cssClass);

System.out.println(cssClass);

}

}

} catch (Exception e) {

e.printStackTrace();

}

}

}

Page 18: SDJ_11_2008_PL_E-Commerce

11/200818

Biblioteka miesiącaJericho HTML

www.sdjournal.org 19

jąc metodę getTextExtractor() dla dowolne-go segmentu. To ostatnie rozwiązanie pozwa-la na bardzo szybkie operacje na tekście za-wartym w tagach HTML. Zostało to zilustro-wane na Listingu 4. Można tam zauważyć, iż dla otrzymanego obiektu typu TextExtractor wywołujemy metodę setIncludeAttributes, która informuje narzędzie o tym, czy atrybu-ty tagów mają być uwzględniane w generowa-nym tekście czy nie. Ponieważ metoda settera zwraca referencję do swojego obiektu, wygod-nie można tworzyć cały łańcuch operacji.

TextExtractor pozwala na bardziej zaawanso-wane reguły eksportowania tekstu z kodu HTML, wprowadzając dodatkowe mechanizmy filtro-wania. W tym celu należy stworzyć własną kla-sę dziedziczącą po TextExtractor i nadpisać in-teresujące nas metody. Przykład takiego rozwią-zania przedstawiono na Listingu 5. Jak widać obiekt nadpisuje metodę includeElement, któ-ra jako parametr pobiera obiekt typu StartTag a zwraca wartość logiczną. Metoda ta będzie wy-wołana dla każdego taga otwierającego w zadanym segmencie. Jeśli metoda zwróci wartość false, Te-xtExtractor pominie przetwarzanie danego taga i nie zwróci dla niego żadnego tekstu. W przedsta-wionym przykładzie, program wyszukuje jedy-nie tagów typu P, których atrybut class jest róż-ny od „info”. Pozostałe elementy segmentu zosta-ną zignorowane. Na podobnej zasadzie funkcjonu-je metoda excludeElement, która zwraca wartość true dla wszystkich elementów, które mają zostać pominięte w generowaniu tekstu.

RendererRenderer jest dużym narzędziem dbającym o ge-nerowanie sformatowanego tekstu, który możli-wie najwierniej będzie reprezentował tekst opi-sany językiem HTML. Z punktu widzenia pro-gramisty, narzędzie jest czarną skrzynką, którą możemy co najwyżej dostosować do swoich wy-magań z użyciem kilku zaledwie parametrów.

Przetworzenie całej strony HTML do czystego tekstu zmieści się w dwóch liniach kodu:

Source source=new Source(new URL(url));

System.out.println(

source.getRenderer().toString());

Po takiej operacji otrzymamy tekst, który nie bę-dzie tylko długim ciągiem znaków. Akapity będę od siebie oddzielone wolnymi liniami. Listy będą numerowane lub wypunktowane z użyciem zna-ku *. Odnośniki będą wyróżnione trójkątnymi nawiasami. Całość będzie prawie przypominać efekt otwarcia strony pod przeglądarką Lynx.

Jak widać na przedstawionym kodzie, filo-zofia dostępu do obiektu Renderer jest iden-tyczna jak w przypadku klasy TextExtractor. Możemy tutaj otrzymać obiekt klasy rendere-ra bezpośrednio z segmentu, poprzez meto-dę getRenderer lub utworzyć nową instancję klasy z operatorem new, podając w parametrze konstruktora obiekt segmentu.

Sterowanie generowaniem tekstu odbywa się za pomocą kilku setterów. Poniżej wymieniono najważniejsze z nich:

• setMaxLineLength(int maxLineLength) – ustawia maksymalną długość linii, po której nastąpi automatyczne łamanie tek-stu; wartość domyślna to 76;

• setNewLine(String newLine) – ustawia znak reprezentujący koniec linii; domy-ślanie wartość jest identyczna jak w pliku źródłowym;

• setListBullets(char[] listBullets) – ustawia znaki elementów listy UL dla jej po-szczególnych poziomów (domyślnie *, o, + #);

• setListIndentSize(int listIndentSize) – ustawia wielkość wcięcia dla elementów li-sty (domyślnie 6);

• s etTa ble C e l lS e p a r at or( St ri n g

tableCellSeparator) – ustawia znak od-

dzielający poszczególne kolumny w tabeli (domyślnie tabulator).

Każda z wymienionych metod zwraca swój obiekt (this), dzięki czemu łatwo można zbu-dować łańcuch operacji.

Formatowanie kodu HTMLZa formatowanie kodu HTML odpowiada kla-sa SourceFormatter. To kolejna z klas narzędzio-wych biblioteki, która – udostępniając niewielki in-terfejs, kryje za sobą niemałą funkcjonalność. Klasa nie buduje kodu HTML z czystego tekstu i nie zaj-muje się żadną konwersją. Jak każde narzędzie Jeri-cho – oczekuje na wejściu obiektu typu Segment, a więc istniejącego dokumentu HTML (lub jego fragmentu). Jej zadanie sprowadza się więc do po-nownego zbudowania pliku HTML, który będzie sformatowany zgodnie ze wskazanymi parametra-mi. Można tutaj definiować wielkości wcięć, okre-ślić znak definiujący koniec wiersza, etc. – całość łudząco przypomina składnię opisanej wcześniej klasy Renderer. Dodatkową metodą, o której war-to tu wspomnieć, jest setTidyTags(boolean), któ-ra (przy podaniu parametru true) wymusza gene-rowanie tagów zgodnych z XHTML. Zachęcam do poeksperymentowania z klasą SourceFormatter i przedstawionym w pierwszym przykładzie kodem filtru HTTP. Poniżej niewielki przykład demon-strujący, jak w kilku liniach kodu można uporząd-kować wygląd zadanego pliku HTML:

Source source=new Source(url);

new SourceFormatter(source).setTidyTags(true)

.writeTo(new OutputStreamWriter(

System.out));

Modyfikowanie kodu HTMLBiblioteka nie byłaby kompletna, gdyby nie po-zwalała na modyfikowanie kodu HTML i mani-pulowanie na jego strukturze. Jak wszystkie in-ne elementy Jericho – i ten moduł jest logiczny i prosty. Aby móc modyfikować źródłowy kod HTML należy zapoznać się przede wszystkim z klasą OutputDocument, która reprezentuje kod wynikowy. W konstruktorze tej klasy należy po-dać obiekt typu Source. OutputDocument do-starcza zbioru metod umożliwiających zmiany na kodzie źródłowym. Przede wszystkim są to meto-dy typu replace (z rożnymi typami parametrów wejściowych – od Attributes po Segment), któ-re pozwalają na podmianę w bieżącym dokumen-cie wybranych jego elementów. Schemat działania często będzie zatem polegał na odczytaniu kawał-ka kodu dokumentu, wprowadzeniu oczekiwa-nych poprawek i podmianie elementu w doku-mencie. Ponieważ Jericho jest biblioteką do bez-pośrednich manipulacji na tekście, istnieje moż-liwość zastąpienia dowolnej sekwencji znaków (w zadanym położeniu) lub wstrzyknięcia w po-danej lokalizacji dowolnego tekstu. Zostało to do-brze zobrazowane w programie przykładowym o nazwie ConvertStyleSheets, dostarczanym wraz z biblioteką (patrz Listing 6, przedstawiający nie-

Listing 4. Przykład użycia narzędzia TextExtractor do wypisania wszystkich linków zawartych w zadanym fragmencie strony

public static void showAllLinks(Segment seg) {

List links = seg.findAllElements(HTMLElementName.A);

for(Iterator it=links.iterator(); it.hasNext();) {

Element link = (Element)it.next();

System.out.println(link.getTextExtractor()

.setIncludeAttributes(false).toString());

}

}

Listing 5. Przykład użycia mechanizmu filtrowania wewnątrz klasy TextExtractor

TextExtractor textExtractor=new TextExtractor(seg) {

public boolean includeElement(StartTag tag) {

return tag.getName()==HTMLElementName.P

&& !"info".equalsIgnoreCase(tag.getAttributeValue("class"));

}

};

textExtractor.writeTo(new OutputStreamWriter(System.out));

Page 19: SDJ_11_2008_PL_E-Commerce

11/200818

Biblioteka miesiącaJericho HTML

www.sdjournal.org 19

co zmodyfikowaną wersję programu). Program odnajduje w kodzie HTML deklaracje zewnętrz-nych stylów CSS a jeśli takie napotka, przenosi za-wartość pliku CSS bezpośrednio do wnętrza kodu HTML, zamykając całość tagami style. W orygi-

nalnym kodzie przykładowym, tagi budowane są z użyciem operacji na klasie StringBuffer, poprzez jawne podawanie tekstu taga i konkatenację z atry-butami. Jest to praktyka podatna na błędy i zwy-czajnie nieładna, a przecież biblioteka udostępnia

(co prawda bardzo podstawowe) narzędzia, umoż-liwiające na budowanie kodu tagów w ładniej-szy sposób. Służą do tego celu statyczne metody generateHTML w klasach OpenTag i EndTag, zade-monstrowane na przykładowym Listingu.

Najważniejszym elementem przykładowego programu jest linia:

outputDocument.replace(

startTag,sb.toString());

która podmienia kod odwołania do zewnętrzne-go pliku CSS na uprzednio wygenerowany tekst z tagiem style. Ostatnia linia programu zapisu-je nowo wygenerowany kod HTML na wyjściu, z użyciem znanej już nam metody writeTo.

Modyfikowanie danych formularzy HTMLModyfikowanie fragmentów kodu HTML z uży-ciem Jericho polega głównie na bezpośrednich operacjach na tekście, jednak w kwestii modyfika-cji danych formularzy HTML, biblioteka udostęp-nia narzędzia, pozwalające w łatwiejszy sposób na dokonywanie manipulacji. Za całość odpowie-dzialne są klasy FormFields i FormField, których metody pozwalają na szybki dostęp do poszczegól-nych pól formularza HTML (Listing 7).

Przedstawiony kod pobiera z podanego źró-dła listę pól formularza. Metoda clearValues usuwa wszystkie domyślne wartości, natomiast metoda addValue ustawia nową wartość dla za-danego pola (jest to skrót operacji formFields.get("name").addValue("John Smith");).

Oprócz manipulacji na wartościach pól for-mularza, możemy również modyfikować do-datkowe atrybuty, jak na przykład ReadOnly lub Disabled. Całość finalnie musi zostać za-pisana w dokumencie wynikowym, z użyciem opisanej wcześniej klasy OutputDocument.

PodsumowanieJericho jest typowym przykładem udowadniają-cym siłę w prostocie. Niewielki, czytelny kod, ko-rzystający jedynie z bibliotek standardowych oraz prosta koncepcja tworzą dość wszechstronne na-rzędzie programistyczne, które może znaleźć za-stosowanie w wielu aplikacjach Java. Na chwilę obecną największą wadą Jericho jest brak wersji biblioteki zgodnej ze składnią Java 5 oraz nazbyt uproszczony mechanizm generacji kodu HTML. Ponadto mimo że narzędzie znalazło zastosowa-nie w wielu projektach i zdobyło zaufanie progra-mistów, pewnym ryzykiem jest fakt, iż jest to opro-gramowanie jednego autora. Przydałaby się grupa programistów bądź instytucja czuwająca nad dal-szym rozwojem biblioteki.

DAVID DE ROSIERProgramista-podróżnik. Pasjonat WEB 2.0, estetycz-

nego kodowania i algorytmów szachowych. Zawo-

dowo – specjalista od aplikacji J2EE i MDA w sekto-

rze bankowym.

Kontakt z autorem: [email protected]

Listing 6. Program dołączający zawartość pliku CSS bezpośrednio do kodu HTML (zmodyfikowana wersja jednego z programów dostarczanych wraz z biblioteką)

import au.id.jericho.lib.html.*;

import java.util.*;

import java.io.*;

import java.net.*;

public class ConvertStyleSheets {

public static void main(String[] args) throws Exception {

if (args.length==0) {

System.err.println("Podaj URL lub nazwe wejsciowego dokumentu HTML");

System.exit(1);

}

String sourceUrlString=args[0];

if (sourceUrlString.indexOf(':')==-1)

sourceUrlString="file:"+sourceUrlString;

URL sourceUrl=new URL(sourceUrlString);

Source source=new Source(sourceUrl);

OutputDocument outputDocument=new OutputDocument(source);

StringBuffer sb=new StringBuffer();

List linkStartTags=source.findAllStartTags(Tag.LINK);

for (Iterator i=linkStartTags.iterator(); i.hasNext();) {

StartTag startTag=(StartTag)i.next();

Attributes attributes=startTag.getAttributes();

String rel=attributes.getValue("rel");

if (!"stylesheet".equalsIgnoreCase(rel))

continue;

String href=attributes.getValue("href");

if (href==null)

continue;

String styleSheetContent;

try {

styleSheetContent=Util.getString(

new InputStreamReader(new URL(sourceUrl,href).openStream()));

} catch (Exception ex) {

continue; // nie konwertuj dla błędnego URLa

}

sb.setLength(0);

Attribute typeAttr=attributes.get("type");

sb.append(StartTag.generateHTML(HTMLElementName.STYLE,

typeAttr != null ? Collections.singletonMap(typeAttr.getKey(),

typeAttr.getValue()) : null, false))

.append("\n").append(styleSheetContent).append("\n")

.append(EndTag.generateHTML(HTMLElementName.STYLE));

outputDocument.replace(startTag,sb.toString());

}

outputDocument.writeTo(new OutputStreamWriter(System.out));

}

}

Listing 7. Przykład modyfikacji danych formularza

FormFields formFields=source.findFormFields();

formFields.clearValues();

formFields.addValue("name","John Smith");

OutputDocument outputDocument=new OutputDocument(source);

outputDocument.replace(formFields);

Page 20: SDJ_11_2008_PL_E-Commerce

11/200820

E-commerceSklep internetowy w PHP i SQLite

www.sdjournal.org 21

Powodów, dla których nie warto wdra-żać gotowych rozwiązań może być wie-le. Dla prostego sklepu internetowego,

w którym właściciel chce zaoferować kilka pro-duktów wykorzystanie osCommerce może być nieoptymalne. Dodatkowo modyfikowanie ta-kiej gotowej platformy również nie należy do rzeczy najprostszych – jeśli dostępna jest do-kumentacja, wystarczy się z nią zapoznać. Jeśli jednak jej nie ma, pozostaje metoda prób i (nie-stety najczęściej) błędów. W obu przypadkach potrzebujemy czasu – który możemy poświę-cić na stworzenie własnego, dedykowanego roz-wiązania. Za chwilę zobaczysz, że w mniej niż 60 minut można zbudować sklep interneto-wy, który pomimo okazałej nazwy jest po pro-stu interfejsem pośredniczącym pomiędzy ba-zą danych a użytkownikiem, wykonującym na niej określone operacje. Struktura takiej ba-zy najczęściej nawet nie jest bardzo skompli-kowana, tak więc można użyć praktycznie do-wolnego silnika baz danych. Nie ma to żadne-

go wpływu na poziom trudności pracy. Dlate-go nasz sklep zbudujemy wykorzystując PHP5 oraz… SQLite.

Przed rozpoczęciem pracy…… należy zastanowić się nad funkcjonalnością sklepu. Chcemy oczywiście sprzedawać okre-ślone produkty – to oczywiste. Zastanówmy się jednak, co dokładnie chcemy przedsta-wić potencjalnemu nabywcy. Na pewno bę-dzie to nazwa produktu oraz jego opis. Lu-dzie lubią widzieć, co kupują, wskazane jest więc umieszczenie co najmniej jednego zdję-cia. Część produktów wymaga dokładniejsze-go sfotografowania, tak więc nie powinniśmy ograniczyć maksymalnej liczby zdjęć. Oczy-wiście niezbędne jest również uwzględnienie ceny oraz stawkę podatku VAT. W zależno-ści od typu produktów można pomyśleć rów-nież nad dodatkowymi polami określający-mi jego parametry (dla sklepu z butami war-to pomyśleć o polach z rozmiarami, sprzeda-jąc dyski twarde warto zaznaczyć ich pojem-ność) a jeśli znamy stan magazynu możemy również wykorzystać tą informację. Nie ma bowiem sensu pokazywać użytkownikowi to-waru, którego nie mamy na stanie, lub który został już raz sprzedany. Produkt powinien

zostać również umieszczony w konkretnej kategorii – ułatwi to przeszukiwanie sklepu użytkownikowi.

Klient naszego sklepu w przypadku doko-nania zakupu powinien przekazać nam da-ne niezbędne do zrealizowania zamówienia (m.in. imię, nazwisko, adres, dane do faktu-ry, dane wysyłki). Przyjęliśmy więc, że w ce-lu dokonania zakupu konieczne jest posia-danie konta w systemie. Rejestracja powin-na być oczywiście bezpłatna, a klient powi-nien mieć również możliwość samodzielne-go usunięcia konta.

Warto również pomyśleć o systemie ra-batów – pozwoli to zatrzymać klienta oraz uatrakcyjnić cenowo naszą ofertę. Rabat mo-żemy uzależnić od wielu elementów – wiel-kości zakupów, kodu promocyjnego podane-go podczas rejestracji lub przekroczenie okre-ślonej wartości wszystkich zakupów od chwi-li zarejestrowania konta. W naszym sklepie rabat będzie przydzielany ręcznie przez ad-ministratora – czytelnik jednak bez więk-szych problemów będzie w stanie dopasować system rabatowy do własnych potrzeb.

Ostatnim niezbędnym elementem jest lista zamówień. Zastanówmy się jakie informacje są naprawdę potrzebne do sprawnego obsłuże-nia klienta. W większości przypadków powin-no wystarczyć imię i nazwisko zamawiającego, adres wysyłki, data złożenia zamówienia, stan, data wysłania towarów oraz oczywiście zamó-wione towary.

Minuta pierwsza – baza danych Na początku prac zaprojektujemy struktu-rę naszej bazy danych. Do stworzenia ba-

Sklep internetowy w PHP i SQLite

Gotowych rozwiązań na rynku e-commerce są setki. Znajdziemy gotowe skrypty o funkcjonalności systemów aukcyjnych, sklepów internetowych oraz systemów barterowych. To najczęściej sprawdzone i tanie rozwiązania, regularnie aktualizowane – dlatego skorzystanie z nich najczęściej bywa bardzo kuszące. Jednak czy zawsze uzasadnione? Najczęściej o wiele lepiej stworzyć własną platformę e-commerce. Nie jest to trudne – nam zajmie to 60 minut.

Dowiesz się:• Jak zaprojektować od podstaw sklep interne-

towy;

• W jaki sposób korzystać z SQLite;

• Jak wykorzystać sesje do przechowywania da-

nych użytkownika.

Powinieneś znać:• Co najmniej podstawy PHP oraz SQL;

• Podstawy programowania obiektowego.

Poziom trudności

Zaprojektuj i zbuduj w mniej niż godzinę

Page 21: SDJ_11_2008_PL_E-Commerce

11/200820

E-commerceSklep internetowy w PHP i SQLite

www.sdjournal.org 21

zy można użyć zewnętrznych narzędzi (np. zewnętrzny SQLite Manager działający ja-ko dodatek do przeglądarki Mozilla Firefox) lub napisanego samodzielnie prostego skryp-tu w PHP.

Wystarczy do tego podstawowa znajomość języka SQL oraz funkcji wbudowanych w PHP służących do komunikacji z bazą sqlite.

Gotowy skrypt przedstawiony jest na Li-stingu 1. Jego działanie jest proste – łączy-my się z plikiem bazy danych, oraz wywo-łujemy 5 zapytań tworzących 5 tabel – ta-belę do przechowywania informacji o użyt-kownikach, produktach, dostępnych kate-goriach, oraz dwie tabele do przechowywa-nia informacji o zamówieniach użytkowni-ka. Strukturę utworzonych tabel przedsta-wia Rysunek 1.

Część z was najprawdopodobniej zauwa-żyła, że brakuje pól w których będą przecho-wywane informacje o zdjęciach produktów.

Zamiast tego, zdjęcia będą miały nazwę od-powiadającą unikalnemu polu zawierające-mu unikalne ID produktu, znak separato-ra (podkreślnik) oraz kolejny numer zdję-cia produktu. Pozwoli to na umieszczenie praktycznie nieograniczonej ilości zdjęć. PHP dostarcza nam mechanizm umożliwia-jący proste sprawdzenie czy plik w określo-nej lokalizacji istnieje (służy do tego funk-cja file_exist()) – dzięki temu nie musi-my przechowywać informacji o tym fakcie w bazie danych.

Zdziwić może również brak atrybutów AUTOINCREMENT przy tworzeniu bazy. Jest to związane z tym, że w SQLite wszystko jest łań-cuchem znaków. Typ kolumny pomaga silniko-wi bazy dane te odpowiednio posortować, oraz zwiększa przejrzystość tabel.

Autorzy jednak udostępnili substytut atry-butu – wystarczy zadeklarować w tabeli pole INTEGER PRIMARY KEY .

Minuta 10 – obiektyW kolejnym kroku utworzymy klasy repre-zentujące trzy podstawowe typy obiektów które zdefiniowaliśmy na początku artyku-łu – dla użytkownika, produktu, oraz za-mówienia.

W każdej klasie oprócz pól charaktery-stycznych dla bazy danych znajduje się rów-nież prywatne pole error – wykorzystamy je do zapisywania informacji o ewentual-nym błędzie (na przykład błędzie podczas połączenia z bazą danych, lub nieprawidło-wych danych logowania). Przyjmijmy rów-nież, że wszystkie funkcje i metody zwraca-ją wartość logiczną – prawdę, gdy realizowa-na operacja się powiedzie, oraz fałsz gdy wy-stąpi jakikolwiek błąd. Dzięki temu spraw-dzenie poprawności wykonania nawet cy-klu operacji jest dziecinnie proste – sprowa-dza się do wprowadzenia kilku instrukcji wa-runkowych.

Listing 1. Skrypt tworzący tabele w bazie danych

<?php

include 'config.php';

if($db = sqlite_open($sqlitePath, 0666, $sqliteerror))

{

sqlite_query($db, 'CREATE TABLE "users" ( "users_id" INTEGER PRIMARY KEY , "users_username" TEXT NULL , "users_name" TEXT NULL

, "users_city" TEXT NULL , "users_postcode" TEXT NULL , "users_adress" TEXT NULL , "users_phone" TEXT NULL

, "users_mail" TEXT NULL , "users_dname" TEXT NULL , "users_deliverycity" TEXT NULL , "users_password" TEXT

NULL , "users_deliverypostcode" TEXT NULL , "users_deliveryaddress" TEXT NULL , "users_discount" TEXT NULL ,

"users_nip" TEXT NULL );');

sqlite_query($db, 'CREATE TABLE "products" ("products_id" INTEGER PRIMARY KEY , "products_name" TEXT NULL , "products_

description" TEXT NULL , "products_price" TEXT NULL , "products_tax" INT NULL , "products_count" INT NULL ,

"products_categoryid" INT NULL );');

sqlite_query($db, 'CREATE TABLE "category" ( "category_id" INTEGER PRIMARY KEY , "category_name" NULL);');

sqlite_query($db, 'CREATE TABLE "orders" ( "order_id" INTEGER PRIMARY KEY , "order_userid" INT NULL , "order_date" INT NULL ,

"order_status" TEXT NULL , "order_sdate" INT NULL );');

sqlite_query($db, 'CREATE TABLE "order_products" ( "product_id" INTEGER PRIMARY KEY , "order_id" INT NOT NULL , "op_amount" INT

NOT NULL );');

sqlite_close($db);

echo 'Tabele zosta³y utworzone!';

}

else

{

die('Wystąpił błąd: '. $sqliteerror);

}

?>

Listing 2. Zawartość pliku config.php

<?php

$sqlitePath = './sklep2.sqlite';

session_start();

function __autoload($class_name) {

require_once './class/'.$class_name . '.php';

}

?>

Page 22: SDJ_11_2008_PL_E-Commerce

11/200822

E-commerceSklep internetowy w PHP i SQLite

www.sdjournal.org 23

Listing 3a. Fragment klasy user – służącej do obsługi użytkownika

class user

{

public $id;

public $username;

public $password;

public $name;

public $city;

public $postcode;

public $adress;

public $phone;

public $mail;

public $dname;

public $deliverycity;

public $deliverypostcode;

public $deliveryadress;

public $discount;

public $nip;

private $error;

function __constuct($id='')

{

if($id!='')

$this->load($id);

}

function load($id)

{

if($db = sqlite_open($sqlitePath, 0666, $this->error ))

{

$value = sqlite_array_query($db, "SELECT * FROM users

WHERE users_id = '".$id."'");

if(sqlite_num_rows($value) == 0)

{

$this->error = "Brak u¿ytkownika o podanym id!";

return false;

}

$this->id = $value['users_id'];

$this->username = $value['users_username'];

$this->password = $value['users_password'];

$this->name = $value['users_name'];

$this->city = $value['users_city'];

$this->postcode = $value['users_postcode'];

$this->adress = $value['users_adress'];

$this->phone = $value['users_phone'];

$this->mail = $value['users_mail'];

$this->dname = $value['users_dname'];

$this->deliverycity = $value['users_deliverycity'];

$this->deliverypostcode = $value['users_

deliverypostcode'];

$this->deliveryadress = $value['users_

deliveryadress'];

$this->discount = $value['users_discount'];

$this->nip = $value['users_nip'];

$this->error='';

sqlite_close($db);

return true;

}

else

{

return false;

}

}

function checklogin($username, $password)

{

if($db = sqlite_open($sqlitePath, 0666, $this->error ))

{

$value = sqlite_array_query($db, "SELECT users_id

FROM users WHERE users_username =

'".$username."' AND users_password =

MD5(".$password.")");

if(sqlite_num_rows($db) == 0)

{

$this->error = 'Nieprawid³owa nazwa u¿ytkownika

lub has³o!';

sqlite_close($db);

return -1;

}

return $value['users_id'];

}

else

{

return 0;

}

}

function add($username, $password, $name, $city, $postcode,

$adress, $phone, $mail, $dname,

$deliverycity, $deliverypostcode,

$deliveryadress, $discount, $nip)

{

$this->username = sqlite_escape_string($username);

$this->password = sqlite_escape_string($password);

$this->name = sqlite_escape_string($name);

$this->city = sqlite_escape_string($city);

$this->postcode = sqlite_escape_string($postcode);

$this->adress = sqlite_escape_string($adress);

$this->phone = sqlite_escape_string($phone);

$this->mail = sqlite_escape_string($mail);

$this->dname = sqlite_escape_string($dname);

$this->deliverycity = sqlite_escape_

string($deliverycity);

$this->deliverypostcode = sqlite_escape_string($delivery

postcode);

$this->deliveryadress = sqlite_escape_

string($deliveryadress);

$this->discount = sqlite_escape_string($discount);

$this->nip = sqlite_escape_string($nip);

if($this->validate())

{

if($db = sqlite_open($sqlitePath, 0666, $this->error

))

{

sqlite_array_query($db, "INSERT INTO users (users_

id, users_username, users_password,

users_name, users_city, users_postcode,

users_adress, users_phone, users_mail,

users_dname, users_deliverycity, users_

deliverypostcode, users_deliveryadress,

users_discount, users_nip) VALUES

Page 23: SDJ_11_2008_PL_E-Commerce

11/200822

E-commerceSklep internetowy w PHP i SQLite

www.sdjournal.org 23

W naszym systemie skorzystamy z mecha-nizmu automatycznego ładowania plików z klasami wprowadzonego w piątej wersji PHP. Dlatego klasy, z których będziemy korzy-stać bezpośrednio w skrypcie musimy umie-ścić w osobnych plikach o nazwach takich sa-mych jak nazwy klas.

Sama funkcja __autoload() umieszczona została w pliku config.php. Plik ten dołącza-ny jest na początku projektu – gwarantuje to, że funkcja będzie dostępna w każdym miej-scu skryptu.

W pliku tym zdefiniowaliśmy również na-zwę pliku z bazą danych oraz wystartowaliśmy mechanizm sesji.

UżytkownikNa Listingu 3a i 3b przestawiono fragment klasy reprezentującej użytkownika. Powinna ona dostarczyć nam wszystkich operacji nie-zbędnych do obsługi użytkownika. Wszyst-kie pola wyłączając pole $error są publicz-ne – chcemy mieć bowiem do nich dostęp w każdym miejscu skryptu. Oczywiście mo-żesz utworzyć zmienne prywatne i utwo-rzyć metodę do ich zwracania. Pole error nie powinno być modyfikowane z zewnątrz klasy – dlatego pozostanie prywatne, a do-stęp do jego zawartości spoza klasy odby-wa się wyłącznie za pośrednictwem meto-dy geterror().

Klasa posiada zdefiniowany jednoparame-trowy konstruktor. Podanie parametru nie jest jednak konieczne – jeśli nie zostanie po-

dany, zostanie utworzony pusty obiekt. Jeśli jednak jako parametr podamy id użytkow-nika, zostanie wywołana metoda load() któ-

Rysunek 1. Schemat utworzonej bazy danych

�����

��������

������

��������������

��������

������������

�������������������

���������������

���������������

�������������������

�����������������

����������������

���������������

����������������

�����������������������

��������������������������

���������������������������

��������������������������

�������������������

��������������

�������

�������

�������

�������

�������

���������������

������������������

�������������������������

�������������������

����������������

������������������

�����������������������

������������

����������������

��������������

�����������������

���������������

��������������

������������

�������������

���������������

�������������

Listing 3b. Fragment klasy user – służącej do obsługi użytkownika

(NULL, ".$this->username.", ".$this-

>password.", ".$this->name.",

".$this->city.", ".$this->postcode.",

".$this->adress.", ".$this->phone.",

".$this->mail.", ".$this->dname.",

".$this->deliverycity.", ".$this-

>deliverypostcode.", ".$this-

>deliveryadress.", ".$this->discount.",

".$this->nip.");");

sqlite_close($db);

return true;

}

else

{

return false;

}

}

}

function validate()

{

//realizację funkcji validate pozostawiamy czytelnikowi.

//funkcja powinna zwróciæ false gdy nie podano wszystkich

wymaganych pól

return true;

}

function geterror()

{

return $this->error;

}

}

Listing 4. Metoda updatecount() klasy product

function updatecount($id, $newcount)

{

if($db = sqlite_open($sqlitePath, 0666, $this->error ))

{

sqlite_array_query($db, "UPDATE products SET products_

count = '".$newcount."' WHERE products_

id = '".$this->id."';");

sqlite_close($db);

return true;

}

else

{

return false;

}

}

Page 24: SDJ_11_2008_PL_E-Commerce

11/200824

E-commerceSklep internetowy w PHP i SQLite

www.sdjournal.org 25

Listing 5. Fragment odpowiedzialny za wyświetlenie kategorii oraz spisu towarów

<?php

include 'config.php';

$error = '';

$categories = array();

$products = array();

if($db = sqlite_open($sqlitePath, 0666, $error ))

{

//wybieramy wszystkie dostêpne kategorie

$table = sqlite_array_query($db, 'SELECT * FROM category');

foreach($table as $value)

{

$categories[] = array($value['category_id'], $value['category_name']);

}

//Wyœwietlamy u¿ytkownikowi menu z wyborem kategorii:

echo '<div name="categories">';

foreach($categories as $category)

{

echo '<a href="list.php?category='.$category[0].'">'.$category[1].'</a><br>';

}

echo '</div>';

//sprawdzamy, czy u¿ytkownik wybra³ kategorie:

if($_GET['category']=='')

{

echo '<div name="message">Witaj w naszym sklepie internetowym! Wybierz interesuj¹c¹ Ciê kategorie!</div>';

}

else

{

//jeœli tak - pobieramy towary z bazy:

$table = sqlite_array_query($db, 'SELECT products_id FROM products WHERE products_categoryid = "'.sqlite_escape_string($_

GET['category']).'" AND products_count>0;');

if(count($table)==0)

{

echo '<div name="message">Nie znaleziono produktów w kategorii!</div>';

}

else

{

foreach($table as $value)

{

$products[] = $value['products_id'];

}

//oraz wyœwietlamy:

echo '<div name="products">';

foreach($products as $id)

{

$product = new product($id);

echo '<div name="singleproduct"><a href="details.php?productid='.$product->id.'">'.$product->name.'</a><br>

Cena netto: '.$product->price.' (+ '. $product->tax.') z³ <br>

Opis: '.substr($product->description, 0, 150).'<a href="details.php?productid='.$product->id.'">[...] dalej</a></div>';

}

echo '</div>';

}

}

sqlite_close($db);

}

else

{

die('Wyst¹pi³ b³¹d: '. $error);

}

?>

Page 25: SDJ_11_2008_PL_E-Commerce

11/200824

E-commerceSklep internetowy w PHP i SQLite

www.sdjournal.org 25

ra uzupełni wszystkie pola klasy jego dany-mi. Oczywiście funkcja może zostać wyko-nana w dowolnym momencie życia obiektu – możemy więc po prostu utworzyć obiekt i dopiero później uzupełnić pola metodą load().

Klasa zawiera również metodę checkLogin przyjmująca jako argumenty nazwę użytkow-nika i hasło. Zadaniem tej metody jest spraw-dzenie istnienia w bazie użytkownika o poda-nych danych logowania. Jeśli użytkownik ta-ki istnieje – funkcja zwróci jego id, w prze-ciwnym wypadku zwróci wartość 0. Funkcja ta będzie wykorzystywana podczas logowa-nia użytkownika do sklepu.

W klasie zdefiniowano również meto-dy add() , remove() oraz validate(). Z po-wodu ograniczonej objętości artykułu, pe-łen kod klasy znajdziecie na stronie http://sdjournal.org. Pierwsza metoda ustawia po-la klasy zgodnie z wartościami podanymi na parametr oraz zapisuje użytkownika do ba-zy danych. Metoda jest wykorzystywana przy rejestracji użytkownika. Wykorzystu-je ona dodatkowo metodę validate(), któ-ra służy do walidacji danych. Możesz w niej sprawdzać, czy dane spełniają przyjęte zało-żenia – na przykład, czy wypełniono wszyst-kie pola ustalone jako obowiązkowe. Metoda powinna zwracać logiczną prawdę, jeśli dane są wypełnione poprawnie oraz fałsz w prze-ciwnym wypadku. Ostatnia metoda – służy do usuwania użytkownika którego id poda-my jako parametr.

ProduktyKlasa reprezentująca produkty jest bardzo po-dobna do klasy user. Również tutaj znajduje się metoda load() , add(), validate() oraz remove(). Ich funkcjonalność jest identycz-na – nie ma więc sensu ich szerszego omawia-nia. Klasa posiada dwie nowe metody służą-ce do uaktualnienia stanu magazynu. Pierw-sza – updatecount() przedstawiona na Listin-gu 4 służy do zaktualizowania dostępnej licz-by egzemplarzy towaru o określonym ID. Dru-ga – decreasecount() zmniejsza ilość dostęp-nych produktów o jeden.

Kod całej klasy products znajduje się na stro-nie: http://sdjournal.org

ZamówieniaNieco bardziej skomplikowana jest klasa do obsługi zamówień. Związane jest to z tym, że zamówienia przechowujemy w dwóch ta-belach w bazie – w jednej przechowujemy in-formacje o zamówieniu (numer, datę złoże-nia, datę realizacji) a w drugiej identyfikato-ry zamówionych towarów oraz ich ilość. Ko-lejnym problemem jest nieznana ilość typów towarów – nie możemy przewidzieć ile rze-czy zostanie przez użytkownika nabytych. Dlatego nie możemy wprowadzić określonej ilości pól w klasie. Konieczne więc jest wyko-

rzystanie jakieś struktury danych. Niestety, w chwili obecnej PHP nie obsługuje list czy kolejek – trzeba je implementować samo-dzielnie. Sytuacja ma się jednak zmienić – w PHP od wersji 5.3 mają zostać zaimplemen-towane podstawowe struktury danych (m.in. lista, kolejka, stos oraz kopiec). W chwili pi-sania artykułu dostępna była jednak jedynie

wersja PHP 5.1alpha1 – dlatego do przecho-wywania informacji o produktach w zamó-wieniu wykorzystaliśmy rozwiązanie mniej subtelne – zwykłą tablicę. Elementami ta-blicy są obiekty typu orderProduct. Defini-cję tej klasy umieściliśmy w tym samym pli-ku co klasa order – nie jest to błąd. Bezpo-średnio do tej klasy powinny odwoływać się

Rysunek 2. Struktura klasy order

�����

�����

������

����

��

�������������

�����

������

������

�������

������������

�����

������

�������

�����

�������������

��������������

���������

������

�������

�����

�������������

��������������

���������

������������

�����

������

�������

������

�������

�������

�����

�������

�����

����������

�����

�����������

�����

��

����

�����

���

����������

�����

�����������

�����

��

����

�����

���

Listing 6. Wyszukiwanie obrazków danego produktu

//pobieramy długość identyfikatora ID produktu

$length = strlen(trim($_GET['productid']));

//otwieramy katalog images

if($dir = opendir('./images/'))

{

//pobieramy nazwy wszystkich plików

while (false !== ($file = readdir($dir)))

{

//porównujemy pierwsze znaki

if (substr($file, 0, ($length+1)) == trim($_GET['productid'])."_")

{

echo '<img src="./images/'.$file.'">';

}

}

closedir($dir);

}

Page 26: SDJ_11_2008_PL_E-Commerce

11/200826

E-commerceSklep internetowy w PHP i SQLite

www.sdjournal.org 27

tylko instancje klasy order(), a jakiekolwiek odwołanie powinno być możliwe wyłącznie przez pole z tablicą obiektów w tej klasie. Sa-ma klasa orderProduct składa się z czterech pól – zawierającego id produktu, ilość za-mówionych egzemplarzy oraz pole omówio-nego typu product w którym przechowywa-

ne są informacje o produkcie. Struktura kla-sy order może wydawać Ci się skomplikowa-na. Jeśli tak rzeczywiście jest, spójrz na Ry-sunek 2. Powinien on wyjaśnić wszelkie nie-jasności.

Oczywiście klasa posiada również meto-dy load(), add(), remove(), validate() o

funkcjonalności identycznej jak w poprzed-nich klasach.

I to wszystko!Choć może ciężko w to uwierzyć, to klasy które stworzyliśmy wystarczą do stworzenia w pełni funkcjonalnego sklepu. Za chwilę zobaczysz, w jaki sposób umiejętnie manipulując utworzo-nymi obiektami (zarówno polami jak metoda-mi) stworzymy w pełni funkcjonalny sklep in-ternetowy!

Minuta 30 – wystawaCzas zabrać się za kod właściwy. Na początek stworzymy naszą wystawę – stronę, która pre-zentować będzie klientowi dostępne produk-ty wraz z krótkim opisem oraz ich ceną. Po wybraniu produktu klient powinien zobaczyć dokładny opis, wraz ze zdjęciami oraz linkiem umożliwiającym dodanie produktu do wirtu-alnego koszyka.

Listing 7. Dodawanie produktów do koszyka

<?php

include 'config.php';

//jesli nie utworzono wczesniej obiektu w koszyku:

if(!isset($_SESSION['order']))

{

$_SESSION['order'] = new order();

}

//jeœli nie podano iloœci kupowanych produktów, wyœwietlamy formularz.

if($_POST['amount']!='')

{

//dodajemy towar.

$_SESSION['order']->addproduct($_POST['productid'], $_POST['amount']);

header("location:list.php");

exit;

}

else

{

?>

<form method="POST">

<input type="hidden" name="productid" value="<?php echo $_GET['productid'];?>">

Chce kupiæ <input type="text" name="amount" value="1"> sztuk.<br>

<input type="submit" value="Dodaj do koszyka">

</form>

<?php

}

?>

Listing 8. Dodanie zamówienia do bazy danych

<?php

include 'config.php';

//sprawdzamy, czy u¿ytkownik jest zalogowany

if(isset($_SESSION['user']->id))

{

header("location:login.php");

exit;

}

//uzupe³niamy dane zamówienia

$_SESSION['order']->userid = $_SESSION['user']->id;

$_SESSION['order']->date = now();

$_SESSION['order']->status = '';

$_SESSION['order']->add();

//kasujemy zawartoϾ koszyka

unset($_SESSION['order']);

//przekierowujemy klienta na stronê z podziêkowaniami

header("location:thanks.html");

exit;

?>

�����������������������������������

������������������������������

������

����������������������������������������

��������������������������

�������

������������������������������

���

�������������������

�������������������������

���

�������������

�����������

��������

������������������

Rysunek 3. Proces zakupów

Page 27: SDJ_11_2008_PL_E-Commerce

11/200826

E-commerceSklep internetowy w PHP i SQLite

www.sdjournal.org 27

Spis towarów……będzie pierwszą rzeczą którą zobaczy klient po wejściu do naszego sklepu. Dodat-kowo będzie to najprawdopodobniej strona która będzie najczęściej wyświetlana. Dla-tego należy zadbać, aby była czytelna. Nie powinniśmy więc przeładowywać jej ma-ło przydatnymi informacjami – wystarczy wyświetlić nazwę, początek opisu oraz cenę – to właśnie nią kieruje się większość użyt-kowników. Oczywiście informacje wyświe-tlane w naszym sklepie są tylko przykładem – ostateczny wygląd strony zależy od Czy-telnika.

Listing 5 przedstawia gotowy skrypt. Na po-czątku łączymy się z bazą – jeśli połączenie się nie uda, wykonywanie skryptu zostanie prze-rwane. Po połączeniu z bazą pobieramy z ba-zy danych wszystkie kategorie oraz tworzymy tablicę dwuwymiarową w której przechowuje-my pary – nazwa kategorii oraz jej unikalny identyfikator numeryczny. Dane te wyświe-tlamy w bloku <div> o nazwie categories. Umożliwi to prostą zmianę wyglądu sekcji (i całego sklepu) przy użyciu zewnętrznego ar-kusza stylów.

Przy wyświetlaniu strony należy spraw-dzić, czy klient wybrał już kategorie. Ponie-waż informacja o kategorii przesyłana jest jako parametr w adresie, wystarczy spraw-dzić wartość tej zmiennej. Jeśli użytkownik niczego nie wybrał – wyświetlamy komu-nikat powitalny zachęcający do obejrzenia naszej oferty. Jeśli kategoria jest wybrana – pobieramy z bazy danych identyfikatory pro-duktów należących do tej kategorii oraz two-rzymy obiekt klasy products , który wykorzy-stując metodę load() wypełnia wszystkie po-la klasy danymi produktu, które następnie są wyświetlane.

Szczegóły produktuPo wybraniu interesującego produktu kliento-wi powinny wyświetlić się dokładniejsze infor-macje – między innymi pełen opis, cena oraz wszystkie dostępne zdjęcia. Wyświetlenie da-nych przedmiotu nie powinno Ci już sprawić żadnego problemu – również tutaj tworzymy nowy obiekt typu product podając jako para-metr id projektu przesyłane w adresie. Trud-niejsze może wydawać się wyświetlenie wszyst-kich zdjęć produktu.

Kod realizujący to zadanie przedstawiony jest na Listingu 6.

Przypomnijmy – przyjęliśmy, że obrazki produktu o określonym id mają nazwę: id_(numer). Używając funkcji opendir() oraz

readdir() otwieramy folder ze zdjęciami i szu-kamy plików, które rozpoczynają się od tych znaków. Jeśli warunek ten jest spełniony – wy-świetlamy zdjęcia na stronie.

Ponownie, ze względu na ograniczoną obję-tość artykułu, po pełen kod skryptu odsyłamy na http://sdjournal.org

Minuta 45 – koszyk zakupówJednym z najbardziej charakterystycznych rzeczy w sklepach internetowych są niewąt-pliwie koszyki. To one będą przechowywać informację o produktach, które klient zde-cydował się kupić (zarówno o samym pro-dukcie jak i ilości zamówionych egzempla-rzy). Poprawne skonstruowanie koszyka jest bardzo ważne – w koszyku nie mogą pojawić się zakupy kogoś innego, nie mogą one rów-nież zniknąć.

Podstawowa zasada jest więc prosta – na-leży zagwarantować każdemu klientowi wła-sny koszyk. Można to oczywiście zrobić na wiele (lepszych lub gorszych) sposobów. Ko-szyk każdego klienta może być plikiem prze-chowywanym w jednym z folderów sklepu. Może być również wpisem w bazie danych. W obu przypadkach należałoby wybrać pewną unikalną cechę klienta, która sta-nowiłaby jego identyfikator. Pewnie część czytelników zaproponowałaby, aby takim identyfikatorem był adres IP komputera z którego korzysta użytkownik. Niestety ad-resu nie możemy wykorzystać – istnieją roz-wiązania, które umożliwiają współdzielenie adresu IP pomiędzy wieloma komputerami (najpopularniejsze to proxy oraz NAT). Je-śli dwóch naszych klientów korzystałoby z takiej sieci nie jesteśmy w stanie rozróżnić ich koszyków.

Innym rozwiązaniem jest wykorzysta-nie mechanizmu ciastek (cookies) do prze-chowania informacji o zawartości koszyka. Rozwiązanie to jest jednym z lepszych, choć również nie jest pozbawione wad. Nie może-my bowiem zagwarantować, że każdy nasz klient będzie miał włączoną obsługę ciastek w przeglądarce. Co prawda odsetek takich ludzi jest coraz mniejszy, jednak nie oznacza to, że ktoś z tej grupy nie będzie chciał sko-rzystać z sklepu. Odrzucamy to rozwiązanie również z innego powodu – w PHP od daw-na istnieje mechanizm nie posiadający wspo-mnianych wcześniej wad. Mowa oczywiście o sesjach, których zasada działania jest po-łączeniem zasad metod wcześniej wymie-nionych.

Dla każdego użytkownika generowany jest plik, w którym przechowywać możemy da-ne. Dodatkowo każdy użytkownik posiada unikalny identyfikator sesji (PHPSESSID) który pozwala na przyporządkowanie plików konkretnym użytkownikom. Identyfikator ten jest przesyłany pomiędzy podstronami wykorzystując ciastka, lub – jeśli przeglądar-

ka nie obsługuje Cookies – dodając do adre-su parametr. Jednak najlepsze w tym rozwią-zaniu jest to, że nie musimy w ogóle przejmo-wać się szczegółami implementacji tego me-chanizmu – wszystko załatwia PHP. Jedy-ne o co musimy zadbać, to wystartowanie mechanizmu sesji – realizujemy to funkcją session_start().

W plikach sesyjnych możemy przechowy-wać dowolny typ danych, mogą to być proste zmienne, tablice, a nawet obiekty – ograni-czają nas wyłącznie nasze potrzeby oraz wy-obraźnia.

My do budowy koszyka wykorzysta-my utworzoną wcześniej klasę order, któ-ra przechowuje informacje o zamówieniu. W rzeczywistości będziemy korzystać tylko z pola orderproducts, które jest tablicą za-mówionych obiektów.

Aby dodać nowy produkt do koszy-ka stworzyliśmy dodatkową metodę – addproduct(). Przyjmuje ona 2 parametry – ID dodawanego towaru oraz jego ilość.

Gdy klient złoży zamówienie, wystarczy uzupełnić obiekt danymi zamówienia i wywo-łać metodę add() która doda zamówienie do bazy danych. Oczywiście, możemy to wykonać tylko wtedy, gdy klient jest zalogowany – je-śli nie, przekierowujemy go na odpowiednią stronę. Cały proces dokonywania zamówienia przedstawiony jest na Listingu 8.

PodsumowanieWłaściwie mamy już działający sklep. Klient może przeglądać oferowane przez nas produk-ty, dodać je do koszyka i ostatecznie jeśli zde-cyduje się na zakup – zamówić je. Oczywiście, nie jest to pełna funkcjonalność sklepu – po-winieneś stworzyć jeszcze moduł dla obsługi sklepu, który będzie wyświetlał złożone za-mówienia, umożliwiał tworzenie kategorii oraz dodawanie towaru.

Nie powinno to jednak sprawić Ci już naj-mniejszego problemu – wystarczy wykorzy-stać metody load() oraz add() z odpowied-niej klasy. Jeśli jednak nie będziesz czegoś pewien – zachęcamy do przejrzenia kodu pełnego skryptu, umieszczonego na stronie http://sdjournal.org.

Kod jest dosyć szeroko skomentowany, sta-nowi więc dosyć dobre uzupełnienie niniejsze-go artykułu.

W Sieci

• http://www.php.net• http://www.sqlite.org

GRZEGORZ HIBNERAutor jest studentem Politechniki Poznańskiej

i pracownikiem firmy zajmującej się consultingiem

IT. Z PHP związany jest od pierwszych wersji PHP4.

Interesuje się szeroko pojętym programowaniem

(PHP, C/C++, C#, JAVA), bazami danych oraz za-

rządzaniem projektami.

Kontakt z autorem: [email protected]

Page 28: SDJ_11_2008_PL_E-Commerce

11/200828

E-commerceWydajny, elastyczny i przyjazny CMS

www.sdjournal.org 29

Textpattern to darmowy, elastyczny, ele-gancki, łatwy w użyciu system zarządza-nia treścią. Informację taką znajdziemy

na oficjalnej stronie projektu i chyba jest to naj-trafniejsza definicja której słuszności mam na-dzieję dowiodę.

Owszem, jest wiele innych systemów CMS, które możemy objąć podobną definicją. Dlate-go warto wspomnieć o tym co odróżnia Texpat-tern (w skrócie TXP) od innych systemów za-rządzania treścią.

Podobnie jak inne znane rozwiązanie te-go typu TXP wykorzystuje PHP, XHTML, ar-kusz CSS oraz bazę danych MySQL. Tak jak in-ne systemy zarządzania treścią może wykorzy-stać TXP do budowy witryny firmowej, porta-lu korporacyjnego czy prywatnego bloga.

Różnice odnajdziemy kiedy rozpoczniemy pracę nad budową własnej witryny w oparciu o prezentowane rozwiązanie. Wiele z systemów CMS z którymi się spotkałem oferowało możli-wość łatwego wprowadzania treści, dodawania artykułów oraz podstron.

Nie będąc zawodowym webmasterem użyt-kownik, po zainstalowaniu i wstępnym skon-

figurowaniu, mógł cieszyć się własną witryną WWW. Dla szukających szybkiej i w miarę bez-bolesnej metody na zaistnienie w Sieci to zna-komite rozwiązanie, które porównałbym do mieszkania w stanie pod klucz.

Po odmalowaniu, wyłożeniu wykładziny, umeblowaniu możemy cieszyć się własnym kątem. TXP natomiast przedstawiłbym jako mieszkanie w stanie surowym, w którym mo-żemy zdecydować o ilość i układzie pokoi, bu-dowie ścianek działowych, lokalizacji pomiesz-czeń.

TXP oferuje większą swobodę. Dostajemy solidny i stabilny szkielet na którym realizuje-my naszą wizję. W minimalnym stopniu ogra-niczona jest wolność twórcza. Dzięki zastoso-waniu przejrzystej składni opartej o charakte-rystyczne znaczniki, dokonanie zmian odbywa się w intuicyjny i prosty sposób.

InstalacjaDo prawidłowej instalacji, TXP wymaga działa-jącej platformy LAMP w postaci tria serwerów – WWW, PHP i MySQL.

Minimalne wymagania to PHP w wersji 4.3 lub wyższej wraz z obsługą MySQL (my-sql extension) i XML (XML extension) , serwera baz danych MySQL w wersji 3.23 lub wyższej. Rekomendowane jest posiadanie PHP od wersji 4.4.1 lub od wersji 5.0.2 oraz MySQL w wersji 4.2.7 lub wyższej.

Zalecany jest również serwer Apache od wer-sji 1.3 lub 3.0 z włączonym modułem wsparcia dla przyjaznych linków (clean URLs) mod_rew-riter.

Po szczegółowe informacje odnośnie wyma-gań warto zajrzeć na domową stronę projektu http://www.textpattern.com.

W dalszej części zakładam, iż posiadamy za-instalowane, skonfigurowane i działające środo-wisko dla TXP.

LicencjonowanieTXP jest darmowym rozwiązaniem open sour-ce objętym licencją GNU GPL (General Public License). Oznacza to, że możemy zarówno w ce-lach komercyjny jak i prywatnych wykorzysty-wać, dystrybuować i modyfikować CMS.

Należy pamiętać, iż zewnętrzne rozwiązania zwiększające funkcjonalność TXP, plugin'y, do-datki itp. mogą być objęte odrębnymi warunka-mi licencyjnymi.

Od wersji 4.1 planowane jest objęcie TXP li-cencją BSD (Berkley Software Distrybution).

Zgodnie z zasadami licencji Textpattern nadal pozostanie darmowym rozwiązaniem. Zasady licencji BSD czynią zasady korzystania nawet bardziej liberalnymi.

Proces instalacjiŚciągamy paczkę instalacyjną z witryny projekt. Rozpakowaną zawartość kopiujemy do wybra-nego katalogu naszego serwera w obrębie któ-rego powstawać będzie nasza witryna np. http://localhost/cms

W oknie przeglądarki wpisujemy adres na-szej lokalizacji wskazując na podkatalog textpat-tern, http://localhost/cms/textpattern/.

Pojawia się ekran powitalny na którym musimy dokonać wyboru domyślnego języka. TXP posia-da wsparcie dla języka polskiego, jednak wybierz-my język angielski. Uczyni to zdobytą wiedzę bar-

Wydajny, elastyczny i przyjazny CMS

TXP nie jest tak popularny jak np. Joomla. Nie posiada tak rozbudowanej listy plugin'ów i dodatków. Mniej znany, nie oznacza jednak gorszy czy też mniej wydajny. Stanowi ciekawą alternatywę i chociażby tylko ze względu na to warto poszerzyć horyzonty i przyjrzeć się rozwiązaniu bliżej. Niniejszy artykuł pełni rolę wprowadzenia.

Dowiesz się:• Zdobędziesz podstawową wiedzę na temat

CMS Textpattern;

• Dowiesz się jak zainstalować i przygotować

TXP do pracy, skonfigurować podstawowe i

zaawansowane opcje.

Powinieneś wiedzieć:• Znać podstawy XHTML, CSS i PHP;

• Posiadać podstawową wiedzę na temat ser-

werów WWW oraz witryn internetowych zbu-

dowanych w oparciu o system CMS;

• Orientować się w tematyce budowy wydaj-

nych stron WWW.

Poziom trudności

Poznajemy Textpattern cz.1

Page 29: SDJ_11_2008_PL_E-Commerce

11/200828

E-commerceWydajny, elastyczny i przyjazny CMS

www.sdjournal.org 29

dziej uniwersalną, poza tym większość dokumen-tacji dostępna jest w języku angielskim.

W następnym oknie musimy podać nazwę użytkownika MySQL, hasło, adres serwera My-SQL oraz nazwę istniejącej bazy danych (pro-ponuję stworzyć wcześniej pustą bazę np. z wy-korzystaniem phpMyAdmin).

Możemy również wprowadzić ścieżkę do in-stalacji (Site path) oraz adres URL (Site URL). Pozostawiam domyślne wartości bez zmian i przechodzimy dalej (Next).

W oparciu o wprowadzone dane zostaje auto-matycznie wygenerowany skrypt konfiguracyjny.

Zaznaczamy cały kod, za pomocą np. notat-nika tworzymy plik config.php i wklejamy kod. Zapisany plik przesyłam na serwer do podkata-logu textpattern.

Jeśli wykonaliśmy wszystko poprawnie, po kliknięciu przycisku I did it ukaże się kolejne okno w którym wprowadzamy dane o admini-stratorze (Publisher).

Podajemy pełną nazwę użytkownika, login, hasło oraz istniejący adres email.

Po kliknięciu na przycisk Next zostanie utwo-rzona odpowiednia struktura. Wstrzymujemy oddech i naszym oczom ukazuje się informacja o pomyślnej instancji. Możemy zalogować się do webowego interfejsu użytkownika.

GUI zorganizowane jest w postaci paneli lub też zakładek – Content, Presentation, Admin, View Site. Pod każdą z zakładek kryją się dodat-kowe panele ze szczegółowymi opcjami konfi-guracyjnymi.

Przejdźmy do zakładki Admin. Pierwszym krokiem jest wykonanie diagnostyki instalacji.

Panel podzielony jest na dwie części w pierw-szej Preflight check otrzymujemy ostrzeżenia ze-brane po wstępnym sprawdzeniu instalacji.

W oknie Diagnostyki info znajdują się szcze-gółowe dane dotyczące m.in. konfiguracji ser-wera WWW, zainstalowanych modułów ser-wera, ustawień lokalnych itd.

KonfiguracjaPanel konfiguracyjny podzielony jest na trzy części Basic, Advanced, Langugae.

W zakładce Language mamy możliwość zde-finiowania używanego języka, wyboru języków dodatkowych z dostępnej listy, a także instalacji pliku zewnętrznego.

Basic zawiera opcje podstawowej konfigura-cji. Definiujemy Site name (nazwa witryny), Site slogan (motto), Site URL (domyślny katalog in-stalacyjny), strefę czasową Time Zone, automa-tyczną zmianę czasu letni/zimowy, format da-ty używany przez TXP Data format, oraz for-mat daty którą opatrzone będą dodawane przez nas artykuły.

Production status pozwala zdefiniować jeden z trzech stanów w który aktualnie znajduje się witryna.

Debugging umożliwia identyfikację problemów z funkcjonowaniem szablonu, plugin'ów lub do-danych skryptów. Testing to tryb wykorzystywany

podczas normalnej pracy z witryną np. konfigura-cja, zamiany ustawień, modyfikacja treści.

Oba statusy powodują wyświetlanie infor-macji o czasie budowy poszczególnych pod-stron, ilości wysłanych zapytań MySQL oraz zużyciu pamięci.

W trybie Debugging wszystkie napotkane podczas budowania witryny tagi widoczne są również w postaci kodu XHTML. Status Live to publikacja w trybie normalnego użytkowa-

nia, ustawiamy kiedy chcemy aby nasz projekt ujrzał światło dzienne.

Use textile – opcja definiuje domyślny edy-tor TXP. Textile jest ciekawym rozwiązaniem znacznie upraszczającym budowę treści zgod-nej z XHTML. Edytor wykorzystuje uproszczo-ną składnię dzięki czemu szybko możemy dodać treść, która będzie prezentowana w postaci po-prawnego kodu XHTML. Pseudokod jest automa-tycznie formatowany do właściwej postaci.

Rysunek 1. Strona powitalna

Rysunek 2. Konfiguracja dostępu do bazy danych

Rysunek 3. Wygenerowany skrypt konfiguracyjny

Page 30: SDJ_11_2008_PL_E-Commerce

11/200830

E-commerceWydajny, elastyczny i przyjazny CMS

www.sdjournal.org 31

Ustawienie opcji na Convert linebreaks igno-ruje wszystkie znaczniki poza znacznikiem przełamania wiersza. Leave text untouched wy-łącza opcje autofrmatowania.

Accept commnets? Włączenie/wyłączenie opcji umożliwiającej użytkownikom zamieszczanie komentarzy. Po ustawieniu na Yes, na ekranie pojawiają się dodatkowe opcje definiujące spo-

sób zamieszczania komentarzy. W niniejszym artykule pominąłem omawianie szczegółów związanych z publikacją komentarzy.

Po zapisaniu konfiguracji podstawowej prze-chodzimy do konfiguracji opcji zaawansowa-nych – Advanced. Opcje konfiguracyjne po-dzielone są na kilka części. Omówię te najważ-niejsze.

Admin

• Image directory – definiuje domyślny kata-log do którego będziemy zaciągać zdjęcia i ilustracje;

• File directory path – definuje ścieżkę do kata-logu przechowywania zaciągniętych plików;

• Use ISO-8859-1 encoding in e-mails sent (de-fault is UTF-8) – zmiana kodowania w ge-nerowanych wiadomościach e-mail.

Style

• Use raw editing mode by default? Ustawienie opcji na Yes spowoduje, że do edycji arku-sza stylów wykorzystywany będzie edytor z wyłączonym autoformatowaniem, praca będzie odbywała się z surowym kodem.

Do dyspozycji mamy również edytor organizu-jący arkusz stylów do postaci tabeli, grupującej selektory i klasy w przejrzystą formę. Aby użyć edytora Textpattrern zmieniamy opcje na No.

PublishNajważniejsze z punktu widzenia prawidłowe-go i bezpiecznego funkcjonowania witryny są opcje zawarte w sekcji Publish.

• Prevent widowed words in article titles? Włą-czenie opcji zapobiega powstawaniu jed-nowyrazowych linii w tytułach artyku-łów. Jeśli TXP wykryje, iż w tytule wystą-pi przełamanie wiersza pomiędzy przed-ostatnim, a ostatnim wyrazem automa-tycznie zostaje dodany odpowiedni znacz-nik XHTML. Dwa ostanie wyrazy będą traktowane jako jeden;

• Artricle use excerpts? Definiuje czy artyku-ły będę opatrzone skrótami tzw. zajawka-mi których rozwinięcie stanowi właściwy artykuł;

• Allow from override? Kiedy opcja jest włą-czona możemy wybranym artykułom nadać odmienny format bez konieczno-ści separowania poprzez umieszczania w osobnych sekcjach;

• Send „lats-Modified” header? Włączenie opcji powoduje, że do przeglądarki odwie-dzającego wysłane zostaje zapytanie o wer-sje witryny przechowywanej w cash'u. Je-śli witryna nie zmieniła się Textpattern nakazuje przeglądarce korzystanie z wersji znajdujące się w cash'u. Rozwiązanie po-zwala ograniczyć czas ładowania witryny oraz zmniejszyć zapotrzebowanie na prze-pustowość łącza klienta;

• Attach titles permalinks? Zaznaczenie powo-duje, że Textpattern tworzy przyjazne linki w oparciu o nazwę artykułu. Opcja wyma-ga włączonej obsługi przyjaznych linków;

• Ping Textpattern? Zaznaczenie umożliwia po-wiadomienie zespołu Textpattern.com o fakcie istnienia i działania naszej witryny w Sieci;

Rysunek 4. Wprowadzenie danych użytkownika

Rysunek 5. Ekran logowania

Rysunek 6. Konfiguracja opcji podstawowych

Page 31: SDJ_11_2008_PL_E-Commerce

11/200830

E-commerceWydajny, elastyczny i przyjazny CMS

www.sdjournal.org 31

• Ping ping-o-matic.com? Wysyłanie powia-domień do wyszukiwarek o aktualizacji strony za pośrednictwem serwisu http://pingomatic.com/;

• Logs expire after how many days? Wyrażony w dniach okres przechowywania logów o odwiedzających w bazie danych TXP;

• Maximum URL length (in characters). Defi-niuje maksymalną długość adresów URL. Przydatna opcja zabezpieczająca witrynę przed atakami typu przeładowanie bufora przy użyciu ekstremalnie długich linków;

• Use plugins? Włączenie obsługi plugin'ów. Warto wyłączyć w przypadku konieczno-ści identyfikacji problemów z funkcjono-waniem witryny;

• Use admin-side plugins? Włączenie/wyłączenie plugin'ów interfejsu administratora.

• Allow PHP in pages? Włączenie funkcjonal-ności umożliwi użycie kodu PHP w sza-blonie witryny po umieszczeniu w znacz-nikach <txt:php>...</txp:php>;

• Allow PHP in articles? Opcja nie zalecana ze względów bezpieczeństwa. Umożli-wia stosowanie kodu PHP w treści arty-

kułów, co jest wbrew postulatowi o od-dzieleniu warstwy logicznej od warstwy prezentacji;

• Allow raw PHP? Zalecane jest wyłączenie funkcjonalności. Rozwiązanie przydatne w sytuacji upgrade witryny z wersji wcze-śniejszych, gdzie kod PHP stosowany był jawnie w treści artykułów.

Dodawanie nowego użytkownikaPrzejdźmy do zakładki Users. Oprócz zmia-ny danych dodanego wcześniej administratora (nazwa, email, nowe hasło, uprawnienia) ma-my możliwość dodania nowych użytkowników o zróżnicowanych prawach dostępu.

• Publisher – użytkownik o pełnych upraw-nieniach. Może tworzyć, edytować i usu-wać artykuły, a także zarządzać komen-tarzami i odnośnikami. Publisher może zmienić status artykułów, konfigurację witryny, zarządzać sekcjami i artykułami oraz zarządzać użytkownikami;

• Managing Editor – posiada podobne uprawnienia co Publisher za wyjątkiem

tworzenia, usuwania i edycji uprawnień innych użytkowników;

• Copy Editor – może modyfikować artyku-ły, odnośniki, komentarze użytkowników witryny, ponadto posiada uprawnienia do zmiany szablonu i formularzy;

• Staff Writer – tworzy, edytuje, publikuje i usuwa artykuły. Może zaciągać ilustracje i zdjęcia;

• Freelancer – może tworzyć i edytować ar-tykuły oraz zmieniać ich status. Publikacja wymaga jednak akceptacji użytkownika o roli Managing Editor lub Publisher;

• Designer – odpowiada za kreację wyglądu witryny. Posiada pełen dostęp do szablonu oraz stylów CSS. Nie może jednak zmie-niać publikowanej treści.

Pozostałe paneleZakładka Visitor Logs nie wymaga szerszego omó-wienia. Mamy możliwość przeglądania zebranych logów, filtrowania zawartości i szczegółowego wy-szukiwania informacji o odwiedzających.

Plugins umożliwia instalację dodatków. Pro-ces instalacji jest specyficzny i polega na wkleje-niu odpowiedniego kodu w polu Install plugin i zaciągnięciu na serwer (Upload).

Bardzo ciekawą funkcjonalność oferuje za-kładka Import. Mamy możliwość importowa-nia zawartości witryn opartych o inne platfor-my. W wersji 4.0.6 Textpattern wspiera import z systemów Movable, WordPress, b2 i Blogger.

Importowaną treść możemy przypisać do od-powiednich sekcji oraz nadać wybrany status. Nieco rozczarowuje brak popularnych syste-mów CMS.

PodsumowanieMam nadzieję, że Textpattern zainteresował Cię drogi Czytelniku. Zapoznałeś się z proce-sem instalacji oraz szczegółowej konfiguracji. Wspólnie udało się nam stworzyć szkielet, na którym zbudujemy witrynę.

W następnej części ożywimy nasz projekt do-dając treść, zmieniając domyślny wygląd po-przez edycję szablonu i arkusza CSS. Zainstalu-jemy wybrany plugin i skonfigurujemy witrynę na nasze potrzeby.

W Sieci

• http://www.textpattern.com – strona do-mowa projektu

Rysunek 7. Konfiguracja opcji zaawansowanych

Rysunek 8. Dodawanie użytkowników

KRYSTIAN RAJSKIAutor interesuje się tworzeniem aplikacji webo-

wych oraz technologiami internetowymi. Związa-

ny z grupą ProgInn. Na co dzień pracuje jako So-

ftware Test Engineering w firmie ADVA Optical Ne-

tworking.

Kontakt z autorem: [email protected],

http://www.p-innovations.com

Page 32: SDJ_11_2008_PL_E-Commerce

11/200832

Programowanie PHPPorównanie opensource-owych platform blogowych

www.sdjournal.org 33

Wiele firm (np. Microsoft) zaczęło wykorzystywać platformy blogo-we jako formę kontaktu z klien-

tem, kontaktu, choć częściowo anonimowe-go, jednak bardziej przyjaznego. Równocześnie wraz z tym boomem rozwinęło się PHP i stało powszechnie stosowanym językiem programo-wania w aplikacjach internetowych. Natural-nym było, więc, że wiele platform blogowych powstało właśnie w oparciu o niego i zazwyczaj w sprzężeniu z systemem baz danych MySQL. W temacie artykułu podkreśliłem właśnie tech-niki (PHP + bazy danych), na jakich omawiane w artykule blogi bazują. Powodem tego jest fakt, że konkurencyjne rozwiązania (Perl, Ruby-OnRails) również oferują darmowe, opensour-ce-owe platformy blogowe (odpowiednio Mo-vableType, Typo etc.). We wstępie chciałbym jeszcze wytłumaczyć powody wybrania oma-wianych platform. Wordpress i Texpattern są zapewne wielu czytelnikom doskonale znane, jeśli nie z praktyki to chociażby ze słyszenia. Dwie ostatnie aplikacje wybrałem ze względu na to, iż pracują w trybie Multi – Users (MU), co pozwala na prowadzenie wielu niezależnych

blogów w oparciu o jedną platformę. Jako, że temat jest obszerny przy omawianiu każdego ze skryptów chciałbym skupić się na rzeczach podstawowych i najważniejszych a więc kwe-stia związana z łatwością i intuicyjnością zarzą-dzania blogiem, sposobem tworzenia własnych them-ów (sposoby szablonowania), dostępność plugin-ów (rozszerzeń), dokumentacja aplika-cji oraz wsparcie techniczne.

Wordpress (wersja 2.3.2)Poczynając od instalacji a na zarządzaniu koń-cząc można śmiało powiedzieć, że Wordpress jest skryptem zarówno stabilnym jak i przyja-znym użytkownikowi. Zarówno grafika pane-lu administracyjnego jak i jego filozofia czynią go bardzo łatwym w opanowaniu i intuicyjnym w zarządzaniu. Co ważne, a o czym pisałem na wstępie, dostosowanie panelu administracyjne-go do obsługi w ojczystym języku jest łatwiej-sza niż strony frontowej, nawet dla osób niezna-jących PHP. Rozwijanie możliwości bloga przez wgrywanie własnych them-ów czy plugin-ów również nie przysparza najmniejszych proble-mów. Dodatkową zaletą jest obszerna i prosta możliwość konfiguracji systemu. Wordpress został zaprojektowany tak, że doskonale nada-wać się może nie tylko jako skrypt typowo blo-gowy, ale również jako bardzo dobry CMS do prowadzenia małych i średnich stron interne-towych.

Them-yWordpress jak wszystkie omawiane w tym ar-tykule skrypty posiada system szablonów moż-liwych do łatwej instalacji. Osoby, które nie mają wiedzy, a które nie chcą korzystać z do-myślnych, po instalacji mogą pobrać setki, wie-le them-ów. Skupię się jednak na omówieniu kwestii technicznej pracy z szablonami tego skryptu. Wordpress nie korzysta z systemu sza-blonów takiego jak Smarty, bądź HTML_Tem-plate_IT (parser klas Pear). Odbija się to lekko na wydajności gdyż mechanizmy cache-owania w wymienionych wcześniej systemach znacz-nie przyspieszają przetworzenie i wyświetlenie widoków. Kolejnym bardzo poważnym manka-mentem jest kwestia tego, że wiele słów zaszy-tych jest na stałe w szablonie. Takie rozwiązanie uniemożliwia łatwą internacjonalizację strony frontowej i wymaga ręcznej edycji. Włączenie mechanizmu cache-owania możliwe jest przez instalacje dodatkowych rozszerzeń jak plugin WP-Cache.

Plugin-yDomyślnie po instalacji mamy możliwość ko-rzystania z dwóch dostarczonych domyślnie plugin-ów.

Zamiast jednak opisywać przykładowe z nich, tak w tym skrypcie jak i pozostałych chciałbym się skupić bardziej na teoretycznych kwestiach. Jak wiadomo by napisać własne rozszerzenie, potrzebna jest znajomość, co najmniej PHP. Co jednak jest jeszcze bardzo ważne to dokumen-tacja gotowego skryptu, oraz tutoriale, pomaga-jące deweloperom w pisaniu własnego plugin-a. W przypadku Wordpress-a, nie można mieć żad-nych zastrzeżeń w tych względach. Na oficjalnej stronie projektu, umieszczono bardzo wiele in-formacji na temat rozwoju własnych rozszerzeń a także, co jest ogromnym ułatwieniem, można

Opensource-owe platformy blogowe

W przeciągu ostatnich lat blogi internetowe zjednały sobie wielką popularność wśród użytkowników internetu. Przestały być tylko i wyłącznie formą pamiętników a stały się miejscem wymiany zdań pomiędzy różnymi środowiskami jak choćby programistów.

Dowiesz się:• O najpopularniejszych platformach blogo-

wych napisanych w PHP;

• O ich obsłudze, możliwościach i porównaniu z

rozwiązaniami konkurencyjnymi.

Powinieneś wiedzieć:• Powinieneś mieć wiedzę na temat zarządzania

systemami CMS (instalacja systemów, obsługa

panelów);

• Powinieneś znać PHP i umieć konfigurować

bazy danych MySQL.

Poziom trudności

Porównanie oparte o PHP i bazy danych

Page 33: SDJ_11_2008_PL_E-Commerce

11/200832

Programowanie PHPPorównanie opensource-owych platform blogowych

www.sdjournal.org 33

tam znaleźć API przygotowane właśnie pod tym kątem. Osoby nieznające PHP, mają szeroki wa-chlarz dostępnych rozszerzeń, dostępnych całko-wicie za darmo a oferujących duże możliwości rozszerzenia swojego bloga o dodatkową funk-cjonalność.

Wsparcie techniczne i dokumentacjaTak jak pisałem już w poprzednich paragrafach wsparcie techniczne dla opisywanego skryp-tu nie pozostawia dla mnie nic do życzenia. Podobnie ma się sytuacja z techniczną doku-mentacją (API). Dzięki ogromnej popularno-ści Wordpress-a osoby nieznające języka angiel-skiego, dzięki dobremu suportowi w wielu kra-jach nie miałyby żadnego problemu z pracą z tym skryptem.

Zalety

• stabilność skryptu;• intuicyjność i przyjazność środowiska pra-

cy nawet dla niezaawansowanych użyt-kowników;

• możliwość pisania własnych them-ów z samą znajomością PHP (dodatkowo też API);

• nieduże wymagania (dla omawianej wer-sji: PHP 4.2, MySQL 4.0, opcjonalnie mod _ rewrite włączony na serwerze) sys-temowe oraz lekkość skryptu;

• duża popularność a co za tym idzie bardzo dobre wsparcie techniczne i dokumenta-cja, duże możliwości rozwoju skryptu za-równo przez początkujących jak i zaawan-sowanych użytkowników;

• możliwość wykorzystania jako pełnego CMS-a.

Wady

• co może wydać się niekonsekwencją, jed-nak ze względu na dużą popularność wie-le dostępnych rozszerzeń jest niestabil-nych i napisanych na niskim poziomie;

• brak dobrego sposobu internacjonalizacji frontu strony;

• sposób szablonowania ze względu na czy-telność oraz wydajność;

• obsługa tylko i wyłącznie systemu baz da-nych MySQL;

• wiele plugin-ów wykorzystujących Java-Script korzysta z metod niezgodnych z wytycznymi DOM level 1 i 2, oraz spe-cyfikacji języka JavaScript (ECMAScript) opracowanego przez organizację ECMA;

• Wordpress pracujący w trybie MU jest nie-stabilny, dlatego wyłączyłem jego opis i skupiłem się na możliwościach trybu dla jednego użytkownika.

Textpattern (wersja 4.0.6)Poczynając od instalacji jak i zarządzaniu same-go panelu Textpattern również jest skryptem

intuicyjnym. Mimo, że na oficjalnej stronie projektu opisywany jest jako CMS a nie platfor-ma blogowa, wydaje się jednak, że został stwo-rzony z myślą o tym drugim przeznaczeniu. Co prawda możliwości konfiguracyjne skryptu są bogate niemniej, dotyczą one przede wszyst-kim właśnie ustawień związanych z prowadze-niem bloga. To, co na pewno jest istotną kwe-stią i wiele osób może zachęcić, to możliwość wyboru języka zarówno instalacji jak i prowa-dzenia bloga już w pierwszym kroku konfigu-racji skryptu. Dla osób myślących o wykorzysta-niu go tylko i wyłącznie jako skrypt blogowy i niemyślących o dalszym rozwoju swojej strony, najpoważniejszym mankamentem wydawać się może tylko ubogi edytor tekstowy WYSIWYG służący do wprowadzania i edycji wpisów.

Them-yTextpattern dysponuje dość różnym podej-ściem do systemu szablonów. Na stronie, twórcy zaznaczają, że skrypt nie posiada ta-kowego systemu jak większość pozostałych skryptów. Podejściem przypomina bardziej serwisy blogowe jak http://www.blox.pl czy http://www.blogger.com, ze względu na we-wnętrzny system znaczników. Jest to rozwią-zanie ciekawe i wydajne, jednak poważnym ograniczeniem jest fakt, braku pełnej inge-rencji w widoki, bez dokładniejszego pozna-nia struktury skryptu. Edycja them-ów moż-liwa jest z poziomu panelu administracyjne-go, gdzie tak jak napisałem możemy ingero-wać zarówno w strukturę HTML/XHTML jak i arkusze CSS. Dla Textpattern-a, dostęp-

Tabela 1. Zestawienie platform

Wordpress Textpattern b2evolution LifeType

Wymagania plat-formy

PHP 4+MySQL

PHP 4+MySQL

PHP 4+MySQL

PHP 4+MySQL

Sposób szablono-wania

Pełna możliwość edycji, jednak w przypadku chę-ci dostępu do cał-kowitego forma-towania przez au-tora wymaga zna-jomości choćby podstaw PHP

System szablono-wania ciągle nie jest w fazie koń-cowej i trwają nad nim prace

Pełna możliwość edycji szablonów

Pełna możliwość edycji szablonów z ograniczeniami spowodowanymi systemem Smarty

Importowanie danych z innych platform

obsługa impor-tu z ponad 20 in-nych platform

b2, Blogger, Mo-vable Type, Word-press

Obsługa między innymi: Word-Press, Movable Type, Blogger, Li-veJournal

Brak

Rozmiar skryptu/prędkość wyko-nywania *

średni skrypt/średni czas wyko-nania

duży skrypt/dość szybki czas wyko-nania

niewielki skrypt/szybki czas wyko-nania

duży skrypt/średni czas wy-koanania (moż-liwość włącze-nia cache-owania dzięki szablonom Smarty)

Optymalizacja pod silniki wyszu-kiwarek

Dobra obsługa przyjaznych URL-i, wiele plugin-ów przydatnych do optymalizacji

Dobra obsługa przyjaznych URL-i, istnieją plugin-y do optymalizacji

Dobra obsługa przyjaznych URL-i, istnieją plugin-y do optymalizacji

Dobra obsługa przyjaznych URL-i, istnieją plugin-y do optymalizacji

Społeczność/wsparcie/dokumentacja

Bardzo wiele użytkowników/wsparcie w wie-lu językach, rów-nież wspar-cie komercyjne/bardzo dobra do-kumentacja

Dość duże gro-no użytkowni-ków/ ograni-czone wspracie w językach po-za angielskim/obszerna doku-mentacja

Średnie grono użytkowników, przede wszystkim osoby o zaawan-sowanej wiedzy o PHP i admini-stracji/ ograni-czone wspracie w językach po-za angielskim/obszerna doku-mentacja

Średnie grono użytkowników, przede wszystkim osoby o zaawan-sowanej wiedzy o PHP i admini-stracji/ ograni-czone wspracie w językach po-za angielskim/obszerna doku-mentacja

Domyślny format wyjściowy da-nych

XHTML 1.0 Trans-itional

XHTML 1.0 Trans-itional

XHTML 1.0 Trans-itional

XHTML 1.0 Strict

Edytor WYSIWYG Tak Tak Tak Tak

Obsługa kanałów informacyjnych RSS/Atom

Tak Tak Tak Tak

* testy przeprowadzone przy użyciu rozszerzenia Xdebug

Page 34: SDJ_11_2008_PL_E-Commerce

11/200834

Programowanie PHPPorównanie opensource-owych platform blogowych

www.sdjournal.org 35

nych jest wiele gotowych tematów, z których niektóre znaleźć można w odnośnikach na końcu artykułu.

Plugin-yDecydując się na pracę z Textpattern-em z jednej strony możemy być zaskoczeni lekkością skryp-tu, jego minimalizmem i łatwą obsługą, z dru-giej możliwościami, jakie daje przy prowadze-niu bloga. Właśnie dzięki plugin-om, o bardzo dużych możliwościach jest to osiągalne. W mo-mencie powstawania artykułu na równoległej do strony http://www.textpattern.com witrynie http://www.texpattern.org można było znaleźć prawie pięćset rozszerzeń i plugin-ów dla opi-sywanego skryptu. Osoby zainteresowane pisa-niem własnych dodatków, również dostępnych jest wiele tutoriali i dobra dokumentacja skryp-tu. Również ciekawą kwestią jest sposób pracy z plugin-ami opierający się też o autorski dla Text-pattern-a system znaczników/tagów. Więcej in-formacji na ten temat można znaleźć w linkach na końcu artykułu.

Wsparcie techniczne i dokumentacjaNa oficjalnej stronie skryptu, możemy zna-leźć odnośniki do pełnej dokumentacji stwo-rzonej przez użytkowników i twórców Text-pattern-a, która została nazwana TextBook i za-wiera wszystkie niezbędne informacje zarów-no dla początkujących jak i zaawansowanych użytkowników. Dokumentacja w dniu powsta-wania artykułu dostępna była w kilkunastu ję-zykach (bez języka polskiego). Na temat Texpat-tern-a została napisana również książka: Text-pattern, Solutions, która jest uznana za oficjal-ną dokumentację dostępną w formie książko-wej. Pozycja ta jest w pełni dostępna i możliwa do nabycia w internecie.

Zalety

• stabilność skryptu;• intuicyjność i przyjazność środowiska na-

wet dla niezaawansowanych użytkowni-ków;

• lekkość skryptu;• zaawansowane możliwości jako skrypt blo-

gowy;• wiele dostępnych them-ów i plugin-ów;• szeroki zakres języków instalatora dla pa-

nelu i bloga;• bogata dokumentacja i duża ilość artyku-

łów poświęconych Textpattern-owi;• ze względu na strukturę kodu, skrypt jest

bardzo wydajny i szybki.

Wady

• mniejsza popularność w porównaniu do Wordpress-a również jeśli chodzi o zaple-cze programistyczne;

• obsługa tylko i wyłącznie systemu baz da-nych MySQL;

• wbrew oficjalnemu opisowi skrypt nie po-siada bogatych możliwości jako CMS i na-daje się raczej na platformę blogową;

• mocno strukturalny kod co w pewien spo-sób ogranicza możliwość rozwoju w szyb-ki i łatwy sposób;

• brak dobrego systemu szablonowania o pełnych możliwościach.

b2evolution (wersja 2.4.0)Tak jak w pozostałych platformach tak i w przypadku b2evolution instalacja jest bar-dzo prosta i przebiega w trybie graficznym. Ze względu na tryb MU jako główne prze-znaczenie tego skryptu, panel administra-cyjny jest już jednak dużo bardziej zaawan-sowany. Niestety po zainstalowaniu pojawia się problem z polskimi znakami. Mimo, że w wykazie dostępnych kodowań i języków znajduje się język polski niestety nawet po jego wybraniu blog niepoprawnie interpre-tował polskie znaki. Na oficjalnym forum su-portu również nie udało mi się znaleźć roz-wiązania, stąd opis poniższych możliwości opieram na dyskusjach jakie znalazłem w in-ternecie oraz dokumentacji skryptu. Prze-glądając panel administracyjny w pierw-szym momencie, można mieć duże proble-my z ogarnięciem wszystkich jego możliwo-ści. Zagłębiając się dalej, łatwo jednak od ra-zu rozpoznać ogromne możliwości jakie da-je b2evolutions. Można stwierdzić, że duży nacisk położono na bezpieczeństwo skryp-tu choćby po tym jak wiele opcji zarządza-nia uprawnieniami użytkowników oferuje panel. Oczywiście poza wieloma możliwo-ściami ustawień samego trybu MU przez ad-ministratora również wiele ustawień doty-czy samego sposobu prowadzenia konkret-nego bloga.

Them-ySystem szablonów b2evolution spośród 4 opisywanych tu platform najbliższy jest po-dejściu jakie oferuje Wordpress. Różnicą na pewno jest użycie słownika do łatwiejszej in-ternacjonalizacji strony frontowej. Tutaj jed-nak znów natrafiłem na problem, mimo usta-wienia jakiegokolwiek z dostępnych języków, zarówno front strony jak i panel administra-cyjny nie zareagowały na zmienione usta-wienia. Plusem jest spora ilość darmowych them-ów do ściągnięcia z oficjalnej strony platformy.

Plugin-yW przypadku plugin-ów, b2evolution również oferuje na swojej stronie duży wybór. Podzielo-ne są zarówno kategoriami jak i wersjami wy-dania. Co bardzo ważne dokumentacja wspo-magająca tworzenie własnych rozszerzeń jest bardzo szczegółowa. Brak natomiast jest do-brych tutoriali, a względna popularność plat-formy (tryb MU), powoduje również znacznie

mniejszą ilość informacji do znalezienia w in-ternecie.

Wsparcie techniczne i dokumentacjaNiestety, jak pisałem na początku, po poja-wieniu się dość poważnego problemu nie uzyskałem pomocy. Mimo iż b2evolution wydaje się wyjątkowo wielojęzycznym skryp-tem to dokumentacja choć dobrze przygoto-wana, dostępna jest zaledwie w dwóch języ-kach w tym oczywiście w języku angielskim. Ocena powyższa jak powiedziałem opiera się mniej na własnym doświadczeniu, bardziej na informacjach przeczytanych w internecie. To samo dotyczy listy zalet i wad jakie przed-stawiam.

Zalety

• możliwość pisania własnych them-ów z sa-mą znajomością PHP (dodatkowo API);

• duże możliwości administracyjne;• jak na specyfikę przeznaczenia (tryb MU)

duża ilość them-ów i plugin-ów;• czytelna i bogata dokumentacja;• popularność w swojej kategorii;• możliwość obsługi kilku systemów baz da-

nych.

Wady

• mała popularność w porównaniu z plat-formami dla trybów blogowych przezna-czonych dla jednego użytkownika;

• brak dobrego wsparcia na oficjalnym fo-rum suportu przy bardziej skomplikowa-nych zagadnieniach;

• niewiele informacji w języku innym niż angielski;

• duży brak kompatybilności pomiędzy wersjami.

LifeType (wersja 1.2.5)LifeType jest skryptem wymagającym zdecy-dowanie większej wiedzy w porównaniu za-równo z Wordpress-em jak i Texpattern-em. Choć miałem raczej opisywać ogólnie pewne aspekty a nie wnikać w szczegóły chciałbym jednak podsunąć pewne rozwiązanie dla osób instalujących skrypt po raz pierwszy. Otóż w pliku wizard.php, czyli skrypcie instalacyjnym bloga w linii siódmej znajduje się następujący zapis: set_time_limit (5 * 3600), zapobie-ga on samoczynnemu wykonywaniu się po-szczególnych czynności w czasie instalacji je-żeli trwają powyżej określonego czasu. Insta-lowałem LifeType-a lokalnie oraz na serwerze firmy home.pl w obydwu przypadkach zapis ten niestety powodował zatrzymanie proce-su instalacji w momencie tworzenia i wypeł-niania tabel w bazie. Polecam więc zakomen-towanie tej linii.

Przechodząc do panelu administracyjne-go użytkownik z prawami administratora za-

Page 35: SDJ_11_2008_PL_E-Commerce

11/200834

Programowanie PHPPorównanie opensource-owych platform blogowych

www.sdjournal.org 35

pewne szybko zwróci uwagę na to, że autorzy skryptu główny nacisk, jeśli chodzi o możli-wości konfiguracyjne postawili na zarządza-nie możliwościami bloga przez administra-tora dając mu wiele opcji. Z tych najważniej-szych ale i kierowanych do osób z pewnym doświadczeniem wymienię np. możliwości ustawienia cache-owania zarówno szablonów Smarty (system szablonowania LifeType-a), cache-owania przez HTTP, czy ze względów bezpieczeństwa uniemożliwienie edycji i tworzenia skryptów PHP właśnie w szablo-nach jak i w samym skrypcie. Jeśli natomiast chodzi o możliwości konfiguracyjne samego bloga i kwestie, które najbardziej powinny za-interesować przeciętnego użytkownika, Life-Type oferuje tylko te podstawowe, co dla wie-lu użytkowników może okazać się zniechęca-jące. Dodatkowo, w wersji, którą opisuję nie ma zarówno spolszczenia dla frontu jak i pa-nelu administracyjnego, szczegóły jednak opi-szę poniżej.

Them-yLifeType co napisałem we wstępie korzysta z szablonów Smarty. Nie chciałbym wnikać i skupiać się na wadach i zaletach tego po-dejścia, gdyż nie tego dotyczy artykuł i wie-le na ten temat zostało już napisane. W przy-padku użytkowników nieposiadających do-świadczenia w architekturze Smarty, wyko-nanie własnego them-u nie powinno jednak przysporzyć większych trudności. Konstruk-cja nie jest skomplikowana i łatwo (posiada-jąc choć podstawową wiedzę z programowa-nia w PHP) można na zasadzie porównania z domyślnym szablonem wykonać swój wła-sny. Dodatkowym atutem jest użycie w sza-blonach mechanizmu słownika (i18n) przez co spolszczenie można dokonać dodając od-powiedni plik do folderu z tłumaczeniami a następnie ustawić go z poziomu panelu ad-ministracyjnego. Użycie szablonów Smarty umożliwia ustawienie dla nich wielu opcji, jak choćby system cache-owania, o którym pi-sałem powyżej. Jeśli chodzi o gotowe szablo-ny dedykowane blogowi niestety na oficjalnej

stronie jest ich bardzo niewiele i również w internecie ciężko jest znaleźć takowe.

Plugin-yJak pozostałe skrypty, LifeType posiada dobrą dokumentację dla osób chcących wykonać wła-sne rozszerzenia. API skryptu jest udokumen-towane w pełni (nie w języku polskim), brak natomiast szerszej sekcji z tutorialami odno-śnie budowy plugin-ów. Podobnie jak w przy-padku them-ów, tak i jeśli chodzi o plugin-y dla LifeType-a nie ma ich wielu, natomiast bez pro-blemu można znaleźć te najbardziej powszech-ne jak chociażby chmura tagów lub ogranicze-nie dostępu do bloga osobom nieupoważnio-nym przez weryfikację hasłem.

Wsparcie techniczne i dokumentacjaMimo dobrej dokumentacji w języku angiel-skim, ze względu na popularność zarówno ofi-cjalne forum skryptu jak i informacje możli-we do znalezienia w internecie mogą zniechę-cić wielu użytkowników do rozpoczęcia pracy z LifeType-m. Zdecydowanie jest on przezna-czony dla osób posiadających wiedzę zarów-no jeśli chodzi o PHP jak i administrację CMS-ami. Na stronach w języku polskim próżno szu-kać jakichkolwiek informacji na temat skryp-tu, w języku angielskim jak wspomniałem sy-tuacja jest podobna. Rozwiązaniem pozostaje w tym względzie poświęcenie się lekturze wi-ki jak i dokumentacji API w przypadku chęci poważnych zmian podstawowej funkcjonalno-ści skryptu.

Wady

• nieduża ilość gotowych them-ów oraz plu-gin-ów;

• dokumentacja przede wszystkim w języku angielskim;

• niewiele tutoriali oraz artykułów dotyczą-cych LifeType-a;

• nieduże możliwości administracyjne sa-mym blogiem;

• obsługa tylko i wyłącznie systemu baz da-nych MySQL.

Zalety

• stabilność skryptu;• dobra dokumentacja skryptu (język angiel-

ski);• w swojej klasie nie posiada dużej konku-

rencji;• duży nacisk postawiony na bezpieczeń-

stwo;• bogate możliwości dla administratora (sys-

tem zarządzania blogami oraz użytkowni-kami);

• system szablonów oparty na Smarty.

PodsumowaniePowyższy artykuł napisany został z zamia-rem przedstawienia czytelnikom najpopu-larniejszych systemów blogowych wraz z ich docelowym przeznaczeniem, stąd też celowe rozgraniczenie na systemy napisane dla try-bu single/multi user/s. Oczywiście istnieje du-żo alternatywnych rozwiązań i platform ta-kich jak np. Serendipity czy boastMachine, które jednak ze względu na popularność ce-lowo ominąłem. Tekst ma być podpowiedzią dla osób, które stojąc przed wyborem instala-cji jakiegoś rozwiązania chciałyby mieć ogól-ne spojrzenie na możliwości prezentowane przez poszczególne platformy, dlatego też celowy podział przy każdym opisie na kwe-stie najważniejsze w pracy z opisanymi sys-temami. Warto podkreślić jednak, że podob-nie jak w przypadku CMS-ów, kierując się wyborem jakiegoś rozwiązania najlepiej jest dobrać skrypt w oparciu o docelowe wyma-gania stawiane przez klienta bądź użytkow-nika. Niekoniecznie więc decyzja na insta-lację bardzo rozbudowanej platformy blo-gowej będzie słuszną decyzją w przypadku kiedy użytkownik oczekuje prostoty, lekko-ści i intuicyjności a duża część dostępnych możliwości nie będzie wykorzystana. Dla-tego właśnie warto czasem rozważyć decy-zję wyboru chociażby bardzo popularnego Wordpress-a na rzecz lekkiego i bardzo przy-jaznego Textpattern-a. Z drugiej strony pro-gramiści bądź webmasterzy mający wykonać serwis blogowy dla wielu użytkowników, po-winni dobrze zapoznać się z platformami b2evolution i LifeType ze względu na róż-norodność opcji administracyjnych. Artykuł nie miał na celu zasugerowania lepszego roz-wiązania, a wszystkie opisane platformy ma-ją zarówno rzesze zwolenników jak i prze-ciwników. Zakończeniem artykułu są linki do stron związanych z omówionymi w tek-ście zagadnieniami.

LECH ALBRZYKOWSKIAutor od kilku lat zajmuje się programowaniem

aplikacji internetowych oraz wdrażaniem syste-

mów CMS.

Kontakt z autorem: [email protected]

W Sieci

• http://www.problogger.net/archives/2006/02/15/choosing-a-blog-platform/ – tekst poświęco-ny wyborowi platformy blogowej (EN);

• http://www.siteground.com/choose_blog_tool.htm – porównanie platform blogowych (EN);• http://txpmag.com/article/textpattern-versus-wordpress – porównanie platform Wordpress i

Textpattern (EN);• http://asymptomatic.net/blogbreakdown.htm – porównanie wielu platform blogowych (EN);• http://www.ojr.org/ojr/images/blog_software_comparison.cfm – porównanie wielu platform

blogowych (EN);• http://unblogbar.com/software/ – porównanie wielu platform blogowych (DE);• http://www.weblogmatrix.org/ – porównanie wielu platform blogowych (EN);• http://wordpress.org/ – oficjalna strona platformy Wordpress (EN);• http://textpattern.com/ – oficjalna strona platformy Textpattern (EN);• http://b2evolution.net/ – oficjalna strona platformy b2evolution (EN);• http://lifetype.net/ – oficjalna strona platformy LifeType (EN).

Page 36: SDJ_11_2008_PL_E-Commerce

11/200836

Testowanie oprogramowaniaSAP GUI Scripting API

www.sdjournal.org 37

Niemiecki producent oprogramowania SAP tworzy szeroką gamę komplemen-tarnych rozwiązań do informatyczne-

go wsparcia procesów biznesowych. Poszczególne elementy systemu wydzielane ze względu na biz-nesowy obszar ich zastosowania określane są mia-nem modułów. W celu zapewnienia kompatybil-ności i spójności poszczególnych modułów całość napisana jest w dedykowanym języku programo-wania ABAP lub w Javie, który to język programo-wania posiada niekwestionowaną pozycję na ryn-ku języków programowania systemów bizneso-wych. W obu przypadkach oprogramowanie uru-chamiane jest na dedykowanych serwerach. Ser-wery funkcjonują w kilku wersjach w rozróżnie-niu na konkretne infrastruktury systemu opera-cyjnego i bazy danych, które stanowią szkielet da-nej wersji konfiguracji serwera.

Rozbudowany system aplikacji biznesowych SAP można również podzielić na część transak-cyjną (moduły odpowiadające różnym proce-som przedsiębiorstwa) oraz część szeroko rozu-mianego raportowania – Business Intelligence.

Struktura aplikacji SAP wyraźnie rozgranicza warstwę przechowywania danych (Oracle, Ma-xDB, MS SQL Server), warstwę wykonywania lo-giki biznesowej (ABAP, J2EE) oraz warstwę inter-fejsu użytkownika (SAP GUI for Windows, SAP

GUI for Java, dostęp przez przeglądarkę interne-tową dla aplikacji z interfejsem webowym).

Artykuł poniższy opisuje pokrótce SAP GUI Scripting API (dalej SGS), skryptowe API dostępu do funkcjonalności SAP GUI. Wszystkie odniesie-nia dotyczą SAP GUI for Windows 7100.1.5.1033.

Głównym celem przyświecającym powsta-niu SGS było stworzenie narzędzia emulują-cego działania użytkownika. SGS zapewnia ta-ką właśnie funkcjonalność wykonania każdego działania, jakie może podjąć użytkownik w in-terakcji z systemem za pomocą SAP GUI. Dzia-łania dostępne przez SGS to:

• użycie/aktywacja elementów SAP GUI (np. wybranie pozycji menu, naciśnięcie przyci-sku);

• zapisanie czynności wykonanych przez użyt-kownika do postaci skryptu;

• logowanie informacji systemowych do pliku.

Przykładowe zastosowania SGS:

• testy wydajności (symulowanie aktywno-ści wielu użytkowników);

• automatyzowanie powtarzalnych czynno-ści (zarówno administratorów jak i użyt-kowników systemu);

• łączenie SAP GUI z aplikacjami zewnętrz-nymi.

Porównaniem mogącym dać zupełnie nowym użytkownikom pewien obraz SGS w SAP GUI, może być JavaScript i przeglądarka internetowa.

Przy czym SGS nie umożliwia dokonywania z poziomu SGS jakichkolwiek zmian w samym GUI np. dodawania nowych elementów ekranu.

Skrypty są wykonywane w SAP GUI, a niewie-le można z SAP GUI zrobić bez podłączenia się do serwera aplikacji i otwarcia sesji. Dlatego do poznania SGS i wypróbowania przykładowego kodu będzie potrzebna instalacja zarówno SAP GUI jak i samego serwera aplikacji.

SAP udostępnia wersje testowe swojego sytemu, które można pobrać ze strony http://sdn.sap.com, do czego wymagana jest rejestracja. Z sekcji Down-loads > SAP NetWeaver Main Release można po-brać SAP NetWeaver 7.0 ABAP Trial Version. SAP GUI można pobrać z ftp://ftp.sap.com/pub/sapgui/, gdzie znajdują się obie wersje SAP GUI dla Win-dows oraz Java. Należy zwrócić uwagę na to, że oprogramowanie skali SAP Netweaver ma duże wymagania sprzętowe, które podane są na stro-nie pobierania.

Kolejnym krokiem jest instalacja. Uruchamia-na jest poprzez otwarcie w przeglądarce inter-netowej prezentacji w formacie html, w której wszystkie kroki są przejrzyście opisane. Przed uruchomieniem instalatora warto zwrócić uwa-gę na kwestie dotyczące długości nazwy kompu-tera oraz zawartość plików services oraz hosts z ka-talogu %windir%/system32/drivers/etc/. Dodatko-wo, w przypadku, gdy nasz komputer nie po-siada adresu IP innego niż 127.0.0.1, konieczne jest zainstalowanie Microsoft Loopback Adapter. Szczegóły można znaleźć w instrukcji instalacji.

Po instalacji i uruchomieniu serwera SAP Ne-tweaver oraz SAP GUI, aby móc połączyć się z serwerem, należy zainstalowany system dodać do listy systemów w zakładce Systemy w SAP Lo-gon. W polu opis wpisać można np. NSP, w polu Serwer aplikacji nazwę albo adres IP komputera na którym serwer jest uruchamiany, Numer syste-mu to dla wersji testowej 00, ID systemu to NSP. Jeśli wszystko zostało wykonane zgodnie z in-strukcją instalacji i serwer został uruchomiony, po dwukrotnym kliknięciu na nowo dodanej po-zycji NSP w SAP Logon, SAP GUI otworzy się na ekranie logowania do systemu.

SAP GUI Scripting API

SAP GUI Scripting API to interfejs pozwalający na emulowanie każdej czynności jaką może wykonać użytkownik w środowisku SAP GUI. Dzięki jego użyciu można zautomatyzować czynności powtarzalne, ale również uzyskać dostęp do SAP GUI z poziomu innych aplikacji, np. Windows Scripting Host.

Dowiesz się:• W jaki sposób tworzyć skrypty automatyzują-

ce czynności użytkownika w SAP GUI;

• W jaki sposób połączyć SAP GUI z aplikacją MS

Office.

Powinieneś wiedzieć:• Czytelnik powinien posiadać dobrą orientację

w posługiwaniu się SAP GUI, czynności bądź

transakcje SAP jakie będą miały zostać zauto-

matyzowane;

• Czytelnik powinien znać podstawy programo-

wania w języku skryptowym typu JavaScript

lub JScript.

Poziom trudności

Automatyzacja czynności w SAP GUI

Page 37: SDJ_11_2008_PL_E-Commerce

11/200836

Testowanie oprogramowaniaSAP GUI Scripting API

www.sdjournal.org 37

Po zainstalowaniu obsługa SGS nie jest do-myślnie aktywowana w ustawieniach serwera SAP Netweaver. Do wyboru są dwie możliwo-ści uruchomienia obsługi SGS po stronie serwe-ra – tylko dla bieżącej sesji uruchomienia serwe-ra lub zapisać to ustawienie aktywne dla wszyst-kich nowo uruchamianych sesji serwera.

W pierwszym przypadku należy użyć transak-cji rz11 wybierając parametr sapgui/user_scripting. Ostatnia pozycja Current value ma wartość FAL-SE. Należy kliknąć na niej i wybrać z paska narzę-dziowego przycisk Change Value. Następnie po wpisaniu wartości TRUE w polu New value na-leży kliknąć ikonę dyskietki, aby zapisać zmiany. W środowisku produkcyjnym koniecznym mo-że być zaznaczenie również opcji Switch on all se-rvers. Do kolejnego uruchomienia, dla wszystkich nowych sesji użytkownika w bieżącej sesji serwe-ra, SGS jest już aktywne. Takie rozwiązanie jest praktyczne, jeśli w standardowym trybie nie udo-stępnia się SGS użytkownikom, a chce tylko jed-norazowo wykonać czynności administracyjne lub testy nie wymagające wielokrotnego urucha-miania serwera SAP Netweaver. Jeśli jednak SGS ma być dostępne po restarcie serwera SAP Netwe-aver, należy wprowadzić wpis aktywujący obsługę SGS w pliku profilu serwera.

Plik profilu uruchomieniowego serwera zawie-ra parametry uruchomieniowe serwera. W syste-mie testowym plikiem profilu jest: %nazwa_serwe-ra, domyślnie NSP%_DVEBMGS00_%nazwa_kom-putera_na_którym_uruchomiony_jest_serwer% znajdujący się w katalogu: %katalog_instalacji, do-myślnie c:\SAP%\ %nazwa_serwera, domyślnie NSP%\SYS\profile. Za pozycją rdisp/myname dopi-sujemy w nowej linii: sapgui/user_scripting = TRUE. Po wprowadzeniu tej zmiany, każda nowo urucho-miona sesja serwera będzie obsługiwać SGS.

Po wykonaniu opisanych dotąd czynności sys-tem jest gotowy do używania w nim SAP GUI Scripting API.

Skrypty SGS można uruchamiać po zalogo-waniu poprzez kliknięcie pierwszego od prawej przycisku ustawień layout’u (Alt+F12) i wybra-niu Script Recording and Playback, a następnie poprzez kliknięcie zielonego przycisku odtwa-rzania, aby wybrać w wyświetlonym oknie plik skryptu do wykonania. Wybranie pliku podwój-nym kliknięciem albo po zaznaczeniu go klik-nięcie przycisku OK rozpoczyna wykonanie za-pisanego w pliku skryptu. Aby rozpocząć nagry-wanie wykonywanych czynności klika się w tym samym oknie na czerwony przycisk nagrywa-nia. Po kliknięciu przycisku More można wpisać ścieżkę do pliku, w jakim zostaną zapisane czyn-ności wykonywane przez użytkownika w trakcie działania rejestratora skryptów.

Zarówno podczas nagrywania, jak i wykonywa-nia skryptu, w prawym dolnym rogu okna SAP GUI aktywny jest czerwono-biały wskaźnik działa-nia skryptu, który podczas normalnego użytkowa-nia SAP GUI również widoczny, ale nieaktywny.

Krótki przegląd możliwości zastosowania i składni kodu SGS przedstawiony zostanie po-

niżej na przykładzie zautomatyzowania exportu wyników raportu SAP Query. Jako, że SAP Qu-ery oferuje kilka formatów, do jakich można eks-portować wyniki raportów, w przykładzie wy-brano bezpośredni eksport do pliku tekstowego, który dobrze nadaje się do późniejszego użycia w aplikacjach zewnętrznych.

Przykładowy skrypt napisany jest przy założe-niu, że będzie on wykonywany bez potrzeby inge-rencji użytkownika, a więc potrzebne będzie wpi-sanie hasła i nazwy użytkownika. W przykładzie te dane wpisane są do kodu, co może być dozwo-lone w środowisku systemu deweloperskiego, jed-nak ze względów bezpieczeństwa w zastosowa-niach produkcyjnych, lepiej zastosować monit o te dane np. przy użyciu elementu InputBox.

Pierwszą czynnością, jaką należy wykonać w celu uruchomienia skryptu SGS, jest przygoto-wanie środowiska uruchomieniowego dla skryp-tu, a więc uruchomienie SAP GUI. Pojawia się zatem okazja wykorzystania możliwości uży-cia SGS w połączeniu z Windows Scripting Host (WSH) i zautomatyzowania również tej operacji kodem zawartym w jednym, rozpoznawalnym przez WSH pliku vbs.

W celu zawarcia całego kodu w jednym pliku aplikacja SAP Logon uruchamiana jest przez WSH. Tworzony jest obiekt silnika WSH, a wywołanie metody Run uruchamia SAP Logon przez otwarcie domyślnie tworzonego podczas instalacji skrótu na pulpicie. Do momentu wystartowania SAP Lo-gon nie można odwołać się do silnika SGS, dlate-go na potrzebny na to czas, zależny od wydajności systemu, na którym SAP GUI jest używane, nale-ży skrypt uśpić. Po uruchomieniu SAP Logon two-rzone są kolejno obiekty aplikacji, silnika, połącze-nia oraz sesji. Połączenie definiowane jest przez po-danie nazwy wpisu dla połączenia z listy w SAP Lo-gon. Po zainicjalizowaniu tych obiektów można się już odwoływać do elementów sesji i ekranu SAP

GUI. Okno jest maksymalizowane, co jest przydat-ne do zapewnienia zawsze tej samej widoczności, ponieważ SGS może się odwoływać tylko do wi-docznych elementów, jest to istotne np. przy póź-niejszym odwoływaniu się do pozycji wyświetla-nych list. Na końcu w pola tekstowe wpisywane są nazwa i hasło użytkownika, a całość zatwierdzana klawiszem Enter powodując zalogowanie użytkow-nika w systemie. W celu odwoływania się do ele-mentów ekranu użyta jest metoda findById().

W zależności od rozdzielczości ekranu, na któ-rym uruchomione zostało SAP GUI, zmienia się ilość widocznych elementów. Jeśli element nie jest widoczny na ekranie SGS nie może się do nie-go odwołać, co powoduje powstanie wyjątku. Np. przy wysokiej rozdzielczości widocznych jest 25 li-nii raportu, przy niższej rozdzielczości już tylko 12, więc nie można odwoływać się do wiersza 25. Należy zwrócić na to uwagę, jeśli skrypty mogą być uruchamiane przy innej rozdzielczości ekranu.

Podana powyżej metoda zdefiniowania obiektu sesji i odwoływania się do elementów ekranu uła-twia późniejsze bezpośrednie użycie kodu genero-wanego przez rejestrator skryptów. Kolejność wy-woływania obiektów składających się na ekran SAP GUI, do którego elementów odwołuje się skrypt jest następująca: Aplikacja>Połączenie>Sesja.

Aplikacją jest uruchomiony SAP Logon, dlatego zawsze istnieć będzie tylko jeden taki obiekt. Połą-czenie z serwerem aplikacji jest otwierane poprzez zalogowanie się w SAP GUI. Domyślna maksy-malna ilość połączeń do sesji serwera wynosi 200 i nie jest proporcjonalnie dystrybuowana między użytkowników. Dlatego w teorii jeden użytkow-nik mógłby otworzyć do 200 sesji na serwerze.

Oddzielną sesją w rozumieniu tego artykułu, określane jest każde otwarte okna SAP GUI. W każdej sesji można wykonywać niezależnie różne od siebie różne transakcje. Dla jednego połączenia można utworzyć maksymalnie pięć sesji. Dlatego

Listing 1. Uruchomienie SAP Logon oraz zalogowanie użytkownika do systemu

Set WshShell = WScript.CreateObject("WScript.Shell") ‘tworzymy obiekt do

odwoływania się do silnika WSH

WshShell.Run("""d:\profiles\All Users\Desktop\Sap Logon.lnk""") ‘uruchamiamy SAP GUI

poprzez skrót na pulpicie

WScript.Sleep(5000) ‘usypiamy skrypt na czas uruchomienia SAP GUI

Dim objSapGui

Set objSapGui = GetObject("SAPGUI")

Dim objScriptingEngine

Set objScriptingEngine = objSapGui.GetScriptingEngine ‘kolejno obiekt silnika SGS

Set objConnection = objScriptingEngine.openConnection("NSP") ‘połączenia

Set session = objConnection.Children(0) ‘oraz sesji

session.findById("wnd[0]").maximize ‘maksymalizuje główne okno

session.findById("wnd[0]/usr/txtRSYST-BNAME").text = "bcuser" ‘wpisanie nazwy uzytkownika

session.findById("wnd[0]/usr/pwdRSYST-BCODE").text = "minisap" ‘wpisanie hasła

session.findById("wnd[0]/usr/txtRSYST-LANGU").text = "EN" ‘wybór języka sesji

session.findById("wnd[0]").sendVKey 0 ‘wysłanie użycia klawisza Enter

Listing 2. Uruchomienie transakcji sq01

session.findById("wnd[0]/tbar[0]/okcd").text = "/nsq01"

session.findById("wnd[0]").sendVKey 0

Page 38: SDJ_11_2008_PL_E-Commerce

11/200838

Testowanie oprogramowania

przy domyślnych ustawieniach, możliwe jest teo-retycznie otwarcie tysiąca okien SAP GUI i wyko-nywanie w każdym z nich, innej transakcji.

Uruchamianie transakcji można wykonywać poprzez rozwinięcie drzewa menu i wybranie od-powiedniego jego elementu, ale dużo praktyczniej-szym z punktu widzenia zastosowania w SGS spo-sobem jest wpisywanie kodu transakcji do pola ko-mend i wysłanie do GUI procedury wciśnięcia kla-wisza Enter. Tak więc, aby już po zalogowaniu uru-chomić transakcję tworzenia raportów ad hoc SAP ABAP Query, użyty zostanie kod z Listingu 2.

Najpierw kod transakcji wpisywany jest do okna komend, a następnie wysyłane naciśnięcie klawisza Enter, do uruchomienia wpisanej trans-akcji. Poprzedzanie nazw transakcji znakiem /n umożliwia uruchamiania tej samej transakcji wie-lokrotnie w jednej sesji, jeśli np. zamierzamy wy-wołać po kolei kilka kwerend w tej samej sesji.

W celu zapewnienia kontroli dostępu, rapor-ty SAP Query przypisane są do specjalnych grup użytkowników SAP Query. Dlatego, aby na ekra-nie transakcji sq01 odwołać się do określonej kwe-rendy należy dla każdego nowego połączenia wy-brać docelową grupę użytkowników. Wybór ten będzie zapamiętany do zamknięcia danego połą-czenia. Jeśli uruchomimy transakcję sq01 w no-wej sesji dla tego samego połączenia, wyświetlo-ny zostanie katalog kwerend dla ostatnio wybra-nej grupy użytkowników. Wybranie przycisku wyświetlenia listy grup użytkowników, wywo-

łuje nowe okno modalne zawierające listę grup. Dla zautomatyzowania tego wyboru, użyta zo-staje funkcja filtra, który zawęża wyświetlane po-zycje do jednej konkretnej nazwy grupy. Kolejno, wywoływane jest wybranie i podwójne kliknię-cie na pierwszy wiersz listy, co powoduje zmia-nę wyświetlanej listy kwerend na listę dla grupy /SAPQUERY/QD.

Dzięki wyszukiwaniu elementu ekranu po jego wartości, zapewnia się dostęp bez względu na to, czy w nowo otwartym oknie wyboru szukany ele-ment jest widoczny, ponieważ po zastosowaniu filtra wyświetlana jest tylko jedna, właściwa dla dalszego wykonania skryptu wartość.

Po wybraniu grupy użytkowników wyświetlo-na zostaje lista dostępnych kwerend. Do pola na-zwy kwerendy skrypt wprowadza nazwę kweren-dy i uruchamia z wcześniej zapisanym wariantem. Pojawia się okno wyboru nazwy wariantu, do któ-rego skrypt wstawia zapisaną w kodzie nazwę. Wy-bór zatwierdzany jest klawiszem Enter, a następnie poprzez wybór klawisza F8, kwerenda zostaje uru-chomiona z wybranym wariantem. W wariancie dla transakcji można zapisać wiele ustawień. W powyższym przykładzie wariant zawiera wybra-nie z opcji Output format – File store z podaniem ścieżki, czyli zapisu wyniku kwerendy do pliku. Po wykonaniu zapytania, wyświetla się okno, w któ-rym jeszcze raz można zmienić ścieżkę do pliku. W tym samym oknie dokonuje się formaty pliku w jakim zapisane mają być wyniki. W przykładzie

pozostawiony zostaje domyślny wybór DAT, jedy-nie dodatkowo zaznaczane jest pole With column heeaders. Zapisuje to w pierwszym wierszu pliku nazwy kolumn, co np. ułatwia późniejsze użycie pliku jako tabeli połączonej w MS Access. Ostatnia linia kodu zatwierdza zapisanie danych.

Po wykonaniu wszystkich czynności w SAP GUI w celu zamknięcia wszystkich otwartych dla wykonania skryptu sesji użyta zostaje transak-cja /nex. Powoduje to zamknięcie sesji bez pytania o potwierdzenie tego wyboru.

Wywołanie kwerendy SAP Query z poziomu transakcji sq01 umożliwia testowanie ich wyko-nania użytkownikom je tworzącym, jeszcze za-nim dla zapytania zostanie utworzona nowa transakcja dodana do menu użytkownika koń-cowego. Ponadto, umożliwia to późniejsze uży-cie tego samego kodu, do wywoływania różnych kwerend poprzez użycie funkcji i przekazywanie nazw kwerendy i wariantu w jej parametrach.

Użycie SAP GUI Scripting wymaga dobrej zna-jomości systemu od strony użytkownika, dlatego jest to narzędzie, które można polecić użytkowni-kom kluczowym, pracownikom pierwszej i dru-giej linii wsparcia, osobom, które potrzebują wy-konać różnego rodzaju czynności administracyj-ne z poziomu SAP GUI. Do sprawnego rozumie-nia i edycji kodu przydatna jest znajomość pod-staw programowania, np. w JavaScript.

Możliwość łączenia w jednym pliku kodu SGS z WSH umożliwia łatwy dostęp do SGS z pozio-mu każdej aplikacji mającej również możliwość wywołania skryptu WSH. Ta właściwość umoż-liwia na przykład uruchamianie skryptów SGS poprzez Zaplanowane zadania Windows, z makr aplikacji Microsoft Access lub z pliku batch w li-nii komend Windows. Dostarcza to dużą ela-styczność w dostępie do SAP GUI z innych apli-kacji przy dopasowywaniu rozwiązań do wyma-gań konkretnej sytuacji.

PodsumowanieSGS, jak każdy skrypt, jest narzędziem użytecz-nym we wszystkich sytuacjach, w których wystę-pują czynności powtarzalne, a których złożoność czyni je pracochłonnymi lub podatnymi na błędy użytkownika. Może się okazać bardzo przydatne dla osób tworzących szkolenia, ponieważ pozwala na stworzenie interaktywnych tutoriali. Dla pro-gramistów jest to otwarcie dostępu do SAP GUI do wykorzystania w zewnętrznych aplikacjach.

Dokumentacja SAP GUI Scripting dostępna jest przy wybranym domyślnym katalogu instala-cji SAP GUI w pliku Program Files/SAP/FrontEnd/SAPgui/SAPguihelp/SAPGUIScripting.chm. Moż-na w nim znaleźć dobrze ustrukturyzowaną i ła-two dostępną, popartą przykładami dokumen-tację API.

ROMAN GRYZOWSKIAutor od 3 lat zajmuje się programowaniem VBA,

a od 2 pracuje jako kluczowy użytkownik systemu

SAP MM-SD.

Kontakt z autorem: [email protected]

Listing 3. Użycie filtra w celu ograniczenia ilości wpisów na liście wyboru

session.findById("wnd[0]/tbar[1]/btn[19]").press

session.findById("wnd[0]").sendVKey 19

session.findById("wnd[1]/tbar[0]/btn[29]").press

session.findById("wnd[2]/usr/subSUB_DYN0500:SAPLSKBH:0600/cntlCONTAINER1_FILT/

shellcont/shell").selectedRows = "0"

session.findById("wnd[2]/usr/subSUB_DYN0500:SAPLSKBH:0600/cntlCONTAINER1_FILT/

shellcont/shell").doubleClickCurrentCell

session.findById("wnd[2]/usr/subSUB_DYN0500:SAPLSKBH:0600/btn600_BUTTON").press

session.findById("wnd[3]/usr/ssub%_SUBSCREEN_FREESEL:SAPLSSEL:1105/ctxt%%DYN001-

LOW").text = "/SAPQUERY/QD"

session.findById("wnd[3]/usr/ssub%_SUBSCREEN_FREESEL:SAPLSSEL:1105/ctxt%%DYN001-

LOW").caretPosition = 12

session.findById("wnd[3]/tbar[0]/btn[0]").press

session.findById("wnd[1]/usr/cntlGRID1/shellcont/shell").selectedRows = "0"

session.findById("wnd[1]/usr/cntlGRID1/shellcont/shell").doubleClickCurrentCell

Listing 4. Uruchomienie kwerendy w transakcji sq01 z wariantem zapisującym wyniki bezpośrednio do pliku

session.findById("wnd[0]/usr/ctxtRS38R-QNUM").text = "NAZWA_KWERENDY"

session.findById("wnd[0]/tbar[1]/btn[17]").press

session.findById("wnd[1]/usr/ctxtRS38R-VARIANT").text = "NAZWA_WARIANTU"

session.findById("wnd[1]/usr/ctxtRS38R-VARIANT").caretPosition = 4

session.findById("wnd[1]").sendVKey 0

session.findById("wnd[0]").sendVKey 8

session.findById("ses[0]/wnd[1]/usr/chkRSAQDOWN-COLUMN").selected = true

session.findById("ses[0]/wnd[1]/tbar[0]/btn[0]").press

Listing 5. Zamykanie sessji bez potwierdzenia wylogowania

session.findById("wnd[0]/tbar[0]/okcd").text = "/nex"

session.findById("wnd[0]").sendVKey 0

Page 39: SDJ_11_2008_PL_E-Commerce
Page 40: SDJ_11_2008_PL_E-Commerce

11/200840

Testowanie oprogramowaniaIBM Rational Data Architect – pierwsze kroki

www.sdjournal.org 41

W celu głębszego poznania funk-cjonalności Rational Data Ar-chitect przed instalacją tego na-

rzędzia powinniśmy zainstalować serwer ba-zodanowy, na którym będziemy przeprowa-dzać testy na modelach, oraz wykonywać za-pytania SQL.

W moim przypadku serwerami bazodano-wymi, na których będę działał są DB2 v.9.5 Express-C oraz SQL Server 2005 Express Edition.

Rational Data Architect w najnowszej wer-sji dostępny jest do pobrania za darmo ze stro-ny IBM, do której odnośnik znajduje się czę-ści W Sieci. W moim przypadku jest to wer-sja v7.0.

Proces instalacji Rational Data Architect jest prosty i intuicyjny. Oczywiście mamy możliwość samodzielnego ustawienia po-szczególnych parametrów, ale na potrzeby rozpoznania tego narzędzia wystarczy nam instalacja z domyślną konfiguracją. Po uru-

chomieniu Rational Data Architect uka-że się środowisko graficzne dobrze znane dla osób, które wcześniej pracowały na ec-lipsie. Interfejs jest bardzo przyjazny i intu-icyjny dla użytkowników tego narzędzia. W zasadzie nie jest wymagana żadna dodatko-wa konfiguracja. Po zakończeniu procesu in-stalacji Rational Data Architect jest gotowy do pracy.

Tworzenie modelu logicznegoW celu rozpoczęcia prac nad oprogramo-waniem dla naszej uniwersyteckiej biblio-teki musimy stworzyć projekt całego syste-mu. Jednym z jego elementów będzie mo-del logiczny, który wyrazi nam tabele, oraz relacje między nimi, dające zrealizować się w każdym Systemie Zarządzania Bazą Da-nych (SZBD).

W celu rozpoczęcia prac nad modelem powinniśmy otworzyć nowy projekt (File-> New-> Data Design Project), w ramach któ-rego będziemy tworzyć modele bazodano-we i nie tylko. Mamy możliwość stworzenia modelu logicznego na kilka sposobów – jed-nym z nich jest stworzenie pustego modelu (File-> New-> Logical Data Model). Po skorzy-staniu z tej opcji zostanie otwarty obszar ro-

boczy – widoczny na Rysunku 1 – na którym stworzymy model logiczny bazy danych bi-blioteki.

Po prawej stronie opisywanego obszaru na-szym oczom ukazuje się zakładka Palette, w której znajdują się kontrolki służące do mo-delowania diagramów. Podstawowe kontro-lki odkryją się po zaznaczeniu opcji Data. Znajdują się tu między innymi kontrolki ta-kie jak encja i relacja, które są najczęściej wy-korzystywanymi elementami przy tworzeniu diagramów związków encji. Dodatkowo dla każdej kontrolki możemy ustawić interesu-jące nas opcje w obszarze Properties, domyśl-nie znajdującym się poniżej naszego obszaru roboczego.

Wiedząc gdzie znajdują się podstawowe funkcje Rational Data Architect możemy przy-stąpić do modelowania bazy danych bibliote-ki. Aby stworzyć encję, bądź relację wystarczy przeciągnąć interesującą nas kontrolkę na ob-szar roboczy.

Na potrzeby testów stworzymy niewiel-ki model składający się z kilku encji – Doku-ment (DokumentID, Tytul, ISBN, AutorID, Wy-dawcaID) połączonej w relacji wiele-do-wielu z encjami Autor (AutorID, Imie, Nazwisko), Wy-dawca (WydawcaID, Nazwa) oraz w relacji jeden-do-wielu z encją Egzemplarz (Egzempla-rzID, Ilosc_egz).

Przedstawiony powyżej model nie od-zwierciedla rzeczywistych potrzeb biblio-tek, ale nam do testów w zupełności wy-starczy. Schemat ten widoczny jest na Ry-sunku 2.

Tworzenie modelu fizycznegoMając gotowy model logiczny pójdźmy krok dalej i stwórzmy model fizyczny bazy danych.

IBM Rational Data Architect

Wyobraźmy sobie sytuację, w której musimy stworzyć oprogramowanie dla biblioteki. Chcąc wywiązać się z zadania musimy zaprojektować system, który będzie spełniał wymagania stawiane przez naszego zleceniodawcę. Z pomocą przychodzi nam Rational Data Architect, który jest narzędziem służącym do tworzenia zarówno prostych, jak i bardzo złożonych modeli bazodanowych.

Dowiesz się:• Czym jest IBM Rational Data Architect;

• W jaki sposób tworzyć modele baz danych za

pomocą IBM Rational Data Architect;

• W jaki sposób konfigurować połączenie z bazą

(bazami danych);

• Jak generować modele baz danych na serwe-

rach bazodanowych;

Powinieneś wiedzieć:• Czym jest model logiczny oraz model fizyczny

bazy danych;

• Znać podstawową składnię języka SQL;

• Znać podstawy konfiguracji serwerów bazo-

danowych.

Poziom trudności

Pierwsze kroki...

Page 41: SDJ_11_2008_PL_E-Commerce

11/200840

Testowanie oprogramowaniaIBM Rational Data Architect – pierwsze kroki

www.sdjournal.org 41

I tutaj ponownie Rational Data Architect da-je nam szereg możliwości tworzenia owych modeli.

Podobnie jak w przypadku modelu logicz-nego możemy stworzyć nowy model fizyczny postępując analogicznie do sposobu opisanego przeze mnie powyżej.

Ścieżka, pod którą znajdziemy kreator mo-delu fizycznego to File-> New-> Phisical Data Model. Tutaj ponownie pojawia się nam za-kładka Palette po prawej stronie ekranu, na której znajdują się kontrolki, które wykorzy-stamy do stworzenia modelu fizycznego od zera.

Bardzo ciekawą opcją jest możliwość ge-nerowania modelu fizycznego z istniejące-go już modelu logicznego. Nie jest to żad-na nowinka wśród oprogramowania służą-cego do modelowania baz danych, ale za-skakująca jest prostota z jaką przebiega ca-ły ten proces.

Powstanie modelu odbywa się w sposób niemal natychmiastowy i aby tego doko-nać nie jest nam potrzebna żadna specjali-styczna wiedza, tak jak to jest w przypad-ku niektórych produktów konkurencyjnych. Po prostu wybieramy z menu opcję Data-> Transform-> Phisical Data Model. Pojawi się nam nowe okno, w który ustawiamy param-tery ułatwijące nam późniejszą pracę na mo-delach.

Jedną z największych zalet Rational Data Architect jest to, że współpracuje nie tylko z produktami firmy IBM, ale również z nie-mal wszystkimi najpopularniejszymy ser-werami bazodanowymi, do których moż-liwe jest podłączenie za pomocą sterowni-ka JDBC.

W związku z tym, że każdy serwer bazo-danowy charakteryzuje się różnymi typami danych, Rational Data Architect ma wpro-wadzone słowniki typów danych, które wy-bieramy przy generowaniu modelu fizycz-nego.

W tej sytuacji w zależności od naszych wy-magań wybieramy słowniki typów danych odpowiadające naszym potrzebom. W mo-im przypadku jest to DB2 UDB.

Po przebrnięciu przez proces konfigura-cji naszego nowego modelu fizycznego za-twierdzamy wszystkie ustawienia przyci-

skiem Finish i po chwili mamy gotowy mo-del fizyczny.

Korzystając z tej samej funkcji możemy również uaktualnić istniejący model fizycz-ny o zmiany, które wprowadziliśmy w mode-lu logicznym. W tej chwili jedyne co musimy z nim zrobić, to poukładać encje wedłgu na-

szego uznania. Oczywiście Rational Data Ar-chitect posiada funkcję, która się tym zajmu-je, ale nie zawsze działa ona tak, jak byśmy te-go chcieli.

W sposób analogiczny wykorzystując funk-cję transformacji do modelu logicznego (Data-> Transform-> Logical Data Model) możemy wy-

Rysunek 1. Starter instalacji Rational Data Architect

Rysunek 2. Obszar roboczy dla modelu logicznego

Rysunek 3. Konfiguracja połączenia z SQL Server 2005

Page 42: SDJ_11_2008_PL_E-Commerce

11/200842

Testowanie oprogramowaniaIBM Rational Data Architect – pierwsze kroki

www.sdjournal.org 43

generować model logiczny z istniejącego sche-matu fizycznego.

Innym sposobem tworzenia modelu fi-zycznego jest funkcja inżynierii odwrotnej (Reverse Engeneering), która pozwala nam na pobranie modelu fizycznego istniejącej bazy danych z serwera baz danych. Aby tego doko-nać musimy skonfigurować połączenie z ba-zą danych.

Nawiązanie połączenia z bazą danychAby nawiązać połączenie z bazą danych musi-my w widoku Database Explorer zaznaczyć pra-

wym przyciskiem myszy folder Connections a następnie wybrać opcję New Connection...

Po wykonaniu powyższych wskazówek otworzy się nam okno kreatora połączeń. Teraz musimy skonfigurować wszystkie nie-zbędne ustawienia. Zacznijmy od nadania nazwy. Rational Data Architect ustawia do-myślną nazwę dla połączenia, ale zaleca się jego zmianę. Następnie wybierzemy ser-wer bazy danych, z którym chcemy się po-łączyć (pole Select a database manager). W moim przypadku jest to SQL Server 2005. W polu User ID wprowadzamy nazwę użyt-kownika serwera baz danych. Następnie po-

dajemy hasło podanego użytkownika w po-lu Password.

W polu Database wpisujemy nazwę bazy danych, z którą chcemy się połączyć oraz po-dajemy host.

W przypadku, gdy serwer znajduje się na tym samym komputerze, na którym zainsta-lowany jest Rational Data Architect w po-lu host wpisujemy localhost. Konieczne jest również wpisanie numeru portu, na którym serwer baz danych nasłuchuje połączeń. Na ogół serwery bazodanowe mają domyślnie przypisany numer portu.

Ostatnią rzeczą, którą należy zrobić jest podanie ścieżki dostępu do sterownika JDBC w polu Class location. Gdy podamy wszyst-kie niezbędne dane powinniśmy skorzystać z opcji Test Connection aby sprawdzić, czy wprowadzone przez nas informacje są po-prawne. Jeśli test nie zwróci nam żadnego błędu, wówczas zatwierdzamy ustawienia przyciskiem Finish. W tej chwili powinni-śmy mieć gotowe połączenie z bazą danych, do którego odnośnik znajduje się w widoku Database Explorer.

Chcąc nawiązać połączenie z serwerami baz danych wspieranych przez firmę IBM sprawa jest dużo łatwiejsza, mianowicie większość da-nych wypełniona zostaje automatycznie. Nie musimy również dostarczać sterownika JDBC dla bazy danych, gdyż Rational Data Architect go posiada.

Rational Data Architect dając możliwość nawiązania połączenia z serwerami baz da-nych otwiera przed nami olbrzymie możli-wości.

Jakie możliwości daje nam możliwość na-wiązania połączenia? Generowanie, aktuali-

Konfiguracja połączenia z SQL Server 2005W celu nawiązania połączenia Rational Data Architect z SQL Server-em 2005 potrzebny będzie nam sterownik JDBC dla SQL Server 2005. Na pierwszym etapie skonfigurujemy serwer bazodanowy. W tym celu musimy uruchomić narzędzie, które zostało zainstalowane wraz z serwe-rem bazy danych SQL Server Configuration Manager (domyślnie znajduje się w Start-> Programy-> Microsoft SQL Server 2005-> Configuration To-ols). Z wyświetlonej listy wybieramy opcję TCP/IP. W tym miejscu konieczne jest uaktywnienie możliwości nawiązania połączenia z serwerem bazodanowym, więc przy polu ENABLE wybieramy z listy YES, a następnie przechodzimy do zakładki IP Addresses, gdzie podamy port, w któ-rym SQL Server będzie nasłuchiwał połączeń. Domyślnym portem dla SQL Server 2005 jest 1433. Zatwierdzamy wprowadzone zmiany klikając na Apply.Kolejnym ważnym elementem przy nawiązywaniu połączenia jest wybór sposobu logowania się do serwera bazodanowego. Logowanie nie może odbyć się za pomocą Windows Authentication. Musimy uaktywnić użytkownika sa (domyślne konto dla administratora bazy danych), lub stworzyć no-wego użytkownika.Mając skonfigurowany SQL Server 2005 możemy nawiązać połączenie z nim za pomocą Rational Data Architect w sposób opisany w części Nawiąza-nie połączenia z bazą danych.

Rysunek 4. Widok na mapowane modele bazodanowe

W Sieci

• http://www.ibm.com/developerworks/downloads/r/rda/ – Rational Data Architect w wersji trial• http://www-306.ibm.com/software/data/db2/express/download.html – DB2 9.5 Express-C• http://www.microsoft.com/sql/downloads/trial-software.mspx#EZC – SQL Server 2005 Express Edition• http://www.microsoft.com/downloads/details.aspx?FamilyID=c243a5ae-4bd1-4e3d-94b8-5a0f62bf7796&displaylang=en – SQL Server 2005 Manage-

ment Studio Express Edition• http://msdn.microsoft.com/en-us/data/aa937724.aspx – JDBC dla SQL Server 2005

Page 43: SDJ_11_2008_PL_E-Commerce

11/200842

Testowanie oprogramowaniaIBM Rational Data Architect – pierwsze kroki

www.sdjournal.org 43

zacja modeli baz danych na serwerach, pobie-ranie modeli z serwerów, mapowanie źródeł, synchronizacja modeli, kojarzenie odrębnych źródeł danych, odszukiwanie podobieństw w modelach, w sytuacji, kiedy nie istnieje fi-zyczna implementacja relacji pomiędzy ni-mi, analiza modeli i źródeł danych pod ką-tem zgodności ze standardami korporacyjny-mi stworzonymi w ramach Rational Data Ar-chitect(!). Wymieniłem tylko najistotniejsze zalety płynące z możliwości połączenia z ba-zą danych. Ich lista jest dużo dłuższa.

Mapowanie modeliMapowanie modeli ma na celu umożliwienie nam porównania różnych źródeł danych mię-dzy sobą, znalezienie powiązania w źródłach danych, oraz przeprowadzenie szczegółowej analizy porównawczej modeli.

Rysunek 4 obrazuje nam sposób w jaki wy-glądają dwa przykładowe mapowane modele bazodanowe. Abyśmy mogli wykonać mapo-wanie modeli, konieczne jest umieszczenie źródeł danych w jednym projekcie. Aby ma-

pować stworzony przez nas model z mode-lem znajdującym się na serwerze baz danych, konieczne jest użycie funkcji Reverse Engine-ering w celu pobrania modelu do Rational Data Architect.

Aby wykonać mapowanie modeli w ob-rębie jednego projektu w menu wybieramy opcję File-> New-> Mapping Model. Prawdo-podobnie na etapie poznawania narzędzia Rational Data Architect funkcja ta nie znaj-dzie zastosowania więc postanowiłem, że nie będę jej dogłębnie analizował.

Wykonywanie poleceń SQL za pomocą RDARational Data Architect posiada wbudowane narzędzie służące do tworzenia poleceń SQL. Można uzyskać dostęp do niego na wiele spo-sobów, włączając dostęp bezpośrednio z panelu Database Explorer.

Na potrzeby artykułu wykorzystałem połą-czenie z SQL Server-em 2005. Aby wykonać polecenie SQL musimy wykonać następują-ce kroki:

• prawym przyciskiem myszy klikamy na połączeniu z bazą danych w panelu Da-tabse Explorer i wybieramy opcję New SQL Statement;

• w oknie, które się otworzy po wykonaniu polecenia z punktu pierwszego wpisujemy nazwę polecenia oraz jego typ (SELECT, INSERT, itp.);

• po wykonaniu poleceń z powyższych punktów otworzony zostanie edytor, w którym podajemy polecenie SQL, oraz do-dajemy tabele (poprzez klikniecie prawym przyciskiem myszy na widoku Tables i wy-branie opcji Add Tables), na których bę-dziemy operować;

• podajemy polecenie SQL i aby je wykonać używamy funkcji znajdującej się w: Run > Run SQL.

Narzędzie służące do tworzenia poleceń SQL w Rational Data Architect posiada sze-roki wachlarz możliwości przy budowaniu zapytań SQL, oraz operacji na wynikach za-pytań.

Wszystko to powoduje, że Rational Data Ar-chitect jest narzędziem wielofunkcyjnym słu-żącym nie tylko do tworzenia modeli baz da-nych, ale również do ich testowania.

PodsumowanieRational Data Architekt jest narzędziem, które dzięki swoim funkcjom pozwala na drastyczną redukcję czasu pracy nad mode-lami baz danych.

Narzędzie to zbudowane w oparciu o open source-ową platformę eclipse nie tylko posia-da przyjazne użytkownikom środowisko gra-ficzne, ale również pozwala na zsynchroni-zowanie pracy architektów tworzących pro-jekty oprogramowania nie tylko bazodano-wych. Wystarczy dodać kolejne wtyczki do elipsa i osoby odpowiedzialne za różne ele-menty powstawania projektu oprogramo-wania mogą wymieniać się efektami swojej pracy ciągle korzystając z tego samego na-rzędzia.

Rational Data Architect jest jak szwajcar-ski scyzoryk przy zarządzaniu modelami baz danych. Czy to znaczy, że RDA może wszyst-ko? Nie. Szwajcarski scyzoryk, również nie może, ale możliwości, które dają te dobrze zorganizowane narzędzie pozwalają na od-nalezienie zastosowania w niemal każdej sy-tuacji.

SZYMON GRUSZEWSKIAutor jest studentem na wydziale informatyki w Polsko-Japońskiej Wyższej Szkole Technik Kompu-terowych w Warszawie. Odbył praktyki w firmie IBM Polska, których tematem było rozpoznanie na-rzędzia Rational Data Architect.Kontakt z autorem: [email protected]

Rysunek 5. Widok narzędzia służącego do wykonywania poleceń SQL

Współpraca Rational Data Architect z serwerami baz danychRational Data Architect w swojej pełnej funkcjonalności współpracuje z:

• Cloudscape®• DB2 for iSeries®• DB2 for Linux®, UNIX®, and Windows®• DB2 for z/OS®• Derby• Informix® Dynamic Server• Microsoft SQL Server Enterprise• MySQL• Oracle• Sybase Adaptive Server Enterprise• Teradata

Page 44: SDJ_11_2008_PL_E-Commerce

11/200844

Testowanie oprogramowania

www.sdjournal.org 45

Niestety, łączność opisana powyżej spra-wia, że systemy są narażone na infil-trację przez rosnącą rzeszę cyber-terro-

rystów oraz szantażystów. W rzeczywistości, zło-śliwi hakerzy pokonali już wiele różnych syste-mów SCADA, systemów kontroli HVAC, urzą-dzeń przenośnych oraz systemów bezpieczeń-stwa nuklearnego przy użyciu wirusów, ataków DoS (zablokowanie usług) oraz innych progra-mów sieciowych.

Aby opanować takie ataki wielu projektantów systemów skierowało się do bezpiecznego partycjo-nowania. Mówiąc krótko technologia ta pozwa-la projektantom wyizolować procesy oprogra-mowania na wirtualne części lub partycje oraz alokować predefiniowane zapasy pamięci lub czasu CPU do każdej partycji. System operacyj-ny może wtedy wykorzystywać te zapasy, a co za tym idzie chronić procesy w którejkolwiek par-tycji przed fałszywym lub złośliwym monopoli-zowaniem zasobów wymaganych dla tych proce-sów w innych partycjach – Rysunek 1. Przy po-mocy partycjonowania zasobów, projektant sys-temu może wyizolować procesy oprogramowa-

nia w osobne partycje oraz alokować zagwaran-towany zapas pamięci oraz czasu CPU do każdej z partycji. W wyniku tego, złośliwe lub źle napi-sane procesy nie będą mogły zmonopolizować zasobów niezbędnych dla innych procesów

Partycjonowanie może również ochronić przed problemami z wydajnością i niezawod-nością, które nieuchronnie pojawiają się pod-czas integrowania wielu podsystemów. Projek-tant staje często przed problemem połączenia dowolnej liczby podsystemów opracowanych na miejscu z podsystemami i elementami od zewnętrznych dostawców oprogramowania. W trakcie fazy integracji wszystkie te podsyste-my łączą się i rozpoczynają współzawodnictwo o zasoby, co często skutkuje nieoczekiwanymi zachowaniami systemu. Podsystemy, które pra-widłowo funkcjonowały w izolacji, teraz pracu-ją wolno lub w ogóle odmawiają pracy.

Rozwiązanie takich kwestii związanych z zasobami jest skomplikowanym i czasochłon-nym zadaniem. Po zidentyfikowaniu głównej przyczyny projektant systemu musi żonglować priorytetami różnych podsystemów, lub co gor-sze ponownie wdrożyć logikę podsystemu, aby uzyskać pożądane zachowanie. Proces ten mo-że z łatwością przedłużyć realizację projektu o dodatkowe tygodnie lub miesiące.

Partycjonowanie odpowiada na te problemy na etapie projektowania, pozwalając projektan-

tom systemów alokować predefiniowane zaso-by dla każdego z podsystemów. Kiedy rozpo-czyna się testowanie podsystemu, opracowują-cy go może ograniczyć partycję podsystemu do alokowanego zapasu zasobów oraz może testo-wać podsystem w symulowanych warunkach pesymistycznych. Dzięki temu może on roz-wiązać potencjalne kwestie związane z wydaj-nością oraz rywalizacją o CPU we wczesnym etapie, w dużym stopniu upraszczając następ-na fazę integracji systemu.

Skalowanie partycji w procesorach wielordzeniowychDo dziś partycjonowanie stosowano prawie wy-łącznie w środowiskach procesorów jednordze-niowych. Jednakże, przy rosnącej popularno-ści procesorów wielordzeniowych, producen-ci potrzebują sposobu na wdrożenie partycji w dwóch, czterech, ośmiu i większej liczbie rdzeni procesowych.

W tym jest wyzwanie. W środowisku proce-sorów pojedynczych, program planujący RTOS alokuje pojemność CPU do każdej partycji. W idealnej sytuacji program planujący RTOS mo-że po prostu rozszerzyć ten koncept na wszyst-

Bezpieczne partycjonowanie

W dzisiejszych czasach praktycznie każdy wbudowany system podłączony jest fizycznie lub bezprzewodowo do świata zewnętrznego. Taka łączność sieciowa pozwala użytkownikom na zdalne monitorowanie i sterowanie oraz pozwala systemom pobierać nowe oprogramowanie i treści wtedy, kiedy jest to konieczne.

Dowiesz się:• Co to jest technologia partycjonowania?

• Jak optymalnie wykorzystywać czas CPU

w systemach wieloprocesorowych?

• Jak tworzyć bezpieczne systemy?

Powinieneś wiedzieć:• Co to jest system wbudowany?

• Na czym polega przetwarzanie współbieżne?

Poziom trudności

Systemy wielordzeniowe QNX

Rysunek 1. Schemat partycjonowania zasobów

�������������������

��������������������

��������������������

��������������������

���������������������������

Page 45: SDJ_11_2008_PL_E-Commerce

11/200844

Testowanie oprogramowania

www.sdjournal.org 45

kie rdzenie procesowe w systemie wielordzeniowym. Niestety, wiele Syste-mów Operacyjnych Czasu Rzeczywistego (RTOS) nie zapewnia tej możli-wości, w dużej mierze z powodu ich ograniczonych możliwości w zakresie przetwarzania wieloprocesorowego.

RTOS (System Operacyjny Czasu Rzeczywistego) może obsługiwać jeden lub większą liczbę następujących modeli przetwarzania wielopro-cesorowego:

• Asymetryczne Przetwarzanie Wieloprocesorowe (AMP) — traktuje każ-dy rdzeń jako odrębny CPU. Osobny RTOS działa na każdy rdzeń, wymuszając na projektancie systemu statyczną konfigurację pamię-ci, przerwań oraz innych współdzielonych zasobów systemowych. Aplikacje działające na danym rdzeniu mogą wykorzystywać wyłącz-nie zasoby, które zostały statycznie skonfigurowane dla tego rdzenia;

• Symetryczne Przetwarzanie Wieloprocesorowe (SMP) — pojedynczy RTOS zarządza wszystkimi rdzeniami. RTOS zarządza współdzie-lonymi zasobami systemowymi, pozwalając im na wykorzystanie przez którąkolwiek z aplikacji działających na którymkolwiek rdze-niu. Dodatkowo, RTOS może dynamicznie planować wszelkie pro-cesy na którymkolwiek rdzeniu, umożliwiając pełne wykorzysta-nie CPU. Podejście to nie tylko upraszcza rozbudowę, ale również oferuje większą elastyczność podczas wykorzystywania bezpiecz-nych partycji w środowiskach wielordzeniowych;

• Ograniczone Przetwarzanie Wieloprocesorowe (BMP) — rozszerza SMP poprzez umożliwienie projektantowi powiązać wszelkie pro-cesy (oraz wszystkie wątki z nimi powiązane) z określonym rdze-niem. Podejście to łączy w sobie sterowanie AMP oraz uproszczone programowanie oraz większą skalowalność SMP.

Z natury AMP nie jest w stanie odpowiedzieć na wymagania przetwa-rzania związane z rdzeniami wielokrotnymi. Z tego powodu wszelkie partycje w AMP są ograniczone do rozmiaru pojedynczego rdzenia, do 100%. W SMP oraz BMP, z drugiej strony, RTOS posiada całkowity ob-raz systemu, co pozwala mu na wykorzystanie całkowitej pojemności CPU procesora wielordzeniowego (np. wszystkich rdzeni) do partycjo-nowania. Projektanci systemu mogą w wyniku tego elastycznie mapo-wać partycje na wiele rdzeni w dowolny sposób, odpowiedni do wymo-gów systemowych — oraz niezależnie od ograniczeń procesora. Na przy-kład, na Rysunku 2, Bezpieczna Partycja 1 rozciąga się na dwa rdzenie CPU, podczas gdy inne partycje pracują na pojedynczych rdzeniach.

Elastyczność ta umożliwia projektantom systemów dostosowywać rozwój platformy, zarówno w oprogramowaniu jak i w sprzęcie. Na przy-kład, wprowadzanie nowych funkcjonalności oprogramowania do apli-kacji może nadwerężyć partycję do poziomu, w którym pojedynczy rdzeń CPU nie będzie już w stanie poradzić sobie z obciążeniem prze-twarzania. W takim przypadku, partycje można łatwo rozszerzyć, aby obejmowała dwa rdzenie. Migracja do nowej platformy sprzętowej może również wymagać zmian w zasobach partycji, co z kolei spowoduje po-trzebę zawarcia wielu rdzeni w partycji.

O firmie QNX Software Systems QNX Software Systems, międzynarodowa firma należąca do Har-man International, jest liderem w przemyśle technologii wbudo-wanych systemów operacyjnych czasu rzeczywistego. Konstrukcje QNX® Neutrino® RTOS oraz QNX Momentics® oparte na komponen-tach tworzą najbardziej niezawodną i skalowalną ramę do budowy innowacyjnych i wysoce wydajnych systemów wbudowanych. Świa-towe firmy takie jak Cisco, DaimlerChrysler, General Electric, Lockhe-ed Marti oraz Siemens zależne są od technologii QNX oraz routerów sieciowych, sprzętu medycznego, układów telematycznych dla mo-toryzacji, systemów bezpieczeństwa i obrony, robotów przemysło-wych oraz innych aplikacji. Założona w 1980, firma QNX Software Systems posiada swoja siedzibę główną w Ottawie, Kanada, i dystry-buuje produkty do ponad 100 krajów na całym świecie.

Page 46: SDJ_11_2008_PL_E-Commerce

11/200846

Testowanie oprogramowania

Jeśli partycja wymaga dedykowanego rdze-nia CPU, projektant systemu może zastosować ograniczone przetwarzanie wieloprocesorowe, aby ta i wyłącznie ta partycja była uruchamia-na na tym rdzeniu.

Maksymalne wykorzystanie CPU Schemat partycjonowania powinien również być elastyczny w sposobie zarządzania zaso-bami CPU. Niektóre wdrożenia ściśle wymu-szają zasoby CPU w każdej sytuacji, aby każ-da z partycji zużywała w całkowite zasoby, na-wet w przypadku, gdy ma do wykonania nie-

wielka pracę. Na przykład, jeśli w partycji alo-kowano 30% CPU, będzie ona zawsze wykorzy-stywała 30%, nawet jeśli w danej chwili potrze-buje tylko 10%. To podejście stało-cyklowe mar-nuje cenne (i dostępne) cykle CPU i uniemoż-liwia systemowi radzenie sobie z zapotrzebo-waniem impulsowym. Inne aplikacje najlepiej wykorzystują takie jałowe cykle poprzez dyna-miczną alokację do partycji, co może przynieść korzyści z dodatkowego czasu przetwarzania. Takie podejście daje nam bardziej czuły system oraz eliminuje kosztowną przebudowę związa-ną z podejściem stało-cyklowym.

Tworzenie systemów, które przetrwają Żadna, nawet największa liczba przeprowa-dzonych testów nie jest w stanie w pełni wy-eliminować wirusów lub potencjalnych dziur w skomplikowanym systemie, jak również ża-den test nie jest w stanie przewidzieć każde-go zagrożenia, na które może napotkać system. Projektanci systemów oraz twórcy oprogramo-wania muszą, w rezultacie zaadoptować tech-nologie, które zawierają błędy w oprogramowa-niu oraz inne zagrożenia i szybko je naprawić. W prawidłowy sposób wdrożone, partycjono-wanie może zapewnić taką ochronę oraz ska-lowanie ze zwiększającą się liczbą rdzeni pro-cesora. W wyniku takiej ochrony, zarówno pro-cesory pojedyncze jak i systemy wielordzenio-we mogą:

• zawierać blokadę ataków;• zawierać wadliwe podsystemy, które po-

wodują obciążenie CPU lub wyczerpanie pamięci;

• zapewniać gwarantowany czas CPU dla procesów przeprowadzających diagnosty-kę systemu oraz odzyskiwanie danych;

• zapewniać zagwarantowany czas CPU dla interfejsów użytkownika (idealne dla sys-temów, w których gwarantowany dostęp zdalny jest wymogiem kluczowym);

• integrować podsystemy od różnych pro-ducentów oraz dostawców przy jednocze-snym uniknięciu typowych w takich sytu-acjach konfliktów zasobów, które utrud-niają integrację.

Co istotne, dobrze wdrożony plan partycjo-nowania nie wymaga zmian kodów w istnie-jących aplikacjach i umożliwia projektantom pracę zgodnie z tym samym planem i priory-tetami zadań jak dotychczas. Dzięki adapta-cyjnemu partycjonowaniu QNX, projektant systemu może na przykład uruchomić istnie-jące aplikacje i usługi systemowe w partycjach a program planujący systemu operacyjnego za-pewni, że każda partycja otrzyma swoje aloko-wane zasoby. W ramach każdej partycji, pro-gram planujący rozdysponuje wątki zgodnie z tradycyjnymi zasadami priorytetowego szere-gowania z wywłaszczeniem.

KERRY JOHNSON, QNX SOFTWARE SYSTEMS Kontakt z autorem: [email protected]

ROMAIN SAHA, QNX SOFTWARE SYSTEMSKontakt z autorem: [email protected]

W Sieci

• http://www.qnx.com

Rysunek 2. W modelach symetrycznego i ograniczonego przetwarzania wieloprocesorowego, partycje mogą w sposób elastyczny rozciągać się na różne rdzenie

��� ��� ��� ���

�����������

����������

�����������������

�����

����������������������������������������

���������������������

������

����� �����

���

�����������

����������

�����������

����������

������������

�����

���

Rysunek 3. Inteligentne partycjonowanie, opatentowane przez QNX Software Systems, narzuca czas CPU dla budżetu partycji, kiedy system jest obciążony. Niewykorzystany czas CPU jest dynamicznie alokowany do partycji w sytuacji niepełnego obciążenia

�����������

���������������������

���������

���������������������

���������

�������������������������

����������

���������

����������� ����������� �����������

������� ����������� �����������

��� ��� ���

��� ��� �� ����

��� ��� ��� ����

�������������������

���������������

����������� ����������� �����������

���������������

���������������

�������������������

������������������

�������������

���������������

Page 47: SDJ_11_2008_PL_E-Commerce
Page 48: SDJ_11_2008_PL_E-Commerce

11/200848

Testowanie oprogramowaniaNowy Joomla 1.5 i nowe w Joomla!

www.sdjournal.org 49

Przystosowanie Joomla!, którego początki sięgają przecież 2001 roku do zmieniającej się natury internetu i nowoczesnych tech-

nologi sieciowych wymagało gruntownej przebu-dowy kodu, wzbogacenia użyteczności i uprosz-czenia interfejsu użytkownika. Jak poprzednio, nowe wydanie Joomla! zapewnia użytkownikom i projektantom wygodny i łatwy w użyciu szkie-let publikacji treści w witrynach internetowych wszelkiego typu. W Joomla! 1.5:

• istotnie zwiększono funkcjonalność – za-równo użyteczność, jak i wykonalność (ang. manageability), skalowalność i wydajność, zo-stawiając daleko w tyle oryginalne Mambo;

• zapewniono obsługę dowolnego języka – dwubajtowe kodowanie utf (język japoński!), obsługa tekstów w językach z pisownią od prawej (np. arabski, farsi i hebrajski);

• rozwinięto zdolność integracji z aplikacjami zewnętrznymi przez usługi sieciowe i zdalne uwierzytelnianie, np. lekki protokół dostępu do usług katalogowych (LDAP);

• udoskonalono technikę dodawania treści, szablony i formy prezentacji, aby zapewnić obsługę standardów dostępności i użytecz-ności dla dowolnych odbiorców;

• zbudowano nowoczesny, prostszy i elastycz-ny szkielet projektowy dla komponentów i innych rozszerzeń;

• zachowano zgodność wsteczną z poprzedni-mi wydaniami Joomla!, komponentami, sza-blonami, modułami i innymi dodatkami.

Uniwersalność i lokalizacjaDla polskich użytkowników Joomla! 1.0 nie jest zbytnią nowością w pełni zlokalizowany inter-fejs Joomla 1.5 – zarówno witryny, jaki zaplecza. Wielu użytkowników Joomla 1.0 w Polsce nie by-ło i nie jest nawet świadomych faktu, że oryginal-ny Joomla! przemawia na zapleczu tylko w języ-ku angielskim.

W UTF-8 W Joomla 1.5 problem lokalizacji rozwiązano gruntownie i definitywnie. Dla wydawców pol-skiego Joomla! skończył się problem z tygodnia-mi pracy potrzebnej na dokonanie niezbędnych zmian w skryptach. Do nowego wydania trzeba co najwyżej dotłumaczyć kilka nowych fraz w pli-kach językowych.

Zmianą najważniejszą jest zapewnienie peł-nej obsługi przez Joomla 1.5 standardu UTF, a więc wielobajtowego kodowania znaków. W efekcie Joomla 1.5 stał się projektem w pełni uniwersalnym, obsługującym dowolny język, w tym języki z kierunkiem pisma od prawej do le-wej czy języki, w których stosowane jest pismo morfosylabiczne (chiński, japoński).

Doskonalszy PDFDostosowanie do standardu UTF pozwoliło rów-nież lepiej niż dotychczas rozwiązań problem ge-nerowania dokumentów PDF. W miejsce stoso-wanego w poprzednim wydaniu Joomla! skryp-tu free-PDF skorzystano z obsługującej UTF kla-

sy tcpdf, zapewniając atrakcyjniejsze dokumenty i ograniczając częste wcześniej problemy z kodo-waniem znaków, czy obsługą niektórych forma-tów graficznych.

Łatwiejsza lokalizacja rozszerzeńNowe rozwiązania w językowej warstwie Joomla! już w najbliższej przyszłości będą zapewne skut-kować szybszą polonizacją rozszerzeń. Już teraz mamy do czynienia ze znacznie częstszymi pró-bami lokalizacji nowości, niż miało to miejsce w przypadku rozszerzeń dla Joomla 1.0. Proble-mem może być wprawdzie utrzymanie pewnych standardów, zapewnienie wysokiej jakości tłuma-czeń, ale sam proces stał się bardzo łatwy. Wystar-czy zainstalować specjalny komponent Transla-tionManager. Komponent wyświetla na zapleczu frazy języka witryny i zaplecza, które wystarczy przetłumaczyć i zapisać, by korzystać w swoim Joomla! i ewentualnie udostępnić społeczności.

UstawieniaUstawienia lokalne w Joomla 1.0 definiowano w Konfiguracji globalnej. W Joomla 1.5 nie znaj-dziemy w globalnych ustawieniach takich opcji. Kod języka i kod kraju ustawiane są teraz przez plik językowy – jezyk.xml (np. pl-PL.xml). We-wnątrz znacznika locale można umieścić wiele ciągów ustawiających lokalizację. System wybiera spośród nich automatycznie jedno, odpowiednie do konfiguracji serwera. Jeśli zatem mamy pro-blemy z umiejscowieniem, takie jak niepoprawne wyświetlanie daty, można – razem z administra-torem serwera sprawdzić i zmodyfikować wpisy w znaczniku locale.

Zarządzanie rozszerzeniamiOznaczenie komponentów, modułów, dodatków, szablonów i pakietów językowych jednym termi-nem – rozszerzenia, to najdrobniejsza ze zmian. Przede wszystkim uproszczono proces instalacji.

Joomla 1.5

21 stycznia, w dwa i pół roku po pierwszym głównym wydaniu Joomla! (miało to miejsce 16 września 2005 roku) zespół projektantów udostępnił społeczności z radosnym komunikatem długo oczekiwane wydanie drugie. Od tego momentu ukazało się pięć kolejnych aktualizacji, eliminujących zauważone błędy, wnoszących dziesiątki drobniejszych poprawek i udoskonaleń.

Dowiesz się:• Jakie zmiany wprowadzono do wersji 1.5.

Powinieneś wiedzieć:• Podstawy użytkowania Joomla 1.0.

Poziom trudności

Nowości

Page 49: SDJ_11_2008_PL_E-Commerce

11/200848

Testowanie oprogramowaniaNowy Joomla 1.5 i nowe w Joomla!

www.sdjournal.org 49

W wydaniach sprzed Joomla 1.5 trzeba było do-brać rodzaj instalatora do typu rozszerzenia. W Jo-omla 1.5 instalatorowi dodano inteligencji, w re-zultacie sprytnie sam rozpoznaje rodzaj instalo-wanego rozszerzenia. Użytkownik nie musi się już martwić o poprawny wybór – po prostu wskazuj rozszerzenie, a resztę pracy wykonuje instalator.

Rozwiązano często doświadczane kłopoty na serwerach Linuksowych i Uniksowych, a spowo-dowane ograniczeniami praw dostępu do plików i bezpiecznym trybem działania PHP. Jak wiado-mo, bezpieczny tryb ogranicza PHP do możliwo-ści wykonywania operacji tylko na tych plikach lub folderach, których właściciel jest tożsamy z używanym przez PHP (zwykle jest to użytkownik 'apache'). Normalnie pliki tworzone są albo przez Joomla!, albo podczas transmisji przez FTP. W Jo-omla 1.5 dodano obsługę protokołu FTP przez rdzeń systemu. Kombinacja akcji PHP na plikach i włączona obsługa FTP przez Joomla! umożliwia bezproblemowe działanie przy włączonym safe mode. Włączenie FTP umożliwia operację na pli-kach (np. instalację rozszerzeń lub zmiany w pli-ku konfiguracyjnym) bez konieczności dokony-wania zmian praw zapisu dla katalogów i plików. Takie rozwiązanie znacznie ułatwia życie admini-stratorowi i zwiększa bezpieczeństwo witryny.

Zarządzanie artykułamiWprawdzie nie dokonano bodaj najbardziej ocze-kiwanej zmiany – możliwości przypisywania arty-kułów do wielu kategorii tudzież tworzenia wielo-poziomowego systemu kategorii, ale i w sferze za-rządzania artykułami zmiany są znaczące. Sposób obsługi został uproszczony, stając się jeszcze bar-dziej intuicyjnym, niż był w Joomla 1.0.

Czytaj więcejZrezygnowano z formalnego podziału artykułów na część wstępną i tekst główny. W konsekwencji w edytorze artykułów mamy zamiast dwóch jed-no pole na cały tekst. Oczywiście, nie zrezygno-wano jednak z możliwości wyodrębniania zapo-wiedzi i właściwego tekstu. Wszak zapowiedzi są niezwykle użytecznym sposobem prezentacji ar-tykułów w przeglądach (zwanych dawniej bloga-mi). Teraz jednak, aby podzielić artykuł na zapo-wiedź i tekst główny, używamy markera Czytaj więcej. Można przy tym wpisać odpowiednie po-lecenie, ale wygodniej zastosować przycisk wsta-wiający marker, umieszczony pod edytorem. W miejscu wstawienia znacznika pojawi się czerwo-na przerywana linia, oddzielająca wstęp artykułu od całości. O obsługę podziału na stronach witry-ny zadba nowy dodatek (ang. plg_readmore). War-to przy tym wspomnieć, że w przypadku migracji danych ze starszych stron, nie będzie to powodo-wać żadnych problemów. Nowe rozwiązanie jest w pełni zgodne z poprzednimi.

Nieprzypisane zamiast statycznychW wydaniach sprzed Joomla 1.5 istniał specy-ficzny typ artykułu nazywany materiałem sta-tycznym. Ewolucja jego właściwości następo-

wała już w kolejnych wydaniach Joomla 1.0. Po-czątkowo taki materiał można było udostępnić jedynie przez publikację odnośnika w menu, nie można go było udostępnić w przeglądach arty-kułów ani w modułach typu Popularne czy No-wości. Chociaż z czasem stało się to możliwe, ar-tykuł statyczny nadal różnił się od zwykłego, dy-namicznego – nie można go było przenieść do ka-tegorii, a tym samym udostępnić w przeglądzie czy na liście artykułów w kategorii.

Odmienność typu wiązała się w Joomla 1.0 z dwoma różnymi procedurami tworzenia arty-kułów i materiałów statycznych. Wspomniana wcześniej rezygnacja z formalnego podziału ar-tykułów na część wstępną i tekst główny rozwią-zała również kwestię materiałów statycznych. Re-dakcję obu typów artykułów obsługuje jedna, taka sama procedura. A dawne materiały statyczne są teraz po prostu artykułami nieprzypisanymi do żadnej kategorii.

W efekcie – jeśli potrzebujemy umieścić w wi-trynie statyczny artykuł, jak statyczną, niezmien-ną stronę HTML, możemy to uczynić – redaguje-my nowy artykuł w taki sam sposób, jak standar-dowy i zamiast przypisać go do konkretnej sekcji i kategorii, wybieramy na liście możliwości opcję Nieprzypisany. W każdym jednak momencie nie-przypisany artykuł możemy umieścić w dowolnej kategorii i sekcji, co w Joomla 1.0. możliwe nie by-ło, a także każdy artykuł przypisany do kategorii i sekcji możemy przekształcić w nieprzypisany ma-teriał statyczny.

Ilustrowanie artykułówUnowocześniony sposób zarządzania obrazkami zaowocował również istotnymi zmianami w spo-sobie ilustrowania artykułów. W Joomla 1.0 ilu-strowanie artykułów obsługiwał specjalny, nie-zbyt intuicyjny dodatek (mosimage). Co prawda, samo stosowanie dodatku osobom nauczonym, jak go używać kłopotu nie sprawiało, ale jeśli ktoś nie doczytał, jak to się robi, miał problem.

W Joomla 1.5 – podobnie jak w Joomla 1.0 wstawiamy ilustracje do artykułów za pomo-cą przycisku Wstaw obraz, ale teraz polecenie to otwiera specjalny edytor, umożliwiający zarówno wybór obrazka, jak i opis jego właściwości.

Co więcej – w Joomla 1.0 nie można było umie-ścić w artykule obrazka, który nie został przesłany na serwer przed przystąpieniem do pisania arty-kułu. W Joomla 1.5 jest to, oczywiście, możliwe.

Podgląd artykułu i inne usprawnieniaW Joomla 1.0 redagowany artykuł można było podejrzeć dopiero po zapisaniu go w bazie da-nych. W Joomla 1.5 podgląd możliwy jest już po napisaniu pierwszych słów, a więc w każdym momencie.

Usprawniono również podział długich arty-kułów na strony i generowanie spisu treści arty-kułów wielostronicowych. Przycisk Podziel stronę wywołuje teraz okno, w którym podajemy para-metry podziału – tytuł nowej strony oraz inną na-zwę umieszczaną w spisie treści. Poprzednio ko-

nieczne było ręczne wpisanie markera wraz z od-powiednimi atrybutami.

W Joomla 1.0 dysponowaliśmy jednym edyto-rem wizualnym – TinyMce. Wprawdzie możliwe było doinstalowanie innych edytorów, ale trzeba to było uczynić, jeśli TinyMCE nie spełniał naszych oczekiwań. Joomla 1.5 udostępnia dwa edytory wizualne, obok TinyMCE – XStandard Lite. Edy-tor ten oferuje wprawdzie znacznie mniej funkcji, ale zapewnia większą zgodność generowanego ko-du ze standardami XHTML niż TinyMCE.

W Joomla 1.5 na dobre zagościła też możliwość wyboru przez użytkowników uprawnionych do współtworzenia witryny własnego edytora.

Parametry globalneObowiązujących w całej witrynie, podstawo-wych ustawień prezentacji artykułów w Jo-omla 1.0 dokonywaliśmy w edytorze konfigu-racji globalnej witryny. W Joomla 1.5 edytor tych ustawień przeniesiono w bardziej natural-ne miejsce – do menedżera artykułów. W każ-dym bądź razie tak sądzili projektanci. W rezul-tacie użytkownicy Joomla! 1.0 zastanawiają się często, gdzie się te ustawienia podziały. A kryją się w przyborniku menedżera artykułów (strona Wszystkie artykuły), pod ikoną Preferencje.

Takie rozwiązanie wynika nie tylko z woli uproszczenia interfejsu, ale także z rozwiniętych w Joomla 1.5 możliwości zarządzania rozszerze-niami. W Joomla 1.0 parametry globalne można było zdefiniować w zasadzie tylko dla treści zarzą-dzanych przez komponent Artykuły (Content). W Joomla 1.5 można ustawiać parametry globalne także dla niektórych komponentów i modułów. W przybornikach na stronach menedżerów tych rozszerzeń również znajdziemy ikonę Preferen-cje (być może w następnych polskich wydaniach użyjemy określenia Ustawienia lub Parametry). Za pierwszym przemawia jego polski rodowód, za drugim spójność terminologiczna.

Projektowanie menuSpore udoskonalenia przyniosła w Joomla 1.5 obsługa menu. Zmiany, pozornie drobne, mają jednak charakter wręcz rewolucyjny.

Zmiana najtrudniej dostrzegalnaZmiana najmniej widoczna, najtrudniej do-strzegalna, a najbardziej rewolucyjna wynika z konsekwentnego zastosowanego w Joomla 1.5 wzorca projektowego MCV (Model-Kontroler-Widok). Pozwala on projektantom witryn na stosunkowo łatwe zaprojektowanie własnych sposobów prezentacji treści, innych niż wido-ki domyślne. W efekcie spora już w Joomla 1.0 ilość typów pozycji menu w Joomla 1.5 jest prak-tycznie nieograniczona. Każdy może wzboga-cać oferowaną domyślnie paletę o nowe, od-powiednie dla konkretnej witryny rozwiąza-nia. Po umieszczeniu skryptów definiujących nowe widoki wśród skryptów szablonu, po-jawią sie one w zestawie typów pozycji menu do wyboru.

Page 50: SDJ_11_2008_PL_E-Commerce

11/200850

Testowanie oprogramowania

Trzy kliknięciaNie chodzi tu o dotarcie po 3 kliknięciach do po-szukiwanej treści, ale o tworzenie nowej pozycji menu w Joomla 1.5. Dodajemy je dosłownie za pomocą trzech kliknięć – w pierwszym wybie-ramy w przyborniku polecenie Utwórz, w dru-gim wskazujemy zakres treści (artykuły, kompo-nent, łącze zewnętrzne), w trzecim widok – spo-sób prezentacji (typ pozycji), po czym trafiamy na stronę edytora pozycji, gdzie wystarczy jedy-nie uściślić zakres treści i ewentualnie zdefinio-wać dodatkowe parametry prezentacji.

Pozycja domyślnaDomyślna startowa pozycją menu w Joomla 1.0 musiała być pierwszą pozycją w głównym menu witryny. Joomla 1.5 zapewnia w tej mierze peł-ną swobodę – domyślną pozycją menu, wska-zującą na stronę startową witryny, wywoływaną po wpisaniu w przeglądarce adresu witryny mo-że być dowolna pozycja w dowolnym menu. W każdym też momencie można ją zmienić.

Zmiana typu bez usuwania W Joomla 1.0 takiej możliwości nie było w ogó-le. Raz ustalonego typu pozycji menu zmienić się nie dało. Jedynym wyjściem było usunięcie takiej nieodpowiadającej nam pozycji i stworzenie no-wej. W Joomla 1.5 wystarczy prosty zabieg – w edytorze pozycji menu naciskamy przycisk Zmień typ, a następnie dokonujemy odpowiednich usta-wień. Walory tego rozwiązania można poznać tak naprawdę dopiero w trakcie migracji z Joom-la 1.0 do Joomla 1.5. Kto już przechodził ten pro-ces, wie, ze podczas migracji tracimy – niestety – wszystkie połączenia pozycji menu z nierdzen-nymi komponentami. Dzięki możliwości zmia-ny typu menu po doinstalowaniu komponentów przywrócenie połączeń w różnych menu witryny przebiega łatwo, bez zbędnego stresu.

Szablony graficzneO najistotniejszej zmianie już wspominaliśmy: konsekwentne rozdzielenie warstwy aplikacji, warstwy danych i warstwy prezentacji – zastoso-wanie modelu MCV – otworzyło nowe możliwo-ści przed projektantami szaty graficznej. W Joom-la 1.0 o mechanizmach personalizacji szablonów można było raczej pomarzyć. Oczywiście, stosu-jąc specjalne skrypty, projektanci udostępniali użytkownikom pewne możliwości dostosowania szablonu do swoich preferencji. Teraz te możliwo-ści wzrosły w sposób w zasadzie nieograniczony.

Skrypt konfiguracyjny szablonu może posia-dać sekcję parametrów definiujących opcjonalne rozwiązania różnych kwestii – rozmiarów stro-ny, układu jedno- lub wielokolumnowego, roz-mieszczenia elementów, kolorystyki, wielkości czcionki. Oczywiście, nie wystarczy samo zde-finiowanie możliwości wyboru – szablon trze-ba odpowiednio zaprogramować. Jest to jednak działanie niezwykle proste – najczęściej wystar-czy zdefiniowanie odpowiednich arkuszy stylów dla poszczególnych opcji.

Zwolenników standardów dostępności intere-suje zapewne, na ile zmodyfikowano kod, który w Joomla 1.0 preferował stosowanie do rozmieszcza-nia treści obciążających kod i łącza, a przy tym wy-soce niedostępnych tabel. Gorszą wiadomością jest ta, że tabele w kodzie pozostały. Nie zdecydowano się na pełne wykorzystanie doświadczeń projektu a8e. Ale jest i dobra wiadomość, którą się już dzie-liliśmy. Proces generowania kodu HTML został przeniesiony do odrębnych skryptów, które mo-gą być swobodnie modyfikowane przez projektan-tów bez ingerencji w rdzenny kod. W efekcie każ-dy projektant witryny może skutecznie wyelimi-nować z kodu wszystkie niepotrzebnie zastosowa-ne tabele, zastępując je rozwiązaniami w pełni ko-rzystającymi z możliwości CSS. Istotą rozwiązania jest mechanizm podmiany skryptów rdzenia Joom-la! skryptami szablonu. Przykład takiego rozwiąza-nia dołączono, oczywiście, do oficjalnego wydania Joomla 1.5. Zainteresowanych odsyłamy do przej-rzenia skryptów szablonu Beez, zwłaszcza tych umieszczonych w katalogu /templates/beez/html. Znajdziemy tam wzorcowe skrypty widoków dla rdzennych komponentów i modułów (contact, con-tent, poll, search, user, weblinks). Można je wykorzy-stać we własnych rozwiązaniach projekowych.

OtwartośćCechą umieszczającą Joomla 1.5 w ścisłej czołów-ce najnowocześniejszych rozwiązań współczesnej informatyki jest jego otwartość i łatwość integra-cji z innymi systemami. W porównaniu z Joomla 1.0, które pod tym względem również przodowa-ło wśród innych CMS (systemów zarządzania wi-trynami ineternetowymi), w Joomla 1.5 dokona-no niemalże skoku o pokolenie wzwyż. Mechani-zmy integracji oparto na znanym już z poprzed-niej wersji, ale rozbudowanym typie rozszerzenia nazwanych obecnie dodatkami lub wtyczkami. Zmiana ich nazwy nie jest ucieczką od przypomi-nających związek z Mambo mambotów czy krócej botów, ale podkreśla istotną zmianę ich roli.

W Mambo i w Joomla 1.0 boty umożliwiały do-dawanie funkcji, których zadaniem było przetwa-rzanie treści (np. osadzanie obrazków i ich parame-trów, paginacja materiałów wielostronicowych).

W Joomla 1.5 dodatki (kalka językowa – wtycz-ki do najpiękniejszych nie należy, ale popularyzo-wana przez nas od lat nazwa dodatki może budzić nieporozumienia) mogą poszerzać funkcjonal-ność Joomlowego frameworka. W dystrybucji 1.5 znajdujemy kilka takich dodatków, m.in.:

• upoważnienie – LDAP: obsługujący uwie-rzytelnianie do usługi sieciowej LDAP;

• upoważnienie – OpenID: obsługujący identyfikację za pomocą OpenID;

• upoważnienie – GMail: obsługuje integra-cję z usługami sieciowymi Gmail;

• XML-RPC - Blogger API: obsługuje inter-fejs oprogramowania XML-RPC Blogger.

Przykładów praktycznego wykorzystanie tych i innych dodatków oferowanych przez projektan-

tów spoza zespołu Centrum Projektu nie znaj-dziemy jeszcze w Sieci zbyt wielu, ale jaskółki w tym przypadku dość szybko uczynią wiosnę.

Kompatybilność z 1.0 i rozszerzeniamiProjektanci Joomla 1.5 uczynili wszystko, co możliwe, aby zachować w maksymalnym stopniu wsteczną zgodność z Joomla 1.0, a tym samym i z rozszerzeniami stworzonymi dla Joomla 1.0. Za-stosowane w Joomla 1.5 rozwiązania projekto-we, oparte na obiektowym PHP z natury rzeczy wymagają rozszerzeń napisanych wedle nowego wzorca projektowego. Natywnych rozszerzeń dla Joomla 1.5 jest już sporo (niestety, niewiele spo-lonizowanych), ale nie na tyle, by można zupeł-nie zrezygnować z opracowanych dla Joomla 1.0, zwłaszcza że zastosowanie alternatywnych roz-wiązań pociąga za sobą koszty migracji danych, a projektanci dawnych rozszerzeń albo porzucili swoje dawne rozwiązania, albo publikują nowsze wersje na licencjach komercyjnych.

W Joomla 1.5 można korzystać z rozszerzeń projektowanych dla Joomla 1.0 (komponentów, modułów, szablonów, dodatków) w specjalnym trybie – trybie zgodności wstecznej. Uaktywnienie trybu jest proste – wystarczy włączyć odpowiedni dodatek, wybierając w menu zaplecza ->Dodatki -> System : Spuścizna (Plugins -.System – Legacy).

Zdarzyć się może, że włączenie trybu zgodno-ści wstecznej nie rozwiąże jednak problemów z dawnymi rozszerzeniami. Na nic zda się narze-kanie na niedobrych projektantów, co to nie prze-widzieli kilka lat temu, jakie możliwości i wyma-gania będzie mieć Joomla! w roku 2008, 2009 i następnych. Jeśli jakieś starocie ma miejsce w muzeum, poradzić się nie da. Trzeba poszukać nowszych rozwiązań. Szczególnie dotyczy to komponentów stworzonych jeszcze dla Mam-bo, wymagających rejestrowania zmiennych glo-balnych. Nawet usilne próby bez zasadniczych zmian w kodzie nie przywrócą im życia.

PodsumowanieStworzenie doskonałej witryny ze wszystkimi funkcjami, jakie sobie wymarzysz, może wymagać czasu i zaangażowania. Ale ze społecznością Joom-la!, wsparciem projektantów oraz dzięki licznym rozszerzeniom tworzonym dla Joomla! 1.5, jest to jak najbardziej możliwe. Możesz również tworzyć własne rozszerzenia i udostępniać je ku uciesze ca-łej społeczności.

STEFAN WAJDAStefan Wajda [Zwiastun] jest liderem PCJ!, koordyna-

torem Zespołu Tłumaczy i Dokumentacji akredytowa-

nym przy Translation Work Group projektu Joomla!,

wydawcą witryn PCJ, autorem w pełni zlokalizowa-

nych wersji Mambo i Joomla!, komponentów josDirec-

tory i josResource. Spolonizował ponad 150 rozszerzeń

dla Joomla!, opublikował w Internecie około 600 arty-

kułów poświęconych wszystkim aspektom Joomla!

Kontakt z autorem: [email protected]

Page 51: SDJ_11_2008_PL_E-Commerce
Page 52: SDJ_11_2008_PL_E-Commerce

11/200852

XMLSpring 2 Schema

www.sdjournal.org 53

Spring jest popularnym frameworkiem IOC (Inversion Of Control) dla języka Java. Ofe-ruje on kilka sposobów konfiguracji apli-

kacji oraz wstrzykiwania zależności, jednak naj-bardziej popularną techniką uzyskiwania tych ce-lów jest konfiguracja w pliku XML. Jak powszech-nie wiadomo XML oferuje czytelną, hierarchiczną strukturą prezentowanych przez siebie informa-cji, które to m.in. zapewniły mu rolę niepisanego standardu konfiguracji aplikacji webowych. XML jednakże cechuje się również tendencją do gadatli-wości tzn. do konieczności opisywania zawartych w nim danych za pomocą dużej ilości tekstu. Pro-gramiści używający Springa w wersji niższej niż 2.0 skazani byli na używanie dość ograniczonego zestawu narzędzi redukujących rozmiar plików konfiguracyjnych XML oraz zjawiska tzw. XML hell (np. stosowanie dziedziczenia definicji be-anów lub automatycznego wiązania). Na szczęście twórcy Springa od wersji 2.0 swojego frameworka dodali możliwość konfiguracji aplikacji za pomocą plików XML zdefiniowanych nie tylko zgodnie z DTD, ale i mechanizmem XML Schema. Oczywi-ście stare konfiguracje napisane pod kątem DTD

w dalszym ciągu działają w wersji 2.0 Springa (ze względu na słynne umiłowanie kompatybilności wstecz przez jego autorów), jakkolwiek zalecaną formą konfiguracji XML jest teraz XML Schema.

MotywacjaNie trzeba nawet specjalnie zachęcać do stoso-wania nowej definicji plików konfiguracyjnych XML, gdyż oferuje nam ona rozliczne korzyści o których użytkownicy DTD mogą tylko poma-

rzyć. Zaliczyć do nich należy głównie usprawnio-ne uzupełnianie składni w edytorach XML do-stępnych w popularnych IDE oraz zestaw dodat-kowych przestrzeni nazw włączonych do dystry-bucji Springa począwszy do wersji 2.0. W szcze-gólności predefiniowane przestrzenie nazw oka-zują się być przydatne w codziennej pracy – po-zwalają one m.in. na zastąpienie rozbudowanych definicji fabryk typu FieldRetrievingFactoryBean, ListFactoryBean lub TransactionProxyFactoryBe-an ich kompaktowymi odpowiednikami wyrażo-nymi za pomocą określonej przestrzeni nazw.

Twórcy Springa nie poprzestali na szczęście na dostarczeniu nam zestawu predefiniowa-nych przestrzeni nazw, ale udostępnili również mechanizm do samodzielnego tworzenia tych-że. Nie muszę chyba wspominać o tym jak bar-dzo konfiguracja naszej aplikacji zyska na czy-telności po zastosowaniu elementów oraz atry-butów własnej konstrukcji, dostosowanych do

Spring 2 Schema

Ten artykuł wprowadzi Cię szybko w podstawowe techniki tworzenia własnych przestrzeni nazw XML Schema dla plików konfiguracyjnych Spring IOC. Autorzy Spring Framework pisząc o dobrym oprogramowaniu promują zasadę DRY (Don't Repeat Yourself ) – wyraźnie widać to w mechanizmie rozszerzania konfiguracji XML kontenera Springa.

Dowiesz się:• Jak za pomocą własnej przestrzeni nazw XML

stworzyć najprostsze rozszerzenia składni pli-

ków konfiguracyjnych XML dla Spring Frame-

work w wersji 2.x.

Powinieneś wiedzieć:• Podstawowa znajomość języka Java oraz kon-

figuracja kontenera Inversion Of Control dla

Spring Framework 2.x za pomocą plików XML;

• Wskazana jest również minimalna wiedza z za-

kresu języka XML oraz API programowej ob-

sługi kontenera Spring IOC.

Poziom trudności

Własne przestrzenie nazw w Spring 2.x

Listing 1. Szkielet konfiguracji kontenera Springa oparty na XML DTD

<!-- Stara konfiguracja -->

<?xml version="1.0" encoding="UTF-8"?>

<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN 2.0//EN"

"http://www.springframework.org/dtd/spring-beans-2.0.dtd">

<beans>

</beans>

Listing 2. Szkielet konfiguracji kontenera Springa oparty na XML Schema

<!-- Nowa konfiguracja -->

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/

beans/spring-beans-2.0.xsd">

</beans>

Page 53: SDJ_11_2008_PL_E-Commerce

11/200852

XMLSpring 2 Schema

www.sdjournal.org 53

naszych konkretnych potrzeb. Zysk ten będzie widoczny w szczególności jeżeli planujemy wielokrotne wykorzystywanie naszego kodu w aplikacjach używających np. pisanej przez nas biblioteki. W artykule tym chciałbym właśnie przedstawić podstawowe techniki rozszerzania możliwości konfiguracyjnych XML w Springu.

Migracja na nowy styl konfiguracjiPrzejście na nowy styl konfiguracji jest bardzo proste. Wystarczy zamienić w istniejących pli-kach konfiguracyjnych parę pierwszych linijek dokumentu.

Migracja zaprezentowana na Listingu 2 jest niemalże bezbolesna. Niemalże, gdyż istnieje parę (dosłownie parę) szczegółów konfigura-cji które zostały uznane przez twórców Sprin-ga za przestarzałe (deprecated) i które należy w związku z tym dostosować do nowej konfigura-cji opartej na XML Schema. Do szczegółów te-go typu należy np. atrybut singleton elemen-tu <bean>, który w nowej konfiguracji powi-nien zostać zamieniony na atrybut scope (ze względu na wprowadzenie mechanizmu roz-szerzalnych zasięgów w nowszych wersjach Springa).

Witaj przestrzenio – przypadek użyciaNa początku spróbujemy napisać jak najszyb-ciej najprostszą przestrzeń nazw z jednym ele-mentem. Na potrzeby przykładów minimal-nych zawartych w tym artykule załóżmy, że pracujemy dla firmy Foo i naszym zadaniem jest stworzenie elementu XML który pozwo-li nam na bardziej efektywne używanie kom-ponentu Bar w aplikacjach korzystających ze sprzedawanej przez nas biblioteki. Wyobraźmy sobie, że docelowo nasz klient chciałby konfi-gurować swoją aplikację za pomocą komponen-tu Bar w następujący sposób – Listing 3.

Oczekujemy, że powyższa konfiguracja utwo-rzy w kontenerze instancję klasy Bar o id rów-nym bar oraz wartości prywatnej właściwości value równej barValue. Sam komponent Bar wygląda następująco – Listing 4.

Schemat krokówKlasyczny schemat kroków wykonywany podczas tworzenia własnej przestrzeni nazw to kolejno:

• napisanie dokumentu XSD;• stworzenie parserów dla nowych elemen-

tów lub atrybutów XML;• zaprogramowanie własnej klasy typu

NamespaceHandler, która pozwoli nam na zmapowanie parserów i dekoratorów do określonych elementów i atrybutów XML;

• dodanie do wynikowej aplikacji lub biblio-teki meta-danych potrzebnych Springowi.

W kolejnych sekcjach opiszę szerzej każdy z tych kroków.

Listing 3. Przykład użycia komponentu z własnej przestrzeni nazw

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"

xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

xmlns:myns="http://www.foo.com/customSchema"

xsi:schemaLocation="

http://www.springframework.org/schema/beans http://www.springframework.org/schema/

beans/spring-beans-2.0.xsd

http://www.foo.com/customSchema http://www.foo.com/customSchema.xsd">

<myns:bar id="bar" value="barValue" />

</beans>

Listing 4. Kod przykładowego komponentu Bar

package foo;

public class Bar {

// wartość komponentu

private String value;

public Bar(String value) {

this.value = value;

}

@Override

public String toString() {

return value;

}

}

Listing 5. Dokument XML Schema definiujący przykładową przestrzeń

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns="http://www.foo.com/customSchema"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:beans="http://www.springframework.org/schema/beans"

targetNamespace="http://www.foo.com/customSchema"

elementFormDefault="qualified"

attributeFormDefault="unqualified">

<xsd:import namespace="http://www.springframework.org/schema/beans" />

<xsd:element name="bar">

<xsd:complexType>

<xsd:complexContent>

<xsd:extension base="beans:identifiedType">

<xsd:attribute name="value" type="xsd:string" use="required" />

</xsd:extension>

</xsd:complexContent>

</xsd:complexType>

</xsd:element>

</xsd:schema>

W Sieci

• http://springframework.org – Strona projektu Spring Framework • http://static.springframework.org/spring/docs/2.5.x/api – Spring 2.5 API • http://static.springframework.org/spring/docs/2.5.x/reference/xsd-config.html – Konfiguracja

oparta na XML Schema w Spring 2.5 • http://static.springframework.org/spring/docs/2.5.x/reference/extensible-xml.html – Własna prze-

strzeń nazw wg Spring 2.5 Reference • http://www.w3.org/XML/Schema – XML Schema• http://www.w3.org/ – DOM XMl DOM

Page 54: SDJ_11_2008_PL_E-Commerce

11/200854

XMLSpring 2 Schema

www.sdjournal.org 55

Dokument XSDDokument XML Schema pozwoli nam określić składnię naszej przestrzeni nazw, czyli m.in. ja-

kie elementy oraz atrybuty są w niej dopusz-czalne, a jakie nie. Schema uwzględnia również informacje o tym jakie typy danych zawarte są

w poszczególnych elementach i atrybutach na-szej przestrzeni oraz czy są one obowiązkowe. Interesujący nas schemat mógłby mieć następu-jącą postać – Listing 5.

Tematyka tworzenia definicji XML Schema jest poza zakresem tego artykułu. Ograniczę się zatem do podsumowania, że zdefiniowaliśmy właśnie element o nazwie bar zawierający jeden (wymagany) atrybut o nazwie value. Element ten dziedziczy również po identyfikowalnym typie Springa, co w praktyce oznaczna tyle, że również implicite dziedziczy atrybut id. Na-stępnym krokiem zbliżającym nas do działającej przestrzeni nazw będzie zmapowanie elementu XML zdefiniowanego powyżej do Javy.

Parser elementuAby przekonwertować element XML do instan-cji zarejestrowanej w kontenerze musimy napi-sać parser implementujący interfejs org.springframework.beans.factory.xml.BeanDefiniti

onParser. Klasy implementujące wspomniane-go interfejsu służą do analizy pojedynczego ele-mentu XML znajdującego się bezpośrednio mię-dzy elementami <beans></beans>, wraz z ew. podelementami znajdującymi się wewnątrz na-szej definicji. Nasz konkretny element <bar> jest raczej prosty tzn. nie zawiera zagnieżdżonych elementów i zwróci tylko jedną instancję (klasy Bar) do rejestracji w kontrolerze. Ograniczmy się zatem do dziedziczenia z klasy AbstractSingleBeanDefinitionParser – Listing 6.

Klasa BeanDefinitionBuilder jest jedną z najważniejszych klas programowej obsługi kon-tenera Springa.

Temat ten zasługuje na co najmniej parę osobnych artykułów, tak więc ograniczę się tyl-ko do podania informacji, że klasa ta służy do programowego tworzenia instancji klasy prze-znaczonej do rejestracji w kontenerze. W tym konkretnym przykładzie chcemy, aby nowy obiekt klasy Bar został stworzony za pomocą jednoargumentowego konstruktora.

Zarejestrowanie elementu w NamespaceHandlerInstancje interfejsu org.springframework.beans.factory.xml.NamespaceHandler służą do łą-czenia przestrzeni nazw z parserami elementów oraz atrybutów XML. Sam NamespaceHandler nie wykonuje logiki związanej z analizą elemen-tów i atrybutów XML, ponieważ całą logikę związaną z czytaniem dokumentu XML zawar-liśmy w poprzednim kroku (w definicji parse-ra). NamespaceHandler oferuje parę metod po-zwalających na interakcję z nim w określonych momentach jego cyklu życia, jakkolwiek na na-sze skromne potrzeby zainteresujemy się jedynie bezargumentową metodą init() wywoływaną w momencie inicjalizacji handlera.

W powyższym przykładzie (Listing 7) zma-powaliśmy parser napisany w poprzednim kroku do elementu XML <bar>. W miażdżą-cej większości przypadków jeden handler bę-

Listing 6. Przykładowy parser komponentu Bar

package foo;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;

import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;

import org.w3c.dom.Element;

public class BarParser extends AbstractSingleBeanDefinitionParser {

@Override

// Oczekujemy instancji klasy Bar

protected Class<Bar> getBeanClass(Element element) {

return Bar.class;

}

@Override

protected void doParse(Element element, BeanDefinitionBuilder builder) {

// Odczytaj wartość atrybutu

String value = element.getAttribute("value");

// i dodaj ją jako argument konstruktora wynikowej instancji

builder.addConstructorArgValue(value);

}

}

Listing 7. Handler mapujący przykładowy element 'bar' do wybranego parsera

package foo;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class BarNamespaceHandler extends NamespaceHandlerSupport {

@Override

public void init() {

// zarejestruj instancję parsera dla

// elementów <bar/> z tej przestrzeni nazw

registerBeanDefinitionParser("bar", new BarParser());

}

}

Listing 8. Zawartość pliku META-INF/spring.handlers

http\://www.foo.com/customSchema=foo.BarNamespaceHandler

Listing 9. Zawartość pliku META-INF/spring.schema

http\://www.foo.com/customSchema.xsd=foo/foo.xsd

Listing 10. Kod minimalnego komponentu 'Bar' rozszerzonego o listę swoich potomków

package foo;

import java.util.List;

public class Bar {

private String value;

private List<Bar> children;

public Bar(String value) {

this.value = value;

}

@Override

public String toString() {

return value;

}

public void setChildren(List<Bar> children) {

this.children = children;

}

public List<Bar> getChildren() {

return children;

}

}

Page 55: SDJ_11_2008_PL_E-Commerce

11/200854

XMLSpring 2 Schema

www.sdjournal.org 55

dzie mapował wiele parserów i/lub dekorato-rów –nie implementujemy wielu handlerów dla jednej przestrzeni nazw. Jak wspomnia-łem wcześniej nasze potrzeby względem han-dlera są bardzo skromne – dlatego właśnie dziedziczymy z klasy org.springframework.beans.factory.xml.NamespaceHandlerSupp

ort. Dzięki wspomnianej klasie pomocniczej możemy nadpisać metodę init() interfejsu oraz nie martwić się o logikę związaną z reje-stracją parsera.

Meta-dane dla SpringaOstatnim krokiem jest dodanie do korzenia ścieżki klas naszej aplikacji lub biblioteki fol-deru META-INF wraz z plikami spring.handlers oraz spring.schemas – Listing 8 i Listing 9.

Jak widać pierwszy z nich mapuje URI prze-strzeni nazw na napisany przez nas wcześniej handler – tą metodą Spring wie których par-serów powinien użyć dla poszczególnych ele-mentów i atrybutów w określonej przestrzeni nazw. Drugi zaś wskazuje fizyczną lokalizację pliku XSD z definicją naszej przestrzeni – w tym konkretnym przypadku plik z definicją po-winien znajdować się w pakiecie foo i nazywać się foo.xsd. Pragę zwrócić uwagę na koniecz-ność poprzedzania znaków dwukropka w oby-dwu plikach znakiem backslash (ze względu na fakt, że nie tylko znak równości, ale i dwukro-pek są poprawnymi symbolami końca klucza w plikach właściwości Javy).

Zagnieżdżanie elementów – rozszerzony przypadek użyciaPowyższy przykład jest nieco prosty, gdyż za-kłada że sparsowany element XMLa zareje-struje tylko jedną instancję określonej klasy w kontrolerze. Jeżeli chcielibyśmy rekurencyjnie parsować i rejestrować zagnieżdżone elemen-ty XML powinniśmy stworzyć parser dziedzi-czący po czymś potężniejszym niż AbstractSingleBeanDefinitionParser – tą klasą jest np. AbstractBeanDefinitionParser. Wyobraź-my sobie, że nasz przypadek użycia rozszerzy-my w następujący sposób – otóż nasz potężny komponent Bar został rozszerzony o listę swo-ich dzieci (dla uproszczenia przykładu również instancji klasy Bar) – Listing 10.

Przykładowy scenariusz konfiguracji drzewa komponentów Bar w pliku XML mógłby wy-glądać następująco – Listing 11.

Powyższa zmiana konfiguracji pociąga za so-bą oczywiście konieczność aktualizacji doku-mentu XML Schema – Listing 12.

Poza schematem XML w stosunku do po-przedniego przykładu zmianie uległby w zasa-dzie tylko sam parser – Listing 13.

Powyższy parser mógłby dziedziczyć po kla-sie AbstractSingleBeanDefinitionParser i dalej zwracać wynik zgodny z zadanym scena-riuszem, jakkolwiek dziedziczenie po AbstractBeanDefinitionParser pozwala na jego nie-co czytelniejszą implementację.

Listing 11. Przykład użycia zagnieżdżonego komponentu

<myns:bar id="bar" value="parent">

<myns:bar value="child1">

<myns:bar value="grandChild" />

</myns:bar>

<myns:bar value="child2" />

</myns:bar>

Listing 12. Uaktualniony dokument XML Schema uwzględniający zagnieżdżanie elementów

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns="http://www.foo.com/customSchema"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

targetNamespace="http://www.foo.com/customSchema"

elementFormDefault="qualified" attributeFormDefault="unqualified">

<xsd:element name="bar">

<xsd:complexType>

<xsd:choice minOccurs="0" maxOccurs="unbounded">

<xsd:element ref="bar" />

</xsd:choice>

<xsd:attribute name="id" type="xsd:ID" />

<xsd:attribute name="value" use="required" type="xsd:string" />

</xsd:complexType>

</xsd:element>

</xsd:schema>

Listing 13. Parser elementu 'bar' uwzględniający rekurencję

package foo;

import java.util.List;

import org.springframework.beans.factory.support.AbstractBeanDefinition;

import org.springframework.beans.factory.support.BeanDefinitionBuilder;

import org.springframework.beans.factory.support.ManagedList;

import org.springframework.beans.factory.xml.AbstractBeanDefinitionParser;

import org.springframework.beans.factory.xml.ParserContext;

import org.springframework.util.xml.DomUtils;

import org.w3c.dom.Element;

public class BarParser extends AbstractBeanDefinitionParser {

protected AbstractBeanDefinition parseInternal(Element element,

ParserContext parserContext) {

// Stwórz budowniczego definicji elementu

BeanDefinitionBuilder barBuilder = BeanDefinitionBuilder

.rootBeanDefinition(Bar.class);

barBuilder.addConstructorArgValue(element.getAttribute("value"));

// Wyszukanie dzieci elementu określonego typu

List<Element> childElements = DomUtils.getChildElementsByTagName(

element, "bar");

if (childElements != null) {

// Dodanie potomków do listy zarządzanej przez kontener

ManagedList children = new ManagedList(childElements.size());

for (Element e : childElements) {

// Rekurencja

children.add(parseInternal(e, parserContext));

}

barBuilder.addPropertyValue("children", children);

}

return barBuilder.getBeanDefinition();

}

}

Page 56: SDJ_11_2008_PL_E-Commerce

11/200856

XML

Własne atrybuty – przypadek użyciaOstatnim istotnym przypadkiem użycia jest dodanie własnego atrybutu do dowolnego ele-

mentu w pliku konfiguracyjnym – Listing 14. Załóżmy, że chcemy aby podczas parsowania elementu oznaczonego atrybutem myns:bar (o dowolnej wartości) na konsoli pojawiała się

wartość licznika wskazującego ile elementów oznaczonych identyczną wartością znaleziono dotychczas w kontenerze.

Zmiany w implementacjiJak łatwo się domyśleć na pierwszy ogień pój-dzie aktualizacja schematu XML – Listing 15.

Podobnie jak w przypadku własnych ele-mentów, dla nowego atrybutu również musi-my napisać własny parser. Możemy to wygod-nie zrobić poprzez implementację interfejsu BeanDefinitionDecorator – Listing 16.

Tym razem będziemy również musieli zmo-dyfikować BarNamespaceHandler.

Wynika to z faktu, iż tym razem nie rejestru-jemy parsera definicji beana, a tylko tzw. deko-rator, czyli mniejszy parser służący do mody-fikacji lub wzbogacania wybranego fragmen-tu definicji. Oczywiście wyświetlanie informa-cji o tym którą z kolei definicję oznaczoną kon-kretną wartością parsuje kontener, jest w real-nym świecie średnio przydatne, jakkolwiek do-stęp do parametrów BeanDefinitionHolder oraz ParserContext daje nam możliwość ma-nipulacji kolejno definicją dekorowanego ele-mentu (możemy również zwrócić całkowicie nową instancję zamiast modyfikować istnie-jącą) oraz całym rejestrem kontenera. Nieste-ty ze względu na ograniczony rozmiar niniej-szego artykułu jestem zmuszony przemilczeć szczegóły dotyczące możliwości programowej manipulacji definicjami beanów oraz zawarto-ścią kontenera.

Podsumowanie W niniejszym artykule poznaliśmy podsta-wowe sposoby rozszerzania możliwości kon-figuracyjnych plików XML w Springu za po-mocą własnych przestrzeni nazw. Znając spo-soby na analizę elementów XML najwyższe-go poziomu (wraz z ich ew. zagniżdżenia-mi) oraz atrybutów XML możemy rozpocząć tworzenie własnych przestrzeni nazw, któ-re przy minimalnej znajomości XML DOM oraz API programowej manipulacji zawar-tością kontenera IOC Springa pozwolą nam na napisanie w pełni funkcjonalnych mapo-wań dla naszych komponentów. Tematyka tego artykułu powinna w szczególności za-interesować osoby dostarczające dla innych firm programistycznych gotowe rozwiąza-nia oparte na Springu ze względu na zmini-malizowanie wiedzy wymaganej przez klien-ta do poprawnego stosowania naszych kom-ponentów.

HENRYK KONSEKAutor pracuje na stanowisku projektanta JEE w

warszawskiej firmie Artegence. Udziela się rów-

nież jako administrator serwisu javablackbelt.com.

W wolnym czasie interesuje się swoją Anią oraz

m.in. psychiatrią oraz dobrymi technologiami.

Kontakt z autorem: http://www.hekonsek.pl lub he-

[email protected].

Listing 14. Przykład użycia atrybutu XML z własnej przestrzeni nazw

<bean class="java.lang.String" myns:bar="barValue" >

<constructor-arg value="someValue"/>

</bean>

Listing 15. Dokument XML Schema dla minimalnego atrybutu

<?xml version="1.0" encoding="UTF-8"?>

<xsd:schema xmlns="http://www.foo.com/customSchema"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

targetNamespace="http://www.foo.com/customSchema"

elementFormDefault="qualified" attributeFormDefault="unqualified">

<xsd:attribute name="bar" type="xsd:string" />

</xsd:schema>

Listing 16. Parser minimalnego atrybutu z własnej przestrzeni

package foo;

import java.util.HashMap;

import org.springframework.beans.factory.config.BeanDefinitionHolder;

import org.springframework.beans.factory.xml.BeanDefinitionDecorator;

import org.springframework.beans.factory.xml.ParserContext;

import org.w3c.dom.Attr;

import org.w3c.dom.Node;

public class BarParser implements BeanDefinitionDecorator {

HashMap<String, Integer> counters = new HashMap<String, Integer>();

@Override

public BeanDefinitionHolder decorate(Node node,

BeanDefinitionHolder holder, ParserContext ctx) {

// odczytaj wartość atrybutu

String value = ((Attr) node).getValue();

// sprawdź wartość licznika

Integer i = counters.get(value);

if (i == null) {

i = 0;

}

// zwiększ licznik

counters.put(value, ++i);

// wyświetl wynik

System.out.println(value + ": " + i);

return holder;

}

}

Listing 17. Handler mapujący parser do atrybutu 'bar'

package foo;

import org.springframework.beans.factory.xml.NamespaceHandlerSupport;

public class BarNamespaceHandler extends NamespaceHandlerSupport {

@Override

public void init() {

registerBeanDefinitionDecoratorForAttribute("bar", new BarParser());

}

}

Page 57: SDJ_11_2008_PL_E-Commerce
Page 58: SDJ_11_2008_PL_E-Commerce

11/200858

Kasa dla webmasteraLinkLift – pewny zarobek na reklamie

www.sdjournal.org 59

Z biegiem czasu formy reklamy w In-ternecie rozwinęły się. Początkowo dostępne były jedynie reklamy tek-

stowe lub graficzne, płaciło się zaś za ilość wyświetleń.

Następnie prym zaczęły wieść reklamy ro-bione we flashu, a wraz z nimi przyszło pła-cenie niezależne od ilości wyświetleń, lecz od ilości kliknięć w reklamę. Niektórzy po-sunęli się jeszcze dalej – korzyści otrzymy-wało się jedynie, jeśli użytkownik kliknął w reklamę na naszej stronie, a następnie za-rejestrował się na witrynie reklamowanej lub kupił z niej jakiś produkt, bądź zamó-wił usługę (taka forma reklamy jest dostęp-na także w Google AdSense jako tzw. skie-rowania).

Rezultatem takich praktyk było obniżenie się zarobków webmasterów do tego stopnia, że reklama na witrynie średnio poczytnej za-częła być dyskusyjna – czy jest ona jeszcze opłacalna.

W tej sytuacji odważniejsze serwisy wy-szły naprzeciw wymaganiom twórców stron i wprowadziły reklamy płatne za czas wy-świetlania, nie zaś za ilośc odsłon lub klik-nięć. Pionierskim serwisem tego typu w Pol-sce jest LinkLift.

Z kim wchodzimy w interesyLinkLift został założony w 2006 roku w Niemczech, zaś swym zasięgiem obejmuje już Francję, Włochy, Hiszpanię i Polskę. Fir-ma zatrudniła także polskich administrato-rów, dzięki czemu można otrzymać odpo-wiedź na każde pytanie w ciągu kilku dni. Na-leży podkreślić, że są to osoby pomocne i cier-pliwe – pomogą nawet w instalacji skryptu na własnej platformie.

Wycena linkuLinkLift oferuje jedynie odnośniki tek-stowe, podobnie jak do niedawna Google AdSense. Zarejestrować w serwisie mo-żemy się przez stronę http://www.linklift.pl/?ref=a1267774449. Następnie, jeśli chce-my oferować przestrzeń reklamową na na-szej stronie, zgłaszamy ją do serwisu. W cią-gu tygodnia (zazwyczaj dużo krócej) zosta-nie ona zweryfikowana przez administrato-rów i podana zostanie wycena jednego lin-ku tekstowego. LinkLift oferuje umieszcze-nie do dziesięciu linków tekstowych na jed-nej stronie, przy czym możemy określić, w której części strony będą one wyświetla-ne – w nawigacji, części głównej strony, lub stopce. Określamy także kategorię strony i, czy reklamy będą widoczne na pojedynczej stronie, czy także na wszystkich jej podstro-nach. W zależności od tych ustawień, mo-żemy oszacować wycenę jednego linku (Ry-sunek 1). Pomoże w tym poręczny kalkula-tor na witrynie LinkLiftu. Jeśli po akceptacji

strony i wyceny będziemy chcieli zmienić te dane, będzie to możliwe (ręczna zmiana wy-ceny jest właśnie wdrażana, lecz można o nią poprosić administratora). Sam algorytm wy-ceny uwzględnia takie czynniki, jak tematy-ka strony, pozycja linków na stronie, liczba sprzedanych linków, liczba linków zewnętrz-nych, wiek strony, ilość linków zwrotnych i sąsiedztwo oraz przynależność do określo-nej branży.

Osoba chcąca umieścić swoją reklamę, bę-dzie mogła przeglądać dostępne przestrze-nie reklamowe, wraz ze statystykami strony m.in. w Yahoo, DMOZ i Alexa Rank. Poda-ne są także Page Rank strony oraz Page Rank i ilość stron linkujących do danej, także bar-dzo szczegółowe statystyki, które powodu-ją, że znajomość dokładnego adresu nie jest potrzebna (jeśli zezwolimy, będzie on wi-doczny).

Instalacja skryptuSerwis współpracuje ze stronami stworzony-mi w PHP, Perlu, WordPressie, Joomli, Dru-

LinkLift

Internecie królują systemy reklamy kontekstowej. W oparciu o treść witryny, wyświetlane są odpowiednie reklamy z takich serwisów jak Google AdSense, czy AdKontekst Wirtualnej Polski. Zarobki z takich reklam są jednak stosunkowo niewielkie, stąd istnieje zapotrzebowanie na inne formy reklamy. Gwarantowany zarobek oferuje nowy wchodzący do Polski LinkLift.

Dowiesz się:• Jak dodatkowo zarobić na reklamie;

• Dlaczego era reklamy kontekstowej może się

kończyć.

Powinieneś wiedzieć:• Jak umieścić kod PHP na swojej stronie.

Poziom trudności

Koniec z reklamą kontekstową

Rysunek 1. Kalkulator pomagający oszacować wartość jednego linka

Page 59: SDJ_11_2008_PL_E-Commerce

11/200858

Kasa dla webmasteraLinkLift – pewny zarobek na reklamie

www.sdjournal.org 59

palu, Xoops, Serendipity oraz Joggerze. Ten ostatni jest polskim systemem blogowania, który został dodany ekskluzywnie na potrze-by polskich bloggerów – widać więc, że fir-ma rozwija się prężnie i nie pozostaje obojęt-na na potrzeby rynku. Wybierając którąś z po-wyższych opcji, szybko skonfigurujemy nasz skrypt, który wystarczy wkleić do szablonu naszej strony.

Nadszedł czas na główną zaletę LinkLiftu – brak inwazyjności. Niby Google AdSense oferuje także linki tekstowe, jednak według swojego szablonu, którego nie można zmie-niać, co często jest bardzo irytujące. Rekla-ma wyświetlana przez linklift ma przykłado-wą strukturę:

<a href=”http://blog.eldoras.com”

rel=”nofollow”>Blog autora</a>

I tyle! Żadnych dodatkowych znaczników, ca-łość możemy dowolnie modyfikować pod ką-tem wyglądu i rozmieszczenia. Pełna swobo-da. Na Rysunku 2 widać reklamy LinkLiftu (czerwona obwódka) i Google AdSense (zie-lona obwódka) w akcji – jedna linijka LinkLi-ftu zawiera 4 reklamy, które idealnie kompo-nują się ze stroną, podczas gdy Google Ad-Sense jest wyraźnie bardziej inwazyjne.

Należy podkreślić, iż LinkLift nie jest re-klamą kontekstową, więc może występo-wać równolegle z reklamami Google AdSen-se. Reklamy LinkLiftu mają w swoim kodzie rel=”nofollow”, dzięki czemu nie są przez wyszukiwarki traktowane jak linki wychodzą-ce, które obniżają nasz Page Rank – zapobie-ga to wykorzystaniu systemu przez reklamo-dawców do podwyższenia swoich pozycji w wy-szukiwarkach przez zwiększenie ilości stron do nich linkujących.

Pierwsi klienciDopóki pierwszy klient nie zamówi u nas re-klamy, będzie wyświetlana domyślna (dar-mowa). Dla strony o Page Rank 0 (czyli no-wej w Internecie) cena wyjściowa to około 4zł - 7zł za jednego linka tekstowego. Jeśli ktoś zdecyduje się wykorzystać naszą prze-strzeń reklamową, zostaniemy poinformo-wani o tym mailem. W ciągu 24 godzin mo-żemy zaakceptować lub odrzucić propozy-cję reklamy z oferowaną przez zleceniodaw-cę wyceną. Po tym czasie link jest automa-tycznie akceptowany na okres 30 dni. Ceny podawane na witrynie są cenami netto (z ra-cji oferowanych usług w różnych krajach o różnych stawkach podatkowych) – w Pol-sce otrzymujemy 70% wartości podanej na witrynie.

Wszystkie płatności w serwisie są realizowa-ne przez PayPal, który jest w pełni dostępny w Polsce. Minimalna kwota do wypłaty to 60zł.

Program partnerskiJak każdy porządny system reklamowy (poza Google AdSense), tak też LinkLift oferuje Pro-gram Partnerski. Do wyboru mamy całą gamę linków graficznych i tekstowych, które może-my umieścić na naszej witrynie. Wynagrodze-nie można otrzymać za:

• polecenie naszej strony użytkownikowi, który zarejestruje się jako reklamodawca i dokona zakupu linku tekstowego ("Adver-tiser Lead") lub ;

• polecenie strony użytkownikowi, który zarejestruje się i zostanie zaakceptowany jako reklamobiorca ("Publisher Lead").

Partner otrzymuje wynagrodzenie w wyso-kości:

• 25 zł plus bonus promocyjny w wysokości 5 zł za Advertiser Lead ;

• 25 zł plus bonus promocyjny w wysokości 5 zł za Publisher Lead .

Należność za Advertiser Lead przysługuje, gdy reklamodawca (ang. advertiser) zamó-wi linki tekstowe o wartości minimum 120 zł. Należność za Publisher Lead przysługu-je, gdy skierowany reklamobiorca (ang. pu-blisher) udostępni swoją stronę w serwisie przez minimum miesiąc (bez przerw).

Reklamujemy naszą stronęOczywiście, możemy także wykupić prze-strzeń reklamową u innych użytkowników systemu. Po wpłaceniu pierwszych pienię-dzy na konto przez PayPal, otrzymujemy do-datkowe 60zł na kupno przestrzeni rekla-mowych.

PodsumowanieZ usług LinkLiftu często korzystają użytkow-nicy blogosfery, czyli autorzy witryn o Page Rank 3 – 6. Osoby te mnóstwo czasu spędza-ją w Internecie i są świetnie obeznane w syste-mach reklamowych.

LinkLift zdobył ich zaufanie i sprawdza się bardzo dobrze, dlatego polecamy go wszyst-kim, którym nie odpowiadają dotychczasowe formy reklamy. Zasady są proste – płacimy za reklamę na miesiąc i przez miesiąc ona widnie-je na danej stronie. Prostota to kolejny plus Lin-kLiftu.

Rysunek 2. Porównanie reklam Google AdSense i LinkLiftu

Rysunek 3. Estetyczna strona porządnego systemu LinkLift

KRZYSZTOF TRYNKIEWICZKrzysztof Trynkiewicz studiuje Informatykę na

Uniwersytecie Jagiellońskim. Od wielu lat zajmu-

je się tworzeniem witryn w technologii PHP i Flash

oraz publicystyką. Obecnie rozwija kilka równole-

głych projektów autorskich dostępnych na witrynie

http://blog.eldoras.com

Kontakt z autorem: [email protected]

Page 60: SDJ_11_2008_PL_E-Commerce

11/200860

Narzędzia programistycznePlugin

www.sdjournal.org 61

Na początek zaprezentuję najczęściej wykorzystywane pluginy w Symfony, których jest w chwili pisania artykułu

ponad 200. Następnie stworzymy prosty doda-tek do wysyłania maila (ang. plugin) w symfony, bez dodatkowego nakładu naszej pracy.

Pluginy w SymfonyW Symfony jeden z największych walorów mo-żemy odnaleźć w liczbie i różnorodności plu-ginów. Obecnie z ponad 200 pluginów mo-żemy np. szybko stworzyć prosty CMS, Blog czy Forum, podłączyć do naszej aplikacji bez-pieczny mechanizm autoryzacji i autentyfika-cji sfGuardPlugin, czy łatwo podczepić AJAX-owe biblioteki.

Wszystkie z nich tworzone są bezpłatnie przez społeczność Symfony i znajdziemy je na stronie: http://www.symfony-project.org/plugins/

Każdy plugin posiada dostępny kod źródło-wy, który budowany jest zgodnie z przyjętą w Symfony strukturą, dzięki czemu łatwo się nam w nim odnaleźć. Wśród dostępnych plugi-nów można między innymi znaleźć:

• sfSimpleCMSPlugin – prosty CMS do za-rządzania treścią i strukturą strony;

• sfGuardPlugin – autoryzacja i zarządzanie użytkownikami oraz uprawnieniami;

• sfThumbnailPlugin – tworzenie miniaturek zdjęć;

• sfControlPanelPlugin – interfejs do zarzą-dzania Symfony z poziomu przeglądarki;

• sfLightboxPlugin – łatwe wykorzystywanie skryptu AJAX-owego Lightbox2;

• sfSslRequirementPlugin – wprowadzenie kodowania SSL dla akcji;

• sfPropelActAsNestedSetBehaviorPlugin – wdrożenie algorytmu nested set zintegro-wanego z obiektami Propela;

• sfPokaYoke – walidacja formularzy po stro-nie klienta.

Zmiany warto śledzić na bieżąco, gdyż pluginy cały czas są tworzone i rozwijane.

Przy korzystaniu z projektów, warto jest za-interesować się licencją, zgodnie z którą jest wy-dawany plugin. Licencję pluginu można zna-leźć na stronie pluginu na http://symfony-pro-ject.com oraz w głównym katalogu pluginu, w pliku LICENSE.

Zdecydowana większość z nich jest wydawa-na na licencji MIT, tak jak i samo symfony, w związku z czym bez przeszkód możemy je wyko-rzystywać również w celach komercyjnych.

Instalacja pluginuNajczęściej pluginy wymienione na Symfony Plugins zostały przygotowane jako paczki PE-AR, dlatego możemy je zainstalować, podając w Symfony 1.0 polecenie:

<cd mojprojekt

<symfony plugin-install nazwapluginu

lub w wersji 1.1:

<cd mojprojekt

<symfony plugin:install nazwapluginu

Dokładną informację, jak należy zainstalować potrzebny plugin do określonej wersji Symfo-ny, możemy podejrzeć na stronie pluginu, w zakładce Installation.

Rozpoczęcie pracyDo rozpoczęcia pracy potrzebujemy oczywiście utworzonego projektu Symfony. Poszczególne kroki tworzenia projektu dokładnie przedstawi-liśmy na początku prezentacji multimedialnej.

Jak stworzyć plugin, zaprezentowaliśmy na płycie dołączonej do Software Developer’s Jour-nal 7/2008. W związku z tym, że sam plugin był tworzony ponad pół roku temu, niektóre wyko-rzystane w nim techniki są już wycofywane.

Aby nasz plugin był zgodny z symfony 1.0 na-leży włączyć parametr compat_10 w pliku konfi-guracyjnym config/settings.yml naszej aplikacji.

Jest tam również kod źródłowy pluginu. Po-niżej omówimy zawartość płyty oraz pokaże-my, w jaki sposób można ją rozbudowywać.

Struktura pluginuSporym ułatwieniem jest, zorganizowanie struktury katalogów i plików pluginu, w bardzo podobny sposób co struktura naszej aplikacji. Dzięki temu bez problemu może-my odnaleźć się w jego zawartości. Łatwo jest również przenieść istniejącego moduł w na-szej aplikacji, aby funkcjonował jako osob-ny moduł.

Struktura plików przedstawiona została na Listingu 1.

Pamiętaj – aby po każdej zmianie struktury pluginu zalecane jest czyszczenie cache projek-tu komendą symfony cc.

Postaramy się przedstawić najważniejsze ele-menty struktury i podać przykłady informacji, jakie można w nich zawrzeć.

Plugin

Tworzenie aplikacji, składa się zarówno z tych bardziej twórczych, jak i bardziej odtwórczych prac. Mimo wszelkich naszych starań tworzenia wedle zasady DRY (z ang. DRY – Don't Repeat Yourself ), ile razy zdarza się, że dla tej samej funkcjonalności powielamy i dostosowujemy ten sam kod w różnych elementach aplikacji lub pomiędzy różnymi aplikacjami.

Poziom trudności

Wielokrotne wykorzystanie sprawdzonych narzędzi

Dowiesz się:• Efektywnie wykorzystywać pluginy w swojej

pracy;

• Stworzyć własny plugin;

• Wykorzystywać istniejące pluginy to szybkie-

go tworzenia aplikacji.

Powinieneś wiedzieć:• Jak stworzyć projekt w symfony;

• Posiadać doświadczenie w tworzeniu aplika-

cji;

• Posiadać doświadczenie w obiektowym PHP.

Page 61: SDJ_11_2008_PL_E-Commerce

11/200860

Narzędzia programistycznePlugin

www.sdjournal.org 61

ModułyModuły umieszczamy w katalogu modules/. Nasz prezentacyjny plugin posiada moduł (ang. Modu-les) sfMailForm. W zależności od potrzeby, każdy moduł może zawierać cztery katalogi:

• actions – definiujący dostępne akcje dla modułu;

• config – określający specyficzną konfigura-cję samego modułu;

• templates – widoki dla modułów zwracane po wywołaniu akcji;

• validate – formularze sprawdzania wpro-wadzanych danych przez formularze.

W praktyce przyjęło się tworzenie dodatkowe-go katalogu lib/, zawierającego klasę z wszystkimi akcjami (Listing 1). W pliku actions.class.php po-zostawia się jedynie rozszerzenie do klasy z kata-logu lib/ (Listing 2). Takie rozwiązanie zostało za-stosowane w przykładowym pluginie.

Konfiguracja pluginuKonfigurację dla pluginu definiujemy config/ w katalogu pluginu. Może ona składać się z dwóch elementów:

• konfiguracji dla naszego pluginu – plik config.php;

• struktury bazy danych – plik schema.xml lub schema.yml.

W pliku konfiguracyjnym config.php może-my elastycznie odwoływać się do konfiguracji naszej aplikacji i dowolnie dopisywać lub mo-dyfikować wprowadzone wartości. Przykła-dowo możemy stworzyć przyjaźniejszy ad-res wysyłania formularza na /wyslij zamiast /sfmailForm/submit (przykład na Listingu 2).

W pliku definicji struktury bazy danych (plik schema.yml lub schema.xml) tworzymy konfigurację – podobnie jak w całym projek-cie. Wyjątkiem jest zawarcie w pliku informacji o pakiecie (przykład na Listingu 3). Stworzona schema będzie bez problemu wykrywana przez wywoływanie komendy z prefiksem propel.

Na Listingu 3 znajduje się przykład pliku schema.yml, zawierający tabelę sfMailform_archive, która będzie zapisywać dane wprowa-dzone w naszym przykładowym formularzu.

Po skonfigurowaniu pliku czeka nas jesz-cze tylko dobre skonfigurowanie pliku databa-ses.yml w naszym projekcie oraz budowa mode-lu Propela, SQL-a i stworzenie struktury w ba-zie danych (np. za jednym zamachem komendą symfony propel-build-all).

Dane do testów (fixtures)Dane do testów umieszczamy w plugine w ka-talogu data/fixtures/. Wywoływanie ładowa-nia danych wykonujemy komendą symfony propel-load-data. Zawieramy tutaj dane, które chcielibyśmy umieścić w bazie danych, tak aby nasz plugin działał poprawnie.

Zadania do uruchomienia z linii komendNowe zadania (ang. Tasks) tworzone w plu-ginie zawieramy w katalogu data/tasks/. Każ-de zadanie umieszczamy w oddzielnym pli-ku, który powinien zawierać wywołanie funk-cji pake_desc oraz pake_task, a także funkcję

wywołującą zadanie (zainteresowanych odsy-łam do Listingu 4).

Tworzenienie pluginu jako paczki PEARAby nasz plugin można było instalować za pomo-cą komendy symfony plugin:install musi on

Listing 1. Struktura plików pluginu

nazwaPluginu/

config/

*schema.yml # plik ze schematem bazy danych

config.php # specyficzna konfiguracja dla pluginu

data/

generator/

sfPropelAdmin/

nazwaSzablonu/ # skórka dla admin generatora

template/

skeleton/

fixtures/

*.yml # testowe informacji do bazy danych

lib/

*.php # miejsce na nasze klasy

helper/

*.php # pomocniki

model/

*.php # model danych, generowany z propela

task/

Task.class.php # zadania do uruchomienia w pasku komend

modules/

nazwaModulu/ # nazwa tworzonego modułu

actions/

config/

module.yml

view.yml

security.yml

templates:

*.php

validate:

*.yml

Listing 2. Przykład wykorzystania konfiguracji w pliku config.php

$r = sfRouting::getInstance(); // pobranie instancji odpowiedzialnej

za przekierowania

$r->prependRoute('submit', '/wyslij',

array(

'module' => 'sfMailForm',

'action' => 'submit')

); // dopisanie czytelniejszego adresu

// z /sfMailForm/submit na /wyslij

Listing 3. Przykładowa schema.yml z encją gromadzącą informacje z wprowadzonych danych z formularzy

propel:

_attributes: { package: plugins.sfMailFormPlugin.lib.model }

# deklaracja informacji o pakiecie (miejscu zapisu

klas pluginu)

sfMailForm_archive:

attributes: { phpName: pluginMailForm }

id:

content: { type: longvarchar }

created_at:

Page 62: SDJ_11_2008_PL_E-Commerce

11/200862

Narzędzia programistycznePlugin

www.sdjournal.org 63

mieć zdefiniowany w głównym katalogu plik pac-kage.xml. Plik ten zawiera w odpowiednio przy-gotowanym formacie XML-owym wszystkie po-trzebne informacje o pluginie. Opiszę wszystkie możliwe do zastosowania znaczniki wraz z przy-kładowymi wartościami dla naszego pakietu.

Możliwe znaczniki Główny znacznik w pliku package.xml zawiera <?xml version="1.0" encoding="UTF-8"?>, a pod nim mamy informację o pakiecie: <package packagerversion="1.4.1"

version="2.0" xmlns="http://pear.php.net/

dtd/package-2.0" xmlns:tasks="http:

//pear.php.net/dtd/tasks-1.0" xmlns:

xsi="http://www.w3.org/2001/XMLSchema-

instance" xsi:schemaLocation="http:

//pear.php.net/dtd/tasks-1.0 http://

pear.php.net/dtd/tasks-1.0.xsd http:

//pear.php.net/dtd/package-2.0 http://

pear.php.net/dtd/package-2.0.xsd">. Z ele-mentów poniżej mamy:

• <name>: nazwa pluginu; w naszym przy-padku: sfMailFormPlugin;

• <channel>: informacja na jakim serwerze znajduje się paczka (w przypadku paczek dostępnych na symfony-project.org, będzie to: plugins.symfony-project.org);

• <summary>: krótki opis o samym pluginie;• <description>: dłuższy opis;• <lead>: informacja o liderze projektu:

• <name>: imię i nazwisko;• <user>: nazwa użytkownika (w przy-

padku gdy jest to projekt na symfony-project.org, będzie to login do zarzą-dzania projektami);

• <email>: poprawny adres e-mail lidera;• <active>: informacja czy osoba nadal

pracuje nad tym projektem (wartości: yes lub no);

• <date>: data ostatniej poprawki w paczce (np.: 2008-12-31);

• <time>: czas ostatniej poprawki w paczce (np.: 23:59:00);

• <version>: informacje o wydanej wersji:• <release> i <api>: numer wydania;

• <stability>: informacja o stabilności wy-dania;• <release> i <api>: słowna informacja

o stabilności (np. stable, beta, alpha);• <license uri=”xxx”>: informacja o na-

zwie licencji wraz z odesłaniem do strony z jej treścią podawaną w atrybucie uri;

• <notes>: miejsce na dodatkowe komentarze;• <contents>: lista zamieszczonych plików:

• <dir name=”xxx”>: nazwa katalogu podawana w atrybucie name;

• <file role=”data” name=”xxx”>: nazwa pliku (atrybut name);

• <dependencies>: zależności występu-jące przy naszej paczce:

• <php>: zależność od wersji PHP (np. ze znacznikiem <min>5.2.0</ min>, umożlwi instalację, gdy na ser werze znajdować będzie się wersja 5.2.0 lub wyższa);

• <pearinstaller>: zależność od wersji PEAR;

• <package>: zależność od innych paczek symfony:

• <name>: nazwa paczki; • <channel>: informacja o ser

werze, na którym paczka się znajduje;

• <min>: minimalna wersja paczki; • <max>: maksymalna wersja

paczki;

PIOTR PLENIK, FIRMA TEAMLABWspółzałożyciel firmy TeamLab.pl, specjalizującej

się w wytwarzaniu oprogramowania klasy enter-

prise. Zawodowo zajmujący się tworzeniem oraz

rozwojem aplikacji dla biznesu, typu CMS i CRM.

W wolnym czasie redaktor serwisu www.symfo-

ny.pl. W PHP programuje 2000 r., w frameworku

symfony od 2006 r.. Administrator portalu dla Or-

ganizacji Pozarządowych – www.ngo.pl. Absol-

went ostatniego roku Polsko-Japońskiej Wyższej

Szkoły Technik Komputerowych. Interesuje się za-

rządzaniem projektami biznesowymi oraz open

source, programowanie (PHP, ASP.NET, Java) oraz

bazy danych (MS SQL, PostgreSQL, MySQL).

Kontakt z autorem: [email protected], strona

http://www.teamlab.plRysunek 1. Schemat utworzonej bazy danych

Listing 4. Przykładowa budowa zadania mailform-raport<?php

/**

* Raport o statystykach wypełniania formularza

* plik: /plugins/sfMailFormPlugin/data/tasks/sfMailFormRaport.php

*//

pake_desc('raport o statystykach do administratora – przeslanie na adres e-mail');

pake_task('mailform-report', 'project_exists');

pake_alias('mailreport', 'mailform-report'); // możliwość używania skrótu „mailreport”

/**

* Funkcja wywoływana przy uruchomieniu zadania

* @param pakeTask $task

* @param Array $args

*/

function run_mailform-report($task, $args)

{

if (!count($args))

{

throw new Exception('Podaj proszę adres e-mail, na który ma przyjść raport');

}

$emial = $args[0];

// ...

// miejsce na kod wyciągający dane z bazy i wysyłający mail z raportem

// ..

}

Page 63: SDJ_11_2008_PL_E-Commerce

11/200862

Narzędzia programistycznePlugin

www.sdjournal.org 63

Poprawnie stworzony plugin zawsze powi-nien mieć plik LICENSE, opisujący warunki jego używania. Zalecane jest również doda-nie pliku README zawierającego np. historię zmian, działanie pluginu, jak instalować, itd.

PodsumowanieWiele rozszerzeń dla symfony już powstało – są gotowymi pluginami, łatwymi do insta-lacji, aktualizacji czy odinstalowania z naszej aplikacji. Tworzenie nowych pluginów o do-

wolnej funkcjonalności jest równie proste jak tworzenie nowych bibliotek PEAR i umożli-wiających ponowne wykorzystywanie pomię-dzy różnymi aplikacjami.

Listing 5. Przykład zawartości paczki package.xml dla pluginu w symfony

<?xml version="1.0" encoding="UTF-8"?>

<package packagerversion="1.4.6" version="2.0" xmlns="http:

//pear.php.net/dtd/package-2.0" xmlns:

tasks="http://pear.php.net/dtd/tasks-

1.0" xmlns:xsi="http://www.w3.org/

2001/XMLSchema-instance" xsi:

schemaLocation="http://pear.php.net/

dtd/tasks-1.0 http://pear.php.net/dtd/

tasks-1.0.xsd http://pear.php.net/dtd/

package-2.0 http://pear.php.net/dtd/

package-2.0.xsd">

<name>sfPrzykladowyPlugin</name>

<channel>plugins.symfony.pl</channel>

<summary>przykładowy plugin w symfony</summary>

<description>To jest przykładowy plugin w symfony, w celu

pokazania zawartosci package.xml</

description>

<lead>

<name>Piotr PLENIK</name>

<user>jupeter</user>

<email>[email protected]</email>

<active>yes</active>

</lead>

<date>2008-01-01</date>

<time>12:53:01</time>

<version>

<release>1.0.0</release>

<api>1.0.0</api>

</version>

<stability>

<release>beta</release>

<api>beta</api>

</stability>

<license uri="http://www.symfony-project.org/license">MIT

license</license>

<notes>-</notes>

<contents>

<dir name="/">

<file role="data" name="README" />

<file role="data" name="LICENSE" />

<dir name="config">

<!-- model -->

<file role="data" name="schema.yml" />

</dir>

<dir name="data">

<dir name="fixtures">

<!-- fixtures -->

<file role="data" name="fixtures.yml" />

</dir>

</dir>

<dir name="lib">

<dir name="model">

<!-- model classes -->

<file role="data" name="sfSampleClass1.php" />

<file role="data" name="sfSampleClass2.php" />

</dir>

<dir name="task">

<!-- tasks -->

<file role="data" name="sfSampleTask.class.php" />

</dir>

<dir name="validator">

<!-- validators -->

<file role="data" name="sfSampleValidator.class.

php" />

</dir>

</dir>

<dir name="modules">

<dir name="sfSampleModule">

<file role="data" name="actions/

actions.class.php" />

<file role="data" name="config/security.yml" />

<file role="data" name="lib/BasesfSampleModuleAc

tions.class.php" />

<file role="data" name="templates/

indexSuccess.php" />

</dir>

</dir>

<dir name="web">

<dir name="css">

<!-- stylesheets -->

<file role="data" name="sfSampleStyle.css" />

</dir>

<dir name="images">

<!-- images -->

<file role="data" name="sfSampleImage.png" />

</dir>

</dir>

</dir>

</contents>

<dependencies>

<required>

<php>

<min>5.2.0</min>

</php>

<pearinstaller>

<min>1.4.1</min>

</pearinstaller>

<package>

<name>sfGuardPlugin</name>

<channel>pear.symfony-project.com</channel>

<min>1.1.13</min>

<max>1.1.15</max>

<exclude>1.1.14</exclude>

</package>

</required>

</dependencies>

<phprelease />

<changelog />

</package>

Page 64: SDJ_11_2008_PL_E-Commerce

11/200864

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 65

Jest to bardzo trafne pytanie, które po-winna zadać sobie każda osoba planu-jąca stworzyć grę komputerową. Zakła-

dam, że wielu z czytelników SDJ-ta, będą-cych z przyczyn oczywistych programistami, odpowiedziałaby: nie ma na co czekać, bie-rzemy się za kodowanie!. Takie podejście jest właśnie przyczyną upadku wielu przedsię-wzięć związanych z produkcją gier. Otóż to od czego zawsze powinno zaczynać się two-rzenie gry, to opracowanie jej koncepcji. Po-nieważ temat projektowania gier (ang. game design), chociaż bardzo ciekawy, nie pokry-wa się z tematem niniejszego artykułu – pój-dziemy na łatwiznę i zaczerpniemy pomysł na naszą aplikację z klasyki polskiej myśli kreatywnej w dziedzinie komputerowej roz-rywki. Opisywana w niniejszym artykule gra – LaserQuest – bazuje na koncepcji logicz-nej gry pt. Lasermania, wydanej pierwotnie na ośmiobitowe Atari przez Laboratorium Komputerowe Avalon. LaserQuest imple-

mentuje podstawowy podzbiór funkcjonal-ności oryginalnej Lasermanii – szczegółowy opis koncepcji gry, do którego lektury gorą-co namawiam przed przejściem do kolejnej części artykułu, znajduje się w ramce zatytu-łowanej LaserQuest: skrócony podręcznik użyt-kownika.

Gotowi...? Zaczynamy!Punktem wyjścia do naszych rozważań będzie szkielet aplikacji opracowany w poprzedniej odsłonie niniejszego cyklu. Dla porządku przy-pomnę, że szkielet ten oferuje nam:

• implementację pętli gry;• obsługę zdarzeń klawiatury;• podstawową obsługę przerwań (utrata

i uzyskanie focusa).

Pierwszym zadaniem – być może niespe-cjalnie twórczym, aczkolwiek niezbędnym – jest dostosowanie istniejącego szkieletu do wymogów naszego projektu. Wbrew po-zorom – zmienia się wiele rzeczy – nazwa aplikacji, UI, identyfikator zasobów, autor itd. Oczywiście można pokusić się o ręczne przerabianie kodu, ale podejście takie jaw-nie gwałci zasadę DRY (ang. Don't Repeat

Yourself). Czytelników niezaznajomionych z tą zasadą zapraszam do lektury wspania-łej książki pt. Pragmatyczny Programista au-torstwa Andrew Hunta i Davida Thomasa. Tym, którzy mimo wszystko zdecydują się podjąć tę żmudną pracę, gwarantuję wiele niezapomnianych emocji związanych z pró-bami uruchomienia programu. Tych, którzy wolą bardziej pragmatyczne podejście nama-wiam na zautomatyzowanie tego procesu. Ja do wygenerowania szkieletu projektu Lase-rQuest wykorzystałem proste narzędzie o nazwie Template-2-Text (w skrócie t2t). T2t to prosty silnik renderowania tekstu na ba-zie zadanych szablonów. To co wyróżnia to narzędzie od całego zestawu innych, podob-nych rozwiązań, to możliwość generowa-nia całego drzewa katalogów na bazie drze-wa szablonowego, możliwość wykorzysta-nia zmiennych szablonowych w nazwach plików oraz automatyczny mechanizm wy-krywania tych zmiennych w celu pobrania ich od użytkownika. Aby dostosować nasz szkielet aplikacji do wymagań t2t, skopio-wałem go do oddzielnego katalogu i zmody-fikowałem nazwy i zawartości plików. Roz-ważamy plik GameSkeletonApplication.cpp (Listing 1).

W nowej odsłonie plik ten będzie miał na-zwę [%PROJECT-NAME%]Application.cpp. Jak się można łatwo domyśleć, tag o strukturze '[%NAZWA%]' oznacza zmienną, która przy ge-nerowaniu tekstu na bazie zadanego szablonu zostanie podmieniona na konkretną wartość. Zawartość szablonu [%PROJECT-NAME%]Ap-plication.cpp przedstawiona jest na Listingu 2.

Analizując plik szablonu można zauwa-żyć takie zmienne jak – [%PROJECT-NAME%]

Programowanie gier dla Symbian OS

W poprzednim artykule Czytelnicy mieli okazję przebrnąć przez gąszcz stosunkowo zawiłych szczegółów dotyczących programowania aplikacji pod Symbian OS. W rezultacie powstał prosty szkielet gry. W niniejszej części cyklu zajmiemy się tematem znacznie ciekawszym – odejdziemy (chwilowo) od niskopoziomowych zagadnień systemowych i zrobimy to co Tygrysy lubią najbardziej – zbudujemy grę!

Dowiesz się:• Jak zaprojektować architekturę prostej gry i

jak zaimplementować ją pod system operacyj-

ny Symbian;

• Jak zaprojektować i zaimplementować silnik

gry oparty na przyrostach czasu;

• Jak oprogramować menu gry.

Powinieneś wiedzieć:• Jak się programuje w języku C++;

• Co to jest pętla gry;

• Jak działa szkielet aplikacji opisany w poprzed-

niej odsłonie cyklu.

Poziom trudności

Budujemy grę!

Page 65: SDJ_11_2008_PL_E-Commerce

11/200864

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 65

(nazwa projektu), [%AUTHOR%] (autor), [%EMAIL%] (kontaktowy adres email autora) oraz [%UID%] (unikalny identyfikator aplika-cji). W podobny sposób przekształcone zosta-ły pozostałe pliki projektu GameSkeleton. Na-rzędzie t2t oraz szablon szkieletu gry są do-stępne do pobrania z witryny SDJ. Po skonfi-gurowaniu narzędzia (patrz Ramka Konfigu-racja narzędzia t2t) wystarczy wywołać ko-mendę:

t2t -d GameSkeletonS60 LaserQuest

W dalszej kolejności narzędzie poprosi o war-tości kolejnych zmiennych – UID, AUTHOR, RESOURCE-ID, VENDOR, EMAIL oraz PROJECT-NAME po czym wygeneruje w bieżącym kata-logu podkatalog LaserQuest z odpowiednią zawartością. Bardziej dociekliwi Czytelnicy mogą w tej chwil zadać pytanie – skąd mam wziąć UID aplikacji? Dla nich właśnie przygo-towałem specjalną Ramkę o tytule podobnym do przedstawionego wyżej pytania.

LaserQuest – pierwsze wyjście z mrokuTytuł niniejszego podpunktu brzmi nieco ta-jemniczo, czy wręcz złowieszczo. Skąd taka nazwa? Sprawa jest prosta. W punkcie tym opiszemy sposób uruchomienia nowo wy-generowanej aplikacji na telefonie. Dlaczego już teraz? Otóż – na nieszczęście programi-stów – program działający idealnie pod emu-latorem urządzenia, na realnym sprzęcie ma szansę działać zupełnie niepoprawnie. Wyni-ka to z istnienia szeregu subtelnych różnic pomiędzy tymi dwoma środowiskami. Zasa-da jest prosta – im dłużej będziemy odwle-kać uruchomienie aplikacji na telefonie, tym większe jest prawdopodobieństwo wystąpie-nia takich błędów i tym większe będą koszty ich znalezienia.

Aby uruchomić naszą grę na urządzeniu musimy wykonać następujące kroki – zbudo-wać binarną wersję aplikację przeznaczoną do uruchomienia na telefonie, wygenerować insta-lator i podpisać go oraz przetransportować po-wstałą paczkę instalacyjną na telefon.

Pierwsze dwa kroki można zautomatyzo-wać przy pomocy środowiska Carbide. W tym celu należy przestawić aktualną konfi-gurację na Phone Release (GCCE) a następnie kliknąć prawym przyciskiem na nazwie pro-jektu w panelu Project Explorer i wybrać za-kładkę Carbide.c++ -> Carbide Build Confi-gurations -> SIS Builder (Rysunek 1). Po wci-śnięciu przycisku Add możemy skonfiguro-wać sposób budowania aplikacji (Rysunek 2). Kluczową rolę odgrywa tutaj plik LaserQu-est.pkg (można go znaleźć w podkatalogu sis projektu) opisujący dokładnie sposób genero-wania paczki instalacyjnej. Do zawartości te-go pliku wrócimy w kolejnych podpunktach. Oprócz wpisania nazw generowanych plików

należy ustawić dodatkowo opcję Self sign sis file. Osoby zainteresowane szczegółami pod-pisywania aplikacji zapraszam do Ramki Jak podpisać aplikację dla Symbian OS?. Po ta-kich zabiegach konfiguracyjnych wystarczy wybrać opcję Build Project i spokojnie cze-kać aż w podkatalogu sis projektu pojawi się podpisana paczka instalacyjna LaserQu-

est.sisx. Kwestia przetransportowania paczki z grą na telefon jest mocno zależna od posia-danego systemu. W większości przypadków wykorzystuje się w tym celu sieć Bluetooth – należy przy tym pamiętać o włączeniu od-biornika Bluetooth w telefonie i ustawianiu jego widoczności dla innych urządzeń (mię-dzy innymi dla komputera z którego będzie-

Listing 1. Zawartość pliku GameSkeletonApplication.cpp

//

// FILE NAME:

// GameSkeletonApplication.cpp

//

// AUTHOR(S):

// Rafal Kocisz <[email protected]>

//

#include "GameSkeletonApplication.h"

#include "GameSkeletonDocument.h"

const TUid KUidGameSkeletonApp = { 0xA000958F };

CApaDocument* CGameSkeletonApplication::CreateDocumentL()

{

return ( static_cast< CApaDocument* >(

CGameSkeletonDocument::NewL( *this ) ) );

}

TUid CGameSkeletonApplication::AppDllUid() const

{

return KUidGameSkeletonApp;

}

// Eof

Listing 2. Zawartość szablonu [%PROJECT-NAME%]Application.cpp

//

// FILE NAME:

// [%PROJECT-NAME%]Application.cpp

//

// AUTHOR(S):

// [%AUTHOR%] <[%EMAIL%]>

//

#include "[%PROJECT-NAME%]Application.h"

#include "[%PROJECT-NAME%]Document.h"

const TUid KUid[%PROJECT-NAME%]App = { [%UID%] };

CApaDocument* C[%PROJECT-NAME%]Application::CreateDocumentL()

{

return ( static_cast< CApaDocument* >(

C[%PROJECT-NAME%]Document::NewL( *this ) ) );

}

TUid C[%PROJECT-NAME%]Application::AppDllUid() const

{

return KUid[%PROJECT-NAME%]App;

}

// Eof

Page 66: SDJ_11_2008_PL_E-Commerce

11/200866

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 67

my wysyłać paczkę). Paczka instalacyjna poja-wia się jako nowa wiadomość w skrzynce od-biorczej. Po jej otwarciu automatycznie roz-poczyna się proces instalacji. Po jego pomyśl-nym zakończeniu pozostaje jedynie urucho-mić aplikację. W naszym przypadku otrzy-mujemy znajomy z poprzedniej części cyklu czarny ekran z mrugającym przyjaźnie liczni-kiem FPS. Kolejny etap naszych zmagań za-kończył się sukcesem!

Architektura gryDobrneliśmy wreszcie do momentu kiedy można zacząć myśleć o tym, co nas najbardziej interesuje – mowa tu oczywiście o implemen-tacji zawartości gry. Zanim przejdziemy do ko-dowania, wypada zastanowić się nad architek-turą naszego rozwiązania.

Rozwiązanie, które zdecydowałem się za-stosować w przypadku projektu LaserQuest, to drzewiasta hierarchia obiektów reprezen-tujących poszczególne składniki gry. W hie-rarchii tej wyróżniać będziemy kilka pozio-mów. Na szczycie hierarchii umieszczony zo-stanie obiekt reprezentujący grę jako całość – w naszym przypadku obiekt ten będzie re-prezentowany przez klasę CLaserQuestGame. Obiekt ten będzie odpowiedzialny za in-tegrację warstwy gry z warstwą szkieletu aplikacji oraz za zarządzanie trybami gry. Obiekty reprezentujące wspomniane try-by stanowić będą kolejną warstwę w naszej hierarchii. W naszym przypadku wyróżni-my dwa rodzaje trybów – tryb menu (kla-sa CLaserQuestGameMenuMode) oraz tryb rozgrywki (klasa CLaserQuestGamePlayMode). Tryb gry, to według prezentowanego tu zamysłu, maszyna stanów określająca, co się w danej chwili z grą dzieje. Dla przykładu – tryb rozgrywki (CLaserQuestGamePlayMode) przechowuje i zarządza takimi informacja-mi jak poziom etapu gry, warunki jej zakoń-czenia itd. Tryb gry może z kolei przechowy-wać obiekt reprezentujący silnik określonej części rozgrywki. W przypadku LaserQuest wyróżnimy tylko jeden silnik, reprezentowa-ny przez klasę CLaserQuestGameBoardEngine. Obiekt silnika – w naszym przypadku stano-wiący liść hierarchii – reprezentować będzie planszę na której odbywa się faktyczna roz-grywka. W tym miejscu zaimplementowna będzie mechanika gry oraz reguły nią steru-jące. Gwoli jasności należy w tym miejscu mocno podkreślić, że przedstawiona tu hie-rarchia bazuje na kompozycji (to znaczy – obiekty wchodzące w jej skład zawierają sie-bie nawzajem), a nie na dziedziczeniu.

To co łączy klasy opisujące obiekty na po-szczególnych poziomach to wspólna koncep-cja przetwarzania oparta na dwóch metodach – Draw() oraz Update(). Zadaniem pierwszej z tych metod jest renderowanie danego skład-nika, druga odpowiada za uaktualnianie oraz obsługę ewentualnych przejść pomiędzy sta-

Listing 3. Definicja klasy CLaserQuestGame

class CLaserQuestGame : public CBase

{

public:

enum TMode { EMenu, EPlay };

static CLaserQuestGame* NewL(

const TLaserQuestKeyState& aKeyState );

CLaserQuestGame(

const TLaserQuestKeyState& aKeyState );

~CLaserQuestGame();

void Draw( CBitmapContext& aGc ) const;

void Update( TInt64 aDt );

TBool ExitFlag() const { return iExitFlag; }

private:

void ConstructL();

void UpdateMenuMode( TInt64 aDt );

void UpdatePlayMode( TInt64 aDt );

const TLaserQuestKeyState& iKeyState;

TMode iMode;

CLaserQuestGamePlayMode* iPlayMode;

CLaserQuestGameMenuMode* iMenuMode;

TBool iExitFlag;

}; // class CLaserQuestGame

Listing 4. Definicja metody Draw() w klasie CLaserQuestContainer

void CLaserQuestContainer::Draw(

CBitmapContext& aGc ) const

{

aGc.Reset();

aGc.SetBrushColor( KRgbBlack );

aGc.SetBrushStyle( CGraphicsContext::ESolidBrush );

aGc.DrawRect( Rect() );

iGame->Draw( aGc );

TBuf< KFpsMessageMaxLength > fpsMessage;

fpsMessage.Format( KFpsMessageFormatString,

iFpsCounter->Fps() );

aGc.UseFont( iEikonEnv->NormalFont() );

aGc.SetPenColor( KRgbWhite );

aGc.DrawText( fpsMessage,

TPoint( KFpsMessagePosX,

KFpsMessagePosY ) );

aGc.DiscardFont();

}

Listing 5. Definicja metody Update() w klasie CLaserQuestContainer

void CLaserQuestContainer::Update( TInt64 aDt )

{

iGame->Update( aDt );

if ( iGame->ExitFlag() )

{

if ( iAppUi != NULL )

{

iAppUi->Exit();

}

}

}

Page 67: SDJ_11_2008_PL_E-Commerce

11/200866

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 67

nami gry (czytaj: przekazywania kontroli po-między poszczególnymi składnikami). W przypadku programowania bardziej skom-plikowanych gier warto zastanowić się nad zbudowaniem szkieletu gry opartego na po-wyższej koncepcji – tak aby raz zaprogramo-waną funkcjonalność można było wykorzy-stać w przyszłości. Można by dla przykładu stworzyć bazową klasę reprezentującą skład-nik gry (np. CLaserQuestGameEntity) i z niej dziedziczyć klasy bazowe reprezentujące po-szczególne składniki hierarchii. W przypad-ku LaserQuest – aby nie zaciemniać tematu – zbudujemy opisaną wyżej hierarchię w spo-sób bezpośredni.

Warto w tym miejscu zatrzymać się na chwilę i zwrócić uwagę na zastosowaną kon-wencję nazewnictwa klas w naszym projek-cie. Ponieważ przy programowaniu aplika-cji C++ dla Symbian OS nie stosuje się za-zwyczaj przestrzeni nazw, dlatego zdecydo-wałem się nadawać wszystkim klasom repre-zentującym składniki gry nazwy rozpoczyna-jące się prefiksem CLaserQuestGame. Podej-ście takie pozwala w łatwy sposób odróżniać klasy szkieletu aplikacji od klas reprezentują-cych samą grę.

Warto w tym punkcie poruszyć jeszcze jed-ną kwestię natury architektonicznej. Podejrze-wam, że wielu purystów projektowania obiek-towego obruszy się widząc w jednej klasie me-tody odpowiedzialne za przetwarzanie i ren-derowanie swojej zawartości. Słyszę niemal-że jak padają groźnie pytania pokroju – a co z separacją warstwy logiki od warstwy prezen-tacji?! Odpowiedź jest prosta – w przypadku programowania gier rzadko zachodzi ku te-mu potrzeba. Co więcej – w grach kompute-rowych warstwa logiki często łączy się z war-stwą prezentacji (np.: badanie kolizji pomię-dzy obiektami występującymi w grze na za-sadzie badania zawartości sprite'ów) i czasami wprowadzanie takiego podziału jest sztuczne i powoduje niepotrzebny narzut. W takich sy-tuacjach warto jest stosować zasadę Brzytwy Ockhama – nie mnóżmy niepotrzebnych by-tów (czytaj: klas) jeśli nie ma po temu rzeczy-wistej potrzeby. Co więcej – nasza koncepcja wcale nie kłóci się z ideą separacji wspomnia-nych warstw. Po prostu użyliśmy do tego inne-go narzędzia – zamiast umieszczać te funkcjo-nalności w różnych klasach, umieściliśmy je w różnych funkcjach. Dodatkowo, fakt iż meto-da Draw() posiada modyfikator const jest do-datkowym gwarantem, iż wspomniane war-stwy nie będą się przeplatać.

W kolejnych podpunktach opiszę szczegó-łowo kolejne klasy w przedstawionej tu hierar-chii. Schemat hierarchii przedstawiony jest na Rysunku 3.

Gra zamknięta w obiekcieW niniejszym podpunkcie opiszę interfejs oraz implementację klasy CLaserQuestGame,

Listing 6. Definicja metody Draw() w klasie CLaserQuestGame

void CLaserQuestGame::Draw( CBitmapContext& aGc ) const

{

switch ( iMode )

{

case EMenu: iMenuMode->Draw( aGc ); break;

case EPlay: iPlayMode->Draw( aGc ); break;

default: break;

}

}

Listing 7. Definicja metody Update() w klasie CLaserQuestGame

void CLaserQuestGame::Update( TInt64 aDt )

{

switch ( iMode )

{

case EMenu: UpdateMenuMode( aDt ); break;

case EPlay: UpdatePlayMode( aDt ); break;

default: break;

}

}

Rysunek 1. Narzędzie do konfiguracji procesu budowania aplikacji

Konfiguracja narzędzia t2tAby skonfigurować narzędzie t2t (pod systemami z rodziny Windows) należy podjąć następujące kroki:

• rozpakować archiwum z narzędziem do wybranego podkatalogu;• ustawić zmienną środowiskową %T2T _ HOME%, przypisać jej nazwę wybranego podkatalogu

i dodać ją do zmiennej %PATH%.

Po takich zabiegach konfiguracyjnych (zakładając, że w systemie dostępny jest interpreter języka Perl) narzędzie t2t można uruchomić z dowolnego miejsca w systemie wpisując z linii poleceń ko-mendę t2t. Po uruchomieniu tej instrukcji bez żadnych argumentów wyświetlona będzie lista po-leceń narzędzia wraz z prostą instrukcją obsługi opatrzoną przykładami.

Page 68: SDJ_11_2008_PL_E-Commerce

11/200868

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 69

która, jak wspomniałem wyżej, reprezentuje grę jako całość. Klasa ta jest – niejako z powo-łania – punktem styku silnika gry oraz opisa-nego w poprzednim odcinku szkieletu aplika-cji. Na początek przyjrzyjmy się definicji klasy (plik LaserQuestGame.h w podkatalogu inc ka-talogu projektu; paczkę z kodem źródłowym do niniejszego artykułu można pobrać z witry-ny SDJ). Definicja klasy przedstawiona jest na Listingu 3.

Prześledźmy na początek publiczne skład-niki interfejsu tej klasy. Statyczna metoda NewL(), konstruktor oraz prywatna meto-da ConstructL() stanowią część mechani-zmu dwufazowej konstrukcji obiektów (ang. two-phase construction). Osoby planujące na poważnie zająć się programowaniem natyw-nych aplikacji dla Symbian OS powinny za-poznać się z tym mechanizmem – tak samo jak z mechanizmem stosu czyszczącego (ang. cleanup stack). Obydwa mechanizmy opisa-ne są w Ramce zatytułowanej Stos czyszczący oraz dwufazowa konstrukcja obiektów w Sym-bian OS.

W tym punkcie zakładamy, że meto-da NewL() przejmuje rolę konstruktora kla-sy. Destruktor klasy uchował się na szczę-ście od Symbianowych dziwactw i nadal po-zostaje zwykłym destruktorem. Metody Draw() i Update() mają szczególne znacze-nie. Do Draw() przekazywany jest kontekst bitmapy reprezentującej tylny bufor apli-kacji. Z kolei Update() otrzymuje przyro-sty czasu pomiędzy poszczególnymi iteracja-mi pętli gry. Znaczenie publicznej metody ExitFlag() opiszę w dalszej części tego pod-punktu. Obiekt klasy CLaserQuestGame jest przechowywany i tworzony w obiekcie kon-tenera (klasa CLaserQuestContainer, pli-ki LaserQuestContainer.h/cpp). Tworzenie obiektu gry zrealizowane jest w metodzie CLaserQuestContainer::ConstructL():

iGame = CLaserQuestGame::NewL( iKeyState );

Warto zwrócić uwagę na to, w jaki sposób do obiektu gry przekazywany jest stan klawia-tury. Prywatna składowa iKeyState prze-

Listing 8. Definicja metody CLaserQuestGame::UpdateMenuMode()

void CLaserQuestGame::UpdateMenuMode( TInt64 aDt )

{

iMenuMode->Update( aDt );

if ( iMenuMode->IsFireKeyPressed() )

{

switch ( iMenuMode->ActiveOption() )

{

case CLaserQuestGameMenuMode::EExit:

{

iExitFlag = ETrue;

break;

}

case CLaserQuestGameMenuMode::EStart:

{

iMode = EPlay;

iPlayMode->Reset();

break;

}

}

}

}

Listing 9. Definicja metody CLaserQuestGame::UpdatePlayMode()

void CLaserQuestGame::UpdatePlayMode( TInt64 aDt )

{

iPlayMode->Update( aDt );

if ( iPlayMode->MenuKeyPressed() )

{

iMode = EMenu;

iMenuMode->Reset();

}

}

LaserQuest – skrócony podręcznik użytkownikaJak wspomniano we wstępie artykułu, LaserQuest to gra logiczna, bazująca na Lasermanii. Roz-grywka LaserQuest odbywa się na dwuwymiarowej planszy podzielonej na równomierne pola, wypełnionej przeróżnymi elementami. Elementy występujące w grze to:

• emiter lasera, czyli urządzenie generujące wiązkę skondensowanego światła;• ściany absorbujące promień lasera;• ściany odbijające promień lasera;• ruchome lustra odbijające promień lasera;• czujniki układu alarmowego;• teleport do kolejnej planszy;• pojazd sterowany przez gracza.

Zadaniem gracza jest zniszczenie wszystkich czujników układu alarmowego i wejście do telepor-tu prowadzącego do następnej planszy. Czujniki można niszczyć promieniem lasera. W prakty-ce oznacza to, że gracz musi w taki sposób manipulować ruchomymi częściami planszy (lustrami) aby nakierować odbijający się promień lasera na kolejne czujniki, a gdy zostaną one zniszczone – dotrzeć do teleportu. Wspomniane manipulacje wykonywane są za pomocą sterowanego joystic-kiem pojazdu, który można wykorzystać do przesuwania luster.W niniejszym odcinku cyklu logika otaczająca główny silnik gry jest bardzo uboga, aczkolwiek kompletna. Po uruchomieniu gry użytkownik ma do dyspozycji proste menu z dwoma opcjami – Start i Exit. Opcja pierwsza powoduje przejście do testowej planszy i rozpoczęcie rozgrywki. Opcja druga powoduje natychmiastowe opuszczenie aplikacji. Po rozpoczęciu rozgrywki gracz ma następujące opcje. Może sterując pojazdem próbować rozwiązać planszę – jeśli mu się to uda, to rozgrywka zostanie zakończona i gra przejdzie ponownie do trybu menu. Gracz może wrócić do wspomnianego trybu w dowolnym momencie rozgrywki – wciskając prawy softkey. Jeśli w trakcie rozgrywki gracz uzna, że znalazł się w położeniu bez wyjścia, to może zrestarto-wać grę przy pomocy lewego softkey'a.

Rysunek 2. Narzędzie do konfiguracji procesu budowania paczki instalacyjnej programu

Page 69: SDJ_11_2008_PL_E-Commerce

11/200868

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 69

chowywana jest w klasie CLaserQuestGame jako referencja do stałej. Idea tej decyzji pro-jektowej polega na tym, iż mając referencję do zmiennej reprezentującej stan klawiatury wszelkie dotyczące jej zmiany (wykonywane na poziomie klasy CLaserQuestContainer) będą widoczne w klasie CLaserQuestGame. Referencję tę możemy oczywiście przeka-zać dalej – tak aby obiekty niżej w hierar-chii również mogły śledzić stan klawiatu-ry. Wykorzystanie referencji do stałej da-je nam gwarancję, że nikt nie popsuje war-tości składowej iKeyState (tylko klasa CLaserQuestContainer ma prawo ją uaktu-alniać, wszyscy inni mogą ją tylko czytać). W rezultacie – stosując takie podejście – możemy badać stan klawiatury na zasadzie bezpośredniego odpytywania (ang. key pol-ling), a nie na zasadzie notyfikacji (ang. key event notification).

Innymi słowy – to obiekt zainteresowany stanem klawiatury pyta o jej stan, w odróż-nieniu od sytuacji gdy obiekt śledzący stan klawiatury informuje o zmianach wszystkich zainteresowanych. Stosowanie pierwszego po-dejścia w przypadkach pisania prostych gier znacznie ułatwia oprogramowywanie war-stwy logiki.

Kolejne miejsca w których podpinamy nasz silnik gry to metody Draw() i Update() w klasie CLaserQuestContainer (Listingi 4 i 5).

W przypadku metody CLaserQuest-

Container::Draw() stosujemy proste podej-ście – wystarczy w odpowiednim miejscu wy-wołać funkcję Draw() na obiekcie iGame. Za-wartość metody Update() jest trochę bardziej skomplikowana. Problem z tą metodą polega na tym, że oprócz komunikacji przebiegającej w dół hierarchii (w tym konkretnym przypad-ku mowa jest o wywołaniu iGame->Update( aDt )) musimy również odczytać wiadomość wędrującą w górę hierarchii – obiekt reprezen-tujący grę powiadamia swojego rodzica (czyli klasę CLaserQuestContainer) o tym, że gdzieś w jej wnętrzu zapadła decyzja o zakończeniu działania aplikacji. Aby przekonać się o tym, kontener sprawdza odpowiednią flagę w sil-niku gry.

Nasi znajomi puryści projektowania obiek-towego mogliby tym razem zauważyć, że al-ternatywą dla tego rozwiązania mógłby być wzorzec projektowy znany pod nazwą Ob-serwatora, bazujący na wywoływaniu funk-cji zwrotnych.

Owszem – jest to alternatywa warta roz-ważenia, aczkolwiek w przypadku nie-wielkich gier zastosowanie prostego od-pytywania jest zwyczajnie prostsze. Żąda-nie zakończenia gry trzeba przekazać jesz-cze o jeden poziom wyżej, do obiektu klasy CLaserQuestAppUi. W tym celu trzeba by-ło zmodyfikować kod szkieletu i przekazać wskaźnik na wspomniany obiekt do konte-nera (patrz: nowa składowa iAppUi w klasie

kontenera). Wywołanie iAppUi->Exit() w CLaserQuestContainer::Update finalnie za-łatwia sprawę.

Omówienie mechanizmu interakcji na linii silnik gry – pętla gry mamy za sobą. Wróćmy ponownie do implementacji silnika i przeana-

Listing 10. Definicja klasy CLaserQuestGameMenuMode

class CLaserQuestGameMenuMode : public CBase

{

public:

enum TOption { EStart, EExit };

static CLaserQuestGameMenuMode* NewL(

const TLaserQuestKeyState& aKeyState );

CLaserQuestGameMenuMode(

const TLaserQuestKeyState& aKeyState );

~CLaserQuestGameMenuMode();

void Reset();

void Draw( CBitmapContext& aGc ) const;

void Update( TInt64 aDt );

TOption ActiveOption() const

{ return iActiveOption; }

TBool IsFireKeyPressed() const

{ return iIsFireKeyPressed; }

private:

void ConstructL();

const TLaserQuestKeyState& iKeyState;

TOption iActiveOption;

CFbsBitmap* iTitle;

CFbsBitmap* iStart;

CFbsBitmap* iActiveStart;

CFbsBitmap* iExit;

CFbsBitmap* iActiveExit;

TLaserQuestPeriod

iMenuOptionsTransitionDelayPeriod;

TBool iIsFireKeyPressed;

}; // class CLaserQuestGameMenuMode

Listing 11. Definicja zasobu LaserQuestMenu.mbm w pliku LaserQuest.mmp

START BITMAP LaserQuestMenu.mbm

SOURCEPATH ..\gfx

TARGETPATH resource\apps

HEADER

SOURCE c24 LaserQuestMenuExit.bmp

SOURCE c24 LaserQuestMenuExitActive.bmp

SOURCE c24 LaserQuestMenuStart.bmp

SOURCE c24 LaserQuestMenuStartActive.bmp

SOURCE c24 LaserQuestMenuTitle.bmp

END

Listing 12. Zawartość wygenerowanego automatycznie pliku nagłówkowego LaserQuestMenu.mbg

// LaserQuestMenu.mbg

// Generated by BitmapCompiler

// Copyright (c) 1998-2001 Symbian Ltd. All rights reserved.

//

enum TMbmLaserquestmenu

{

EMbmLaserquestmenuLaserquestmenuexit,

EMbmLaserquestmenuLaserquestmenuexitactive,

EMbmLaserquestmenuLaserquestmenustart,

EMbmLaserquestmenuLaserquestmenustartactive,

EMbmLaserquestmenuLaserquestmenutitle

};

Page 70: SDJ_11_2008_PL_E-Commerce

11/200870

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 71

lizujmy wewnętrzne mechanizmy jego działa-nia. Jak wspominałem wcześniej, gra LaserQu-

est składa się z dwóch podstawowych trybów – menu oraz rozgrywki. Podział ten uwzględ-

niony jest w klasie CLaserQuestGame. W enu-meracji CLaserQuestGame::TMode zdefinio-wane są dwie wartości reprezentujące wspo-mniane tryby – EMenu oraz EPlay. Informacja o tym jaki jest aktualny tryb gry przechowy-wany jest w składowej iMode. Jeśli zajrzymy do implementacji metod CLaserQuestGame::Draw() oraz CLaserQuestGame::Update() (Listingi 6 i 7) to zauważymy, że są one zaim-plementowane na bazie instrukcji switch.

Instrukcje te delegują zadania do obiek-tów reprezentujących poszczególne tryby gry w zależności od wartości zmiennej iMode. W przypadku metody Draw() sytuacja jest pro-sta – wystarczy wywołać metodę Draw() dla obiektu reprezentującego aktywny tryb gry. W przypadku metody Update() należy dodat-kowo obsłużyć komunikację zwrotną – kod odpowiedzialny za to zadanie umieszczo-ny jest w metodach UpdateMenuMode() oraz UpdatePlayMode() (Listingi 8 i 9).

W UpdateMenuMode() oprócz wywołania metody Update() na obiekcie iMenuMode, sprawdzamy czy użytkownik podjął jakąś akcję związaną z tym trybem. W tym celu wykorzy-stujemy metody – IsFireKeyPressed() oraz ActiveOption() stanowiące część publiczne-go interfejsu klasy CLaserQuestGameMenuMode. Pierwsza metoda zwraca wartość ETrue w przypadku gdy w trybie menu wykryto wci-śnięcie przycisku fire.

Po wykryciu takiej sytuacji, przy pomo-cy drugiej metody – ActiveOption() – po-bierany jest identyfikator opcji, która jest na dany moment aktywna i na tej podsta-wie podejmowane są kolejne akcje – bądź to ustawienie flagi wyjścia z programu, bądź przejście do trybu rozgrywki. W przypadku UpdateMenuMode() dzieje się podobnie – ty-le, że do obsłużenia jest tylko jedna możli-wość – powrót z trybu rozgrywki do trybu menu.

W jaki sposób tryby gry kontrolują swój stan – o tym już za moment. Na początek sprawdzimy...

...co w menu piszczyPo zapoznaniu się ze szczegółami imple-mentacji obiektu reprezentującego grę ja-ko całość, czas przyjrzeć się klasom repre-zentującym obiekty z drugiej warstwy hie-rarchii – mowa tu o warstwie trybów gry. Na początek przyjrzymy się prostszej z dwóch klas występujących w LaserQuest – CLaserQuestGameMenuMode.

Przeanalizujmy Listing 10, na którym znaj-duje się definicja wspomnianej klasy.

Duża część interfejsu klasy wygląda znajo-mo – wiele metod w tej klasie było wykorzy-stywane w obiekcie klasy CLaserQuestGame. To co na pewno rzuca się w oczy to zestaw wskaźników do obiektów klasy CFbsBitmap. Tak, tak – wreszcie dotarliśmy do miejsca gdzie narysujemy coś więcej niż czarny pro-

Listing 13. Fragment definicji metody CLaserQuestGameMenuMode::ConstructL() – wczytywanie bitmapy

void CLaserQuestGameMenuMode::ConstructL()

{

iTitle = new ( ELeave ) CFbsBitmap();

User::LeaveIfError( iTitle->Load(

KLaserQuestMenuMbmFilePath,

EMbmLaserquestmenuLaserquestmenutitle ) );

// ...

Listing 14. Definicja stałej określającej ścieżkę dostępu do pliku mbm

#ifdef __WINS__

_LIT( KLaserQuestMenuMbmFilePath,

"z:\\resource\\apps\\LaserQuestMenu.mbm" );

#else

_LIT( KLaserQuestMenuMbmFilePath,

"c:\\resource\\apps\\LaserQuestMenu.mbm" );

#endif // __WINS__

Listing 15. Fragment definicji metody CLaserQuestGameMenuMode::Draw()

void CLaserQuestGameMenuMode::Draw(

CBitmapContext& aGc ) const

{

aGc.BitBlt( TPoint( KTitlePosY, KTitlePosY ),

iTitle,

iTitle->SizeInPixels() );

// ...

}

Rysunek 3. Schemat architektury gry LaserQuest

��������������������

���������������

����������������������� �����������������������

��������������������������

Page 71: SDJ_11_2008_PL_E-Commerce

11/200870

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 71

stokąt czy informacja o liczniku FPS. Menu w naszej grze jest na tyle proste, że nie war-to rozbijać go na mniejsze klasy. Gdyby by-ło inaczej, to zapewne architektura tej części gry byłaby o wiele bardziej złożona; oprogra-mowanie skomplikowanych interfejsów użyt-kownika w grach to jednak temat na oddziel-ny, wcale niekrótki artykuł. W przypadku La-serQuest klasa CLaserQuestGameMenuMode jest odpowiedzialna za obsługę menu oraz za jego renderowanie. Przyjrzyjmy się jak zosta-ło to zrealizowane.

Klasa CFbsBitmap służy w Symbian OS do reprezentacji specjalnie spreparowanej bit-mapy. Bitmapy takie są w procesie budowa-nia aplikacji przetwarzane dedykowanym na-rzędziem (bmconv), a następnie pakowane w pliki z rozszerzeniem mbm. Tak spreparo-wane paczki bitmap są następnie dołączone do instalatora aplikacji i stanowią integral-ną ich część.

Nagrodą, którą programista otrzymuje za uporanie się z całym tym galimatiasem jest możliwość synchronicznego wczytania bit-mapy na podstawie automatycznie wygene-rowanego identyfikatora (zapisanego jako enumeracja w nagłówkowym pliku z rozsze-rzeniem mbg). Brzmi skomplikowanie? Cóż – niestety – po części tak jest. Prześledźmy jak w praktyce wygląda proces przygotowa-nia bitmap reprezentujących menu gry La-serQuest.

Jako że ponoć jeden obraz wart jest tysią-ca słów, zapraszam Czytelników do zapo-znania się z Rysunkiem 4, na którym poka-zane jest menu gry LaserQuest. Obraz me-nu składa się z kilku bitmap wyświetlonych na czarnym tle. Bitmapy te są reprezento-wane przez następujące składowe w klasie CLaserQuestGameMenuMode: iTitle (tytuły gry), iStart (napis Start), iExit (napis Exit), iActiveStart oraz iActiveExit (podświetlo-ne napisy Start i Exit). Bitmapy zostały nary-sowane w zwykłym edytorze grafiki i zapisa-ne w podkatalogu gfx projektu LaserQuest. W dalszej kolejności zmodyfikowano odpo-wiednio plik definicji projektu (mmp) doda-jąc fragment pokazany na Listingu 11.

W definicji określone są źródłowa i doce-lowa ścieżka dla zasobów oraz lista bitmap, które składają się na paczkę LaserQuestMe-nu.mbm. To, na co warto zwrócić uwagę, to specyfikacja formatu piksela dołączona do każdego elementu we wspomnianej liście. W naszym przypadku używamy wartości c24, która oznacza, iż każdy piksel w docelowej bitmapie reprezentowany jest przez 24 bity. Na tym kończy się praca programisty zwią-zana z przygotowaniem bitmap – pozosta-łą częścią procesu przygotowania pliku mbm zajmuje się łańcuch budowania aplikacji. W tym momencie warto wspomnieć, że Car-bide oferuje wygodne, wizualne narzędzie wspomagające dołączanie bitmap do projek-

tu i zwalniające programistę z ręcznego mo-dyfikowania plików mmp. Aby dostać się do

wspomnianego narzędzia należy otworzyć plik mmp w eksploratorze projektu, a następ-

Listing 16. Definicja metody CLaserQuestGameMenuMode::Update()

void CLaserQuestGameMenuMode::Update( TInt64 aDt )

{

iMenuOptionsTransitionDelayPeriod.Update( aDt );

if ( iMenuOptionsTransitionDelayPeriod.Passed() )

{

if ( iKeyState & KKeyUp || iKeyState & KKeyDown )

{

switch ( iActiveOption )

{

case EStart: iActiveOption = EExit; break;

case EExit: iActiveOption = EStart; break;

}

iMenuOptionsTransitionDelayPeriod.Reset(

KOneSecondInMicroSeconds / 5 );

}

}

if ( iKeyState & KKeyFire )

{

iIsFireKeyPressed = ETrue;

}

}

Listing 17. Definicja klasy TLaserQuestPeriod

class TLaserQuestPeriod

{

public:

TLaserQuestPeriod( TInt64 aPeriod = 0 )

: iPeriod( aPeriod ) { }

void Reset( TInt64 aPeriod )

{ iPeriod = aPeriod; }

void Update( TInt64 aDt )

{ if ( iPeriod > 0 ) { iPeriod -= aDt; } }

TBool Passed() const

{ return iPeriod <= 0; }

private:

TInt64 iPeriod; // In microseconds.

};

Skąd mam wziąć UID dla aplikacji Symbian OS?UID w kontekście Symbian OS, to unikalny w skali światowej identyfikator aplikacji. Utrzy-mywaniem puli i przydzielaniem UID-ów zajmuje się firma Symbian – producent Symbian OS. Nie każda aplikacja musi mieć unikalny UID – np. do celów testowych można wykorzy-stywać jeden UID wielokrotnie, jednakże należy mieć świadomość, że gdy zainstalujemy na jednym telefonie dwie różne aplikacje z identycznym UID-em to efekty będą nieprzewidy-walne (czytaj: coś się na pewno popsuje). Z tego względu – wszystkie aplikacja pretendują-ce do uzyskania certyfikacji Symbian Signed (jeden z podstawowych wymogów przy rozpo-wszechnianiu aplikacji komercyjnych) muszą posiadać swój własny UID. Generalnie, osoby planujące udostępnić swoją aplikację na publicznym forum (niekoniecznie w trybie komer-cyjnym – może to być równie dobrze aplikacja oferowana na zasadach Open Source) powin-na postarać się o taki numer. Aby uzyskać UID na własne potrzeby trzeba zarejestrować się na stronie Symbian Signed (https://www.symbiansigned.com). Po pomyślnej rejestracji należy przejść do zakładki My Symbian Signed a następnie wybrać z bocznej belki opcje UIDs i Re-quest. Dalej należy postępować według przedstawionych instrukcji. Zamówione UID-y od-biera się za pomocą poczty elektronicznej.

Page 72: SDJ_11_2008_PL_E-Commerce

11/200872

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 73

nie wybrać zakładkę Sources. Przyjrzymy się teraz jak obsłużyć nasze bitmapy z poziomu

kodu źródłowego. W tym celu dobrze jest zajrzeć do pliku LaserQuestGameMenuMo-

de.cpp. Na początku należy dołączyć plik na-główkowy zawierający definicję enumeracji z identyfikatorami bitmap:

#include <LaserQuestMenu.mbg>

Plik ten jest generowany automatycznie w trakcie budowania aplikacji i można go zna-leźć w katalogu z systemowymi nagłówkami SDK. Plik nagłówkowy dla zasobu LaserQu-estMenu.mbm w przypadku rozważanej apli-kacji wygląda tak jak przedstawiono na Li-stingu 12.

Wczytywanie bitmap reprezentujących me-nu zrealizowane jest w metodzie ConstrutL() klasy CLaserQuestGameMenuMode. Przyjrzyjmy się fragmentowi tej metody (Listing 13).

Na początek należy stworzyć przy pomocy operatora new obiekt reprezentujący bitma-pę. W drugim kroku – przy pomocy metody CFbsBitmap::Load() wczytujemy zawartość bitmapy z pliku mbm. Oprócz identyfikatora bitmapy podajemy również ścieżkę dostępu do pliku mbm. Ścieżka ta zdefiniowana jest ja-ko stała tekstowa na początku pliku LaserQu-estGameMenuMode.cpp (Listing 14).

Z racji tego, że ścieżki dostępu do pliku mbm są różne w środowisku emulatora i na urządzeniu, dlatego do wyboru właściwej za-stosowałem instrukcję warunkową preproce-sora. Dla ścisłości należy dodać, iż zmienna __WINS__ jest definiowana automatycznie w momencie budowania aplikacji w wersji działajacej pod emulatorem, co – mam na-dzieję – finalnie rozjaśnia sprawę. Niestety, podejście takie nie rozwiązuje do końca na-szego problemu.

Chodzi konkretnie o to, że ścieżka bę-dzie niepoprawna w sytuacji gdy zainsta-lujemy aplikację na karcie pamięci (o ile ta-kowa jest dostępna w telefonie). Sytuację tę można obsłużyć sprawdzając w czasie wyko-

Listing 18. Definicja metody CLaserQuestGameBoardEngine::ComputeNextVehicleMovePosX()

TInt CLaserQuestGameBoardEngine::NextVehicleMovePosX(

TDirection aDir ) const

{

static const TInt KDir2Dx[] = { -1, 1, 0, 0 };

return iVehiclePosX + KDir2Dx[ aDir ];

}

Stos czyszczący oraz dwufazowa konstrukcja obiektów w Symbian OSPisząc aplikacja C++ dla Symbian OS nie da się uniknąć mechanizmu stosu czyszczącego i idiomu dwufazowej konstrukcji. W tym miejscu opiszę obydwa mechanizmy tak, aby Czy-telnik był w stanie zrozumieć prezentowane kody źródłowe i w pewnym ograniczonym za-kresie stosować je przy budowaniu własnych gier. Czytelników zainteresowanych szczegóło-wym zgłębieniem tej dziedziny wiedzy odsyłam do książki Symbian OS Explained autorstwa Jo Stichbury. Drugi, trzeci oraz czwarty rozdział tej książki stanowią w mojej opinii najlepsze dostępne wprowadzenie to tematyki opisywanej bardzo pobieżnie w niniejszej Ramce.Potrzeba wprowadzenia stosu czyszczącego oraz dwufazowej konstrukcji obiektów wzię-ła się z tego, iż kompilatory używane do budowania aplikacji pod pierwotne wersje syste-mu Symbian nie obsługiwały sytuacji wyjątkowych. Na dzień dzisiejszy sytuacja ta może ba-wić, aczkolwiek na ówczesne czasy (początek lat 90) taka była rzeczywistość. Jako, że Sym-bian OS miał być systemem dedykowanym dla urządzeń mobilnych o mocno ograniczonych zasobach, to jego autorzy byli zmuszeni wprowadzić spójny i przekrojowy system zabezpie-czeń przed gubieniem tych zasobów. W tej sytuacji opracowano alternatywny mechanizm obsługi wyjątków w postaci funkcji User::Leave() oraz makra TRAP. Rozważając temat w kategoriach języka C, mechanizmy te odpowiadają bibliotecznym funkcjom setjmp() i longjmp(). W kontekście sytuacji wyjątkowych języka C++, funkcja User::Leave() działa podobnie jak instrukcja throw, zaś TRAP pełni rolę bloku catch. Jednakże wbudowany me-chanizm wyjątków C++ oferuje coś więcej – mowa tu oczywiście o automatycznym wywoły-waniu destruktorów po pojawieniu się sytuacji wyjątkowej co – przynajmniej w teorii – za-pobiega powstawaniu luk w zasobach. Pomijając szereg subtelnych zagrożeń, mechanizm wyjątków C++ stanowi stosunkowo wygodne narzędzie do obsługi nieprzewidzianych sytu-acji w programie. W tym kontekście, symbianowy stos czyszczenia stanowi brakujący skład-nik mechanizmu obsługi wyjątków. Niestety – ze względu na oczywiste ograniczania (jest to w końcu tylko biblioteka próbująca imitować mechanizmy wbudowane w język) – pro-gramiści są zmuszeni ręcznie zarządzać obiektami znajdującymi się na takim stosie. To z ko-lei ciągnie za sobą fakt, iż tylko wybrane klasy mogą ze stosem czyszczenia współpracować – mowa tu o obiektach dziedziczących z klasy CBase. Analizując przedstawione w poszcze-gólnych Listingach nagłówki klas Czytelnik może się łatwo przekonać, iż zasadniczo wszyst-kie klasy reprezentujące silnik LaserQuest dziedziczą z CBase (stąd też bierze się konwencja zakładająca dodawanie klasom prefiksów – z góry wtedy wiadomo, że klasy o nazwach roz-poczynających się na C reprezentują obiekty przechowujące zasoby). W tym miejscu docho-dzimy do genezy problemu na które remedium stanowić ma idiom dwufazowej konstruk-cji obiektów. Chodzi o to, że wbudowany konstruktor obiektów klasy C nie może rzucać wy-jątków (tj. wywoływać operacji leavującej). Jeśli przyjrzymy się dowolnej klasie przechowu-jącej zasoby (np. dynamicznie alokowane obiekty reprezentujące bitmapy) to zauważymy, że operacje związane z ich alokacją mają nazwy zakończone sufiksem L . To oznacza właśnie, iż operacje te mogą bezpośrednio lub pośrednio wywołać operację User::Leave(). Z dru-giej strony, alokacja pamięci jest sama w sobie operacją potencjalnie leavującą. W tej sytu-acji – zakładając iż konstruktor klasy może wywoływać operację User::Leave(), przy dyna-micznej alokacji obiektu mielibyśmy do czynienia z dwoma takimi operacjami wywołanymi pod rząd. A jest to sytuacja niedopuszczalna, gdyż po wykonaniu pierwszej z operacji leavu-jących należy bezzwłocznie umieścić wskaźnik do zaalokowanego zasobu oraz umieścić na stosie czyszczenia (przy pomocy wywołania CleanupStack::PushL()). Aby obejść ten pro-blem stosuje się prosty chwyt – wszystkie potencjalnie leavujące operacje związane z kon-strukcją obiektu umieszcza się w metodzie ConstructL(), którą należy wywołać ręcznie po uprzednim włożeniu wskaźnika do zaalokowanego obiektu na stos czyszczenia. Proces ten można ukryć przed użytkownikiem umieszczając opisane wyżej operacje w statycznej meto-dzie klasy, nazywanej według przyjętej konwencji NewL() lub NewLC(),. Metody te zastępują wbudowany konstruktor, tak że obiekt można zkonstruować w następujący sposób:

iMenuMode = CLaserQuestGameMenuMode::NewL( iKeyState );

W ramach ćwiczenia zachęcam wszystkich Czytelników do przeanalizowania dołączonych źródeł projektu i zbadania implementacji opisanych powyżej mechanizmów w praktyce.

Rysunek 4. Menu gry LaserQuest

Page 73: SDJ_11_2008_PL_E-Commerce

11/200872

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 73

nania programu miejsce jej instalacji i dyna-micznie budując ścieżkę dostępu. Wrócę do tego tematu w kolejnych odsłonach niniej-szego cyklu.

Wracając jeszcze do zawartości Listingu 13, warto zwrócić uwagę na użycie konstruk-cji User::LeaveIfError(). Funkcja ta powo-duje rzucenie symbianowego wyjątku w sy-tuacji kiedy operacja wczytywania zawarto-ści bitmapy z jakichś przyczyn się nie powie-dzie. Voila! Jedyne co nam pozostało to wy-świetlenia bitmapy, co też czynimy w funk-cji CLaserQuestGameMenuMode::Draw() (Li-sting 15).

Rysowanie bitmapy zrealizowane jest przy pomocy operacji szybkiego kopiowania frag-mentu pamięci zaimplementowanego jako me-toda CBitmapContext::BitBlt().

Warto też podkreślić, iż zgodnie z do-brym zwyczajem programistycznym unika-my tak zwanych magicznych numerów zapisa-nych bezpośrednio w kodzie źródłowym, a w zamian za to wykorzystujemy stałe (KTitle-PosY, KTitlePosY). Patrząc z szerszej perspek-tywy, należy uwypuklić fakt, iż w tym miej-scu również idziemy na pewne uproszczenie. Otóż przy profesjonalnej produkcji gier rozło-żenie elementów ekranu realizuje się – w mia-rę możliwości – w sposób niezależny od wy-świetlacza.

W naszym przypadku, zamiast stałej po-winniśmy wykorzystać raczej wartość wylicza-ną, bazującą na takich parametrach jak sze-rokość i wysokość ekranu urządzenia (pobie-ranych w czasie działania programu). W pre-zentowanym przykładzie zakładam, że wy-świetlacz ma stałe rozmiary (240x320 pik-seli). Przeanalizujemy teraz jak działa meto-da CLaserQuestGameMenuMode::Update() (Li-sting 16).

Wspomniana metoda sprawdza stan kla-wiatury i ustawia odpowiednie flagi. To co ewidentnie rzuca się w oczy to wykorzysta-nie składowej iMenuOptionsTransitionDelayPeriod. Składowa ta jest zdefiniowana w kla-sie CLaserQuestGameMenuMode w następują-cy sposób:

TLaserQuestPeriod

iMenuOptionsTransitionDelayPeriod;

Użyta powyżej klasa TLaserQuestPeriod re-prezentuje okres czasu wyrażony w milisekun-dach, a także oferuje proste operacje do zlicza-nia tego okresu na podstawie przyrostów cza-su (Listing 17).

Obiekt tej klasy wykorzystywany jest w metodzie Update() w celu wprowadze-nia opóźnienia przy zmianach opcji w me-nu. Gdyby ta funkcjonalność zaimplemen-towana była bez opisanego mechanizmu to, ze względu na fakt, iż wspomniana funkcja wywoływana jest około 30 razy na sekundę, opcja w menu zmieniałby się tak szybko, że

użytkownik nie byłby w stanie kontrolować tego procesu.

Kończąc niniejszy podpunkt warto zwrócić uwagę na metodę CLaserQuestGameMenuMode ::Reset(). Metoda ta stanowi pewną archi-tektoniczną konwencję – jest ona wykorzy-stywana do resetowania stanu obiektu, co jest bardzo przydatne w momencie kiedy prze-chodzimy pomiędzy trybami gry lub restar-tujemy tryb gry (będzie napisane więcej na ten temat w kolejnym podpunkcie). Wizual-ny efekt naszych wysiłków związanych z opro-gramowaniem menu gry przedstawiony jest na Rysunku 4.

Rozgrywkę czas zacząć!Kolejny tryb gry, zaimplementowany w ra-mach klasy CLaserQuestGamePlayMode re-prezentuje rozgrywkę. Tryb ten – na ten moment – dostarczony jest nieco na wy-rost. Aczkolwiek jego wprowadzenie daje

nam wysoki poziom elastyczności architek-tury w kontekście kolejnych etapów imple-mentacji gry.

Kiedy w następnych odcinkach cyklu bę-dziemy rozszerzać LaserQuest o obsłu-gę wczytywania kolejnych plansz czy sys-tem zapisywania stanu gry – tryb ten bę-dzie bardzo przydatny. W bieżącej fazie projektu nie ma się w tym miejscu specjal-nie o czym rozpisywać. Praktycznie wszyst-kie operacje w tym trybie polegają na de-legowaniu zadań do silnika planszy. To, na co warto zwrócić uwagę, to mechanizm re-startu rozgrywki zaimplementowany w me-todzie Update(), z wykorzystaniem wspo-mnianej wcześniej metody Reset(). Metoda CLaserQuestGamePlayMode::Draw() w przy-szłości również będzie bardziej interesująca – umieścimy tam kod odpowiedzialny za wy-świetlanie aktualnego numeru planszy oraz statystyk gry, a także napisów reprezentują-

Rysunek 5. Przechodzenie fragmentów wiązki lasera przez elementy planszy

Page 74: SDJ_11_2008_PL_E-Commerce

11/200874

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 75

cych opcje przypisane do softkey'ów (restart gry i powrót do menu).

Laserowa łamigłówkaI oto dotarliśmy do implementacji upragnio-nego silnika planszy. Monolityczna klasa CLaserQuestGameBoardEngine stanowi nie-wątpliwie serce naszej aplikacji – tutaj za-implementowano mechanikę działania gry. Tym razem podarujemy sobie zamieszczanie Listingu zawierającego pełną definicję klasy – skupimy się na jej publicznym interfejsie oraz zapoznamy się z wybranymi szczegóła-mi jej wewnętrznej implementacji. W tym podpunkcie Czytelnik znajdzie wiele od-niesień do plików projektu, a w szczególno-ści do dwóch z nich – LaserQuestGameBo-ardEngine.h oraz LaserQuestGameBoardEn-gine.cpp. Z tego względu, sugerowane jest zaopatrzenie się w paczkę z kodami źródło-wymi projektu przed rozpoczęciem czyta-nia niniejszego podpunktu. Przypominam, że wspomniana paczka dostępna jest do po-brania na witrynie SDJ.

Publiczny interfejs klasy reprezentują-cej planszę gry, czyli punkt styku pomię-dzy silnikiem LaserQuest, a obiektem re-prezentującym tryb rozgrywki, nie zadzi-wia niczym niezwykłym. Ponownie widzi-my tu takie metody jak Draw(), Update() czy Reset(). Uwagę należy zwrócić za to na metodę IsSolved(). Metoda ta odpowia-da na pytanie, czy nasza laserowa łamigłów-ka została pomyślnie rozwiązana. Przypo-minam, że według opisanych wcześniej zało-żeń, warunkiem zakończenia gry jest znisz-czenie wszystkich umieszczonych na plan-szy sensorów i dojście do pola oznaczonego jako wyjście.

Prawdziwa mechanika LaserQuest – zgod-nie z zasadą ukrywania informacji – za-mknięta jest w metodach stanowiących nie-publiczny interfejs klasy. Zanim jednak przejdziemy do opisu tej mechaniki, zbada-my jaka struktura danych reprezentuje plan-szę gry. Dla większości Czytelników nie bę-dzie zapewne wielkim zaskoczeniem, iż do

modelowania planszy wykorzystałem zwy-kłą tablicę liczb całkowitych. Aczkolwiek, diabeł – jak zwykle – tkwi w szczegółach. Pierwsza rzecz – rozmiar planszy – 14 na 18 pól, z czego tak naprawdę wykorzystane jest tylko 12 na 16 pól. Zewnętrzny obszar to strefa tak zwanych wartowników (ang. sen-tinels). Wykorzystanie wartowników to dość prosty zabieg pozwalający uniknąć wsta-wiania kłopotliwych i podatnych na błędy warunków brzegowych. Przy programowa-niu logiki planszy często zachodzi potrze-ba sprawdzenia tego co znajduje się na po-lu o indeksie i + 1, lub co gorsza – wsta-wienia tam nowej wartości. Jeśli nie skorzy-stamy z wartowników, to w podobnych sytu-acjach musimy posiłkować się dodatkowymi warunkami, które zazwyczaj mocno zaciem-niają kod.

O błąd naruszenia pamięci w takich wa-runkach nietrudno... Korzystając z wartow-ników mamy gwarancję, że przy takich ope-racjach wyjście poza bufor tablicy nam nie grozi, gdyż wszystkie algorytmy działają-ce na planszy operują na jej wewnętrznym otoczonym warstwą ochronną. Druga spra-wa, to reprezentacja poszczególnych składni-ków planszy. A jest tego trochę – puste pole, ściana, ściana-lustro, lustro ruchome, emi-ter promienia laserowego czy wreszcie sa-ma wiązka lasera – to tylko niektóre elemen-ty rozgrywki. Pomysł na upakowanie tego wszystkiego w jednej tablicy jest następują-cy. Wartość zero oznacza wartownika. War-tości mniejsze od zera oznaczają kolejne ele-menty planszy. Wartość jeden oznacza pole puste. Wartości powyżej jeden to maski bito-we określające jaka część wiązki lasera prze-chodzi przez dane pole. Warto w tym miej-scu zauważyć, że puste pole planszy może zawierać cztery fragmenty wiązki – w róż-nych konfiguracjach. Idea ta jest przedsta-wiona na Rysunku 5, gdzie każdy fragment wiązki przedstawiony jest oddzielnym kolo-rem (zielony – EBeamUpperLeft, niebieski – EBeamUpperRight, czerwony – EBeamBot-tomLeft oraz żółty – EBeamBottomRight).

Innymi słowy – jeśli dane pole ma wartość większą od jeden, to zakładamy, że jest to pu-ste pole przez które przechodzą fragmenty wiązki lasera. Aby przeprowadzić przez da-ne pole wiązkę, możemy skorzystać z opera-cji bitowych. Na przykład wyrażenie:

iCurrentGridData[ 6 ][ 4 ] |=

EbeamBottomRight;

dodaje do pola o określonych indeksach (x=6 i y=4) fragment wiązki znajdujący się w jego dolnym prawym rogu. W tym miej-scu warto zauważyć, iż plansza gry prze-chowywana jest w dwóch wersjach – jedna w postaci oryginalnej i druga – zawierają-ca modyfikacje wprowadzone w trakcie gry. Podejście takie ułatwia implementację me-chanizmu restartu, który w przypadku La-serQuest jest nieodzowny, jako że gracz po-przez niewłaściwe przesuwanie luster może doprowadzić do sytuacji, w której ukończe-nie planszy jest niemożliwe.

Kolejnym ciekawym aspektem związanym z implementacją mechaniki gry jest emisja lasera.

Na początek warto zauważyć, że emiter zaimplementowany w grze może działać w 8 konfiguracjach (jest w stanie wysyłać pro-mień lasera na 8 sposobów). Wspomniana konfiguracja opisana jest przez pozycję emi-tera na planszy, aktywny bok (tj. bok z któ-rego emitowany jest promień lasera) oraz orientację promienia (lewo- lub prawostron-ną). Poszczególne konfiguracje pracy emitera pokazane są na Rysunku 6, przy czym wiąz-ki lasera o orientacji lewostronnej zaznaczo-ne są kolorem zielonym, zaś prawostronnej – białym.

Kluczową rolę w implementacji silnika od-grywa funkcja TrackBeam(). Funkcja ta odpo-wiada za śledzenie wiązki lasera od momen-tu wyjścia z emitera aż do chwili, kiedy trafi ona w materiał, który nie jest w stanie jej od-bić. Algorytm ten korzysta intensywnie z ta-blic przejść (ang. lookup tables) opisujących zmiany fragmentów wiązki dla różnych kon-

ErratraNikt nie ma patentu na nieomylność. W tym miejscu opisane są usterki, które wkradły się do po-przedniej części artykułu. Do implementacji metody CGameSkeletonContainer::OnTick() wkradł się drobny aczkolwiek znaczący błąd. Chodzi konkretnie o fragment kodu w którym obli-czany jest przyrost czasu pomiędzy kolejnymi iteracjami pętli gry:

TInt64 dt = iTickStart.Int64() - iTickStop.Int64();

Przy tak skonstruowanym zapisie przyrosty przekazywane do metody CGameSkeletonContainer::Update() są ujemne...Drugi błąd polega na zastosowaniu zbyt ogólnego kontekstu graficznego w metodzie CGameSkeletonContainer::Draw(). Uważni czytelnicy zauważą, iż w projekcie LaserQuest jako kontekst graficzny przekazywany jest obiekt klasy CBitmapContext, w odróżnieniu do CGraphicsContext używanego w przypadku projektu GameSkeleton. Problem polega na tym, iż ten drugi nie oferuje kluczowej przy programowaniu gier operacji szybkiego kopio-wania bitmap (BitBlit). Warto w tym miejscu podkreślić iż poprawki opisanych usterek zosta-ły zaaplikowane w przykładowych kodach źródłowych są dostępne na witrynie SDJ.

Rysunek 6. Konfiguracje pracy emitera

Page 75: SDJ_11_2008_PL_E-Commerce

11/200874

Programowanie urządzeń mobilnychProgramowanie gier dla Symbian OS

www.sdjournal.org 75

figuracji wejściowych i żonglując przyrosta-mi określa drogę wiązki, na której pozosta-wia ślad przy użyciu odpowiednich operacji bitowych. Osoby zainteresowane szczegóła-mi implementacji tego algorytmu zapraszam do przeanalizowania kodów źródłowych. To na co chciałbym zwrócić jeszcze raz uwagę, to wykorzystanie tablic przejść. Ta użytecz-na technika pozwala niejednokrotnie uczy-nić dany fragment kodu krótszym i czytel-niejszym, toteż gorąco polecam stosowanie jej przy konstruowaniu swoich własnych aplikacji. Jako przykład stosowania tej tech-nik mogę podać implementację pomocni-czej metody CLaserQuestGameBoardEngine::ComputeNextVehicleMovePosX(), przedsta-wioną na Listingu 18.

Wspomniana metoda oblicza wartość składową na osi X dla kolejnej pozycji pojaz-du kierowanego przez gracza przy zadanym kierunku. W implementacji funkcji korzy-stamy z faktu, iż enumeracje opisujące kie-runki ruchu przyjmują wartości z zakresu od 0 do 3. Biorąc to pod uwagę, wykorzy-stujemy wartość kierunku jako indeks w ta-blicy przejść zawierającej odpowiednie przy-rosty na osi X. Ten sam efekt można by uzy-skać stosując operację switch do obsługi ko-lejnych wartościach enumeracji, aczkolwiek przedstawione rozwiązanie wydaje się być bardziej proste, eleganckie i jednocześnie – kompaktowe.

Oprócz struktur danych opisujących roz-grywkę, silnik planszy przechowuje cały sze-reg bitmap wykorzystywanych do renderowa-nia składników gry. W przypadku kafli (ang. tiles), czyli statycznych składników planszy sy-tuacja jest prosta – poszczególne bitmapy prze-chowywane są w tablicy:

CFbsBitmap* iTileBitmaps[ KLaserQuestTileBi

tmapCount ];

Analizując kod źródłowy silnika war-to zwrócić uwagę na makro TILE _ ENUM _

VAL _ 2 _ TILE _ BITMAP _ INDEX, które w sprytny sposób odwzorowuje wartości enu-meracji identyfikujących poszczególne ka-fle na indeks w tablicy z odpowiadający-mi im bitmapami. Nieco bardziej złożone struktury danych wykorzystywane są przy animacji. Jako przykład można podać tu dwuwymiarową tablicę służącą do przecho-wywania klatek animacji pojazdu którym steruje gracz:

CFbsBitmap* iVehicleFrames[ KLaserQuestVehi

cleFrameCount ]

[ KLaserQuestVehicleFrameBitmapCount ];

Pierwszy wymiar tablicy odpowiada nume-rom klatek animacji zaś wymiar drugi – po-szczególnym kierunkom ruchu.

Zarówno rysowanie jak i uaktualnianie za-wartości planszy przebiega w kilku etapach – niektóre z nich aktywowane są jedynie w specyficznych przypadkach – tak na przy-kład dzieje się z animacją zanikającego sen-sora.

Aby zwiększyć czytelność kodu starałem się grupować metody i składowe w grupy te-matyczne.

Niestety, w przypadkach takich jak silnik gry LaserQuest, gdzie mamy do oprogramo-wania zestaw mocno powiązanych i przeni-kających się reguł gry, ciężko jest uniknąć monolitycznych klas. Zresztą LaserQuest jest i tak projektem stosunkowo nieskom-plikowanym – sama Lasermania stanowią-ca jego pierwowzór zawiera o wiele szerszy zestaw reguł rozgrywki powiązanych z do-datkowymi typami elementów występują-cych na planszy gry. Czytelników zaintere-sowanych szczegółami implementacji silni-ka zapraszam do analizy kodu źródłowego. Tych mniej cierpliwych zachęcam do obej-rzenia Rysunku 7, na którym przedstawio-ne są efekty działania opisanych wyżej me-chanizmów.

Gra w kieszeniNadszedł czas aby przetestować naszą grę w jej docelowym środowisku. Procedura budowa-nia paczki instalacyjnej jest identyczna do tej opisanej na początku artykułu. Czytelników, którzy są szczęśliwymi posiadaczami komó-rek Nokia z serii S60 3rd Edition, zapraszam do przetestowania LaserQuest. Mam nadzie-ję, że rozwiązanie przykładowej planszy (ścią-gniętej zresztą z oryginalnej Lasermanii) nie sprawi nikomu dużego problemu. Już po kil-ku minutach grania widać jest, że grze bardzo dużo brakuje do finalnej postaci. Nadal braku-je dźwięku, obsługi wielu plansz, czy wykry-wania orientacji ekranu. Do aspektów tych wrócimy w kolejnych odsłonach cyklu, a te-raz czas na...

PodsumowanieTak oto kończymy drugi odcinek cyklu ar-tykułów o programowaniu gier przeznaczo-nych dla Symbian OS. Niestety – mój ambit-ny plan opisany w podsumowaniu z poprzed-niego odcinka – spalił na panewce – wiele z obiecanych wtedy zagadnień zmuszony by-łem przenieść do kolejnego odcinka. Głów-nym tego powodem stało się ograniczenie wielkości artykułu.

Z drugiej strony – staram się traktować prezentowane zagadnienie bardzo poważ-nie, opisując niełatwy proces tworzenia gier od podszewki i zahaczając o szczegóły pomi-jane często w publikacjach o podobnej te-matyce.

Mam nadzieję, iż prezentacja cyklu two-rzenia gry – od początku do końca – z uwzględnieniem form przejściowych, da pełniejszy pogląd na to zagadnienie. Na sam koniec – zgodnie z tradycją chciałbym za-proponować Czytelnikom zadanie domowe. Proponuję, korzystając z dołączonego do ni-niejszego artykułu szablonu szkieletu apli-kacji oraz narzędzia t2t, stworzyć własny projekt i zaimplementować prostą grę o te-matyce podobnej do tej, którą reprezentuje LaserQuest (dobrymi przykładami tego ro-dzaju gier są takie tytuły jak Sokoban czy Bo-ulder Dash). Osoby, które zdecydują się na taki krok, zachęcam również do rozwijanie obranego projektu na bazie technik opisywa-nych w kolejnych odcinkach niniejszego cy-klu – w myśl starego porzekadła, które w za-wodzie programisty sprawdza się jak nigdzie indziej – nie zrozumiesz dopóty, dopóki nie zro-bisz tego sam.

Na koniec chciałbym wymienić osoby, któ-re dzięki swoim wnikliwym recenzjom przy-czyniły się do znacznej poprawy jakości ni-niejszego artykułu. Wspomniane osoby to: Dawid de Rosier, Jacek „Noe” Cybularczyk oraz Piotr Buła.

Chciałbym również tradycyjnie podzięko-wać mojej ukochanej żonie – Oli, za cierpli-wość, którą mi nieustannie okazuje.

RAFAŁ KOCISZRafał Kocisz pracuje na stanowisku Dyrektora

Technicznego w firmie Gamelion, wchodzącej w

skład Grupy BLStream. Rafał specjalizuje się w

technologiach związanych z produkcją oprogra-

mowania na platformy mobilne, ze szczególnym

naciskiem na tworzenie gier. Grupa BLStream po-

wstała, by efektywniej wykorzystywać potencjał

dwóch szybko rozwijających się producentów

oprogramowania – BLStream i Gamelion. Firmy

wchodzące w skład grupy specjalizują się w wy-

twarzaniu oprogramowania dla klientów korpo-

racyjnych, w rozwiązaniach mobilnych oraz pro-

dukcji i testowaniu gier.

Kontakt z autorem: [email protected] 7. Plansza gry

Page 76: SDJ_11_2008_PL_E-Commerce

Wywiad

11/200876

Wywiad

www.sdjournal.org 77

Software Developer's Journal: Proszę na początek powiedzieć naszym Czytelni-kom kilka słów o sobie – kiedy rozpoczął Pan pracę w firmie EMC i z jakimi proble-mami zetknął się Pan pracując na obec-nym stanowisku?Bartosz Stebnicki: W EMC pracuję już 8 lat i przez ten czas stawiłem czoła wielu wy-zwaniom. Firma w tym czasie zmieniała się i rozwijała dynamicznie – od oferującej po-jedynczy produkt do potężnej korporacji, która proponuje klientom kilkadziesiąt pro-duktów. Miałem dużą przyjemność uczest-niczyć w procesie rozwoju firmy, ale wyma-gało to także dużego wysiłku i sporego na-kładu pracy. W tym czasie dokonaliśmy kil-ku akwizycji, pojawiali się w EMC nowi lu-dzie, firma zwiększała się obroty i rozro-sła się z kilku do kilkudziesięciu zatrudnio-nych osób.

SDJ: Czy wprowadził Pan jakieś rewolu-cyjne zmiany przejmując dowodzenie fir-mą na rynku polskim? Bartosz Stebnicki: Oczywiście wprowadzili-śmy szereg istotnych zmian, ale raczej nie nazwałbym ich rewolucyjnymi. Na pewno pojawiło się kilka zmian w związku z po-stępującymi akwizycjami. Rozpoczęliśmy ekspansję na nowe rynki i otworzyły się przed nami kolejne możliwości. Tak więc w polskim oddziale EMC pojawiły się no-we obszary działania i możliwości rozwo-ju. Wprawdzie nie nastąpiła rewolucja, ale odnotowaliśmy bardzo szybki i harmonij-ny wzrost.

SDJ: EMC swoje usługi oraz produk-ty kieruje głównie do klientów bizne-sowych. Czy macie Państwo także roz-

wiązania dla indywidualnych użytkow-ników? BS: Podjęliśmy już pewne kroki w tym kie-runku: EMC przejęło firmę Iomega, któ-ra oferuje produkty dla rynku konsumenc-kiego.

10 lat temu zaczynaliśmy działania od współpracy z największymi firmami, naszymi klientami były m.in. PKO BP czy TP S.A. Póź-niej nasze produkty stawały się coraz bar-dziej powszechne. Myślę więc, że za jakiś czas produkty EMC można będzie nabyć na-wet w sieciach handlowych, takich jak Carre-four czy Media Markt.

SDJ: Które z produktów w bogatej ofercie EMC cieszą się największą popularnością i najlepiej się sprzedają? BS: Strukturę naszej firmy tworzą czte-ry główne działy odpowiadające specyfice produktów i usług : storage, oprogramo-wanie m.in. Documentum i Legato, trzecia część firmy to produkty związane z bezpie-czeństwem i wreszcie czwarta – wizualiza-cja i rozrywka. Można nas przyrównać do 4-silnikowego samolotu. Obecnie każdy z wymienionych działów osiąga wyśmieni-te wyniki.

SDJ: Czy dostrzega Pan już odpowied-ni potencjał kadrowy do otwarcia cen-trum inżynierskiego EMC, czy woli nadal korzystać z usług podwykonaw-ców takich, jak S4E? Na odpowiedź na to pytanie czeka jeden z naszych Czy-telników.BS: Firma EMC świadczy usługi dedykowa-ne i zauważyliśmy, że ich sprzedaż zwięk-sza się dużo szybciej niż sprzedaż licencji czy sprzętu. Natomiast nie planujemy obec-

Na fali zmian

Bartosz Stebnicki

Informacja to najcenniejszy zasób w firmie. EMC wie, jak sprawić aby ten zasób generował zyski - dzięki integracji sprzętu, oprogramowania i usług.

Page 77: SDJ_11_2008_PL_E-Commerce

Wywiad

11/200876

Wywiad

www.sdjournal.org 77

nie otwarcia centrum projektowego. Ofe-rujemy usługi serwisowe, wdrożeniowe i na nich głównie skupiamy naszą uwagę na chwilę obecną.

SDJ: Czy planujecie wprowadzenie takich usług jak otwarte szkolenia? Czy myślicie o przeprowadzaniu wykładów – czy to na uczelniach, czy za pośrednictwem jakie-goś centrum szkoleniowego? BS: Tak mamy takie plany. Dotychczas szkolenia były organizowane przez na-sze polskie biuro, ale istniała także moż-liwość skorzystania ze szkoleń zagranicz-nych. Jednak w związku z szybko rosną-cą liczbą klientów zamierzamy poszerzyć ofertę szkoleń przede wszystkim dla użyt-kowników naszych produktów. Ale chce-my również szerzej zaistnieć na uczel-niach, gdzie specjaliści EMC mogliby prze-kazywać swoją wiedzę studentom. Mamy nadzieję, że działania te przyniosą za kilka lat korzyści nie tylko naszej firmie, ale też całemu rynkowi.

Nasze podejście jest długoterminowe i podejmujemy wyzwania, które nie są ob-liczone jedynie na szybki, natychmiasto-wy efekt.

SDJ: Jak ocenia Pan udział produktów EMC w polskim rynku pamięci maso-wych ?BS: To zależy, o jakim segmencie tego rynku mówimy. Na rynku dużych przedsiębiorstw jest to około 70%, a kilka procent w przypad-ku firm zaliczanych do SMB.

SDJ: Czy w ramach swoich systemów ope-racyjnych korzystacie też z otwartego oprogramowania?BS: Z otwartego oprogramowania nie, acz-kolwiek naszą dewizą jest otwartość na-szych produktów na inne technologie. Oferowane przez nas rozwiązania współ-pracują z różnymi systemami operacyjny-mi, jak np. systemy firm IBM, HP, ale też z systemem Linux – są to zatem systemy otwarte.

SDJ: Proszę opowiedzieć o Państwa suk-cesach na obszarze Data Center. Jakie ma-cie osiągnięcia w tej materii.BS: Oprócz tradycyjnej gałęzi storage'o-wej, gdzie – tak jak wspomniałem – jeste-śmy obecni u większości dużych klientów, uczestniczyliśmy również w projektowa-niu oraz budowie kilku dużych centrów da-nych w Polsce. Nie chciałbym jednak poda-wać ich nazw.

SDJ: Jak będzie wyglądać przyszłość w sektorze Data Center? BS: Myślę, że bez wykorzystania Data Cen-ter już wkrótce ciężko będzie nam się

obejść. Powstaje też pytanie, jakie to bę-dzie Data Center? Można bowiem myśleć o ofercie outsourcingu, a więc wynajęciu powierzchni, gdzie stawiamy swój wła-sny sprzęt, albo o ofercie szerszej i bar-dziej złożonej jak udostępnianie samej powierzchni dyskowej z gwarancją bez-pieczeństwa i odpowiednio wysokiej wy-dajności.

Taką usługę oferuje EMC – posiadamy du-że możliwości i wydajną infrastrukturę, z której korzysta klient. Sądzę, że właśnie w tym kierunku będzie zmierzać sektor Da-ta Center.

SDJ: Jakie rozwiązania związane z bez-pieczeństwem danych oferuje EMC? W ja-ki sposób archiwizowane i zabezpieczane są dane w oferowanych przez firmę roz-wiązaniach. Jakie gwarancje daje EMC, że świadczone przez firmę usługi są w pełni bezpieczne?BS: Problem bezpieczeństwa widzimy bar-dzo szeroko, rozpatrujemy go na kilku po-ziomach – od płaszczyzny sprzętowej, gdzie same macierze są skonstruowane w sposób zapewniający ochronę danych i minimalizujący ryzyko ich utraty, poprzez przeniesienie danych do chronionej loka-lizacji i ochronę dostępu do tych danych (tutaj korzystamy z rozwiązań RSA), aż po fizyczne zabezpieczanie danych – czyli od-powiednio chroniony budynek. Dzięki te-mu powstaje w pełni bezpieczna infra-struktura, przechowująca zaszyfrowane dane i zapewniająca dostęp do nich tylko upoważnionym osobom.

SDJ: Czy Państwa centrum danych jest zlokalizowane gdzieś blisko czy korzysta-cie z zewnętrznej lokalizacji?BS: Usługa, którą zaczęło świadczyć EMC nosi nazwę Mozy i dotyczy zarówno rynku konsu-menckiego, jak i rynku dużych klientów, in-frastruktura na jej potrzeby, jest zlokalizowa-na poza granicami Polski.

SDJ: Kilka tygodni temutemu miało miejsce otwarcie EMC Signature Solu-tion Center w siedzibie firmy Wola In-fo. Jakie korzyści dla firmy EMC będzie miało otwarcie takiego centrum w Pol-sce?BS: Wspólnie z firmą Wola Info tworzymy centrum testowe. To miejsce, gdzie klien-ci mogą praktycznie zapoznać się z posia-daną przez nas, bardzo bogatą infrastruk-turą, składającą się z serwerów firm trze-cich, bibliotek taśmowych, macierzy dys-kowych, przełączników i jeszcze kilku in-nych elementów.

To centrum daje klientom możliwość przetestowania funkcjonalności i wydaj-ności aplikacji bez konieczności sprowa-

dzania sprzętu bądź dalszego wyjazdu. Myślę, że daje to naszym klientom ogrom-ne korzyści.

SDJ: Jakie jest w samej firmie EMC podej-ście do bezpieczeństwa informacji? W ja-ki sposób firma zabezpiecza się przed wy-pływem informacji oraz przed atakami z zewnątrz?BS: Oczywiście wdrożyliśmy odpowied-nie procedury, sprzęt i oprogramowanie jak firewall czy antywirusy. Jednak przede wszystkim staramy się uświadamiać użyt-kowników, co należy robić, a czego nie w zakresie bezpieczeństwa. Tu bowiem do-strzegamy największe ryzyko. I myślę tu nawet o tak prostych rzeczach jak blo-kowanie komputera odchodząc od biur-ka czy zmienianie haseł jak też nie pozo-stawianie na biurku ważnych dokumen-tów i korzystanie z niszczarki. Są to więc kwestie często mniej związane z IT a bar-dziej z kulturą pracy. O IT troszczy się na-sza korporacja.

SDJ: A czy zanotowaliście Państwo kiedyś próby włamań hakerów np. na stronę in-ternetową korporacji?BS: Obawiam się, że gdy odpowiem prze-cząco, to takie próby się rozpoczną. Jednak dotychczas nie zanotowaliśmy takiego typu zdarzeń. Być może nikt nie uznał nas za fir-mę będącą atrakcyjnym celem podobnych ataków.

SDJ: A jak ocenia Pan pisma dla profesjo-nalistów, takie jak Linux+ , SDJ, lub Ha-king9 – czy pisma te faktycznie dociera-ją do specjalistów i gwarantują podnosze-nie ich umiejętności?BS: Znam doskonale wszystkie te pisma i przyznam, że poziom szczegółowości zagad-nień tam poruszanych jest wysoki. Jest to niewątpliwie świetne źródło informacji dla specjalistów.

SDJ: Na koniec chcielibyśmy poznać Pana spostrzeżenia na temat rozwoju rynku IT w Polsce. Czy polski rynek nie potrzebu-je obecnie silnego impulsu? Czy nie zo-stajemy gdzieś w tyle za rynkami euro-pejskimi? BS: Polski rynek rozwija się i dojrzewa w szybkim tempie. Ale nie jest też tak, że my tylko staramy się dogonić innych, gdyż w wielu dziedzinach dorównujemy już bądź nawet wyprzedzamy inne rozwinięte ryn-ki europejskie. Potencjał jest zatem ol-brzymi.

SDJ: Dziękujemy za rozmowę.

Page 78: SDJ_11_2008_PL_E-Commerce

KLUB PROOferta skierowana dla firm

Jeżeli Twoja firma jest prenumeratorem Software Developer’s Journal za comiesięczną dopłatą 50 PLN +VAT możesz dodatkowo otrzymać reklamę.

Wystarczy tylko, aby profil Twojej firmy pokrywał się z naszym magazynem.

Wyślij do nas: logo firmy, dane kontaktowe i informację o firmie

Reklama przez 12 kolejnych numerów tylko za 600 PLN +VAT.

Jeżeli nie posiadasz jeszcze prenumeraty możesz ją zamówić w atrakcyjnej cenie.

Dla nowych prenumeratorów specjalna oferta – 690 PLN.

FRONTLINE STUDIOSFrontline Studios – amerykańsko-polski twórca gier konsolowych oraz PC – szuka utalentowanych ko-derów (bardzo dobra znajomość C/C++; Java, Del-phi, UML), doświadczonych grafików (2D, 3D) oraz zespołów developerskich. Oferujemy długotermi-nową pracę nad poważnymi projektami. Nie prze-gap tej okazji!

[email protected]

Future ProcessingFuture Processing to dynamiczna firma techno-logiczna działająca na globalnym rynku opro-gramowania. Jesteśmy zespołem wysokiej klasy specjalistów posiadających wiedzę i doświadcze-nie niezbędne do realizacji ambitnych projektów informatycznych. Jeśli programowanie to Twoja pasja dołącz do nas! (możliwość pracy zdalnej).

http://www.future-processing.pl

Skontaktuj się z nami:[email protected] tel. 22 427 36 91

[email protected] http://buyitpress.com

Kei.plKei.pl działa na rynku usług hostingowych od 2000 roku. Do naszych zadowolonych Klientów z du-mą możemy zaliczyć wiele przedsiębiorstw sekto-ra MSP, instytucji oraz osób prywatnych. W ofer-cie Kei.pl znajdują się pakiety hostingowe, a także usługi dla wymagających Użytkowników – platfor-my e-Biznes oraz serwery fizyczne.

http://www.kei.pl

Opera SoftwareOpera Software’s vision is to deliver the best In-ternet experience on any device. We are offering browser for PC/desktops and embedded pro-ducts that operates across devices, platforms and operating systems. Our browser can deliver a faster, more stable and flexible Internet expe-rience than its competitors.

http://www.opera.com

Architektury systemów ITTwórca frameworków JUVE i serwera aplikacji AVAX oferuje usługi, doradztwo, rozwiązania do tworzenia nowoczesnych, dużych systemów i roz-wiązań informatycznych/internetowych, integrują-ce architektury ery post-J2EE/.NET, wykorzystu-jące MDD/MDA dla dziedzin – bankowość, teleko-munikacja, handel, e-commerce, ERP/Workflow/CRM, rozwiązania internetowe, portalowe.www.mpsystem.com [email protected]

Page 79: SDJ_11_2008_PL_E-Commerce

KLUB PRO

SWD Software Sp. z o.oSystem operacyjny czasu rzeczywistego RTOS QNX. Oficjalny dystybutor w Polsce.Zakres działalności: lokalizacja produktów QNX, dostawy sprzętu i oprogramowania, doradztwo przedsprzedażowe, wsparcie techniczne, certyfi-kowane szkolenia, opracowania na zamówienie.

http://www.swdsoft.pl

StatConsultingStatConsulting to firma o znaczącej pozycji na ryn-ku usług analitycznych oraz Data Mining. Nasza oferta obejmuje m.in. modele scoringowe, rozwią-zania Fraud Detection oraz modelowanie ryzyka. Tworzymy także własne rozwiązania informatycz-ne na potrzeby projektów Data Mining, Data Quali-ty, zarządzania ryzykiem itd.

http://www.statconsulting.com.pl

TTS Company Sp. z o.o.Sprzedaż i dystrybucja oprogramowania komputero-wego. Import programów na zamówienie. Ponad 200 producentów w standardowej ofercie. Chcesz kupić oprogramowanie i nie możesz znaleźć polskiego do-stawcy? Skontaktuj się z nami – sprowadzimy nawet pojedyncze licencje.

http://www.OprogramowanieKomputerowe.pl

IT SOLUTIONSWdrożenia i szkolenia z zakresu:• SQL Server• SharePoint Services• MS Project / Server• Tworzenie aplikacji w technologii .NET

http://[email protected]

IT SOLUTIONS

Softline rozwiązania mobilneWiodący producent systemów mobilnych, do-stawca aplikacji użytkowych dla biznesu (Sym-bian OS, Windows Mobile, J2ME ) zaprasza do współpracy. Zostań naszym partnerem. Dołącz do zespołu.

http://www.softline.com.pl

Transition Technologies S.A.Firma w branży high-tech od 1991. Producent opro-gramowania dla przemysłu (ponad 350 referencji z instalacji na całym świecie). Usługi z zakresu: hur-townie danych i Business Intelligence, rozwiązania eBusiness, optymalizacja, integracja danych, aplika-cji oraz procesów biznesowych, portale korporacyj-ne, consulting i outsourcing usług IT, zaawansowa-na automatyka cyfrowa.http://www.tt.com.pl

EPRONaszą misją jest projektowanie najwyższej jako-ści dedykowanych systemów IT, które cechuje wysoka niezawodność, wydajność, ergonomicz-ność i intuicyjność w obsłudze oraz administracji.Głównym elementem oferty EPRO jest oprogra-mowanie sklepu internetowego oraz identyfika-cja wizualna.tel. 085 743 66 38http://www.epro.com.pl

Proximetry Poland Sp. z o.o.Proximetry Poland Sp. z o.o. jest polskim od-działem amerykańskiej firmy Proximetry Inc. – dostawcy systemów zarządzania sieciami bez-przewodowymi opartymi na technologiach WiFi i WiMAX. Naszą misją jest dostarczenie klientom rozwiązań poprawiających jakość usług (QoS) dostarczanych drogą radiową. Dołącz do najlep-szych i zostań członkiem naszej ekipy!

http://www.proximetry.com

Page 80: SDJ_11_2008_PL_E-Commerce

v

Kontakt 1. Telefon+48 22 427 36 91+48 22 427 36 79+48 22 427 36 50

2. Fax+48 22 244 24 59

2. [email protected]

3. AdresBokserska 102-682 WarszawaPolska

Roczna prenumerata

tylko250

Software Developer’s Journal (poprzednio Software 2.0) jest miesięcznikiem głównie dla programistów, którzy li-czą, że dostarczymy im gotowe rozwiązania, oszczędza-jąc im czasu i pracy. Jesteśmy czytani przez tych, któ-rzy chcą być na bieżąco informowani o najnowszych osią-gnięciach w dziedzinie IT i nie chcą, żeby jakiekolwiek istotne wydarzenia umknęły ich uwadze. Aby zadowolić naszych czytelników, prezentujemy zarówno najnowsze rozwiązania, jaki starsze, sprawdzone technologie.

,-

Page 81: SDJ_11_2008_PL_E-Commerce

v 1

Zamówienie prenumeraty

Imię i nazwisko ...............................................................................

Nazwa firmy.....................................................................................

Dokładny adres ..............................................................................

.........................................................................................................

Telefon ............................................................................................

E–mail .............................................................................................

ID kontrahenta ................................................................................

Numer NIP firmy .............................................................................

Fax (wraz z nr kierunkowym) .........................................................

Prosimy wypełniać czytelnie i przesyłać faksem na numer: 00 48 22 244 24 59lub listownie na adres: Software-Wydawnictwo Sp. z o. o.ul. Bokserska 102-682 WarszawaPolskaE-Mail: [email protected] też zamównienia telefoniczne:0048 22 427 36 910048 22 427 36 790048 22 427 36 50

Jeżeli chcesz zapłacić kartą kredytową, wejdź na stronę naszego sklepu internetowego www.buyitpress.com.

Prenumerujesz – zyskujeszl oszczędność pieniędzy l szybka dostawa l prezentyl bezpieczna płatność ność on–line

TytułIlość

nume-rów

Ilość zama-

wianych prenume-

rat

Od numeru pisma

lub mie-siąca

Cena

Software Develope-r’s Journal (1 płyta CD) – dawniej Software 2.0

12 180*/250PLN

□ automatyczne przedłużenie prenumeraty

* cena prenumeraty rocznej dla osób prywatnych

Page 82: SDJ_11_2008_PL_E-Commerce

11/200882

W NASTĘPNYM NUMERZE SOFTWARE DEVELOPER’S JOURNAL 12/2008 168

SYSTEMY OPERACYJNETechnologia Adobe Flash w systemach wbudowanych

SZTUCZNA INTELIGENCJAMiary entropii w sztucznej ewolucji programów komputerowych

PROGRAMOWANIE JAVAObliczenia numeryczne w programach komputerowych

PROGRAMOWANIE PHPZaawansowana obróbka grafiki w PHP

NOWE ARTYKUŁY W DZIAŁACHBiblioteka miesiąca

Testowanie oprogramowania

I WIELE INNYCH ARTYKUŁÓW, KTÓRYCH NIE MOŻESZ PRZEOCZYĆ!

W sprzedaży od 18 listopadaRedakcja zastrzega sobie możliwość zmiany zawartości pisma.

Page 83: SDJ_11_2008_PL_E-Commerce
Page 84: SDJ_11_2008_PL_E-Commerce