martedì 23 dicembre 2008

Fidati del tuo allenatore

Qualche giorno fa ho avuto uno spunto di riflessione parlando con il mio allenatore, il quale mi ha detto che le persone dell'est sono più facilmente allenabili di un italiano perché hanno una mentalità più rigida e si impegnano molto di più per fare quello che il proprio allenatore gli suggerisce.
Questo mi ha fatto riflettere.
Penso che noi italiani, proprio per la nostra mentalità e carattere, tendiamo a fidarci di più del risultato che non delle parole del nostro allenatore. Non ci poniamo il dubbio se quello che ci viene suggerito serva realmente a fare punti, ci facciamo invece distrarre dal risultato e, essendo sempre alla ricerca dei che possono farci fare qualche trucco per fare un giallo in più, tendiamo a pensare di essere più furbi del nostro allenatore. Anche perché spesso tirare bene è scomodo, almeno in un primo tempo, rispetto a tirare nel modo più naturale (e spesso sbagliato). E allora la sfiducia (passatemi il termine) nel nostro allenatore aumenta.
Invece l'allenatore con la sua esperienza e la sua pazienza è un valido sostegno e aiuto per migliorare costantemente. Fidiamoci quindi dei nostri allenatori!

Dependency Injection: costruttori o setter?

La Dependency Injection (DI) viene spesso realizzata mediante uno o più parametri passati al costruttore di un oggetto, ad esempio se una classe ha bisogno di sapere il suo DAO, quest'ultimo può essere passato al costruttore dell'oggetto.
Esiste un lungo dibattito su cosa sia meglio fare per permettere la DI, in particolare se sia meglio usare un costruttore o dei metodi setter. Il vantaggio nell'uso di un costruttore consiste nel fatto che l'oggetto ottenuto è sempre inizializzato correttamente, e quindi non è possibile lasciare in uno stato parziale l'oggetto (ossia tutte le sue dipendenze devono essergli iniettate prima che l'oggetto sia costruito). Il vantaggio nell'uso dei setter è quello di avere la possibilità di riconfigurare l'oggetto in ogni momento, ma si corre il rischio di lasciare l'oggetto non inizializzato correttamente. Da quanto appena detto si evince che l'uso dei costruttori è generalmente quello migliore e quindi quello più consigliato.
Tuttavia esiste un problema nell'uso del costruttore per DI che si verifica nel caso in cui l'oggetto che si sta costruendo abbia molte dipendenze, o abbia necessità di ricevere molti parametri: la signature del costruttore diventa inevitabilmente lunga e quindi di difficile utilizzo e comprensione. Si noti poi che non è consigliato implementare dei setter da usare nel costruttore per realizzare, in un sol colpo, entrambi i metodi di DI, poiché i setter saranno (generalmente) polimorfici, e l'uso di metodi polimorfici nei costruttori è fortemente sconsigliato.
Quindi che soluzione adottare? L'unica che mi sento di consigliare è di usare il costruttore quando si hanno pochi parametri (3,4 al massimo) e di passare a metodi setter per un numero di parametri maggiore. E' comunque bene dare la priorità al costruttore, specificando nella sua signature tutti i parametri DI di maggior importanza, così che l'oggetto non possa essere costruito senza di essi. Infine, occorre informare l'utente in modo chiaro e preciso attraverso la documentazione di tutte le dipendenze e della loro importanza per l'inizializzazione dell'oggetto. Una possibile soluzione per forzare una completa inizializzazione dell'oggetto mantenendo la signature del costruttore corta, o implementando i setter, consiste nell'uso di un costruttore privato e di un metodo factory per ottenere l'istanza. In questo modo il metodo factory può utilizzare tutti i setter per inizializzare opportunamente l'oggetto da restituire.

venerdì 19 dicembre 2008

Creare le share personalizzate per ogni utente in Samba (con LDAP)

Invece che utilizzare la classica share homes di Samba, ho installato su un server una condivisione personalizzata chiamata MyDoc, che deve essere esclusiva di ogni utente. Per fare questo occorre che la share punti sempre ad una cartella di proprietà esclusiva dell'utente che ha effettuato il login, cosa abbastanza semplice da realizzare tramite le variabili messe a disposizione da Samba, nel caso specifico %U (utente di login):

[MYDOC_SMB]
comment = Cartella documenti personalizzati per utenti
path = /mnt/samba/mydoc_smb/%U
browsable = yes
available = yes
writable = yes
printable = no
copy = perm_template
valid users = %U

A questo punto occorre però creare le cartelle di ogni singolo utente, che devono avere come nome il relativo login, e assegnare i diritti a tutte le cartelle in modo che siano di proprietà esclusiva dell'utente stesso. Su un sistema con OpenLDAP è possibile eseguire il seguente script per ottenere lo scopo:

#!/bin/bash

SEARCH_CMD=`which ldapsearch`
SEARCH_OPTIONS=" -x uid "

GREP_CMD=`which grep`
GREP_OPTIONS=" uid:"
AWK_CMD=`which awk`
AWK_OPTIONS="'{print \$2;}' "

EVAL_CMD="eval"

MKDIR_CMD=`which mkdir`
MKDIR_OPTIONS=" -p "

MYDOC_ROOT="/mnt/samba/mydoc_smb"

CHOWN_CMD=`which chown`
CHMOD_CMD=`which chmod`
CHMOD_OPTIONS=" 777 "

SUCCESSES=0
FAILURES=0


for utente in `$EVAL_CMD "$SEARCH_CMD $SEARCH_OPTIONS | $GREP_CMD $GREP_OPTIONS | $AWK_CMD $AWK_OPTIONS" `
do

# devo ottenere il gruppo di questo utente
SEARCH_OPTIONS_2=" -x \"(&(objectClass=posixGroup)(memberUid=$utente))\" "
GREP_OPTIONS_2=" cn: "

echo -en "Processo utente <$utente>..."
dstDir=${MYDOC_ROOT}/${utente}
$MKDIR_CMD $MKDIR_OPTIONS $dstDir > /dev/null 2>&1

if [ $? -eq 0 ]
then
echo -en "ok\n"

# devo cambiare il proprietario della directory. Siccome la directory potrebbe
# contenere piu' gruppi, devo ciclare su ognuno e assegno i permessi dell'ultimo gruppo.

for gruppo in `$EVAL_CMD "$SEARCH_CMD $SEARCH_OPTIONS_2 | $GREP_CMD $GREP_OPTIONS_2 | $AWK_CMD $AWK_OPTIONS" `
do
$CHOWN_CMD $utente:$gruppo $dstDir > /dev/null 2>&1
done

$CHMOD_CMD $CHMOD_OPTIONS $dstDir > /dev/null 2>&1

SUCCESSES=$(( SUCCESSES + 1 ))
else
echo -en "KO\n"
FAILURES=$(( FAILURES + 1 ))
fi

done


echo -en "\n\n\nFinito:\n\t $SUCCESSES processati correttamente,\n\t $FAILURES falliti\n"

In sostanza tramite ldapsearch si va a cercare ogni utente nel sistema, dopdoiché si effettua una ricerca per trovare i gruppi a cui questo utente appartiene. Siccome un utente può appartenere a più gruppi, come scelta implementativa si tiene valido l'ultimo gruppo trovato. Viene creata la directory e vengono impostati i permessi e il proprietario della directory stessa.

mercoledì 17 dicembre 2008

Modificare automaticamente la data di scadenza password su Ubuntu/Samba-LDAP

Se si ha un sistema di gestione account basato su LDAP tramite gli smbldap tools è possibile editare automaticamente tutti gli account per modificare la data di scadenza password. Il seguente script accetta come parametro (opzionale) un numero di anni per i quali la password non deve scadere, dopodiché calcola la data di nuova scadenza della password e ricerca tutti gli utenti (Users) nel sistema LDAP per poi modifcarne la data di scadenza tramite smbldap-usermod:

#!/bin/bash




# considero che incremento di anno ho, se non ne ho nessuno
# allora incremento di default di 4 anni
YEAR_INCREMENT=$1
if [ -z "$YEAR_INCREMENT" ]
then
YEAR_INCREMENT=4
fi

DATE_CMD=`which date`
CURRENT_YEAR=`$DATE_CMD +'%Y'`
FINAL_YEAR=$(( CURRENT_YEAR + YEAR_INCREMENT ))
EXPIRE_DATE="${FINAL_YEAR}-12-31"

echo "Verra' impostata la data di password expiration per $EXPIRE_DATE"


PWD_CMD=`which smbldap-usermod`
PWD_OPTIONS=" --shadowExpire $EXPIRE_DATE --shadowMax 700"


SEARCH_CMD=`which ldapsearch`
SEARCH_OPTIONS=" -x uid "

GREP_CMD=`which grep`
GREP_OPTIONS=" uid:"
AWK_CMD=`which awk`
AWK_OPTIONS="'{print \$2;}' "

EVAL_CMD="eval"

SUCCESSES=0
FAILURES=0


for utente in `$EVAL_CMD "$SEARCH_CMD $SEARCH_OPTIONS | $GREP_CMD $GREP_OPTIONS | $AWK_CMD $AWK_OPTIONS" `
do
echo -en "Processo utente <$utente>..."
$PWD_CMD $PWD_OPTIONS $utente > /dev/null 2>&1
if [ $? -eq 0 ]
then
echo -en "ok\n"
SUCCESSES=$(( SUCCESSES + 1 ))
else
echo -en "KO\n"
FAILURES=$(( FAILURES + 1 ))
fi

done


echo -en "\n\n\nFinito:\n\t $SUCCESSES processati correttamente,\n\t $FAILURES falliti\n"

Si noti che siccome la ricerca dei vari uid avviene tramite una ricerca ldap, filtrata da awk, occorre usare un eval per l'esecuzione del comando per impedire alla shell di interpretare male i caratteri di comando awk.
Lo script di cui sopra mostra poi il risultato della sua esecuzione informando l'utente del numero di utenti modificati e di quelli in cui il comando è fallito.
Sebbene sia consigliabile la modifica delle password periodica, un simile script è utile per quegli ambienti dove gli utenti si autenticano in modo automatico tramite chiavi SSH, e quindi dove non sono interessati a mantenere la propria password che può quindi essere modificata in automatico da un amministratore o da una procedura automatizzata.

lunedì 15 dicembre 2008

Call vs Execution Join Point

Si sente spesso parlare di differenza fra i join point di call e di execution, tanto che la domanda è molto spesso fatta da chi è alle prime armi con l'AOP e AspectJ. Per chiarezza occorre ricordare che mentre un call "osserva" il codice dal lato chiamante (quindi un this punta all'oggetto che invoca un metodo), un execution "osserva" il codice dal lato chiamato (quindi un this punta all'oggetto sul quale il metodo è invocato). Tuttavia esiste un'ulteriore differenza, sottile e subdola e che potrebbe lasciare sconcertati quando si utilizza la reflection: un execution join point, dovendo essere sul lato del codice chiamato, viene sempre messo inline con il codice stesso. Questo significa che anche se la chiamata al metodo avviene tramite reflection il join-point verrà processato. Diverso il caso invece per call, che non può essere messo inline (si avrebbe un contesto differente) e che quindi viene normalmente bypassato dall'uso della reflection. In altre parole, se si vuole gestire un join point di tipo call occorre prevedere tutte le chiamate dirette al metodo e anche quelle che eventualmente vengono fatte tramite reflection.

venerdì 5 dicembre 2008

Gestire un database PostgreSQL mediante Eclipse

Eclipse è un ambiente di sviluppo veramente completo, che consente anche il collegamento a diverse origini dati, fra le quali database SQL. In questo articolo mostrerò come collegare un database PostgreSQL ad Eclipse, in modo che sia possibile amministrare e ispezionare i dati direttamente dall'IDE senza dover appoggiarsi a tool esterni.
Eclipse basa la sua connettività database su JDBC, e quindi è necessario aver scaricato ed installato un driver opportuno dal sito del progetto JDBC di PostgreSQL.
Supponendo di voler collegare un database di nome hrpmdb che risiede sull'host sedeldap i passi da eseguire sono i seguenti:

  1. dal menù Windows selezionare la voce Open view e quindi Others. Dalla finestra di dialogo che si apre cercare la categoria Connectivity e quindi Data source explorer.
  2. Nella nuova vista che si apre, fare click con il tasto destro del mouse sulla voce Databases e quindi selezionare New.
  3. Si apre una finestra di dialogo dalla quale selezionare il tipo di database, che ovviamente è PostgreSQL. Occorre anche dare un nome simbolico a questa connessione e una descrizione (opzionale) della connessione stessa.

  • Nella finestra successiva occorre indicare il driver JDBC da usare per la connessione. Se non si è installato ancora nessun driver, occorre cliccare sul pulsante a fianco del menù a discesca e andare a ricercare il driver da installare. In particolare nella dialog che si apre occorre andare nel tab jar list, aggiungere il file jar contenente il driver e quindi tornare al tab principale per confermare l'installazione del driver.


  • A questo punto è possibile tornare alla configurazione della connessione e impostare tutti i parametri, quali URL (che deve essere nella forma JDBC e quindi con jdbc:postgres://).

  • A questo punto la connessione compare nella view delle sorgenti di dati, ed è possibile esplorare la struttura del database a cui si è connessi.

  • E' infine possibile accedere ed editare i dati di una tabella selezionando dal menù contestuale Data->Edit e agendo sull'editor che viene aperto con il contenuto della tabella selezionata.