Development z Zapomnianej Strony

..:: Paweł Hofman .NET Portal ::..

Czasem zdarza się sytuacja, w której ktoś, kto ma dostęp tylko do odczytu do naszego repozytorium SVN, chciałby w nim coś jednak zapisać. Udało mu się (lub jej) rozwiązać jakąś usterkę czy problem, albo usprawnić działanie. Moglibyśmy w tym miejscu dodać uprawnienia do zapisu i byłoby po sprawie.

Jednak czy na pewno? Zawsze jakieś “ale”! Z czegoś wynikał przecież fakt, że ów użytkownik nie posiadał pełni praw.

  • Czy wspomniana zmiana ma w ogóle sens i czy w ogóle istnieje? (może ktoś tylko chce wyłudzić dostęp)
  • Czy zmiany są w pełni przetestowane?
  • Czy nie wprowadzają luk w zabezpieczeniach i innych ukrytych furtek?
  • Czy zgadzają się one z konwencją nazewniczą i stosują projektowe formatowanie kodu?
  • Czy będziemy pamiętać, o cofnięciu uprawnień, gdy zmiany zostaną już wysłane do repozytorium?

Wyjściem z tej sytuacji może okazać się utworzenie "łatki" (patcha), która zawierała będzie tylko proponowane zmiany w konkretnych plikach i lokalizacjach. Później przekazanie jej zaufanej osobie w projekcie, która zmiany te może przejrzeć, ocenić i ma prawa do zapisu na serwerze. Oto jak się za to zabrać:

  1. Zapamiętanie zmian:

    svn diff > fix.diff

    (Rozszerzenie diff jest rozpoznawane przez wiele edytorów, podświetlając składnię podczas przeglądania, niemniej jednak każde inne byłoby równie dobre)

  2. Aplikacja zmian:

    patch -p0 -i fix.diff

    Teraz można sprawdzić, co i gdzie się zmieniło i po przeglądzie (oraz koniecznie testach) wysłać do repozytorium na serwerze.
  3. Wysłanie na serwer:

    svn commit –m “<message> 


Od jakiegoś czasu staram się rozwijać własną bibliotekę implementującą kliencką część protokołu Bayeux (używającego poniżej formatu JSON). Jest tam jeszcze oczywiście dużo innych rzeczy, ale te są na razie najważniejsze.

Zabawa idzie mi całkiem dobrze i z wyników jestem bardziej niż zadowolony. Jednak z racji tego, że za cel powziąłem sobie współpracę z każdą dostępna platformą .NET, natrafiłem coś zupełnie nieoczekiwanego. O ile przemilczę fakt, że każdy z .NET frameworków (tj. ten z komputera stacjonarnego desktop, Compact Framework, Mono oraz Silverlight dla Windows Phone 7), udostępnia inne API, które nie zawsze są ze sobą zgodne (bo te albo pokazują inne właściwości, albo wręcz brakuje synchronicznych wywołań). To o tyle nie sposób przejść obojętnie obok pewnego problemu, który zmarnował mi trochę czasu ostatnio. Ten sam kod do wymiany danych z użyciem HttpWebRequest, który działa poprawnie na Microsoft .NET Framework nie zadziała na Mono .NET na Linuxie.

Otóż w scenariuszu, w którym łączymy się przy użyciu HTTPS ze znanym z góry serwerem, wszystko pięknie działa na stacjonarnym Windows 7 oraz na Windows Phone 7. Jednak przy testach na Mono 2.8, przy próbie pisania do strumienia sieciowego otrzymujemy wyjątek ze statusem “SendFailure”. Prócz enigmatycznego komunikatu, nie mamy żadnego konkretnego punktu zaczepienia.

The authentication or decryption has failed.

Albo też nagle i niespodziewanie okazuje się, że coś, ale już nie nasz kod, zużywa 100% mocy procesora, 1GB RAMu oraz z wirtualnej maszyny Mono nie ma co zbierać.

Odpowiedzialnym za ten stan rzeczy jest sposób obsługi certyfikatów SSL. Microsoft .NET Framework akceptuje je wszystkie bez wyjątków i pozwala na komunikację. Mono natomiast jest bardziej restrykcyjne i wymaga, aby przed rozpoczęciem wysyłania, zaakceptować certyfikat serwera ręcznie. Jest to tym ciekawsze, że musi być zrobione nawet w sytuacji, gdy mamy zaufany certyfikat, podpisany przez zaufanego dostawcę.

Wystarczy zatem umieścić w swoim kodzie poniższy fragment, aby wszystko zaczęło działać zgodnie z oczekiwaniami:

ServicePointManager.ServerCertificateValidationCallback += CertificateValidationCallback;

public bool CertificateValidationCallback (object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors)
{
    // tutaj należy wstawić logikę sprawdzania certyfikatu!
    return true;
}



Testowanie - niestety temat zapomniany i zupełnie zignorowany przez twórców Windows Phone 7. Jakoś w głowie mi się nie mieści, że premiera telefonu odbyła się trzy miesiące temu, po raz pierwszy telefon pokazano światu w marcu 2010 i do dzisiejszego dnia nie doczekał się od oficjalnego frameworka testowego zintegrowanego z Visual Studio. Aż jestem ciekaw, jakim cudem tak dobrze go przetestowali i czy w ogóle zamierzają coś w tę stronę ruszyć. Bo widzę, nawet po kursie na virtualstudy.pl, że dużo ludzi interesuje się dużo bardziej cyklem życia aplikacji, niż prowadzeniem dobrego projektu na tej platformie (nie obrażając nikogo oczywiście).

Na samym początku wyjaśnię zatem, że oczywiście chodzi nam o pisanie testów, do których już przywykliśmy – czy to używając MS Unit Testing Framework, czy NUnit, używając atrybuty, które znamy i które nie sprawiają nam kłopotu oraz całego tego podejścia.

Tak, czy inaczej, błądząc po Internecie i marnując kolejne godziny możemy znaleźć garść przydatnych materiałów, które pozwolą uzbroić nas w środowisko do zabawy. Podejrzewam, że większość nie ma za dużo czasu, zatem przejdźmy od razu do meritum. Polecam zatem przestudiowanie przynajmniej:

  • Wystąpienia Jeffa Wilcoxa na MIX2010 o testowaniu Silverlight3 i Silverlight4. Co ciekawe, jest on członkiem zespołu Silverlight (tworzącego między innymi Silverlight Toolkit) i pokazuje on tam między innymi swój autorski projekt. Doprawdy, podziwiam takich ludzi. Ale ciągle daje mi do myślenia, dlaczego Microsoft nie wspiera tego aktywniej (albo samemu?).
  • Najnowszą wersję bibliotek, które trzeba dołączyć do projektu automatycznego testowania (o czym za chwilkę) znajdziemy na jego blogu. Dla potomności skopiowałem to również tutaj. Niestety jest to wersja z maja 2010, a mamy ostatni dzień grudnia i choć dzisiaj działa, to ciekawe jak będzie w niedalekiej przyszłości. Kontaktowałem się z Jeffem i obiecał rzucić okiem (popatrzeć na problemy, które mu zgłosiłem) i wypuścić nową wersję niedługo. Wszyscy jednak wiemy, jak to jest z wolnym czasem… no jest wolny ;)

Na koniec zostawiłem sobie zbudowanie aplikacji testowej. Oryginalny post, na którym bazuję znaleźć można tutaj. Jednak jak dla mnie jest on nieco przekombinowany. W skrócie mówi on o tym, że:

  1. Trzeba już mieć zainstalowane narzędzia do pracy z Windows Phone 7.
  2. Utworzyć najzwyklejszy projekt Silverlight3 dla Windows Phone 7.
  3. Dodać referencje do bibliotek Jeffa.
  4. Usunąć wszystkie strony aplikacji, gdyż to framework będzie je tworzył sam (za chwilkę).
  5. Zmodyfikować konstruktor aplikacji App() tak, aby oprócz monitorowania wyjątków, ustawiał odpowiednio widok (wszystko inne należy skasować z konstruktora):
    this.RootVisual = UnitTestSystem.CreateTestPage();
  6. I najważniejsze – CreateTestPage(), posiada też wersję, która przyjmuje dodatkowe opcje konfiguracji (UnitTestSettings). Wśród nich jest między innymi lista assembly, które mają być przeszukiwane w celu lokalizacji testów. Dodajemy do niej oczywiście wszystkie, które nas interesują. Po co? No ja osobiście wolę oddzielić same testy, od aplikacji, która je odpala. Mimo wszystko testy można użyć jeszcze gdzieś indziej, a tej aplikacji to już nie zawsze.

Wesołego TDD!



Jest piękny grudniowy wieczór, kiedy to w świątecznej promocji nabyliśmy Crysis Maximum Edition ze Steam’a. Pobraliśmy go i zainstalowaliśmy na swoim komputerze, a naszym oczom już już ma ukazać się gra. Czekamy, czerwona dioda dysku miga ochoczo do nas… Aż tu nachodzi nas ów nieoczekiwany gość – crash (nie mylić z tytułem gry!), który psuje cały wieczór.

Logi twierdzą wyraźnie, kto jest winny:

Nazwa zdarzenia problemu:    BEX
  Nazwa aplikacji:    crysis.exe
  Wersja aplikacji:    1.1.1.6156
  Sygnatura czasowa aplikacji:    47d6d167
  Nazwa modułu z błędem:    MSVCR80.dll
  Wersja modułu z błędem:    8.0.50727.4927

Niemniej jednak logi kłamią. Jak go naprawić?

Usuwamy katalog: <Moje dokumenty>/My Games/Crysis (i prawdopodobnie tyczy się to także dodatku Warhead).

Otóż, grałem wcześniej w pudełkową wersję, głównie dla DirectX 10 i 64-bit, natomiast Steam pobrał i uruchomił wersję DirectX 10 ale niestety 32-bitową. A z mieszaniem takich ustawień nikt już sobie poradzić nie umiał, jak widać.



Sam temat nie powinien być nieznany. Atrybuty to od takie dodatkowe adnotacje w kodzie, które możemy “przypiąć” do klas, metod, pól (itd.), które nadają im bardziej mistyczne własności, objawiające się już dalej podczas działania samej aplikacji. Ot, po prostu gdzieś później sami będziemy sprawdzać, czy dana klasa, pole czy metoda jest naznaczona wykonywać dla niej specjalny kod, który jest ukryty pod ‘if’ dla typowych elementów.

Jednakże te ‘systemowe’ atrybuty, które oferuje platforma czy kompilator .NET potrafią coś więcej. Dziś pokażę wybrane atrybuty .NET, które według mnie zasługują na szerszy rozgłos i użycie. Niejednokrotnie znajomość ich ułatwiła mi pracę, zatem mam nadzieję, że komuś jeszcze pomogą.

  • InternalsVisibleTo – sprawia, że bez ujawniania chronionych klas, “zaprzyjaźniony” tym atrybutem projekt testów jednostkowych (unit test) będzie widział wszystko i mógł tworzyć bez problemu instancje tych klas.
  • Conditional – pozwala wyrzucić z kodu te funkcje (ich definicje oraz wywołania), dla których wskazany warunek nie jest prawdziwy. Przydatne bardzo do logowania operacji w trybie ‘Debug’, które nie są nam potrzebne w trybie ‘Release’. Oczywiście funkcje muszą spełnić kilka warunków, ale to już odsyłam do dokumentacji.
  • AllowPartiallyTrustedCallers – pozwalamy używać swojego kodu nie w pełni autorytatywnemu kodowi (np. ściągniętemu z Internetu, który nie ma pełni praw wykonania na lokalnej maszynie).
  • TestClass / TestMethod – atrybuty używane w projektach testów od oznaczania pojedynczych testów. Głównie używane z Microsoft Testing Framework, jednakże z poziomu funkcjonalności API, posiada on komplementarne funkcje do NUnit, dzięki czemu przy użyciu kilku dyrektyw ‘using’ można te atrybuty przekształcić na identyczne z NUnit. Dzięki czemu nasz kod testuje się świetnie w systemie Window oraz na maszynach z Linuxem czy MacOS, gdzie dostępne jest Mono.


Jeżeli zależy nam na jakości wytwarzanego oprogramowania (co jest z góry wiadome, że tak) – to pojęcie Continous Integration nie powinno być obce. Mi osobiście do gustu przypadł projekt BuildBot. Jednym zdaniem – mały, prosty, obsługujący wiele platform, bardzo łatwo rozszerzalny i co więcej mamy pełny kod źródłowy, gdyby coś poszło nie tak…

Jak go zatem zainstalować na Windows XP (i późniejszym)? Twardzieli odsyłam do “oficjalnego” przewodnika. Ja postaram się dodać coś od siebie i zmniejszyć ilość potrzebnym kroków:

  1. Instalujemy Python 2.7.1. Inne (czyt.: wyższe) wersje Pythona mogą być nieco niewygodne, bo nie wszystkie ‘pakiety’ wymagane przez BuildBota mogą być już zaktualizowane, aby z nią działać i w chwili pisania, tak właśnie było.
  2. Do zmiennej systemowej PATH dodajemy odpowiednio katalogi (co skróci niektóre męki przy wykonywaniu poleceń z konsoli):
    • C:\Python27
    • C:\Python27\Scripts
      (najprościej chyba we Właściwościach Systemu –> Zaawansowane –> Zmienne środowiskowe i tam znajdziemy Path)
  3. Instalujemy twisted w wersji 10.2.
  4. Instalujemy SetupTools dla Pythona w wersji 2.7.1. Będą one potrzebne, aby później bez problemu pobrać z sieci wszystko to, czego jeszcze brakuje dla działającej instancji BuildBota.
  5. Teraz poleceniami instalujemy:
    • easy_install Zope.Inteface
    • easy_install jinja2
    • easy_install PyCrypto
    • easy_install PyOpenSSL
  6. Wreszcie pobieramy samego BuildBota (jako master i slave). Rozpakowujemy do katalogu C:\Temp.
  7. Instalujemy go:
    • python C:\Temp\buildbot-0.8.2\setup.py install
    • python C:\Temp\buildslave-0.8.2\setup.py install
  8. Sprawdzamy, czy wszystko działa:
    buildbot --version

    Powinno zwrócić numer wersji, a nie krzyczeć o brak zainstalowanego pakietu.
  9. Teraz pozostała już tylko własna konfiguracja maszyn budujących, dostępów do repozytoriów, nadobnych akcji, uruchamiania testów oraz przygotowywaniu release’a. O tym może opowiem coś niedługo. Dokumentacja natomiast opisuje wszystko bardzo czytelnie.

Oczywiście nie byłbym sobą, gdybym w tym momencie nie napotkał na problem oraz nie próbował ostrzec, że bardzo łatwo zmarnować wieczór i stracić dobry humor. Powód dość prozaiczny. Nie działa logowanie oraz podgląd wykonywanych poleceń, historia itp. Generalnie dużo rzeczy wygląda jak nieudane posuniecie i brak wsparcia dla Windowsa. Nic bardziej mylnego.  Winą obarczmy brak zgrania BuildBota z najnowszą wersją twisted. Bardzo ładnie opisano to w tickecie #1697. Z pomocą przychodzi nam tutaj oczywiście otwartość kodu tego projektu. W opisie problemu znajduje się odnośnik do poprawki. Aplikujemy ją bardzo prosto, nadpisując plik builder.py, tym, który ściągamy z repozytorium.

Uruchamiamy ponownie BuildBot mastera i gotowe!



Windows Phone 7 trafił już pod strzechy i mam możliwość przyjrzeć mu się z bliska. Wśród wielu dość szybko rzucających się braków, poniżej opisuję to, co powoduje, iż szkoda marnować czas na niego i lepiej jeszcze poczekać (rok, dwa?), a może go jednak dopracują. Jeśli planujesz zatem zakup, wstrzymaj się choć na sekundkę i przeczytaj czy warto utopić 2500PLN i później żałować…

Co nie wyszło:

  1. WiFi – aby móc korzystać z dobrodziejstw Internetu w domu lub pracy, SSID (nazwa sieci) musi być rozgłaszana. Czyli z wszystkimi tzw. ukrytymi sieciami WiFi ten telefon po prostu nie będzie działał, bo ich nie znajdzie. Oficjalne wytłumaczenie – ‘ukrywanie SSID nie jest sposobem na zabezpieczanie sieci’. Powodzenia zatem!
  2. Lista kontaktów (pobierana z konta LiveID lub Google) będzie zawsze sortowana najpierw po imionach, a dopiero później po nazwisku. Nie można tego zmienić.
  3. Używanie LiveID, które zarejestrowaliśmy z lokalizacją “Polska”, spowoduje, że nic nie pobierzemy (nawet darmowych aplikacji) ze sklepu Microsoftu. Czyli żadnego programu prócz preinstalowanego nie użyjemy. To samo dzieje się przy próbie dostępu do XBox Live – czyli gier. Chociaż ten dostęp został w końcu uruchomiony oficjalnie w Polsce (z wielką pompą 10-tego października 2010 roku - po 3-ch latach od początku sprzedaży konsol XBox w naszym kraju, brawo za refleks), to nasze LiveID nie pozwala na pobieranie równie gier.

    Mała dygresja – tu jestem wyjątkowo cięty na tę usługę, bo znowu czuję się nabijany w butelkę. Kupując legalnie grę Warhammer 40k II, która na moje nieszczęście jest zintegrowana z XBox Live (znanym też jako Games for Windows), po prostu coś mnie trafia, jak chcą jeszcze ode mnie dodatkową opłatę za zmianę ksywki, pod którą jestem widziany w Internecie. Domyślna nazwa jest oczywiście koszmarna. A dobija mnie fakt, że rejestrując się z innego kraju, mogłem chociaż raz ją zmienić. Pytam się tylko – co to za model biznesowy? Bo ja po prostu wiem, że żadnej kolejnej gry z czymś takim po prostu nie kupię!
    • obejść ten problem można prosto poprzez utworzenie LiveID w innym kraju (np. Niemcy, Anglia, Irlandia – tu uwaga, sklep nie działa w całej Europie Zachodniej, także nie tylko my jesteśmy namaszczeni tym razem) i wpisać go jako pierwszy po ‘resecie’ telefonu
    • jako kolejne LiveID można dograć pozostałe, gdzie mamy kalendarz i kontakty i jakoś nawet to zrozumie i będzie je synchronizował
    • bez tych sztuczek, mamy dość drogi zwykły aparat telefoniczny z kilkoma mankamentami, o których poniżej.
    • Otwartym pozostaje tu pytanie – czy gdzieś przypadkiem nie łamie to jakichś postanowień licencji.
  4. Pobierany jest tylko pierwszy kalendarz z konta LiveID. Biada wszystkim tym, którzy mają ich kilka.
  5. Nie można obierać ani wysyłać MMSów.
  6. Co dwa dni wypada zresetować telefon (trzymając przycisk wygaszania ekranu oraz znak Windows przez 5-10sek), gdyż zdarza się, że nie słyszy nas druga strona podczas dzwonienia, choć z naszej perspektywy wszystko wygląda dobrze. No niby najlepiej przetestowany telefon.
  7. Telefon nie pojawia się jako zwykły “pendrive” przy podłączeniu do komputera, zatem nic samemu nie możemy na niego wgrać. Jest to o tyle kłopotliwe, iż aby obejrzeć pliki PDF na telefonie, musimy je wcześniej pobrać przez WWW albo wysłać do siebie maila (oczywiście aby mieć Adobe Readera niezbędne jest wykonanie kroków opisanych w pkt 3). No chyba ktoś tu za długo na słońcu leżał.
  8. Jedyny prawomocny dostęp do telefonu można uzyskać instalując aplikację Zune, która jest światu równie potrzebna jak iTunes.
  9. Zune, ani telefon nie potrafi synchronizować haseł do sieci WiFi, ani aktualizacji programów, a tym bardziej pobranych programów. Czyli jeśli coś pobraliśmy/kupiliśmy w Internecie i ‘zresetowaliśmy’ urządzenie, co się może zdarzyć, powrót do stanu używalności będzie wymagał dobrej pamięci użytkownika. Ciekawe, co wymyślą, jak wyjdą nowe modele i użytkownicy, będą chcieli się przesiąść ze starych. Może również dodatkowy abonament?
  10. Oczywiście nie obsługuje polskich ogonków, polskich ustawień regionalnych itp, chociaż sprzedają go w Polsce, z polską instrukcją obsługi.
  11. Nazwę telefonu można zmienić tylko w Zune.
  12. Wersja “na Polskę” ma tylko 8GB wewnętrznej pamięci, której nie można rozszerzać. Brakuje też gniazda na kartę pamięci, a (jakimś cudem) wyciągnięcie oryginalnej pamięci powoduje, że albo telefon nie wstanie, albo że nowa karta zostanie zaszyfrowana i dalej będzie bezużyteczna, przy próbie dostępu do niej z komputera lub innego urządzenia. Aha, wersja na Wielką Brytanię ma 16GB. Dziwne?
  13. Jeśli planujesz robić na niego gry/programy, wiedź, że:
    • musisz zapłacić $99 rocznie za ten przywilej (OK – Apple też tak ma)
    • 1/3 z twojej sprzedaży bierze Microsoft (OK – Apple też tak ma)
    • możesz mieć max do 3 telefonów (NIE OK - Apple pozwala do 100) – a szkoda, bo jeśli się weźmie pod uwagę prawdziwy ‘firmowy’ development, to trochę mało (zważywszy na chęć testowania dostępnych rozdzielczości na różnych modelach telefonów, które się niebawem pojawią i kilku wersji systemu operacyjnego)
    • istnieją darmowe narzędzia – tj. Visual Studio 2010 Express i inne z Windows Phone w tytule (Apple też tak ma, choć narzędzia te oferują nieco więcej możliwości).
  14. Nie poradził sobie z bezpiecznym dostępem do niektórych moich skrzynek pocztowych. Jeśli certyfikat nie był zaufany, to po prostu się nie połączymy.
  15. Plusem jest to, że ma wbudowanego Office w wersji mobilnej.
  16. Niby obsługuje MP4 i WMV, ale i tak większość z nich Zune musi ‘skonwertować’, co trawa dość długo w zależności od wydajności komputera, wielkości filmu itp.

Opisywana przeze mnie wersja system to: Windows Phone 7.0.7004.0 dla HTC HD7 (T9292).

Oczywiście lista ta jest wynikiem moich prywatnych obserwacji. Jeśli się gdzieś pomyliłem lub ktoś zna rozwiązanie, które przeoczyłem to czekam na kontakt i z pewnością poprawię.

Reasumując, jeśli miałeś/miałaś jakieś wątpliwości. To radzę się wstrzymać. Stare porzekadło, poczekajmy z produktami Microsoft przynajmniej do ServicePack 1 jest dalej na szali. Szkoda tylko, że w swojej zadumie i ślepej pogoni za iPhonem, iPodem i iPadem, Microsoft wybrał najgorsze rozwiązania dla użytkownika i potencjalnego developera i liczy, że wyciśnie tyle samo kasy co konkurent.

AKTUALIZACJA 2010-12-28:

A dobiło mnie to, że pasuję profilem w target ludzi, dla których projektowany był ten telefon. I ja (chyba jako jedyny na ten planecie albo komuś na złość), nie zapamiętuję ulubionych stacji radiowych po ich częstotliwościach. No na litość boską, jak przeglądam listę ulubionych, to mnie trafia. Bo albo pozwólmy użytkownikowi zmienić ich nazwę na liście, albo użyjmy RDS do nadania poprawnej. Niby mamy bleeding-edge telefon, ale znam takie stare modele innej firmy sprzed paru lat, który to umieją (i są do dostania za 1PLN)…



Kontynuując post o samym tworzeniu repozytorium i dostępie do niego z poziomu terminala Linuxa, warto też wspomnieć, że tak samo łatwo skonfigurować go można na Windowsie.

Otóż tunel ssh definiujemy w sekcji [tunnels] pliku (ścieżka dla Windows 7):

C:\Users\<użytkownik>\AppData\Roaming\Subversion\config

 

Wygląda on mniej więcej tak:

ssh = “C:/Programy/Putty/plink.exe” –P <port SVN> –l <użytkownik>
                                  –i “C:/Users/<użytkownik>/.ssh/id_rsa”

Wyjaśniając:

  1. Przy użyciu programu plink (wchodzącego w skład ‘paczki’ putty, którą trzeba pobrać i zainstalować wcześniej), utrzymywane będzie połączenie ssh do serwera.
  2. Plik klucza prywatnego id_rsa, nie jest wymagany, a jedynie stanowi ułatwienie, aby nie wprowadzać hasła przy każdorazowym dostępie do serwera (a ich żądań może być wiele nawet przy jednorazowej aktualizacji plików, czy pobieraniu/przeglądaniu repozytorium).

 

 

Jest jeszcze druga wersja tego tunelu, która pozwala na jednoczesne korzystanie z TortoiseSVN. Wygląda ona tylko nieznacznie inaczej:

ssh = “C:/Program Files/TortoiseSVN/bin/TortoisePlink.exe” –P <port SVN> –l <użytkownik>
                                 –i “C:/Users/<użytkownik>/.ssh/id_rsa”

 

 

Do repozytorium dostajemy się później standardowo poleceniem:

svn co svn+ssh://<ścieżka>

oraz aktualizujemy:

svn up .

Gotowe!



Od jakiegoś już czasu firmware do kilku modeli firmy dLink (DI-524, DIR-628, DIR-655) posiadał dość znaczącą lukę w zabezpieczeniach obsługi protokołu HNAP. O tym jak przejąć kontrolę nad takim ruterem można poczytać tutaj.

Najnowsza aktualizacja do wersji v1.32EUb01 (z 02/10/2010) rozwiązuje ten problem. Niestety wprowadza dodatkowe niedogodności, o których nie ma ani słowa w ‘release notes’. Od tej chwili mimo, że w ustawieniach włączymy UPnP, opcja ta nie będzie dostępna. Zatem wszystkie programy, które używają tej funkcjonalności - automatycznie przestaną działać.

Niestety jedynym lekarstwem, jest nie aplikowanie tej aktualizacji i dalsze pozostawanie przy wersji v1.31EUb02 Beta (z 14/01/2010). A może ktoś zna lepszy sposób? Pozostaje mieć nadzieję, że firma dLink poprawi ten błąd wkrótce.



Kolejny dzień, kolejny problem z serii, “bo coś jest zepsute u podstaw” konfiguracji systemu… Zawczasu ostrzegam, że wpis ten jest wybitnie rozwlekły i nie jest przeznaczony dla osób niecierpliwych.

Zatem po kolei. Będąc zafascynowany “nowymi” rozwiązaniami, postanowiłem w ramach testów uruchomić przykłady z pakietu CometD i zapoznać się nieco z protokołem Bayeux (zainteresowanych tematem odsyłam do dokumentacji projektu). Oczywiście nic prostszego - wchodzimy na stronę projektu, pobieramy odpowiednie źródła, wypakowujemy CometD i uruchamiamy Jetty, które instaluje w sobie odpowiednie rozszerzenie. Wszystko bardzo ładnie w kilku zdaniach opisane jest tutaj.

Jakież wyrazy cisną nam się na usta, gdy ściągane są kolejne pakiety idące już prawie w gigabajty (do Javy, Apache, Maven2, itp…). Mija w końcu to niesłychanie długie 20 minut i oczom naszym ukazuje się Jetty w pełnej krasie. Ostrzegam, że jeszcze nawet nie zaczęliśmy grzebać w naszym testowym Debianie, a przecież chwilkę temu pobraliśmy najnowsze wersje całego oprogramowania na świecie.

~/cometd-2.0.0/cometd-demo$ mvn jetty:deploy-war
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: 'jetty'.
[INFO] ------------------------------------------------------------------------
[INFO] Building CometD :: Demo
[INFO] task-segment: [jetty:deploy-war]
[INFO] ------------------------------------------------------------------------
[INFO] Preparing jetty:deploy-war
[INFO] [enforcer:enforce {execution: enforce-plugin-versions}]
[INFO] [jetty:deploy-war]
[INFO] Configuring Jetty for project: CometD :: Demo
[INFO] Context path = /
[INFO] Tmp directory = /home/pawel/cometd-2.0.0/cometd-demo/target/tmp
[INFO] Web defaults = org/eclipse/jetty/webapp/webdefault.xml
[INFO] Web overrides = none
[INFO] Starting jetty 7.1.5.v20100705 ...
2010-09-05 01:29:34.971:INFO::jetty-7.1.5.v20100705
2010-09-05 01:29:37.803:WARN::EXCEPTION
java.lang.NullPointerException
    at javax.naming.spi.NamingManager.getPlusPath(libgcj.so.90)
    at javax.naming.spi.NamingManager.getStateToBind(libgcj.so.90)
    at org.eclipse.jetty.jndi.NamingContext.bind(NamingContext.java:337)
    at org.eclipse.jetty.jndi.NamingContext.bind(NamingContext.java:415)
    at org.eclipse.jetty.jndi.java.javaRootURLContext.(javaRootURLContext.java:78)
    at java.lang.Class.initializeClass(libgcj.so.90)
    at org.eclipse.jetty.jndi.java.javaURLContextFactory.getObjectInstance(javaURLContextFactory.java:63)
    at javax.naming.spi.NamingManager.getURLContext(libgcj.so.90)
    at javax.naming.spi.NamingManager.getURLContext(libgcj.so.90)
    at javax.naming.InitialContext.getURLOrDefaultInitCtx(libgcj.so.90)
    at javax.naming.InitialContext.lookup(libgcj.so.90)
    at org.eclipse.jetty.plus.webapp.EnvConfiguration.createEnvContext(EnvConfiguration.java:202)
    at org.eclipse.jetty.plus.webapp.EnvConfiguration.preConfigure(EnvConfiguration.java:62)
    at org.eclipse.jetty.webapp.WebAppContext.doStart(WebAppContext.java:378)
    at org.mortbay.jetty.plugin.JettyWebAppContext.doStart(JettyWebAppContext.java:114)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
    at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:165)
    at org.eclipse.jetty.server.handler.ContextHandlerCollection.doStart(ContextHandlerCollection.java:162)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
    at org.eclipse.jetty.server.handler.HandlerCollection.doStart(HandlerCollection.java:165)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
    at org.eclipse.jetty.server.handler.HandlerWrapper.doStart(HandlerWrapper.java:92)
    at org.eclipse.jetty.server.Server.doStart(Server.java:242)
    at org.mortbay.jetty.plugin.JettyServer.doStart(JettyServer.java:67)
    at org.eclipse.jetty.util.component.AbstractLifeCycle.start(AbstractLifeCycle.java:55)
    at org.mortbay.jetty.plugin.AbstractJettyMojo.startJetty(AbstractJettyMojo.java:437)
    at org.mortbay.jetty.plugin.AbstractJettyMojo.execute(AbstractJettyMojo.java:377)
    at org.mortbay.jetty.plugin.JettyRunWarMojo.execute(JettyRunWarMojo.java:68)
    at org.apache.maven.plugin.DefaultPluginManager.executeMojo(DefaultPluginManager.java:451)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoals(DefaultLifecycleExecutor.java:558)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeStandaloneGoal(DefaultLifecycleExecutor.java:512)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoal(DefaultLifecycleExecutor.java:482)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeGoalAndHandleFailures(DefaultLifecycleExecutor.java:330)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.executeTaskSegments(DefaultLifecycleExecutor.java:291)
    at org.apache.maven.lifecycle.DefaultLifecycleExecutor.execute(DefaultLifecycleExecutor.java:142)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:336)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:129)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:287)
    at java.lang.reflect.Method.invoke(libgcj.so.90)
    at org.codehaus.classworlds.Launcher.launchEnhanced(Launcher.java:315)
    at org.codehaus.classworlds.Launcher.launch(Launcher.java:255)
    at org.codehaus.classworlds.Launcher.mainWithExitCode(Launcher.java:430)
    at org.codehaus.classworlds.Launcher.main(Launcher.java:375)

A później jest już prościej, bo co sekundę wyskakuje wyjątek (co zdecydowanie lepiej rzuca się w oczy):

2010-09-05 01:38:42.200:WARN::EXCEPTION java.lang.ClassCastException: gnu.java.nio.ServerSocketChannelImpl cannot be cast to java.nio.channels.SocketChannel
    at org.eclipse.jetty.io.nio.SelectorManager$SelectSet.doSelect(SelectorManager.java:708)
    at org.eclipse.jetty.io.nio.SelectorManager.doSelect(SelectorManager.java:195)
    at org.eclipse.jetty.server.nio.SelectChannelConnector.accept(SelectChannelConnector.java:134)
    at org.eclipse.jetty.server.AbstractConnector$Acceptor.run(AbstractConnector.java:793)
    at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:436)
    at java.lang.Thread.run(libgcj.so.90)

   

Jednym słowem czad!

No niby prosty przykład, a ile radości. Cóż, znowu ktoś zawinił. Tym bardziej ciekawe jest kto oraz że na forum projektu milczą o tym błędzie, jakby się wszyscy pod ziemię zapadli. Podpowiem, że projekty (CometD oraz sam Jetty) dostępne sąt od kilku ładnych lat i na pewno ktoś by się z tym problemem zetknął. Chyba nie jestem aż takim szczęściarzem. A może jednak to jest jakaś niszowa przypadłość? Bynajmniej. Troszkę szperania i co się okazuje. Otóż ani PATH ani JAVA_HOME nie pokazują lokalizacji JVM (Java Virtual Machine). Dokumentacja do Jetty mówi o tym wyraźnie. Ustawiamy ścieżkę do /usr/lib/jvm/java-1.5.0-gcj-xxx i wszystko powinno ruszyć. Teoretycznie. W praktyce, dostajemy dokładnie ten sam błąd. No jakoś się całe środowisko pokumało, że tylko jedna wersja Javy była zainstalowana i nawet bez JAVA_HOME udało się ją załadować. No to może jeszcze inaczej, może gdzieś, jakiś przełącznik, jakaś aktualizacja, patch rejestru (dobra to nie Windows), symlink? wrr, cokolwiek.

Otóż nie. To, co zazwyczaj okazuje się poprawne, zazwyczaj też siedzi na samym szarym końcu rozwiązań i ostatnie wpada do głowy. Cały JVM jest do wyrzucenia :) No bo przecież GNU Java nie jest zgodna z Sun Java (tu wstaw dowolną wersję), bo i po co? Jakichże to kolorów nabiera wtedy życie…

Tak, ale instalacja oryginalnej ‘sunowskiej’ Javy też nie jest wcale taka prosta. Aby uzyskać dostęp do wersji Javy (Sun JDK 1.5 i JDK 1.6), niezbędny jest na początku dodatkowy wpis w konfiguracji apt-get. Te JDK-i oznaczone są bowiem jako “non-free” i musimy zaakceptować dodatkową licencję zanim będziemy mogli z nich skorzystać.

  • Dopisujemy więc na końcu pliku konfiguracyjnego apt-get (/etc/apt/sources.list) następującą linijkę:

deb http://ftp.debian.org/debian lenny main contrib non-free

  • Odświeżamy listę dostępnych pakietów:

apt-get update

  • Instalujemy Javę (kawę i kolejne 20 min mamy już tym razem w pogotowiu):

apt-get install sun-java6-jdk

apt-get install sun-java5-jdk

  • Na koniec, ustawiamy ją jako domyślną w systemie:

update-java-alternatives -s java-6-sun
echo 'JAVA_HOME="/usr/lib/jvm/java-6-sun"' | tee -a /etc/environment

  • Gotowe! Uruchamiamy ponownie skrypt Maven, który uruchamia Jetty i instaluje w nim CometD. Tym razem z powodzeniem pod adresem http://localhost:8080/ mamy już działające przykłady i użycie Bayeux! Nic dodać nic ująć.

Jednak wieczór można uznać za udany. Szkoda tylko, że nie to mi go skradło, na co chciałem go przeznaczyć…

Dziękuję za uwagę.



Autor

Paweł Hofman [CodeTitans]

ASP.NET
C/C++, C#, Objective-C
SQL

License and Disclaimer

Moje Gry i Aplikacje

Zobacz mnie na GoldenLine

Zobacz mnie na LinkedIn
Supported by Polish SQL Server User Group (PLSSUG)

Supported by WrocNet.org

Zine.net.pl

Wpisy

Projekty

Moje projekty open-source:

Sign in