mercoledì 30 luglio 2008

Print the stack trace in bash

Ieri ho partorito una semplice funzione che trovo molto comoda per debuggare gli scritp shell, si chiama print_stack_trace.

print_stack_trace andrebbe invocata quando si incontra una condizione di errore e si vuole risalire a qual'e' stato il flusso delle chiamate che l'ha provocata.

Un esempio di utilizzo è il seguente:
save_to_file() {
    local filename="$1"
    if [[ -e $filename ]]; then
        echo "File already exists: $filename" >2
        print_stack_trace
    exit 1
    fi

... # scrittura su file
}
Quando per qualsiasi motivo la funzione save_to_file() è invocata con un argomento non valido stampa un messaggio di errore seguito dall'elenco delle chiamate a funzione che hanno portato all'errore. Per esempio:


File already exists: test-file
Stack trace:
save_to_file(./print-stack-trace.bash:13)
function_three(./print-stack-trace.bash:22)
function_two(./print-stack-trace.bash:26)
function_one(./print-stack-trace.bash:30)
main(./print-stack-trace.bash:33)


La funzione print_stack_trace è la seguente:

# print_stack_trace: print the stack trace in bash
#
# Copyright (C) 2008 Andrea Francia Trivolzio(PV) Italy
# See also: http://andreafrancia.it/
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, version 3 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
#
print_stack_trace() {
echo "Stack trace:"
for (( i=1; i<${#FUNCNAME[@]}; i++)); do echo " ${FUNCNAME[$i]}(${BASH_SOURCE[$i]}:${BASH_LINENO[$i-1]})" done }

giovedì 24 luglio 2008

coLinux - Linux dentro Windows

In questi giorni ho reinstallato coLinux.
Sapete cos'è?
E la manna dal cielo per quelli che come me hanno deciso di tenere tutto su Windows ma hanno ancora bisogno di usare Linux. E' un software che consente di avviare il kernel di Linux all'interno di Windows.

Una volta avviato coLinux è possibile accedervi sia attraverso la console (virtuale) oppure via rete (attraverso una scheda di rete virtuale).

Io lo uso per continuare a sviluppare il mio programma per linux senza dover riavviare il computer. Quando ne ho bisogno mi ci collego in ssh attraverso putty e faccio quello che devo fare.

Sul mio sito su google sites ho creato una pagina che riporta un po' di appunti riguardo coLinux.

giovedì 17 luglio 2008

Un nuovo dottore

Da oggi abbiamo un nuovo ingegnereedilebarraArchitetto.
Complimenti Ingegnere!

trash-cli incluso in Ubuntu e in Debian

Cercando su internet ho scoperto con mia grande sorpresa che il mio software è stato aggiunto sia a Ubuntu che a Debian:
Credo che per installarlo basti fare:
apt-get install trash-cli

Però dovrebbe funzionare solo sulle versioni intrepid di Ubuntu e unstable di Debian.

Provate e fatemi sapere.

venerdì 11 luglio 2008

Differenze tra AWT, Swing e SWT

Per Java sono disponibili tre diversi gui toolkit: awt, Swing,swt.

Perché esistono tre diverse soluzioni per lo stesso problema? Perché non esiste (ancora) una soluzione che va bene in tutti casi. Quest'articolo che è stato recentemente segnalato su it.comp.java spiega i pregi, i difetti, e le particolarità di ognuna di queste tecnologie.

martedì 1 luglio 2008

L'ideona del loggingDecorator

Oggi ho partorito l'ideona del loggingDecorator.
Anche se sono sicuro che è già venuta a mille altre persone ve la dico lo stesso.

Fate finta che vi serve aggiungere ad ogni metodo dei messaggi di debug del tipo "sono entrato nel metodo", "sto uscendo dal metodo" o simili.

Uno con poca fantasia farebbe così:
public void someMethod() {
logger.debug("Begin of someMethod()");

... // corpo del metodo

logger.debug("End of someMethod()");
}
Io pero' dovevo debbuggare le chiamate a una classe che aveva molti metodi e non volevo usare il copia incolla. Ho preferito scomodare il design pattern decorator e la Java Reflection.

Ho usato:
    EntityManager em = ...
em = LoggingDecorators.loggingDecorator(em, EntityManager.class)
Avendo definito
public class LoggingDecorators {
private static final Logger logger =
Logger.getLogger(LoggingDecorators.class.getName());

public static <T> T loggingDecorator(
final T target,
final Class<T> targetClass) {
return (T) Proxy.newProxyInstance(targetClass.getClassLoader(),
new Class[] { targetClass}, new InvocationHandler() {

public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
logger.info("Begin of " + method);
try {
return method.invoke(target, args);
} catch(InvocationTargetException ex) {
throw ex.getCause();
} finally {
logger.info("End of " + method);
}
}
});
}
}