mercoledì 29 dicembre 2010

Considerazioni sui dischi esterni

Qualche giorno fa mi sono trovato davanti alla scelta di come formattare il mio nuovo hard disk portatile. Pur essendo un accanito utente Linux, mi trovo a volte a dover usare altri sistemi, primo fra tutti Windows, e quindi ho bisogno che i miei dati siano leggibili (e scrivibili) indipendentemente dal sistema operativo. E' quindi da escludere un file system della famiglia ext: nonostante esistano programmi per leggere partizioni ext da Windows, tale sistema non viene riconosciuto dalla maggior parte dei dispositivi multimediali in commercio. Fat è quindi la scelta di portabilità piu' indicata, ma non quella corretta per me, che devo memorizzare file ben piu' grandi di 5 GB. Ho quindi deciso di formattare con il New (?) Technology File System (NTFS), file system leggibile e scrivibile da Windows e Linux, leggibile da Solaris e da OSX. Purtroppo però il driver Linux di questo file system ha prestazioni pessime: formattare un container TrueCrypt significa partire da una banda di 30 MB/s circa per poi arenarsi attorno a 5 MB/s. La stessa formattazione fatta da un sistema Windows parte con una banda di 35 MB/s e si assesta intorno ai 23 MB/s. In generale poi le prestazioni in scrittura, su entrambi i sistemi, sono basse, probabilmente dovute al journaling di questo file system. Ovviamente queste prove non rappresentano un benchmarking effettivo, ma le prove sono state effettuate varie volte sempre con i medesimi risultati.

mercoledì 15 dicembre 2010

OpenBSD Security

Questa mattina ho trovato nella mia casella di posta una e-mail di Theo De Raadt inviata alla lista security-announce di OpenBSD che parla di una cospirazione ad opera dell'FBI. Sostanzialmente Theo ha ricevuto una e-mail privata, che poi ha promosso in mailing list, in cui gli viene spiegato perché OpenBSD ha perso i fondi dal DARPA: l'FBI ha pagato le persone che lavoravano al progetto IPSEC per introdurre delle backdoor volontarie al fine di poter monitorare il traffico cifrato instaurato in un tunnel. Inutile dirlo, gli sviluppatori OpenBSD se la sono presa a male....
Personalmente ritengo che questi sospetti siano infondati, ad ogni modo essendo l'implementazione di OpenBSD molto stimata e replicata, ed essendo il codice Open Source, non penso che passerà molto tempo affinché la verità venga a galla.

martedì 14 dicembre 2010

Eclipse Visual Editor

Finalmente sono riuscito ad installare il Visual Editor su Eclipse Helios, ma ho dovuto scaricare il pacchetto e installarlo manualmente come fosse un repository locale. Per aprire un file visuale con l'editor è necessario fare click destro sulla risorsa e selezionare Open With -> Visual Editor (al posto di Java Editor). Da notare che nel mio caso (applicazione RCP con viste e editor) l'editor non si comporta bene poiché non riconosce esattamente la vista o l'editor se questo viene creato con variabili "temporanee" (ossia non di istanza). Dovrò lavorare un po' per adattare il mio sistema all'uso del VE.

Nebula Table Combo

Usare il Table Combo di Nebula è un'operazione tutto sommato semplice, anche se manca un po' di documentazione a riguardo. Mostro di seguito i passi necessari all'utilizzo del widget, che nel caso della mia applicazione visualizzano una semplice tabella con ID/Descrizione di elementi.
Anzitutto occorre inizializzare il componento e definire le colonne (se si omette questo passo si avrà un combo che visualizza solo una delle colonne). Successivamente si decide se visualizzare o meno le intestazioni di colonna e infine si stabilisce quale colonna (con indice numerato partendo da zero) si deve rendere visibile nel combo quando questo è chiuso. Il seguente pezzo di codice illustra quanto appena descritto:

    // create the combo with the right style
    this.combo = new TableCombo( this ,  SWT.READ_ONLY );

    // say I want two columns
    this.combo.defineColumns( new String[]{ "ID", "Descrizione" }  );
    this.combo.setShowTableHeader( true );
    // the description is the column used for the selection
    this.combo.setDisplayColumnIndex( 1 );

Successivamente occorre inserire gli elementi nel combo, tenendo presente che occorrerà passare una coppia di stringhe in un unico oggetto array:


TableItem tableItem = new TableItem( this.combo.getTable(), SWT.NONE ); 
tableItem.setText( 
        new String[]{ newElement.getId(), newElement.getDescription() } );

PL/Java e Transazioni Distribuite

Al PGDay 2010 ho presentato un tutorial su PL/Java, una estensione Java ai linguaggi procedurali possibili in PostgreSQL. Alla fine del tutorial mi è stata rivolta una domanda interessante relativa ad un problema che non mi ero mai posto, e alla quale ho dato la risposta piu' logica secondo le mie conoscenze di PostgreSQL, di Java e di PL/Java.
Il quesito riguardava l'utilizzo di PL/java per comandare un ambiente enterprise ed eventualmente avviare una transazione distribuita. Cosa succede in questo caso? La risposta è semplice: PL/Java esegue all'interno del processo backend di PostgreSQL e quindi la transazione è confinata all'interno del backend stesso. Il processo backend non sa nulla di quello che PL/Java, che tuttavia esegue come processo esterno, sta facendo, e quindi non c'è modo di collegare la transazione/statement di PostgreSQL ad una eventuale transazione distribuita orchestrata da PL/Java. E' il programmatore PL/Java che deve farsi carico di tutto quanto.
Ad ogni modo, ho voluto chiarire questa faccenda sulla mailing list di PL/Java, qui si trova la discussione ufficiale.

venerdì 10 dicembre 2010

PGDay 2010: un altro successo marcato ITPug. Un altro successo della community.

E' stata una bella edizione quella di Roma 2010 del PGDay, giornata nazionale dedicata a PostgreSQL e giunta ormai alla sua quarta edizione. Ho partecipato all'organizzazione della prima versione del PGDay a Prato, nel 2007, in quello che fu' un evento di carattere internazionale e l'unione collettiva di un gruppo di persone appassionate e volenterose che diedero poi vita a ITPug, l'associazione che si e' fatta carica della promozione di PostgreSQL in Italia.
Ogni anno mi rendo sempre piu' conto che il PGDay non e' solo una giornata o un evento tecnico incentrato su PostgreSQL, bensi' un incontro della comunita', una comunita' di sviluppatori, di appassionati, di professionisti e in generale di gente che ne vuole sapere di piu'.
E come e' ormai tradizione, il PGDay 2010 inizia davanti ad una birra, in un ristorante di Roma, in attesa che un bel piatto di pasta (amatriciana o carbonara le uniche opzione scelte da noi DBA/sviluppatori) fumante ci sfami. Il tavolo e' denso di personalita' dal carisma e dalla competenza eccezzionale: oltre a noi italiani vi e' infatti Simon Riggs, intento a divorare una fiorentina decisamente esagerata anche per le sue capacita', e Jonhatan Katz impegnato con una piu' modesta pizza. Si parla ovviamente di PostgreSQL ma non solo: ogni argomento tecnologico e' valido per essere messo sul tavolo, cosi' come ogni cosa che rigurardi la comunita' e la cultura Open Source. Le discussioni con Daniele, Emanuele e il sempre intraprendente Torello sono avvincenti e illuminanti.

Il giorno seguente ci si alza di buon'ora per andare a preparare l'accoglienza presso lo splendido centro Cavour. E a nche qui ci si rende immediatamente conto del forte senso comunitario che aleggia attorno all'evento: tutti si prestano a lavori manuali per preparare i badge, le borsine, appendere i manifesti, provare i videoproiettori e quanto altro serva. Il tutto ovviamente condito da discussioni tecniche continue che possono nascere da qualunque commento, anche scherzoso.

Simon Riggs apre le danze con una introduzione su PostgreSQL 9 veramente d'effetto, non solo per l'alto livello tecnico e la chiarezza espositiva, ma anche per il saper comunicare efficacemente il vero valore aggiunto di PostgreSQL. E infatti si inizia gia' a parlare di quello che sara' un tema ricorrente nella giornata: il fattore economico. Vale la pena ricordare come PostgreSQL offra funzionalita' comparabili, identiche (e in alcuni casi anche superiori) a quelle di altri database commerciali senza richiedere costi di licenza. E' quindi evidente come la scelta di soluzioni professionali basate su PostgreSQL possa portare ad un risparmio economico anche notevole, soprattutto in un periodo, questo, nel quale le aziende e le amministrazioni faticano a far quadrare i bilanci.






Giusto qualche minuto per un ottimo coffee break e due chiacchere fra amici e via che si inizia con il programma tecnico. Nella mia sala io tengo il primo tutorial, 40 minuti di Java con attenzione a Pl/Java e considerazioni sull'utilizzo di un simile linguaggio di estensione. Il talk ha un buon audience, molto competente e preparato che mi stimola con domande veramente avvincenti. Dopo di me tocca ad Enrico che a tempo di record mostra il partitioning sia con le rules che con i trigger. E poi è la volta di Momjan con il suo primo talk: MVCC Unmasked. Effettivamente nulla di nuovo, nel senso che MVCC è un sistema ben conosciuto all'interno dello scenario database e soprattutto di PostgreSQL. Eppure le slide di Momjan, scarne e minimali se lette individualmente, diventano incredibilmente chiare e precise se accompagnate dalle sue parole. Veramente un ottimo talk. Prosegue Gabriele con la presentazione di un progetto ancora in fase alpha circa il cloud computing Amazon e PostgreSQL.

Altra pausa, questa volta per il pranzo, e poi si riparte con un pomeriggio ancora piu' ricco. Nella sala principale apre le danze Johnatan con un talk sugli ORM molto ben fatto ma che, personalmente, non dice nulla di nuovo. Insomma, uno di quei classici talk validi a livello ingegneristico ma non tecnologicamente avvincenti. Quello che si apprezza di Jonhatan è la pacatezza e il sorriso allegro e invitante, nonché la professionalità nell'esporre il proprio lavoro. E' la volta di David Fetter, con la presentazione di PL/Parrot; presentazione impeccabile e sottile come tutte quelle di David; personalmente apprezzo moltissimo il lavoro di David (in ogni direzione) ma apprezzo poco le sue presentazioni e il suo modo di esporre le cose. Ed è nuovamente la volta di Bruce, che questa volta spiega in modo pacato e con una semplicità disarmante una feature tanto complessa quanto utile: HOT Streaming Replication.

Una nuova pausa che fa apprezzare anche l'ottimo lavoro svolto dal catering e via con una nuova sessione di talk, l'ultima prima di lasciare spazio ai lightning talks; Daniele, Oleg e Gianni si alternano ad intrattenere il pubblico.

Il PGDay è ormai alla fine, torno a casa soddisfatto e compiaciuto del lavoro fatto. Ancora una volta ITPug ha saputo riunione i migliori esperti e professionisti di PostgreSQL (e in generale dello scenario database e Open Source) italiani e stranieri. Qualcuno durante un coffee break mi ha detto che il programma dell'evento era veramente molto denso, "siamo abituati a fare sempre eventi molto tecnici" è stata la mia risposta. Ed è vero: in generale preferiamo talk specialistici a semplice e sterile propaganda. Non voglio essere frainteso: la propaganda è importante, ma io personalmente penso sia meglio dimostrare con i fatti che si è migliori o in cosa si è migliori piuttosto che semplicemente dire che lo si è!

Come ogni anno non mancheranno le critiche, che secostruttive ci aiuteranno a migliorare questo evento che si è di fatto trasformato in un evento garantito e dalla indubbia qualità. I miglioramenti si vedono di anno in anno, grazie anche alle critiche. Fantastica l'idea di quest'anno di avere i nuovi cartellini con il programma "portatile" e le etichette adesive con la classificazione. Si tratta di innovazioni non importantissime ma che permettono di godersi meglio l'evento. E ancora una volta evidenzio l'importanza della comunità, che ha reso possibile tutto questo.Essere seduti a fianco dei committer principali di PostgreSQL ha evidenziato ancora di piu' l'importanza di questo aspetto del progetto, cosa che ITPug si impegna a diffondere da sempre.

A nome personale e di ITPug vorrei ringraziare tutti i volontari che hanno reso possibile questa grande festa di PostgreSQL: Diego, Simone, Marco, Torello, Emanuele, Daniele, Gianluca, Gabriele, Gianni senza nulla togliere a tutti gli altri.
Arrivederci al prossimo PGDay!

venerdì 3 dicembre 2010

Nuovi libri su PostgreSQL

E' un vero piacere vedere l'uscita di nuovi libri che trattino da vicino PostgreSQL:
I libri sono disponibili sia in formato cartaceo che digitale, e gli autori sono di tutto rispetto essendo implicati direttamente nello sviluppo di questo database.

Compilazione di Nebula

Visto che i download binari di Nebula continuano a non essere accessibili per via del refactoring, l'unica alternativa per usare i widget di questo fantastico progetto è quello di compilarli "manualmente". Per compilare i widget occorre avere CVS (per il dowload del codice), Maven per la compilazione e poi un po' di pazienza (tutto sommato il build è veloce).
I passi da seguire sono i seguenti:
  • creare una cartella che conterrà tutto il progetto;
  • effettuare il login anonimo al server CVS
cvs -d :pserver:anonymous@dev.eclipse.org:/cvsroot/technology login

  • scaricare l'albero dei sorgenti e dei progetti di Nebula:
cvs  -d ':pserver:anonymous@dev.eclipse.org:/cvsroot/technology' co org.eclipse.swt.nebula

  • e infine compilare i progetti org.eclipse.swt.nebula.nebula-incubation (ancora non stabili) e org.eclipse.swt.nebula.nebula-release (stabili): occorre entrare nella directory di ogni progetto e dare il comando mvn install. Ogni progetto avrà poi una cartella target che conterrà il jar finale.

giovedì 2 dicembre 2010

RCP: tray icon

Una applicazione RCP può facilmente visualizzare una icona integrata nel vassoio di sistema (tray). A tale icona può poi essere associato un menu' contestuale e delle relative azioni.
Per aggiungere una icona tray ad una applicazione RCP i passi da seguire sono fondamentalmente:
  1. ottenere un oggetto Tray dopo aver aperto la finestra principale, quindi dall'interno dell'ApplicationWorkbenchWindowAdvisor;
  2. si deve creare un TrayItem per ogni icona da visualizzare (tipicamente una sola);
  3. associare ad ogni item un listener per l'evento MenuDetect (click destro/menu' contestuale) e creare nel modo abituale il menu con le relative azioni e contributi;
  4. associare ad ogni item un listener per l'evento DefautlSelection per minimizzare/massimizzare la finestra principale (o un'altra parte dell'applicazione) quando l'utente fa click (sinistro) sull'icona nel tray.
  5. Il codice seguente mostra come configurare il tray in modo semplice, associando al menu' contestuale le azioni About e Exit. Il metodo configureTray dovrebbe essere chiamato nel post-window-open.

   private void configureTray(){
    // get the workbench window
    final IWorkbenchWindow window = this.getWindowConfigurer().getWindow();
   
    // get the tray for the current running system
    Tray tray = window.getShell().getDisplay().getSystemTray();
   
    // the tray could be null if the system does not support it
    if( tray == null )
        return;
   
    // if here I've got a valid tray, create a tray item and configure it with an image
    TrayItem trayItem = new TrayItem( tray,  SWT.NONE );
    // set the icon
    ImageRegistry imgRegistry = Activator.getDefault().getImageRegistry();
    trayItem.setImage( imgRegistry.get( ... ) );
    // set the tooltip
    trayItem.setToolTipText("...");
   
   
    // add a menu listener on the tray element, so that it can
    // show the menu
    trayItem.addListener( SWT.MenuDetect, new Listener(){

        @Override
        public void handleEvent(Event event) {
        // create a new menu manager
        MenuManager manager = new MenuManager();
        // create the context menu
        Menu trayItemMenu = manager.createContextMenu( window.getShell() );
       
        // add entries to the menu
        manager.add( ActionFactory.ABOUT.create(window) );
        manager.add( ActionFactory.QUIT.create(window) );
       
        // the menu must be visible
        trayItemMenu.setVisible( true );       
        }
       
    });
   
   
   
    // add a listener to the tray icon, so that when the user double clicks
    // on the item the window is popped up again and made visible
    trayItem.addListener( SWT.DefaultSelection, new Listener(){

        @Override
        public void handleEvent(Event event) {
        Shell windowShell = window.getShell();
        if( ! windowShell.isVisible() )
            windowShell.setVisible(true);
       
        windowShell.setMinimized(false);
       
           
        }
       
    });
    }

martedì 30 novembre 2010

SWT CLabel

Come è noto SWT è una libreria che utilizza un approccio totalmente differente rispetto a Swing: in SWT si cerca di utilizzare quanto prima i componenti messi a disposizione del sistema operativo, costruendo poi su questi componenti piu' complessi. Questa differenza è evidente ad esempio se si considera un widget tanto semplice quanto utile: le etichette (label). In Swing una label può essere dotata di una propria immagine, mentre in SWT una Label può avere un testo o una immagine, ma non entrambi. La ragione di ciò è nelle limitazioni del sistema operativo stesso e nell'uso pesante che SWT fa dei componenti nativi. Per ovviare all'inconveniente, SWT utilizza una serie di widget custom i cui nomi tipicamente iniziano con una 'C' (per evitare conflitti nello spazio dei nomi), come ad esempio CLabel. Osservando la gerarchia di una CLabel si nota come questa di fatto erediti da un Canvas, ossia da una zona che può essere disegnata arbitrariamente, mentre la piu' povera Label eredita direttamente da Control, e quindi non prevede personalizzazioni particolari. La differenza di gerarchia fra i due componenti evidenzia l'approccio SWT: Label sfrutta tutte e sole le caratteristiche del sistema operativo, mentre CLabel disegna da se i componenti che servono e li dispone nel modo che ritiene piu' opportuno (immagine a fianco del testo).

venerdì 26 novembre 2010

L'importanza delle convenzioni dei nomi

E' innegabile il valore delle convenzioni applicate ad un progetto software di qualsiasi natura. Le convensioni aumentano la leggibilità delle risorse (tipicamente del codice), semplificano il refactoring, la manutenzione e in generale pongono le basi per l'automazione.
In un progetto database le convenzioni sul nome delle tabelle, procedure, trigger e delle colonne è ancora piu' importante: il database può facilmente crescere a dismisura, arrivando ad avere relazioni intricate fra oggetti diversi. Tuttavia occorre ricordarsi che un DBMS è differente da un sistema OOP, e quindi le convenzioni da usare su uno possono essere differenti e portare a differenti risultati rispetto a quelle usate nell'altro. Si prendano ad esempio i nomi delle colonne: in un sistema OOP i nomi degli attributi degli oggetti potrebbero assumere la stessa convenzione al fine di automatizzare l'accesso alle proprietà stesse, complice anche l'ereditarietà. In altre parole, avendo due oggetti come Person e Department ciascuno dotato di un codice identificativo (ID) e di una descrizione (description) si potrebbe pensare di dotare i due oggetti delle stesse proprietà getID/setID e getDescription/setDescription. Facile, comprensibile, omogeno. 
Nel caso di un database con due tabelle che implementino gli stessi concetti si potrebbe pensare a creare due tabelle con le stesse convenzioni sui nomi: person(ID integer, description text) e department(ID integer, description text). La cosa può a prima vista sembrare naturale, e per molte applicazioni lo è. Tuttavia quando si tenta di mappare i due schemi uno sopra all'altro, si scopre che la convenzione sul nome delle colonne appena scelto produce uno spreco di codice. Si immagini infatti di voler esprimere la relazione fra un reparto e la lista delle persone che vi afferiscono: l'oggetto Department dovrà avere una collection di tipo Person, e nel database ci sarà una tabella di join fra le due di cui sopra. Il problema è che nel join i dati di una tabella devono essere riscritti per non andare in conflitto (ambiguità) con quelli dell'altra tabella, e quindi si potrà avere un solo ID e un solo description nell'output della query, mentre l'altro diventerà ad esempio person_ID e person_description. E perché questo semplice aliasing porterebbe alla scrittura di maggiore codice? Perché i DAO usati per caricare un reparto e una persona fanno affidamento a colonne che si chiamano ID e description, che sono venute a mancare nel join. Come si può risolvere questa problematica? Ci sono tre metodi principali:
  1. si scrive un DAO per il caricamento diretto di un Person, di un Department e di un join fra i due. Ovviamente questa soluzione non è molto pratica;
  2. si creano delle viste su tutte le tabelle in modo che i dati ritornati siano sempre person_ID, person_description, department_ID, department_description sia per le query "semplici" che per i join. Ma questo richiede la scrittura di codice aggiuntivo e non molto utile;
  3. si usa una convenzione differente nei nomi delle colonne: ogni colonna viene nominata con un prefisso che corrisponde al nome della tabella: person( personID integer, personDescription text ) e department( departmentID integer, departmentDescription text ). Così facendo i DAO vengono scritti sempre per colonne che sono univoche nel sistema, anche quando le tabelle vengono messe in join.
L'ultima soluzione, seppur appaia la piu' farraginosa, è quella che porta alla scrittura del minor codice possibile e soprattuto garantisce che se un DAO funziona per la tabella singola funzionerà senza variazione alcuna anche per tabelle in join.

giovedì 25 novembre 2010

Università e professionisti... alcune riflessioni (parte 2)

Dopo una settimana dall'articolo di giornale che mi aveva spinto a scrivere alcune considerazioni sul rapporto fra le Università e il mondo dei professionisti mi sono imbattuto in un altro articolo, questa volta sul Resto del Carlino di Modena, che tratta le proteste contro la "riforma Gelmini" presso il cinema teatro Raffaello.
L'articolo inizia evidenziando come ci sia l'assenza di 110 mila tecnici che le imprese in Italia non trovano, fatto questo che porta ad una semplice tesi: occorre maggiore supporto alla formazione di tali tecnici, ossia maggiore supporto alle scuole e agli atenei, asilo nido dove i giovani talenti possono crescere. Tesi troppo semplice, troppo banale. Anzitutto per formare dei buoni tecnici occorrono dei buoni insegnanti, e ricadiamo nel discorso che ho già affrontato sul collegamento docenti-mondo del lavoro. Dopotutto, quanti docenti si prendono un periodo sabbatico per migliorare e aumentare le proprie competenze? Quanti docenti prendono delle certificazioni? Ora voglio stendere una tesi piu' banale ancora di quella dell'articolo che ho letto: se adesso ci si lamenta per il mancato supporto alla didattica, cosa si è fatto di significativo nella didattica fino ad ora? Ovvero, se mancano 110000 tecnici qualificati significa che le persone formate fino a ieri non sono state abbastanza formate per far fronte alle reali necessità del mondo del lavoro. Quindi non può essere la riforma tanto protestata a creare questo ammanco, semplicemente perché l'ammanco esisteva già da prima. Sicuramente un taglio netto ai supporti non può diminuire la carenza di tecnici, anzi la potrà anche aumentare, ma, continuando sulla linea della "tesi-semplice", il supporto fornito fino ad ora a cosa è servito? Evidente a poco....
E per quale motivo i tecnici non possono essere formati direttamente sul campo? Perché al taglio delle ore di laboratorio non si fa fronte con collaborazioni nel mondo professionale? Ah già, i professionisti non vogliono perché è periodo di crisi...

Ma non è che forse ci si sta lamentando troppo? Non è che in realtà quello che si vuole è un pezzo di carta firmato e timbrato che dia, a tavolino, una esperienza e delle capacità che comunque non si sarebbero acquisite nemmeno con maggior supporto? Non è che è ora di rimboccarsi le maniche e dimostrare che si è in grado di formare realmente dei tecnici, e chiedere a fatto compiuto maggiore supporto? Mi sembra si stia discutendo attorno ad un paradosso: dammi il supporto ($) e ti darò i tecnici. Prima però dimostrami che sei in grado di tirarne fuori almeno uno ben formato, e poi sarò ben lieto di darti il supporto ($) per tirarne fuori 110000.

Ma forse sono sempre io che sono troppo polemico e malizioso...
E a proposito di polemica: complimenti a tutti quegli acculturati che hanno imbrattato la città con uova. Ma forse loro fanno parte dei 110000 che non hanno avuto formazione, e con essa educazione.

RCP: aggiunta della log view ad una applicazione

Grazie alla modularità di Eclipse (e OSGi) è veramente semplice aggiungere una vista di "log" ad una applicazione RCP.
Come prima cosa occorre aggiungere alla applicazione la dipendenza del plugin org.eclipse.ui.views.log.
Successivamente occorre aggiungere il comando al proprio set di menu (o pulsanti o toolbar):
  • selezionare l'elemento dove aggiungere il comando (ad esempio il menu') e aggiungere un nuovo comando con click destro -> New -> Command
  • specificare le informazioni del comando con l'id rappresentato in figura
  •  infine aggiungere al comando un parametro (click destro, New -> Parameter) e specificare l'id della vista da aprire come riportato in figura
 A questo punto l'applicazione visualizzerà il nuovo comando e aprirà la vista dei log dell'applicazione. Il sistema di loggin può essere usato in ogni punto dell'applicazione con il seguente frammento di codice:

ILog logger = Activator.getDefault().getLog();
StringBuffer buffer = new StringBuffer( 100 );
//.....
IStatus status = new Status( IStatus.INFO, 
                             Activator.PLUGIN_ID, buffer.toString() );
logger.log(status);

Nuovi supporti tecnologici per Gigetto

Con l'apertura della nuova stazione di Baggiovara, che sostituisce quella della Bertola, anche le stazioni limitrofe del famoso trasporto ferroviario Modena-Sassuolo (Gigetto) hanno subito un restyling. In particolare la stazione di Casinalbo è ora dotata (o nuovamente dotata) di due nuovi strumenti altamente tecnologici di ausilio ai passeggeri:
  • un potente faro luminoso che sovrasta la zona delle biciclette a noleggio. Chissà, forse qualcuno si è accorto che la stazione era rimasta al buio per troppo tempo ed era quindi diventata facile preda di vandali e maleducati!
  • un nuovo display luminoso che segnala ora, treni in arrivo e relativo ritardo. Peccato che tale tabellone continui a segnare un orario sbagliato e quindi informi in modo totalmente sbagliato gli utenti in viaggio. Avevo già descritto questi pannelli luminosi, che visti in azione mi ricordano tanto la mia prima applet Java che faceva scorrere una scritta sullo schermo spostandola ad intervalli di 1 secondo. Tale tabellone fa la stessa cosa, e non è per niente sincronizzato con i treni in transito o con una delle stazioni di scambio.
Insomma, invece che investire correttamente i soldi in sistemi che funzionano, sembra che il comune (o le ferrovie) intendano spendere i soldi in stupidi giocattoli che non sono di scarso ausilio per i viaggiatori, ma che rimangono facile preda dei vandali.

E come volevasi dimostrare, dopo appena una settimana il pannello luminoso mostra una evidente crepa causata, certamente, da una sassata. E come se non bastasse continua a segnare l'orario sbagliato...

Eclipse RCP Preferences: memorizzare informazioni di login in uno splash screen interattivo

Eclipse RCP mette a disposizione dello sviluppatore un sistema complesso di preferenze che possono essere usate per salvare, ad esempio, informazioni di login. Le preferenze di Eclipse possono essere di due tipi fondamentali:
  • in chiaro
  • cifrate
Le ultime vengono salvate con un meccanismo a keyring e i plugin *.security forniscono tutti gli strumenti necessari al loro utilizzo. Ad esempio org.eclipse.equinox.security.ui permette la memorizzazione nel portachiavi con tanto di dialog per la configurazione del portachiavi stesso. 
Si pone tuttavia un problema per l'utilizzo delle preferenze cifrate: il workspace deve esistere ed essere in esecuzione. Ciò significa che lo sviluppatore ha piu' lavoro da svolgere nel caso in cui le preferenze siano usate da applicazioni RCP headless o, come nel mio caso, da splash screen interattivi (che agiscono prima del workspace stesso).
Qui sotto riporto un esempio di utilizzo di un motore di salvataggio/caricamento dei dati dell'ultimo utente che ha effettuato il login nell'applicazione. In questo caso occorrerebbe salvare i dati in modo cifrato, ma essendo il mio un caso di splash screen interattivo, e trattandosi di dati comunque non fondamentali (poiché nella mia applicazione esistono altri meccanismi di sicurezza), ho deciso di usare per semplicità le preferenze in testo semplice. Da notare che il motore qui sotto proposto estrae ed inserisce i dati in un oggetto User che funge da wrapper per la business logic dietro all'utente stesso.


public class UserPreferencesStorage {

    private String PREFERENCES_USER_ROOT_NODE = "saved-user";
    private String PREFERENCES_USERNAME_NODE  = "username";
    private String PREFERENCES_PASSWORD_NODE  = "password";
    private String PREFERENCES_USER_PK_NODE   = "userpk";

 
    /**
     * Saves the preferences of the provided user.
     * @param user the user that must contain the password and the username to store
     * @return true if the storage has been done
     */
    public boolean saveUserPreferences( User user ) throws BackingStoreException{
 try{
     // get the normal preferences and the scope for this plugin
     IEclipsePreferences preferences = new ConfigurationScope().getNode( Activator.PLUGIN_ID );
     // now get the main node for the configuration storage
     Preferences savedPreferences = preferences.node(PREFERENCES_USER_ROOT_NODE);

     // now store the username and the password
     savedPreferences.put( PREFERENCES_USERNAME_NODE, user.getUsername() ); 
     savedPreferences.put( PREFERENCES_PASSWORD_NODE, user.getPassword() ); 
     savedPreferences.put( PREFERENCES_USER_PK_NODE, user.getPrimaryKey() + "" );  
     
     // flush the storage to ensure everything is written to disk
     preferences.flush();
     
     // all done
     return true;
     
 }catch( BackingStoreException se ){
     // log the exception and do nothing, cannot save
     IStatus status = new Status( IStatus.ERROR,     // severity
      Activator.PLUGIN_ID,      // the id of the application/plug-ing
      "Errore nel salvataggio delle preferenze di login utente",  // message
      se
     );

     throw se;
 }

    }
    
    
    /**
     * Loads a user from the prefences store.
     * @return the user loaded or null
     */
    public User loadUser() throws StorageException{
 // get the normal preferences and the scope for this plugin
 IEclipsePreferences preferences = new ConfigurationScope().getNode( Activator.PLUGIN_ID );
 // now get the main node for the configuration storage
 Preferences savedPreferences = preferences.node(PREFERENCES_USER_ROOT_NODE);
 
 // get the values from the storage
 String username  = savedPreferences.get(PREFERENCES_USERNAME_NODE, "");
 String password  = savedPreferences.get(PREFERENCES_PASSWORD_NODE, "");
 String primaryKey  = savedPreferences.get(PREFERENCES_USER_PK_NODE, "0");
 
 
 // create the user with such values
 User user = new User( Integer.parseInt(primaryKey), username, password );
 
 // all done
 return user;
    }
}

giovedì 18 novembre 2010

Università e professionisti...alcune considerazioni

Disclaimer: come tutti i messaggi qui pubblicati, anche questo rappresenta solamente i miei pensieri e le mie riflessioni, a volte dure, spesso criticabili,
ma basate sulla mia esperienza diretta.

Durante una pausa fra le lezioni di informatica, ho sfogliato il giornale (Corriere della Sera - 13/11/2010) e la mia attenzione è stata attirata da un articolo di Isidoro Trovato che parla di come la Autorità di Vigilanza sui lavori pubblici possa far entrare l'Università nelle gare di appalto a fianco dei professionisti. In poche parole, questo significa che i docenti, i ricercatori e tutto il personale strutturato delle università potrebbe partecipare a gare di appalto pubbliche andando a minare pericolosamente, almeno così sostiene Gianni Rolando (presidente del Consiglio Nazionale degli Ingegneri), le posizioni oggi appannaggio esclusivo dei professionisti. Essendo io ingegnere, ed avendo lavorato per anni all'università, dovrei quindi trovarmi in accordo con Rolando, e invece ritengo che lo sbarramento di questa proposta sia semplicemente ridicolo.

Anzitutto ritengo che le università, in generale, siano troppo slegate dal mondo lavorativo senza quindi avere idea dei problemi che tale mondo sta affrontando. Ci si trova quindi nella condizione nella quale le università lavorano a progetti estremamente innovativi il piu' delle volte spinti non da problemi del mondo lavorativo ma da interessi puramente di ricerca. E per fortuna: sono un forte sostenitore dell'iniziativa individuale. Tuttavia ci si trova anche nella condizione ove, per dimostrare che il proprio lavoro scientifico è valido, si debbano trovare i problemi che la propria ricerca risolve. Ma questo è un modo sbagliato di ragionare: è meglio partire dal problema e trovare la soluzione, piuttosto che avere l'intuizione e cercare  il problema che risolve (o il contesto ove collocarla). Così facendo infatti si rischia solo di produrre soluzioni per un mercato non ancora pronto, e infatti molto spesso i risultati della ricerca scientifica vengono applicati diversi anni dopo al mondo lavorativo. E non si tratta di tempi canonici per la stabilizzazione della soluzione, ma semplicemente di tempi nei quali il mercato non è recettivo poiché occupato a risolvere altri problemi che le università reputano banali e quindi non prendono in considerazione.
Ulteriore ostacolo al dialogo fra il mondo del lavoro e delle università sono, molto spesso, i professori stessi: ogni professore ha un suo ambito di ricerca/interesse e tenta di forzare tale ambito ai suoi studenti, stabilendo spesso anche confini ben marcati che separino la propria ricerca da quella dei colleghi. Ci si ritrova quindi con studenti che svolgono attività di ricerca in un ambito (es. database) senza mettere il becco in altri ambiti (es. sistemi operativi) per volontà dei loro professori. I professori dovrebbero invece mettere a disposizione la loro esperienza affinché gli studenti, preso in carico un problema concreto del mondo del lavoro, possano affrontarlo e risolverlo agevolmente. E in questo modo si avrebbero diversi vantaggi:
  • le aziende acquisterebbero molta fiducia nelle università;
  • gli studenti acquisterebbero fiducia nelle proprie capacità (meglio 10 successi piccoli ma certi che un grande successo non applicabile al mercato);
  • gli studenti troverebbero da lavorare piu' facilmente, avendo maturato una esperienza diretta nel mondo del lavoro;
  • i professori resterebbero automaticamente aggiornati sulle problematiche del mercato.
Attualmente gli atenei informatici, come quello che io ho frequentato, hanno una grossa possibilità per dimostrare le proprie competenze e capacità: l'OpenSource. L'OpenSource è un qualcosa che le università temono molto per due motivi principalmente:
  • rilasciare un progetto come OpenSource significa dare al mondo (e quindi ad altre università) i propri sforzi di ricerca;
  • un progetto OpenSource potrebbe vedere la partecipazione di altri professionisti o università che mostrino una superiorità schiacciante in tale ambito.
Spaventati quindi dal vedersi rubare i propri sforzi o dal fare figuracce planetarie, le università preferiscono rimanere tranquillamente nascoste dietro qualche deliverable di qualche progetto strano che non permette la visione del codice e dei prototipi prodotti. Ovviamente non tutti gli atenei sono così, e sempre di piu' si evidenziano facoltà che abbracciano lo spirito OpenSource e riescono ad affermarsi nel panorama accademico e professionale. Tuttavia in Italia la paura è ancora alta, almeno questa è l'impressione che ho avuto girando per i vari atenei. Va comunque notato che, figuraccia o meno, il confronto è sempre un possibile spunto di crescita, e che esistono licenze e strumenti per tutelare il proprio lavoro. 

Torniamo ora all'argomento di discussione specifico: il possibile contrasto fra i professionisti e gli accademici. Di cosa dovrebbero avere paura i professionisti? Dopotutto, la loro professionalità non dovrebbe essere messa in discussione da un qualche professore o studente che si presenta sul mercato: quello che conta, che si tratti di professore, studente, o libero professionista, è l'esperienza e l'abilità, due qualità che non possono essere conquistate stando  solo dietro ad una cattedra o solo nel mondo del lavoro. Io, da ingegnere, non temo il confronto onesto con un altro ingegnere, e poco mi importa sia un docente, uno studente o un professionista: per quello che riguarda il confronto è solo un mio "sfidante". Quali scenari dunque si prospettano e perché spaventano tanto i professionisti? Io riesco ad individuare queste possiblità:
  • l'università inonda il mercato con personale a basso costo e alta qualità: il prezzo dei professionisti è costretto ad abbassarsi di conseguenza per poter reggere la concorrenza, e questo è un bene per chi richiede il servizio;
  • l'università inonda il mercato con personale a basso costo e bassa qualità: è evidente che tale personale non sarà in grado di fornire un servizio alla pari di quello di un professionista esperto, e quindi tale categoria non ha nulla da temere da questo confronto. Va inoltre notato che un professionista non può tutelarsi da questa problematica che non è infatti legata al mondo accademico.
  • l'università inonda il mercato con personale ad alto costo e di alta qualità: in questo caso i professionisti occupano la seconda posizione nelle scelte mission critical, ma il loro costo inferiore li rende una scelta papabile per tutti gli altri casi.
  • l'università inonda il mercato con personale a basso costo, bassa qualità da affiancare a personale professionale: in questo caso si assiste alla formazione di un nuovo professionista a "discapito" di un altro professionista. Ma occorre ricordare che quest'ultimo sarà stato a sua volta formato (si spera) a "discapito" di un docente universitario...
Francamente penso che una persona competente e preparata non debba temere il confronto con un'altra persona competente e preparata, poiché in un confronto onesto è giusto che "vinca" la persona migliore. Quindi impedire il confronto a priori è una scelta sbagliata e, soprattutto, che da una impressione sbagliata sulla categoria dei professionisti, che appaiono ora ai miei occhi come un branco di baroni che vogliono proteggere il proprio feudo. E non ho usato il termine "baroni" a caso: ritengo che dall'altro lato esista un altro gruppo di baroni impegnati a proteggere la propria scrivania. Ebbene se l'apertura al mondo del lavoro destabilizzera il loro regno, a maggior ragione ben venga l'iniziativa di cui si sta discutendo. DI baroni devono governare un impero proporzionale alle proprie capacità.

Anni fa una protesta analoga venne fatta dal lato accademico, spaventato dal possibile ingresso di industrie e professionisti nel loro "regno". E anche in quella occasione io evidenziai i miei dubbi su tanta rigidità: dopotutto aprire l'università all'industria significa, come già detto sopra, aprire la strada a nuovi posti di lavoro. Rolando, che a difesa della sua tesi sottolinea il periodo di crisi del mercato, dovrebbe tenere in considerazione anche questo fattore: dare spazio di lavoro ai giovani significa aumentare l'occupazione, non aumentare la disoccupazione dei professionisti. E quindi mi viene solo da ribadire come ognuno dovrebbe smettere di guardare al prioprio orticello, ma assumere una visione piu' ampia della questione.

Come riflessione conclusiva mi viene in mente che, se entrambe le parti, in tempi e con motivazioni diverse, non vogliono mischiarsi, forse il vero problema non è tanto sulle competenze, sulle capacità, sulla professionalità, ma sulla mancanza di un confronto onesto che tuteli entrambi i lati affinché solo chi è meritevole possa avere successo.

Ma forse sono io che non ho ben capito il reale problema....

    martedì 16 novembre 2010

    SWT Virtual Table: problemi di sorting

    Le tablle Virtual in SWT sono sicuramente un componente tanto potente quanto fragile, lo dimostrano due problemi che ho incontrato nello sviluppo di una applicazione che mi hanno fatto deistere dal continuare ad usarle, almeno per il momento. Il mio ovviamente si tratta di un caso particolare: non sempre è possibile rinunciare alle tablle virtual a favore di quelle normali!
    Il primo problema riguarda l'update degli indici: sembra ci sia un bug che richiede l'update di indici fuori dallo schermo, con conseguente caricamento dei dati necessari, e si può facilmente intuire come in una applicazione database oriented (come la mia) questo sia un consumo eccessivo di risorse che non giustifica l'uso di SWT.VIRTUAL.
    Il secondo problema riguarda il sorting effettuato tramite comparators: se la tabella viene gestita come Virtual (anche se in effetti viene usata come tabella normale), il sistema potrebbe passare un elemento null al metodo di comparazione del Comparator. Il problema non è tanto difendersi da un oggetto null in ingresso, cosa sicuramente banale, ma il fatto che una comparazione fra due entità di cui una null non può essere fatta, poiché questo impedisce la determinazione del corretto indice di inserimento nella table viewer.

    sabato 13 novembre 2010

    OpenSolaris promo t-shirt

    Qualche giorno fa ho comprato una delle magliette promozionali di OpenSolaris. Seppur vero che il destino di OpenSolaris è ormai irrimediabilmente segnato, è altrettanto vero che le magliette promozionali erano dei veri e propri pezzi d'arte!

    venerdì 12 novembre 2010

    Eclipse Labs

    Esiste un progetto, denominato Eclipse Labs, che permette a sviluppatori di progetti Eclipse-related di ottenere un maggiore riconoscimento dei loro sforzi. Gli Eclipse Labs si appoggiano a Google Code, e quindi sono un sistema di hosting dei progetti via SVN/Mercurial (vivamente consigliato il secondo, anche se era preferibile Git) su server Google. I progetti che entrano in Eclipse Labs non sono a tutti gli effetti dei progetti della Eclipse Community, ad ogni è possibile dare al proprio progetto un maggior rilievo nell'ecosistema Eclipse mantenendo all'interno degli Eclipse Labs invece che su un altro sistema di hosting non correlato ad Eclipse.

    mercoledì 10 novembre 2010

    Nebula download corrotto

    E' ormai da un paio di settimane che il sito del progetto Nebula, una serie di widget addizionali basati su SWT, non permette il download dei jar in fase di incubazione riportando uno spaventoso messaggio circa la corruzione di tutti i build del progetto stesso.



    Quello che c'è dietro a questo messaggio di errore viene spiegato in un messaggio sul forum ufficiale di Nebula: un build server è andato in crash, causando l'errore nella ricostruzione dei pacchetti binari. Tutto questo succede mentre il progetto sta migrando la propria storia su un altro sistema, ecco quindi che si è preferito terminare la migrazione piuttosto che spendere tempo nella ricostruzione degli archivi legacy.

    RCP: ottenere le informazioni di plugin a run-time (immagini e versione del prodotto)

    Capita spesso di dover accedere a delle informazioni di definizione di un plugin RCP a run-time. Gli esempi piu' ricorrenti sono le immagini associate ad una applicazione RCP e i dati del bundle che definisce l'applicazione stessa (ad esempio il numero di versione). RCP mette a disposizione una serie di facilities per ottenere tali informazioni.
    Il primo passo consiste nell'ottenere una istanza di IProduct, dal quale si può estrarre il defining bundle e da questo la lista delle immagini configurate nel file plugin.xml. Tale lista è in realtà una stringa unica con tutte le immagini alle varie dimensioni (16x16, 32x32, 48x48, ecc.) dalla quale occorre estrarre la lista effettiva dei percorsi (relativi al bundle) delle immagini. Avendo ottenuto la lista delle immagini è possibile inserirle nella shell corrente (ad esempio uno splash screen). Il seguente blocco di codice riassume i passi da fare:

            // get the product for the running instance
            IProduct product = Platform.getProduct();
           
            // get my shell
            Shell myShell = ...
           
            // the product can be null if the running instance is launched
            // as an eclipse application (e.g., during the development)
            if( product == null )
                return;
           
            // get the bundle symbolic name
            String bundleID = product.getDefiningBundle().getSymbolicName();
            // get the array of the application icons (defined thru the product)
            // the method will return a single string with the list of images
            // used at different sizes (16x16, 32x32, 48x48 and so on). The list is
            // comma separated, so I need to extract every single item.
            String imagePaths = product.getProperty( 
                                            IProductConstants.WINDOW_IMAGES );
            List imagePathList = new LinkedList();
            StringTokenizer commaTokenizer = new StringTokenizer(imagePaths, ",");
            while( commaTokenizer.hasMoreTokens() )
            imagePathList.add( commaTokenizer.nextToken() );
           
            // now that I've got the list of image paths (separated) 
            // I can create every
            // single image using an ImageDescriptor
            Image[] windowImages = new Image[ imagePathList.size() ];
            for( int i = 0; i < imagePathList.size(); i++ ){
               ImageDescriptor currentDescriptor =                    
                   AbstractUIPlugin.imageDescriptorFromPlugin(    bundleID, 
                                                    imagePathList.get(i) );
                   windowImages[ i ] = currentDescriptor.createImage();
            }
           
            // now set the images for this window
            myShell.setImages( windowImages );




    Analogamente, se si volessero ottenere informazioni circa la versione e il nome dell'applicativo si puo' usare il seguente pezzo di codice:


    Bundle definingBundle = product.getDefiningBundle();
    Label valueLabel = new Label(  definingBundle.getSymbolicName() );
    Label versionLabel = new Label( definingBundle.getVersion().toString() );

    o se si vuole cambiare il titolo della finestra principale del workspace affinché rifletta tali informazioni è sufficiente, nel metodo ApplicationWorkbenchWindowAdvisor.preWindowOpen() il seguente blocco di codice:

       // get the window configurer object
        IWorkbenchWindowConfigurer configurer = this.getWindowConfigurer();

       
       
        // set the title of the window
        StringBuffer title = new StringBuffer( 100 );
        title.append( "My App" );    // the fixed part of the title
       
        // get the information from the product
        IProduct product = Platform.getProduct();
        if( product == null )
            title.append( " [Eclipse Application - Development]" );
        else{
            title.append( " [RCP Product -" );
            title.append( product.getName() );
            title.append( " ~~ " );
           
            // get some information from the bundle
            Bundle definingBundle = product.getDefiningBundle();
            title.append(" ID: " );
            title.append( definingBundle.getSymbolicName() );
            title.append(" ~~ Ver.: " );
            title.append( definingBundle.getVersion() );
        }
       
        // set the real title
        configurer.setTitle( title.toString() );

    martedì 9 novembre 2010

    KMail: migrare le impostazioni delle cartelle

    La mia posta elettronica vanta un numero sterminato di cartelle e di filtri che uso per gestire un altrettanto vasto numero di iscrizioni a mailing lists. Una cosa molto gradevole di KMail è che è un client di posta furbo: quando si migra da un computer ad un altro o da una versione all'altra, spostare le cartelle di posta e i file di configurazione è sufficiente per migrare l'intera posta comprensiva di account, regole e filtri.
    Tuttavia KMail non è così furbo da aggiustare anche gli account associati alle cartelle di posta, e quindi a seguito della migrazione un nuovo messaggio creato dentro ad una qualsiasi cartella viene editato con l'account di default. Ovviamente è possibile sistemare manualmente il problema, ma nel mio caso questa soluzione mi avrebbe portato via troppo tempo. 
    Ho quindi deciso di studiare come KMail associa le identità degli account alle cartelle e di creare un banale programma che, in modo molto goffo, aggiusti le cose per me.
    KMail memorizza le identità degli account di posta nel file emailidentities, e ogni identità in tale file contiene un valore identificativo univoco come proprietà dal nome uoid. Ogni identità ha quindi una linea del tipo
    uoid = 1234556
    con il valore numerico che cambia a seconda dell'identità. Il primo passo è quindi quello di recuperare lo uoid associato ad un account di posta (nel mio caso non ho account duplicati su varie identità, altrimenti il test dovrebbe essere piu' complesso).
    A questo punto, nel file di configurazione principale di KMail, kmailrc, occorre analizzare ogni sezione di ogni cartella, e infatti in essa si troverà una linea che indica se occorre usare l'identità di default (UseDefaultIdentity = true) e una linea che indica l'identità da usare al suo posto (Identity = uoid). Quindi individuata la sezione corrispondente alla cartella che si vuole manipolare, è sufficiente inserire le due righe di cui sopra specificando l'identità da usare e facendo in modo che l'identità di default risulti disabilitata per tale cartella.
    Si può fare ancora di piu': nel mio caso le cartelle corrispondenti a mailing list sono, con grande fantasia, tutte raggruppate sotto un'unica cartella dal nome Mailing List. Ebbene, kmailrc contiene nel nome della sezione il percorso completo della cartella, incluso il nome del padre della cartella. Quindi nel mio caso, le cartelle da manipolare non devono essere specificate manualmente ma possono essere ricavate automaticamente usando il prefisso Mailing List.
    Di seguito presento lo script Perl che realizza quanto descritto sopra. Il suo utilizzo, da linea di comando, prevede il passaggio di due argomenti: il percorso al file di configurazione principale kmailrc e un indirizzo di posta da usare per ottenere l'identità dell'account. L'output è un file di configurazione differente, denominato kmailrc.new da sostituire, previo controllo, a quello originale.


    #!/usr/bin/perl
    
    open( KMAILRC, "<$ARGV[0]" )       || die("\nCannot open the specified kamilrc file\n$!\n");
    open( EMAILIDENTITIES, "<$ARGV[1]")|| die("\nCannot open the email identities file\n$!\n");
    open( NEWCONFIG, ">kmailrc.new" )  || die("\nCannot open the new configuration file\n$!\n");
    
    
    $emailAddress = $ARGV[2];
    $IDENTITY = undef();
    
    # first step: find the identity id
    while( ($line = ) && (! defined($IDENTITY) ) ){
        chomp( $line );
        if( $line =~ /$emailAddress/ ) {
     print "\nFound e-mail addrress $line";
     while( ($line = ) && (! defined( $IDENTITY ) ) ){
         if( $line =~ /uoid/ ){
      $line =~ s/(uoid=)(.*)/$2/;
      $IDENTITY = $line;
      print "\nFound an identity uoid = $IDENTITY\n";
      
         }
     }
        }
    }
    
    
    
    
    
    
    
    
    
    
    
    $FolderKey = $ARGV[3];
    
    while( $line =  ){
        chomp( $line );
    
        if( $line =~ /\[Folder-\.$FolderKey/ ){
     chomp( $line );
     print NEWCONFIG $line , "\n";
     print "\nFound folder $line\n";
     $doneThisFolder = "";
    
     while( ($innerLine = ) && (! $doneThisFolder ) ){
         chomp( $innerLine );
    
         if ( $innerLine =~ /UseDefaultIdentity/ ){
      print NEWCONFIG "UseDefaultIdentity=false\n";
      print NEWCONFIG "Identity=$IDENTITY\n";
      $doneThisFolder = "true";
         }
         elsif( $innerLine =~ /Identity/ ){
      # print nothing, it has already be printed in the 
      # UseDefaultIdentity identity
         }
         else{
      print NEWCONFIG $innerLine , "\n";
         }
         
     }
    
        }
        else{
     print NEWCONFIG $line , "\n";
        }
        
    }

    lunedì 8 novembre 2010

    Programma PGDay 2010

    E' disponibile il programma del PGDay 2010.
    Come si evince dal programma stesso, il PGDay di quest'anno avrà un elevato contenuto tecnico e i partecipanti avranno l'occasione di essere a diretto contatto con alcune delle principali figure dello sviluppo PostgreSQL nel mondo.

    lunedì 18 ottobre 2010

    Nuove community dopo l'acquisizione da parte di Oracle di Sun

    E c'è ancora chi non si preoccupa della politica del software! Mi fanno ridere quei guru (presunti) dei database che mesi fa scrivevano di non avere alcun interesse a seguire la faccenda MySQL/PostgreSQL/Oracle, mostrando una pesante incompetenza nel non voler comprendere come il software oggi giorno non sia solo una manciata di file sorgenti ma un vero e proprio sistema politico.
    ad ogni modo, vista la reluttanza di Oracle nel fornire uno straccio di supporto alle comunità OpenSource che alla fine le hanno donato, tramite Sun, ottimi prodotti, molte community si stanno organizzando, ri-organizzando e preparando ad uno sviluppo "parallelo" se non proprio a dei veri e propri fork dei progetti Sun/Oracle.
    Due in particolare vanno citate:
    All of Oracle’s efforts on binary distributions of Solaris technology
    will be focused on Solaris 11. We will not release any other binary
    distributions, such as nightly or bi-weekly builds of Solaris
    binaries, or an OpenSolaris 2010.05 or later distribution. We will
    determine a simple, cost-effective means of getting enterprise users
    of prior OpenSolaris binary releases to migrate to S11 Express.
    • LibreOffice è una comunità nata attorno al progetto OpenOffice con il chiaro intento di produrre una suite per ufficio libera, come lo è stata OpenOffice, senza però nessuna azienda che ne governi il ciclo di vita.
    Quindi dopo la fuga dei cervelli da Oracle, alcuni fra i progetti piu' importanti e visibili ereditati da Sun iniziano a vivere di vita propria per non dover rischiare di vederli morire per una strategia commerciale. 
    Oggi però, come sviluppatore Java, mi da da pensare il fatto che IBM voglia unirsi a Oracle per lo sviluppo di OpenJDK. Dentro di me penso all'eterna battaglia IBM vs Sun per il predominio di Java, battaglia che mi ha sempre fatto pendere dalla parte di IBM per gli ottimi prodotti realizzati (Eclipse, Jikes - compilatore e virtual machine, SWT), e penso che IBM potrebbe tranquillamente stare sulle proprie gambe nella battaglia per Java. Ma forse non è IBM ad avere paura, è Oracle (si veda la battaglia legale contro Google). E allora Oracle, spaventata, cosa fa? Cerca di accaparrarsi le simpatie degli sviluppatori che si fidano di IBM. E IBM accetta perché ha tutto l'interesse nel diventare partner del vendor Java. Almeno, questa potrebbe essere una interpretazione.

    giovedì 14 ottobre 2010

    PGDay 2010

    I lavori per il PGDay 2010, che si svolgerà a Roma prima della fine dell'anno, esattamente il 10 Dicembre, stanno procedendo a pieno ritmo. Sicuramente questa edizione sarà un'ulteriore successo italiano di PostgreSQL.
    Per maggiori informazioni si consulti il sito web ufficiale: www.pgday.ithttp://www.pgday.it

    SWT Widget Disposed & asyncExec

    Quando si eseguono operazioni time-consuming in una applicazione SWT occorre che queste siano eseguite fuori dal thread grafico, pena il freeze dell'interfaccia grafica. SWT mette a disposizione due metodi per l'esecuzione di task lunghi:
    • i job, simili a dei thread Java contengono il codice da eseguire secondo una politica di schedulazione (anche immediata)
    • gli sync/asyncExec, ossia l'esecuzione di un Runnable appena il thread grafico (UI Thread) può
    I due approcci, seppur simili,hanno un utilizzo piuttosto differente: i job vengono usati per tutto quello che è prevalentemente non-UI e che non aggiornerà l'interfaccia grafica, mentre gli xxxExec sono per quei processi che richiedono un aggiornamento costante dell'interfaccia grafica, ad esempio per riportare il progresso di una operazione.
    Il problema degli asyncExec è che potrebbero venire schedulati per l'esecuzione dopo il disposal di un widget, cosa che si verifica ad esempio quando l'applicazione viene chiusa. In questo caso viene generata una eccezione SWTException che indica appunto che era rimasto in coda un qualche Runnable per l'esecuzione ma che il thread UI non ha fatto in tempo ad eseguirlo prima della chiusura del widget:
     
    org.eclipse.swt.SWTException: Failed to execute runnable (org.eclipse.swt.SWTException: Widget is disposed) 
    

    Per ovviare al problema, ogni asyncExec deve testare la validità del widget sopra il quale opera prima di effettuare le modifiche. Si noti che non basta controllare la validità del widget prima della schedulazione del Runnable, poiché questo problema si verifica in base alla capacità del thread UI di schedulare i Runnable e questa non è nota a priori. I Control dispongono tutti di un metodo isDisposed(), che non è però esposto in un Viewer, perciò se si opera con questi ultimi occorre prima recuperare il Control interno (getControl()) e testare quest'ultimo.





     

    giovedì 7 ottobre 2010

    Ottenere informazioni su generics a run-time

    Un problema con il quale mi sono scontrato spesso è quello di rilevare i tipi parametrici usati in una dichiarazione generics a run-time. Senza spendere troppe parole, basti sapere che Java nel suo package reflect, prevede un super-tipo Type che corrisponde a tutti i tipi possibili Java, sia oggetti che primitivi. Una sottoclasse particolare di un tipo è un tipo parametrico, identificato da ParameterizedType. Tale tipo contiene la definizione di un tipo generico, con tanto di identificatore simbolico e classe usata per definire il tipo. Tuttavia la reflection normale di Java non è sufficiente per ottenere la definizione parametrica a run-time: occorre passare attraverso la definizione esplicita di Class con informazioni generiche. Ecco quindi che, da un qualunque tipo, è possibile risalire al primo parametro generics usato nella sua definizione con il seguente semplice metodo:

    public final Class getModelTypeOfThisDAO() {
       
            // get the superclass definition as a generic one
            ParameterizedType genericSuperClass = (ParameterizedType) this.getClass().getGenericSuperclass();
           
            // now get the first argument of the class
            return (Class) genericSuperClass.getActualTypeArguments()[0];
    }

    venerdì 1 ottobre 2010

    Kubuntu 10.04 & Network Management Disabled

    Una cosa piuttosto noiosa del network manager di KDE (KNetworkManager) è l'incapacità di ripristinare la funzionalità delle schede di rete, soprattutto quelle wireless, qualora il sistema venga sospeso o vada in stand-by.
    Quando il network manager continua, insistentemente, a riportare che il network management è disabilitato, la soluzione consiste nel:

    - editare il file /var/lib/NetworkManager/NetworkManager.state impostando lo stato del networking da disabilitato ad abilitato (NetworkingEnabled=true)
    - riavviare il servizio di network management con service network-manager restart

    Gnome 3, Kde 4, libertà e l'inversione di progetto

    Ho usato KDE fin dalla prima versione, e contemporaneamente Gnome da quello che fu' la prima versione stabile (October Gnome). Ho seguito attentamente l'evoluzione di entrambi gli ambienti, preferendo sempre KDE poiché piu' funzionale e completo. Ho studiato le librerie GTK+ (fondamento di Gnome) e quelle Qt (fondamento di KDE). Penso quindi di conoscere bene i due DE (Desktop Environment) per poterne fare una ulteriore analisi.

    Una delle principali accuse rivolte dalla comunità Gnome a quella KDE con l'uscita del ramo 4.x è stata la rivoluzione operata da quest'ultimo: basti pensare che perfino Linus Torvalds, estimatore del desktop del drago, lo ha abbandonato in favore di Gnome perché KDE 4 ha rivoluzionato, forse troppo rapidamente, il modo di fare desktop. Non esiste piu' infatti un concetto di desktop statico, con un pannello, delle icone, e dei menu', ma un sistema di applet (dette Plasmoids) che possono contenersi l'un l'altra. Allora l'applet che indica il livello di carica della batteria può essere messa sul desktop, o sul pannello, o dentro ad un menu', poiché la struttura è "circolare". Ma questo significa anche che il desktop non è piu' un semplice contenitore di cartelle e file (icone), ma una vera piattaforma operativa. Gnome di contro si presenta ancora in versione "semplice", e sicuramente piu' vicina all'utilizzo classico di utenti tradizionali. Ma Gnome 3 cambierà tutto: ho provato la shell su un pc dedicato e devo dire che la rivoluzione sarà pesante anche per gli utenti Gnome. In particolare non capisco perché, per aprire un menù, l'utente sia costretto a vedere ridimensionato l'intero desktop.

    Caduta quindi la tesi rivoluzionaria di KDE, vorrei analizzare i due progetti da altri punti di vista. Anzitutto dal nome: Gnome significa GNU Network Object Model Environment, ossia sistema ad oggetti trasparenti alla rete e, per ammissione del suo fondatore Miguel De Icaza, un sistema con idee prese in prestito dal COM di Microsoft. KDE invece significa Kool Desktop, ed è un ovvio gioco di parole sul CDE. Ad oggi KDE è molto piu' network oriented di Gnome, visto che i plasmoid possono essere condivisi sulla rete da un computer all'altro, il desktop rende realmente ogni operazione trasparente alla rete. Gnome invece si è fossilizzato sul classico desktop, sicuramente funzionale, ma non così network oriented come si era ripromesso. Si è quindi arrivati ad una inversione di progetto: KDE è nato per fornire un desktop efficiente ed efficace, ed oggi è network oriented, Gnome invece era piu' ambizioso e oggi si propone come desktop "statico".

    Ma c'è anche un altro punto fondamentale: la libertà. Gnome nasce su volontà della GNU, proprio per contrastare i problemi di licenza delle Qt, e quindi si propone di fatto come desktop libero. Però la versione 1.x di Gnome non piace molto, o meglio viene sorpassata da KDE in tutto e per tutto. Si deve aspettare l'intervento di grossi vendor come Sun, IBM, RedHat, che investendo sul desktop della scimmia creano quella usabilità di Gnome 2. KDE invece non ha aziende alle sue spalle, solo la comunità di sviluppatori. Quindi, paradossalmente, KDE è piu' libero di Gnome, visto che il primo si evolve come gli sviluppatori vogliono, mentre il secondo come vogliono i vendor. Per meglio comprendere questa cosa si pensi ad Ubuntu e Kubuntu: il primo fornisce codice indietro a Gnome, ma crea personalizzazioni per attirare piu' utenti (ad esempio il recente visualizzatore/controllore audio integrato nel menù del volume), il secondo fornisce una pura installazione KDE senza personalizzazioni. Ancora si pensi ad OpenSolaris (e derivati) che hanno implementato plugin appositi (ad esempio TimeSlider per Nautilus) solo per la versione Gnome, mentre KDE non giova nemmeno del supporto della piattaforma.

    Infine si pensi all'innovazione tecnologica di KDE: chi ammira i prodotti Apple dovrebbe ricordarsi che WebKit, la piattaforma Web di KDE, ha dato vita a Safari e alla dashboard, così come i plasmoidi sono eseguibili nativamente su KDE. In altre parole, KDE e OSX hanno molto in comune, grazie agli sforzi del primo.

    Quindi quali sono i vantaggi e gli svantaggi nell'uso dei due DE? I vantaggi nell'uso di Gnome sono la semplicità e il supporto dei vendor, che garantisce una buona interoperabilità hardware/software. Gli svantaggi sono la scarsa personalizzazione (se raffrontata a KDE) e la scarsa tecnologia. I vantaggi nell'uso del KDE sono la grande innovazione tecnologica, la grande possibilità di personalizzazione e l'interoperabilità con altre piattaforme. Gli svantaggi sono il suo sviluppo, troppo legato agli sviluppatori che quindi creano tool complessi per utenti esperti (in linea con la filosofia Unix) e non si curano troppo degli utenti alle prime armi.

    E come nota conclusiva segnalo che il passaggio alle GTK+ 3 non è stato preso attentamente in considerazione da IBM (che sicuramente recupererà), mentre so che è in corso un porting delle SWT su Qt.

    mercoledì 29 settembre 2010

    WhiteCat: scheduling tasks depending on role events

    I spent a few hours making what seemed a little change to the WhiteCat code, but that soon resulted in a very complex and refactoring-based change: implementing a task scheduler driven by role events.
    WhiteCat already publishes role events when a role is assumed or released, based on that and on the last change on role tasks, the idea is to allow an agent to schedule the execution of a role task as soon as the role is assumed by another agent or before the role is released by an agent. The scenario this change covers is that of asynchronous inter-agent collaboration: an agent can ask another agent to do something once it is ready to do it. To get it simple, consider a scenario where a person goes to work, and assume an employee role; thanks to the scheduling another agent is able to "ask" the former to perform a phone call as soon as it is at the office (i.e., as soon as it assumes the employee role). It is like when you say "call me when you are in office" to a friend of yours, or at the opposite "call me before you get home".
    Now to get into details, the scheduler is fully configured thru Spring and an agent can specify to the scheduler to perform a task specific to a role by a specific agent or by the first agent that is going to assume/release such role. Of course, the event the task must be performed will be specified at the time of the scheduling, so an agent has the following choice for scheduling a task:
    • the task to schedule (of course)
    • an agent that must perform the task or any agent that is able to do the task (i.e., any agent that is going to assume/release the role the task belongs to)
    • when the task must be executed (after the role assumption or before the role release)
    This allows for new dynamic and collaborative solutions in the agent/role modelling! The current implementation exploits AOP to deal with the event dispatching and the task schedulation. Several changes have been done to all the system, starting from the task execution, that now has a task return type that wraps the result of the execution and implements a simple "future reply" pattern, the event dispatching, that now allows for notification of all events no matter of which agent id they are related to, role descriptors and repository, that now are more powerful for inverse role lookup and so on. During the coding several problems have been fixed, and new tests have been added to the code base.
    Of course, all the code is available thru the git repository.
    Drawbacks of this implementation are present, of course: the scheduling is related to a single role instance, and this could be fixed in future releases since it is based on the role repository. Moreover, it could be interesting to implement a real "do it for me" mechanism, where the execution of the task is totally in charge of the agent running the role (i.e., a pure message based system).

    martedì 28 settembre 2010

    Il peso dell'esperienza...

    Anni fa ho realizzato un progetto Java piuttosto complesso, e successivamente sono arrivato a fare un refactoring dello stesso progetto per sistemare le cose che nel frattempo avevo compreso meglio, o che semplicemente potevano essere fatte con pattern differenti. Ebbene, il peso dell'esperienza si fa sentire: il diagramma delle dipendenze dei package mostra un chiaro miglioramento (linearizzazione) fra le due soluzioni. Se la prima ("inesperta") mostrava un groviglio di interdipendenze, la seconda ("esperta") mostra una chiara separazione fra i vari componenti.

    Risultato analogo per le dipendenze delle singole classi, dove si evidenzia un numero minore di "allacciamenti" e quindi di legami forti fra le varie classi. Personalmente non considero molto i diagrammi di dipendenza delle classi, non perché non siano importanti, ma perché tendono a fornire risultati facilmente fuorvianti. Infatti aumentando il numero delle classi riducendo contemporaneamente la complessità di ognuna di esse (quindi tenendo la complessità del progetto costante) si vengono ovviamente a creare un numero di dipendenze maggiori. Inutile dire che queste dipendenze non sono "cattive", ma sono naturalmente forzate dal design del progetto stesso. Basti pensare alla programmazione per interfacce, ove ogni classe avrà una dipendenza con una o piu' interfacce. Ad ogni modo di seguito riporto i diagrammi con la situazione di dipendenza reciproca fra classi nettamente migliorata.


    Infine una curiosità: il progetto nella sua prima versione si basava su AspectJ, proprio per ridurne la complessità. La sua seconda versione non ha ancora introdotto tecniche AOP (piu' che altro per mia pigrizia). Ciò non significa che AOP non serva, ma semplicemente che AOP permette di gestire anche un cattivo design.