Autenticazione nativa Windows Active Directory in Tomcat

Postato da ROb | nella categoria Java, Sviluppo web | venerdì, 22 luglio 2011

0

Per un interessante progetto a cui sto lavorando, ho avuto la necessità di configurare Tomcat per poter autenticare nativamente i client (con browser IE7 e IE8 e Firefox) attraverso il repository Active Directory di Windows 2003 Server.

Per farlo ci sono a disposizione, come spesso avviene, numerose possibilità.
Dopo averne provate un paio alla fine ho scelto la soluzione proposta dalla libreria spnego.

spnego implementa il protocollo Kerberos/SPNEGO invece del classico NTLM per dialogare con i domain controller e, attraverso un filtro inserito nella nostra web application, ci offre la possibilità di verificare l’identità degli utenti (attraverso la chiamata java request.getRemoteUser() ) già autenticati in Windows dopo un logon positivo nel dominio di Active Directory.

La guida offerta dal sito della libreria per il raggiungimento di tale integrazione è molto ben fatta. Qui sotto in breve voglio riassumere i miei passi, che in larga parte seguono appunto tale guida.

  • creazione di un utente in Active Directory, che sarà utilizzato dal filtro per loggarsi al dominio e verificare le credenziali degli utenti.
  • creazione del file krb5.conf (all’interno della directory di esecuzione di Tomcat, nel mio caso la bin) con tale contenuto:
    [libdefaults]
    	default_realm = <NOME_DOMINIO>
    	default_tkt_enctypes = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
    	default_tgs_enctypes = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
    	permitted_enctypes   = aes128-cts rc4-hmac des3-cbc-sha1 des-cbc-md5 des-cbc-crc
    
    [realms]
    	<NOME_DOMINIO>  = {
    		kdc = <DOMAIN_CONTROLLER>
    		default_domain =  <NOME_DOMINIO>
    }
    
    [domain_realm]
    	. <NOME_DOMINIO> =  <NOME_DOMINIO>
    
  • creazione del file login.conf (nella stessa posizione del file krb5.conf) con il seguente contenuto
    spnego-client {
    	com.sun.security.auth.module.Krb5LoginModule required;
    };
    
    spnego-server {
    	com.sun.security.auth.module.Krb5LoginModule required
    	storeKey=true
    	isInitiator=false;
    };
    
  • creazione di una web application (nel mio caso il suo nome è testad) con dentro solamente la directory WEB-INF con dentro una cartella lib con la libreria jar di spnego (nel mio caso l’ultima versione disponibile era la 7, spnego-r7.jar) e il file web.xml con il seguente contenuto (rimpiazzate opportunamente l’utente e la password dell’utente di Active Directory):
    <?xml version="1.0" encoding="ISO-8859-1"?>
    
    <web-app xmlns="http://java.sun.com/xml/ns/javaee"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
       version="2.5">
    
      <filter>
        <filter-name>SpnegoHttpFilter</filter-name>
        <filter-class>net.sourceforge.spnego.SpnegoHttpFilter</filter-class>
    
        <init-param>
            <param-name>spnego.allow.basic</param-name>
            <param-value>true</param-value>
        </init-param>
    
        <init-param>
            <param-name>spnego.allow.localhost</param-name>
            <param-value>false</param-value>
        </init-param>
    
        <init-param>
            <param-name>spnego.allow.unsecure.basic</param-name>
            <param-value>true</param-value>
        </init-param>
    
        <init-param>
            <param-name>spnego.login.client.module</param-name>
            <param-value>spnego-client</param-value>
        </init-param>
    
        <init-param>
            <param-name>spnego.krb5.conf</param-name>
            <param-value>krb5.conf</param-value>
        </init-param>
    
        <init-param>
            <param-name>spnego.login.conf</param-name>
            <param-value>login.conf</param-value>
        </init-param>
    
        <init-param>
            <param-name>spnego.preauth.username</param-name>
            <param-value>utentead</param-value>
        </init-param>
    
        <init-param>
            <param-name>spnego.preauth.password</param-name>
            <param-value>password_utentead</param-value>
        </init-param>
    
        <init-param>
            <param-name>spnego.login.server.module</param-name>
            <param-value>spnego-server</param-value>
        </init-param>
    
        <init-param>
            <param-name>spnego.prompt.ntlm</param-name>
            <param-value>true</param-value>
        </init-param>
    
        <init-param>
            <param-name>spnego.logger.level</param-name>
            <param-value>1</param-value>
        </init-param>
    </filter>
    
    <filter-mapping>
        <filter-name>SpnegoHttpFilter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
    </web-app>
    

    aggiungete anche il file index.jsp nella root della web application con il seguente contenuto:

    <%@page import="java.security.Principal" %>
    <html>
     <head>
      <title>Protected Page for Examples</title>
     </head>
     <body bgcolor="white">
      You are logged in as remote user <b><%= request.getRemoteUser() %></b> in session <b><%= session.getId() %></b>
      <br><br>
      <%
    	if (request.getUserPrincipal() != null) {
      %>
      Your user principal name is <b><%= request.getUserPrincipal().getName() %></b>.
      <br><br>
      <%
       } else {
      %>
       No user principal could be identified.
       <br><br>
      <%
      }
      %>
      <%
      String role = request.getParameter("role");
      if (role == null)
        role = "";
      if (role.length() > 0) {
        if (request.isUserInRole(role)) {
      %>
      You have been granted role <b><%= role %></b>.
      <br><br>
      <%
       } else {
      %>
      You have <i>not</i> been granted role <b><%= role %></b>.
      <br><br>
      <%
       }
      }
      %>
      To check whether your username has been granted a particular role, enter it here:
      <form method="GET" action='<%= response.encodeURL("index.jsp") %>'>
       <input type="text" name="role" value="<%= role %>">
      </form>
      <br><br>
      You can logoff by clicking
      <a href='<%= response.encodeURL("index.jsp?logoff=true") %>'>here</a>.
      This should cause automatic re-logon with Waffle and a new session ID.
      <br>
     </body>
    </html>
    
  • a questo punto inserite questa web application nelle applicazioni del vostro Tomcat
  • per completare il processo bisogna lanciare nel domain controller un paio di istruzioni per abilitare il tab delegation all’utente Active Directory che effettuerà la verifica dei token del Kerberos.
    setspn.exe -A HTTP/<sito> utentead
    setspn.exe -A HTTP/<sito_con_dominio> utentead
    

    poi aprendo le proprietà dell’utente, nel tab “Delegation”, abilitare la funzione “Trust this user for delegation to any service (Kerberos only)”.

  • per permettere al browser di passare le credenziali al server bisognerà, nel caso di IE, inserire il sito all’interno dell’Area Intranet e verificare che sotto la voce Autenticazione Utente (dentro livello personalizzato) sia impostato come “Accesso automatico solo nell’area Internet”, mentre per Firefox (testato con il 3.x) bisogna impostare le seguenti chiavi con il valore del vostro sito web
    network.negotiate-auth.delegation-uris = http://<sito>
    network.negotiate-auth.trusted-uris = http://<sito>
    
  • riavviate ora Tomcat e accedete alla root della vostra nuova web application
  • il filtro di spnego proteggerà tutti i file della web application e chiederà l’autenticazione nativa (o eventualmente l’autenticazione basic tramite prompt). Se l’autenticazione avverrà correttamente accederete al file index.jsp e leggerete il vostro nome utente nella pagina.

Grazie per l’attenzione e buon lavoro!

Fiddler – super web debugging proxy

Postato da ROb | nella categoria Sviluppo web, Utilità | giovedì, 5 maggio 2011

0

Ieri, cercando di risolvere un problema di un sito che si verificava con il browser Safari su Windows, navigando qua e là in cerca di risposte, ho trovato qualcuno che consigliava di installare Fiddler, un web debugging proxy freeware per Windows.

Chi già utilizza l’estensione LiveHttpHeaders per Firefox o Firebug sa già quanto siano importanti tali strumenti per lo sviluppatore web. Essi infatti permettono non solamente di analizzare il codice di una pagina web (html, css, javascript) ma anche di visualizzare tutte le chiamate http effettuate dal browser, con le relative risposte, e di fare debugging del codice Javascript presente nella pagina stessa.

Alcuni browser come Safari, Chrome e altri, pur avendo i propri strumenti di sviluppo, non permettono di scendere  anche nel dettaglio delle singole chiamate http, inoltre non sempre il client delle chiamate web è un browser, in alcuni casi potrebbero essere un software stesso che prova a connettersi a un servizio web per scaricare, ad esempio, gli aggiornamenti.

Per tutti questi casi, ma sicuramente anche per molti altri, Fiddler si offre come valido strumento di analisi, frapponendosi in modo trasparente tra client e server e intercettando tutte le richieste e le risposte http del nostro PC.

Per funzionare ha bisogno del framework .NET che installa autonomamente nel caso non sia già presente. Una volta installato è sufficiente avviarlo e iniziare a navigare con un browser per vedere tutte le nostre chiamate (e anche i nostri dati :-D ) apparire nelle schermate del programma.

Il sito del software è il seguente: http://www.fiddler2.com/

Per il download fate riferimento a quest’altro indirizzo: http://www.fiddler2.com/fiddler2/version.asp

Happy debugging!

Sencha Touch: un breve articolo di IBM developerWorks

Postato da ROb | nella categoria Android, Sviluppo web | mercoledì, 26 gennaio 2011

2

Ecco un interessante articolo su Sencha Touch pubblicato sul canale degli articoli tecnici di IBM, developerWorks.

Sencha Touch è un framework Javascript, nato dall’evoluzione del potente e popolarissimo ExtJS, e orientato al mondo mobile, principalmente Android e iOS.
Il suo obiettivo è quello di costruire interfacce web evolute per tali dispositivi che assomigliano a delle vere e proprie applicazioni native.
Il framework si basa su Javascript e sul potere espressivo del nuovo linguaggio di markup HTML5.

sencha touch

L’articolo, scritto da Michael Galpin, Software Architect presso eBay, presenta una semplice applicazione testata sia in un dispositivo Android che in un iPhone.

Ecco il link diretto all’articolo per chi volesse approfondire.

Generazione di un hash md5 in Java

Postato da ROb | nella categoria Java, Sviluppo web | mercoledì, 10 novembre 2010

0

Con questa semplice funzione è possibile generare una stringa in codifica md5 a partire da una stringa di testo.

       /**
	 * Generates the md5sum of the given digest
	 *
	 * @param digest
	 * @return
	 */
	public static String md5sum(String digest) {
		String message = null;

		if (digest != null) {
			try {
				MessageDigest md = MessageDigest.getInstance("MD5");
				md.reset();
				byte[] messageBytes = md.digest(digest.getBytes());
				BigInteger number = new BigInteger(1, messageBytes);
				message = number.toString(16);
			} catch (NoSuchAlgorithmException e) {
				e.printStackTrace();
			}
		}

		return message;
	}

Costruire un link per visualizzare il codice di una pagina web

Postato da ROb | nella categoria Sviluppo web | lunedì, 11 ottobre 2010

0

Alcuni browser supportano un protocollo speciale chiamato view-source:.

Torre di Pisa tag i

Tale protocollo permette al browser di visualizzare il codice della pagina indirizzata dall’url anziché farne il rendering e visualizzarla.

Sfruttando tale protocollo possiamo costruire un link che permette, a chi è interessato, di visualizzare il codice della nostra pagina senza passare per la relativa funzione browser-specific (tipicamente attivabile con la sequenza di tasti CTRL+u)

 

Ecco una semplice pagina html che mostra tale possibilità:

<html>
<body>
   <h1> Roberto Rossi from Macerata! Hello! </h1>
   <a class="button" onClick='window.location="view-source:" + window.location.href' href="javascript:;;">Visualizza Codice</a>
</body>
</html>

Cliccando sul link “Visualizza Codice” il browser aprirà una pagina che visualizzerà tale codice.

Pulire codice HTML eccetto alcuni tag in Java sfruttando Jsoup

Postato da ROb | nella categoria Java, Sviluppo web | venerdì, 24 settembre 2010

4

Abbiamo già parlato di Jsoup in questo precedente post.
In due parole Jsoup è una potente libreria di parsing html/xml che permette di leggere e manipolare facilmente stringhe e porzioni anche grandi di codice html/xml.

Oggi voglio farvi vedere come possiamo sfruttarla per pulire del codice html (proveniente ad esempio dal campo di un web form) mantenendo solamente i tag che vogliamo.

Questa opzione è infatti molto utile nel caso in cui si voglia permettere agli utenti di arricchire il dato con la formattazione classica dei testi: bold, italico, … senza però rischiare di esporci al pericoloso XSS attack che consiste nell’inserire codice Javascript malevolo che punta verso qualche altro sito.

Con poche righe di codice Jsoup ci permette di definire la nostro lista di tag partendo da alcuni set predefiniti.

        ...
        String unsafe = "<p><a href='http://www.bits4beats.com/' onclick='stealCookies()'>Benvenuto <b>Roberto Rossi</b></a> lo so che che sei di Macerata! <br/>... sei proprio un <i>impiastro</i>!</p>";

		Whitelist myWL = Whitelist.simpleText();
		myWL.addTags("br", "hr");

		String safe = Jsoup.clean(unsafe, myWL);
		System.out.println("stringa sicura: " + safe);
        ...

Se lo eseguiamo otterremo la seguente stringa:

stringa sicura: Benvenuto <b>Roberto Rossi</b> lo sei che sei di Macerata! <br /> sei proprio un <i>impiastro</i>!

In pratica abbiamo detto a Jsoup di partire dalla lista accettata simpleText() che contiene i tag essenziali della formattazione a cui abbiamo aggiunto il tag br e il tag hr.

Java: le variabili di ambiente in un oggetto Properties

Postato da ROb | nella categoria Java, Sviluppo web | giovedì, 16 settembre 2010

0

Ecco come è possibile ottenere in un oggetto di tipo Properties contenente le variabili di ambiente della nostra Linux box.

       /**
	 * Legge le variabili di ambiente e popola un oggetto di tipo Properties
	 */
	public static Properties getEnvironment() throws java.io.IOException {
	    Properties env = new Properties();
	    env.load(Runtime.getRuntime().exec("env").getInputStream());
	    return env;
	}

A questo punto con il seguente codice possiamo conoscere, ad esempio, il valore della variabile LANG che determina la codifica dei file.

       ...
       Properties env = Utils.getEnvironment();
       String lang = (String) env.get("LANG");
       ...

Una comunità di programmatori per programmatori: StackOverflow

Postato da ROb | nella categoria Java, Sviluppo web, Varie | domenica, 12 settembre 2010

2

Quando avevo bisogno di informazioni tecniche e mi affidavo a Google per le mie care ricerche, spesso capitavo in un sito decisamente simpatico dove trovavo quasi sempre le risposte alle mie domande.

Sinceramente non ho mai approfondito la natura del sito, né tantomeno quale fossero gli argomenti prelaventi. Mi limitavo a provare le soluzioni proposte e se funzionavano me ne andavo per sempre dal sito.

Qualche giorno fa, mosso da uno strano spirito di curiosità (non è vero ce l’ho sempre solo che spesso è soffocato dalla voglia di concludere le attività) mi sono soffermato a studiarlo un pò.

Il sito si chiama StackOverflow, un nome decisamente per programmatori, e in realtà unisce un gruppo numerosissimo di sviluppatori in tutto il mondo.
Il suo funzionamento è di una banalità imbarazzante ma forse è anche il motivo del suo successo. Se hai qualche dubbio, problema, richiesta, fai prima una ricerca nel sito e se non trovi niente scrivilo direttamente su StackOverflow.
Troverai sicuramente qualcuno che ha già avuto il tuo stesso dubbio oppure ha già risolto il tuo stesso problema. Se così non fosse magari troverai allora qualcuno disposto ad aiutarti e “perdere” un pò del suo tempo prezioso per rispondere in modo efficace alla tua domanda.

StackOverflow è un sito di programmatori per programmatori. Chiunque comunque può accedere al sito, non sono richiesti particolari prerequisiti, e chiunque può aiutare o rispondere.
In realtà non è sempre così, nel senso che il sistema di StackOverflow è autopremiante e automoderato.
Rispondendo, commentando e risolvendo le domande ogni iscritto riceve dei punti che gli permettono oltre che di guadagnare reputazione e stima dagli altri anche di acquisire facoltà operative.
Non tutti cioè possono fare tutto. Ad esempio chi ha un punteggio pari a 0 non può inserire più di 2 link in una risposta, probabilmente per allontanare gli spammer o chi vuole fare solamente pubblicità.

Se avete voglia di diventare dei guru di StackOverflow, se avete delle forti spinte filantropiche oppure se semplicemente avete bisogno di aiuto in uno dei moltissimi argomenti trattati, di programmazione e non solo, rivolgetevi allora a StackOverflow, iscrivetevi e partecipate a questa grandissima community.

Per chi mi dovesse cercare, io sono impiastro e, come potete vedere, il mio punteggio è ancora veramente molto basso.

Qui sotto trovate il codice javascript che potete inserire all’interno del vostro sito per segnalare la vostra situazione StackOverflow. Questo è il mio.



Firefox in modalità provvisoria

Postato da ROb | nella categoria Informatica in generale, Sviluppo web, Utilità | venerdì, 10 settembre 2010

0

Qualche giorno fa mi è capitato di dover disabilitare un plugin nel mio profilo Firefox perché in conflitto con un altro plugin.

modalità provvisoria

Il problema è che non riuscivo ad accedere alla maschera dei plugin aggiuntivi in quanto il Javascript Firefox che visualizza tale pagina rimaneva bloccato.

Cercando qua e là ho scovato il modo per disattivare i plugin, entrando in modalità provvisoria in Firefox.
Per farlo è sufficiente chiuderlo e riaprirlo con questo comando:

firefox -safe-mode

I plugin vengono tutti disattivati e possiamo quindi scegliere quale bloccare e quale disinstallare definitivamente.

Comodo no? Come al solito gli sviluppatori Mozilla hanno pensato proprio a tutto.

Java: misurare i tempi di esecuzione delle nostre procedure

Postato da ROb | nella categoria Java, Sviluppo web | mercoledì, 21 luglio 2010

0

Spesso mi sono trovato nella situazione di voler possedere uno strumento che mi permettesse di misurare i tempi di esecuzione di una procedura, di un metodo di una classe o di un semplice blocco di codice.

chronometer

Tutte le volte mi sono scritto delle apposite funzioni, che facevano la differenza tra la data di fine e la data di inizio della misurazione e poi stampavano il risultato tramite un sistema di logging.

Ieri però, non soddisfatto delle esperienze precedenti, ho cercato un tool che facesse lo sporco lavoro per me, che fosse affidabile e che permettesse di avere un valido report di visualizzazione dei dati raccolti.

Eccomi quindi arrivato, non so come (perché dal nome del progetto non sono chiare le finalità della libreria), a JETM.
JETM è l’acronimo di “Java™ Execution Time Measurement Library” che dichiara di essere “a small and free library, that helps locating performance problems in existing Java applications.”

Per integrarla nelle nostre applicazioni è sufficiente inserire il file jar della distribuzione, chiamato jetm-x-x-x.jar, all’interno del nostro CLASSPATH e fare in modo tale che la configurazione venga inizializzata prima della registrazione delle misurazioni vere e proprie.

Le applicazioni standalone possono inizializzare la configurazione all’inizio del loro ciclo di esecuzione, le applicazioni web possono affidarsi alla configurazione di Spring oppure tramite degli opportuni ContextListener definiti nel file web.xml.

Il codice banale di inizializzazione è:

	    BasicEtmConfigurator.configure();
	    monitor = EtmManager.getEtmMonitor();
	    monitor.start();

a questo punto per poter collezionare una misurazione dobbiamo definire un punto e successivamente determinare la fine della misurazione, in questo modo:

	    EtmPoint point = monitor.createPoint("Nomedelpuntodicollezione");
	    // do something...
	    point.collect();

Il parametro del metodo createPoint serve per distinguere un punto di misurazione da un altro.
Alla fine della nostra applicazione, o quando lo riteniamo più opportuno, possiamo visualizzare i dati collezionati e al termine stoppare il servizio di monitoraggio:

	    monitor.render(new SimpleTextRenderer(new Locale("it")));
	    monitor.stop();

Il renderer inizializzato in italiano serve per utilizzare i corretti separatori di decimali e migliaia.
L’output ottenuto dal metodo render assomiglia a qualcosa di questo tipo:

Java(TM) Execution Time Measurement Library

Il tempo calcolato è espresso in millisecondi.

Se vogliamo anche visualizzare l’annidamento delle misurazioni/chiamate possiamo passare il parametro “true” al metodo di inizializzazione della configurazione:

        BasicEtmConfigurator.configure();

Per ulteriori informazioni e tutta la documentazione necessaria fate riferimento al sito ufficiale del progetto (http://jetm.void.fm/)

Formattazione di un numero decimale in Java

Postato da ROb | nella categoria Java, Sviluppo web | martedì, 20 luglio 2010

2

Può capitare di dover modificare i caratteri separatori di decimali e migliaia nella formattazione di un numero in Java.

Questa porzione di codice vi permette di farlo sfruttando alcune classi base di Java:

    		DecimalFormatSymbols symbols = new DecimalFormatSymbols();
    		symbols.setDecimalSeparator('$');
        	symbols.setGroupingSeparator('#');

        	String format = "###,###.###";
        	DecimalFormat formatter = new DecimalFormat(format, symbols);
        	formatter.setGroupingSize(3);

        	String numberString = formatter.format(number);

In questo caso, un pò per gioco, abbiamo impostato il carattere $ come separatore dei decimali e # come separatore delle migliaia.

La classe DecimalFormat formatta il numero sfruttando il pattern specificato in questo “###,###.###”. Il suo costruttore però accetta anche una variabile di tipo DecimalFormatSymbols che può essere inizializzata a partire da uno specifico Locale (avremmo infatti potuto rimpiazzare la chiamata con DecimalFormatSymbols symbols = new DecimalFormatSymbols(new Locale(“it”)); ).

A questo punto la variabile symbols può essere utilizzata per sovrascrivere le impostazioni dell’eventuale Locale utilizzato oppure può essere utilizzato in modo nativo lasciando i separatori di default che, per la lingua italiana, sono tipicamente la “,” come separatore dei decimali e il “.” come raggruppatore della migliaia (non sempre visualizzato).

Un semplice feed per conoscere le previsioni del tempo

Postato da ROb | nella categoria Sviluppo web, Utilità | venerdì, 30 aprile 2010

2

Per chi ama informarsi e rimanere aggiornato tramite i feed RSS o Atom, ecco il feed per conoscere le previsioni del tempo per la propria città.

Grazie al servizio Yahoo Weather, in collaborazione con The Weather Channel, è possibile ricevere un feed della situazione meteo e delle prossime previsioni per la propria città.

Sereno variabile

Prima di tutto bisogna trovare il codice della nostra città (il cosidetto WOEID). Puntiamo quindi il browser su http://weather.yahoo.com/italy/ e cerchiamo la nostra locazione. Nel mio caso, Macerata, la pagina trovata è: http://weather.yahoo.com/italy/marche/-12846728/ dove il numero 12846728 è il codice di riferimento.

Ora possiamo invocare il feed per ottenere le previsioni. Prendiamo l’url http://weather.yahooapis.com/forecastrss?w= e aggiungiamo il nostro numero magico 12846728.
Quindi l’url definitivo sarà: http://weather.yahooapis.com/forecastrss?w=12846728 .

Da buoni italiani che siamo comunque ci serve l’output della temperatura in formato gradi Celsius. Per ottenerlo è sufficiente aggiungere il parametro u=c alla chiamata.

Così l’indirizzo definitivo è: http://weather.yahooapis.com/forecastrss?w=12846728&u=c.

Ormai non avete più scuse se dimenticate l’ombrello!

Sfruttare le Google Picasa API per generare una galleria di immagini

Postato da ROb | nella categoria Java, Linux, Sviluppo web | giovedì, 22 aprile 2010

0

Chi non conosce il bellissimo e potentissimo software Picasa?
E’ sempre più facile vederlo installato nei desktop degli utenti come rimpiazzo dell’applicazione di default di visualizzazione immagini. Anche io che uso Linux, nonostante la scelta di software di gestione e visualizzazione immagini sia molto ricca e il fatto che non è un’applicazione nativa Linux ma emulata tramite Wine, ho eletto Picasa come il “mio” software di gestione immagini.

Google Picasa API

Non voglio però dilungarmi molto in merito ai pregi di questo gestore di immagini. L’oggetto di questo post è la possibilità di sfruttare il servizio web ad esso associato (ma anche utilizzabile in modo indipendente) chiamato Picasa Web Albums.

Picasa Web Albums è un servizio web che ci permette di caricare, organizzare i nostri album di foto e di condividerli con chi vogliamo. Migliorato di mese e mese, si è arricchito ultimamente anche della capacità di riconoscere i volti delle persone nelle foto in modo automatico.

Questo servizio Google, come molti altri dell’azienda di Mountain View, espone delle API, cioè delle librerie utilizzabili dagli sviluppatori, che, dopo un’opportuna autenticazione, permettono di leggere e manipolare i dati del servizio stesso.
Nel caso ad esempio delle API di Picasa Web Albums possiamo richiedere la lista dei nostri album oppure ricevere la lista delle immagini contenuto in uno specifico album oppure caricare una foto nell’album e così via.

Oggi voglio parlarvi di una piccola applicazione scritta in Java, che sfrutta l’API del servizio per questo linguaggio, in grado di generare una porzione di codice html partendo da una lista di immagini di uno specifico album caricato in Picasa Web Albums.

Per poter eseguire l’applicazione dovete avere opportunamente scaricato e configurato il pacchetto delle API di Google, impostando correttamente le dipendenze verso i file jar dei servizi che utilizzate.
Per comodità comunque allego in fondo all’articolo l’intero progetto Eclipse zippato.

Il programma deve essere eseguito in due passaggi.
Nel primo passaggio, dopo aver opportunamente modificato l’utente e password, bisogna attendere che il programma stampi a video la lista degli album caricati e i relativi id. Scegliamo a questo punto l’id del nostro album e impostiamolo come valore della variabile albumId.

Rieseguiamo quindi il programma (secondo passaggio) e a questo punto potremmo vedere un output decisamente più ricco che contiene un html generato partendo dai dati e dalle immagini contenuti nell’album specificato.
L’html viene generato utilizzando il motore di templating Velocity a cui è stato passato l’oggetto feed contenente tutti i dati del nostro album. Il file del template è album.vm che si trova all’interno della cartella del progetto di nome templates.
Ovviamente potete modificare a vostro piacimento tale template utilizzando a pieno il modello dei dati messo a disposizione da Google.

Di seguito propongo il codice Java del programma, ovviamente con delle credenziali fasulle:

import java.io.StringWriter;
import java.net.URL;
import java.util.Properties;

import org.apache.velocity.Template;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import com.google.gdata.client.photos.PicasawebService;
import com.google.gdata.data.photos.AlbumEntry;
import com.google.gdata.data.photos.AlbumFeed;
import com.google.gdata.data.photos.UserFeed;

public class Main {
	public static void main(String[] args) {
		try {
			String username = "<username>";
			String domain = "@gmail.com";
			String password = "<password>";
			String albumId = "<empy>";

			PicasawebService myService = new PicasawebService(username);
			myService.setUserCredentials(username + domain, password);

			URL feedUrl = new URL("http://picasaweb.google.com/data/feed/api/user/" + username + "?kind=album");

			UserFeed myUserFeed = myService.getFeed(feedUrl, UserFeed.class);
			for (AlbumEntry myAlbum : myUserFeed.getAlbumEntries()) {
			    System.out.println(myAlbum.getTitle().getPlainText() + " - " + myAlbum.getId());
			}

			URL feedAlbumUrl = new URL("http://picasaweb.google.com/data/feed/api/user/" + username + "/albumid/" + albumId);

			AlbumFeed feed = null;
			try {
				feed = myService.getFeed(feedAlbumUrl, AlbumFeed.class);
			}
			catch (com.google.gdata.util.ResourceNotFoundException rnfe) {
				System.out.println("\nalbum non trovato, controlla l'id");
			}

			if (feed != null) {
				Properties velProps = new Properties();
				velProps.load(Main.class.getResourceAsStream("velocity.properties"));
				Velocity.init(velProps);

				VelocityContext context = new VelocityContext();

				context.put("feed", feed);

				Template template = null;

				try {
				   template = Velocity.getTemplate("templates/album.vm");
				}
				catch( Exception e ) {
					e.printStackTrace();
				}

				StringWriter sw = new StringWriter();

				template.merge( context, sw );

				System.out.println();
				System.out.println(sw);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
}

Questo è invece il codice del template album.vm :

		<h4>$!feed.title.plainText</h4>
		<ul class="gallery clearfix">
#foreach($photo in $feed.getPhotoEntries())
		    <li>
		       <a rel='prettyPhoto[$feed.id]' title="$photo.getDescription().getPlainText()" href='$photo.getMediaContents().get(0).getUrl()' >
		          <img src='$photo.getMediaThumbnails().get(0).getUrl()' width='100' class='thumb' border='0' />
		       </a>
		    </li>
#end
		</ul>

Ecco infine il file compresso contenente il progetto completo in formato Eclipse.

Allungare il tempo delle sessioni in un’applicatione web

Postato da ROb | nella categoria Java, Sviluppo web | giovedì, 15 aprile 2010

0

Per aumentare la durata di una sessione in un’applicazione web Java J2EE è sufficiente inserire una particolare direttiva all’interno del file web.xml dell’applicazione stessa.

Ecco la sintassi:

  ...
  <session-config>
    <session-timeout>120</session-timeout>
  </session-config>
  ...

dove il numero rappresenta i minuti.

Una galleria web di effetto con jQuery e prettyPhoto

Postato da ROb | nella categoria Sviluppo web | lunedì, 22 marzo 2010

2

Grazie a jQuery e ai numerosi plugin che circondano questa libreria ora è davvero semplice e divertente realizzare gallerie web leggere e di effetto.

Galleria di immagini

Oggi voglio presentarvi la galleria che ho realizzato per il sito di Giulia sfruttando jQuery e quello che considero il migliore plugin per la realizzazione di gallerie di immagini (e non solo), prettyPhoto.

Dopo aver scaricato il pacchetto dal sito ufficiale del plugin, ho preparato un pò di foto, creando anche gli opportuni thumbnail con mogrify e ho creato una pagina html che gestisse la galleria.

La realizzazione della galleria di foto, dopo aver opportunamente preparato il codice javascript della pagina, è davvero semplice. Si tratta infatti di creare degli elementi a che puntano alle immagini ingrandite che contengono al loro interno degli elementi di tipo img che visualizzano i rispettivi thumbnail.
Gli elementi di tipo a devono essere opportunamente arricchiti da un paio di attributi. L’attributo rel dichiara l’appartenenza della galleria a un determinato gruppo di foto (in sostanza, un album) mentre l’attributo title serve per sottotitolare la foto con una caption.

Ecco il codice html per ogni singola immagine:

         <li>
            <a rel='prettyPhoto[macerata]' title="La salita delle fosse" href='images/macerata_01.jpg' >
               <img src='images/thumb/macerata_01.jpg' width='100' class='thumb' border='0' />
            </a>
         </li>

Per funzionare la pagina, come anticipato, ha anche bisogno di una dichiarazione di librerie javascript in cima alla pagina:

		<script src="http://www.google.com/jsapi" type="text/javascript"></script>
		<script type="text/javascript" charset="utf-8">
			google.load("jquery", "1.3");
		</script>
		<link rel="stylesheet" href="css/prettyPhoto.css" type="text/css" media="screen" title="prettyPhoto main stylesheet" charset="utf-8" />
		<link rel="stylesheet" href="css/style.css" type="text/css" media="screen" charset="utf-8" />
		<script src="js/jquery.prettyPhoto.js" type="text/javascript" charset="utf-8"></script>

e di un’inizializzazione jQuery contestuale al termine del caricamento della pagina stessa:

		<script type="text/javascript" charset="utf-8">
		$(document).ready(function(){
			$(".gallery a[rel^='prettyPhoto']").prettyPhoto({theme:'facebook'});
		});
		</script>

Ecco la pagina demo che ho realizzato con un pò di fotografie storiche di Macerata e alcune foto della mia labrador Mina.

Il progetto scaricabile è invece in questo link.

Il tema prettyPhoto utilizzato è “facebook”. Ricordo inoltre che prettyPhoto può anche essere utilizzato per visualizzare video, altri siti (tramite iframe) o contenuto html generico.

Rimpiazzare stringhe all’interno di campi di tabelle MySQL

Postato da ROb | nella categoria Sviluppo web, Varie | lunedì, 15 marzo 2010

0

Se avete bisogno di cercare e rimpiazzare una stringa all’interno di un campo in una tabella di un database MySQL esiste la comodissima istruzione replace.

Ipotizziamo di avere la tabella studenti con un campo tel e di voler rimpiazzare tutte le occorrenze del prefisso 0733 con il prefisso +39 0733, ecco il comando SQL per farlo:

update studenti set tel = replace(tel, '0733', '+39 0733');

E’ importante ricordare che la ricerca del testo è case sensitive.

Ulteriori informazioni su replace le trovate nella documentazione ufficiale.

Generatore di testo fasullo, ecco il servizio web farlo

Postato da ROb | nella categoria Sviluppo web, Utilità | mercoledì, 10 marzo 2010

3

Lipsum Generator

Quante volte nei vostri web test o nelle vostre applicazioni avete avuto il bisogno di generare del testo fasullo per riempire le vostre pagine, i campi o alcune tabelle di db?

Ecco un servizio online che lo fa per noi, anche in lingua.
Lipsum generator dà la possibilità di generare il nostro testo fasullo impostando il numero dei paragrafi o dei byte o parole da generare.

Qui sotto trovate il testo generato usando come lingua l’italiano e 10 paragrafi di testo.

Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent pretium tempus augue at congue. Suspendisse quis libero ligula. Donec venenatis, lectus vel vestibulum gravida, massa erat sagittis elit, non lobortis tellus velit a orci. Nulla facilisi. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Proin tempor egestas lectus, id consectetur augue posuere et. Vivamus nec lacus sit amet eros porttitor vulputate. Aenean tristique gravida aliquam. Duis nec commodo mi. Vestibulum vehicula ligula sit amet velit aliquam fringilla. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce non est non lorem vulputate placerat. Phasellus vehicula imperdiet augue. Cras sed nunc diam, non malesuada massa.

Quisque vel condimentum mauris. Sed pretium aliquam lacus, a sodales justo aliquet sed. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse eu nulla ut urna lobortis elementum. Fusce hendrerit sodales tellus, vel mattis nisi sodales id. Vestibulum rhoncus lacus eget leo condimentum ut gravida sem feugiat. Praesent pulvinar risus convallis tellus scelerisque consectetur quis id mi. Donec nec odio eget nibh lobortis posuere. Praesent quis neque vitae dolor feugiat molestie sodales in augue. Nam erat dui, hendrerit sed consequat at, ultricies vel sem. Sed sodales, turpis vitae hendrerit convallis, libero odio elementum nunc, a suscipit leo ante quis ligula. Pellentesque hendrerit est vitae ligula eleifend molestie. Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. In molestie risus a odio faucibus posuere. Integer odio nisl, porta quis commodo a, commodo sed lorem. Nullam tempus neque et dui volutpat posuere.

Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Morbi feugiat posuere lacus ac tempor. Curabitur aliquam, nulla vel luctus tincidunt, nibh turpis pulvinar mi, eget volutpat elit tellus quis dolor. Cras ultricies egestas orci. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos. Praesent mattis, quam eget volutpat malesuada, tellus ipsum porttitor est, vel fringilla lacus nisl quis turpis. Duis a dui dolor. Praesent sodales vulputate leo ut aliquet. Quisque pretium adipiscing placerat. Praesent congue aliquam consectetur. Praesent porta nibh ornare est eleifend vulputate. Curabitur ac dignissim nisl. Mauris rutrum, sem semper vulputate tristique, purus mi pharetra libero, ut elementum est sem eget libero. Mauris a diam in nisl elementum gravida et in urna. Praesent ante neque, porttitor in varius at, blandit tempor tortor. Aliquam pulvinar fringilla est, sit amet auctor purus hendrerit et. In hac habitasse platea dictumst.

Vivamus massa turpis, tempus eget viverra et, cursus eu turpis. Aenean metus dolor, faucibus a tempus ut, condimentum in nunc. Aliquam vitae consectetur quam. Suspendisse potenti. Curabitur semper scelerisque magna, vel egestas ligula accumsan a. Integer blandit faucibus est at adipiscing. Nulla lobortis euismod nulla non egestas. Nunc imperdiet fermentum nibh, a interdum est pharetra id. Praesent a diam in massa ultrices lacinia sit amet sit amet elit. Phasellus consectetur viverra luctus. Nam et justo eu tellus scelerisque rutrum. Suspendisse potenti. Nunc porttitor nibh vitae orci adipiscing a imperdiet orci viverra. Phasellus eleifend porta lorem, sollicitudin interdum elit scelerisque eget. Integer euismod egestas nibh, quis sollicitudin enim imperdiet ut.

Nulla sit amet urna eros. Suspendisse adipiscing aliquam lorem, nec gravida sem consectetur a. Nullam metus augue, ullamcorper sit amet vestibulum in, blandit pellentesque augue. Vivamus eu consectetur lacus. Cras eu nisl eget nulla sagittis sagittis sed in dui. In mollis feugiat sapien id aliquet. Phasellus cursus malesuada congue. Fusce vel nulla ac tellus ullamcorper fermentum. Nunc pellentesque diam in magna fermentum eu ultrices metus auctor. Quisque sit amet risus ut est aliquet iaculis elementum et velit. Curabitur viverra tempus quam non dapibus. Donec eros tortor, varius sed iaculis sit amet, tincidunt ut diam. Quisque ac vulputate lectus. Donec id sem et ipsum dapibus rhoncus. Mauris ac tellus ut nulla auctor interdum vitae ut nisi. Nulla nec justo purus, sed egestas ligula. Morbi eget erat orci.

Nulla elementum neque in ligula posuere et convallis leo cursus. Pellentesque iaculis feugiat venenatis. Aliquam sapien nisl, eleifend et mattis aliquam, malesuada et lacus. Nam porttitor tellus eu neque rhoncus ultrices. Nulla facilisi. Nulla id sollicitudin est. Suspendisse condimentum tincidunt nisl, quis venenatis leo pretium eu. Curabitur ac libero neque. Integer felis nunc, vestibulum ultrices porttitor nec, ornare in arcu. Proin ac volutpat odio. Praesent eget risus vitae felis tincidunt ullamcorper. Fusce in augue vel tellus imperdiet tincidunt in quis urna. Vestibulum porttitor nibh vitae tortor faucibus faucibus.

Phasellus orci mauris, dapibus quis semper vel, vestibulum ac dui. Vivamus velit libero, egestas eget rutrum eu, venenatis id tellus. Nulla facilisi. Mauris in lectus vitae mauris molestie convallis. Curabitur nisi lectus, feugiat eget rhoncus eget, dictum at tellus. Cras purus eros, malesuada id elementum eu, varius sed ligula. Sed consectetur blandit libero, eget viverra enim tincidunt at. Donec id sem vel ante condimentum sodales id ut nulla. Vestibulum quis tortor quam, ac consectetur tellus. Donec suscipit neque a leo suscipit interdum. Duis sed justo massa. Phasellus rhoncus vehicula elit, eu vulputate augue egestas et. In ac quam nulla.

Duis tellus erat, vestibulum ut vestibulum ac, molestie eu purus. Praesent vel quam nec neque feugiat venenatis quis vitae libero. Proin ac lectus erat. Nulla porta, orci ut fermentum ullamcorper, leo ipsum vehicula erat, placerat iaculis eros nisl vitae sem. Donec lacinia massa vitae erat dignissim pellentesque. Fusce sit amet sapien a turpis hendrerit convallis in nec leo. Cras facilisis dignissim enim a imperdiet. Mauris nisi ante, ultricies a commodo ut, elementum ac nisl. Mauris venenatis vestibulum nulla a pulvinar. Duis vel nisi at turpis condimentum dictum eget eu sapien. Fusce eget semper ligula. Vestibulum congue rutrum placerat. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Vivamus tellus leo, ultricies vel gravida ac, volutpat non orci. Curabitur bibendum arcu ut augue tempus sed vulputate lorem dapibus. Aenean porttitor rhoncus ante rutrum rhoncus. Donec ac sem orci, at tempor nunc. Donec eleifend elit ac libero ultricies non ultricies mi hendrerit. Suspendisse vitae lacus ac enim euismod commodo. Praesent euismod velit id diam suscipit euismod.

Donec gravida urna vel ligula lacinia et auctor lacus laoreet. Etiam feugiat est eget erat molestie vel adipiscing nulla cursus. Proin feugiat, risus sit amet blandit mattis, leo urna sodales neque, vel commodo leo arcu at erat. Pellentesque ut ligula eu tellus pretium convallis. Vivamus euismod libero sit amet eros suscipit sollicitudin. Nullam bibendum convallis dolor a luctus. Pellentesque sed dolor diam, vel scelerisque purus. Aliquam consequat imperdiet euismod. Suspendisse dolor tellus, viverra sit amet porta nec, venenatis ac lacus. Maecenas imperdiet magna sit amet magna interdum sit amet facilisis urna aliquam. Phasellus eu metus quis orci ultricies pretium eu sit amet tellus. Nulla dignissim arcu ut magna varius convallis. Aliquam consequat congue augue nec blandit. Phasellus condimentum convallis accumsan. Nunc varius ipsum vel mi faucibus porta. Nulla lacinia sem vel neque fringilla a interdum purus sollicitudin. Duis nec arcu nisl, scelerisque aliquet odio. Nulla velit neque, tincidunt ac posuere sit amet, elementum vitae lorem. Etiam ullamcorper leo ac nulla venenatis egestas. Morbi turpis ante, tempor dictum consectetur non, auctor sit amet est.

Aenean quis sem neque. Nullam a tellus nisi. Morbi sit amet orci eros, volutpat commodo enim. Sed ullamcorper arcu vel nunc aliquam feugiat. Vestibulum ut augue in nibh lacinia mollis. Nam sit amet lorem dolor, id molestie odio. Aliquam pulvinar mi vitae enim tincidunt et aliquam mi ullamcorper. Praesent et nibh leo. Morbi id ante quis sapien fermentum feugiat eu feugiat justo. Sed posuere, mi et posuere lobortis, felis libero auctor mauris, in ornare eros elit a eros. Quisque laoreet ullamcorper interdum.

L’alternativa open di Google Analytics: Piwik

Postato da ROb | nella categoria Sviluppo web, Utilità | sabato, 6 marzo 2010

2

Chi lavora nel mondo dello sviluppo web e del web marketing sicuramente conosce ed utilizza quotidianamente Google Analytics.
Veloce, flessibile, potente e pochissimo invasivo… queste tutte le qualità di GA (Google Analytics) a costo zero.
A tutto questo però si contrappongono due aspetti: non è open source e non abbiamo tutti i dati dei nostri accessi (ma solamente i dati aggregati, nelle varie forme, che Google ci presenta).

statistics

Pochi giorni fa mi sono imbattuto in questo interessantissimo progetto di nome Piwik che, dichiaratamente, si propone come l’alternativa open a GA.

L’installazione richiede un server con PHP dalla versione 5.1.3 in poi e MySQL dalla versione 4.1 in avanti.
Al termine dell’installazione è possibile iniziare a creare i profili dei nostri siti.
Il meccanismo di tracking degli accessi è molto simile a quello di GA; Piwik, per ogni sito, genera una porzione di codice Javascript da copiare e incollare nelle nostre pagine.

Per quanto riguarda la pagina di visualizzazione dei dati raccolti è altamente customizzabile e già multilingua. Il meccanismo di personalizzazione sfrutta il concetto degli widget.
In pratica la dashboard è composta da una serie di widget predefiniti e altri creabili ed aggiungibili a piacere.

piwik screenshot

Ciliegina sulla torta inoltre la possibilità di inserire le statistiche di Piwik direttamente nel nostro sito in tempo reale.

A questo indirizzo è disponibile la demo online, mentre questa è la pagina del progetto.

Come caricare un file sul server in AJAX

Postato da ROb | nella categoria Sviluppo web | martedì, 2 marzo 2010

2

I form html tradizionali negli anni hanno dimostrato numerosi limiti. Quelli più notevoli erano impossibilità di effettuare validazione server side, impossibilità di gestire dei campi autopopolati durante la digitazione, post completo del form senza possibilità di parzializzazione.

Ajax file upload

Tutte queste cose hanno reso il web uno strumento difficilmente utilizzabile per applicazioni che richiedessero un’elevata interazione con l’utente.
Negli ultimi anni AJAX ha rivoluzionato i tradizionali form html permettendo ai programmatori di poter dialogare agilmente con il loro backend e permettendo agli utenti di godere una più dinamica esperienza web.

Recentemente ho avuto la necessità di gestire un campo file in un form ajax. Per form ajax intendo un form che invia i suoi dati serializzati al server e non fa il post dell’intera pagina.
La tecnologia utilizzata era jQuery così ho cercato un plugin che si integrasse bene con tale tecnologia e ho trovato AJAX Upload.

Inseriamo innanzitutto gli script javascript nell’header necessari alla definizione di jQuery e del plugin AJAX Upload:

...
<head>
...
<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="js/ajaxupload.js"></script>
...
</head>
...

A questo punto bisogna creare il div che cliccato avvierà la procedura di caricamento file:

<div id="upload_button">Upload</div>

Infine dobbiamo inizializzare i campi di tipo file all’interno del nostro form:

$(document).ready(function() {
    new AjaxUpload('upload_button_id', {action: 'uploadServletPath'});
}

Al rendering della pagina cliccando sul div upload_button si aprirà la finestra di dialogo per la scelta del file e il file sarà direttamente inviato via POST (senza però il POST dell’intera pagina) alla servlet di upload che abbiamo specificato nell’inizializzazione del componente.

Nel costruttore di inizializzazione possiamo anche passare altri parametri di configurazione e gestire alcuni eventi precedenti (o successivi) al caricamento utili per valorizzare altre variabili del form o per visualizzare la progressione del caricamento o il nome del file caricato sul server.
E’ anche possibile stabilire il tipo di risposta ricevuta dal server: html, xml o json.

Per chi fosse interessato ecco il codice Java necessario al salvataggio del file:

/*
 *	author: Roberto Rossi
 */
package it.bits4beats.servlets;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.FileItemFactory;
import org.apache.commons.fileupload.disk.DiskFileItemFactory;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.io.*;
import java.util.Iterator;
import java.util.List;

public class UploadServlet extends HttpServlet {
	private static Log log = LogFactory.getLog(UploadServlet.class);
	public static final String DEFAULT_UPLOAD_DIR_INIT_PARAM = "DefaultUploadDir";

	/**
	 *
	 */
	private static final long serialVersionUID = 1L;

	/**
	 * This is a default constructor for UploadServlet class.
	 *
	 */
	public UploadServlet(){
	}

	public void init() throws ServletException {
		super.init();
	}

	/**
	 * Receive a file to be uploaded and save it into filesystem
	 */
	public void doGet(HttpServletRequest request,
			HttpServletResponse response)
	throws ServletException,java.io.IOException {
		log.info("method not supported!");
	}

	public void doPost(HttpServletRequest request,
			HttpServletResponse response)
	throws ServletException,java.io.IOException {

		String defaultUploadDir = getServletConfig().getInitParameter(DEFAULT_UPLOAD_DIR_INIT_PARAM);
		if (defaultUploadDir != null && !defaultUploadDir.equals("")) {
			log.debug("> default upload dir: " + defaultUploadDir);
		}

		/* the uploading user */
		String username = request.getParameter("username");
		/* max size of file upload */
		String sizeParam = request.getParameter("sz");
		Long maxBytes = null;
		if (sizeParam != null && !sizeParam.isEmpty()) {
			try {
				/* max 5Mb file uploaded */
				maxBytes = new Long(5242880);
			}
			catch (NumberFormatException nfe) {
				/* do nothing */
			}
		}

		log.debug("remote user: " + request.getRemoteUser());
		log.debug("user principal: " + (request.getUserPrincipal() == null ? "" : request.getUserPrincipal().getName()) );
		log.debug("username: " + username);

		String status = "true";
		String message = "";
		String savedfilename = "";
		String attachmentname = "";
		String originalFilename = "";

		/* reading file streams */
		boolean isMultipart = ServletFileUpload.isMultipartContent(request);

		if (isMultipart) {

			FileItemFactory factory = new DiskFileItemFactory();
			ServletFileUpload upload = new ServletFileUpload(factory);
			List items = null;
			try {
				items = upload.parseRequest(request);

				if (items != null && items.size() > 0) {

					File uploadDirFile = null;
					String uploadDirFileRelativePath = null;

					uploadDirFile = new File(getServletContext().getRealPath(defaultUploadDir));
					uploadDirFileRelativePath = defaultUploadDir;

					Iterator itr = items.iterator();

					FileItem fileItem = null;
					FileItem filenameItem = null;

					while(itr.hasNext()) {
						FileItem item = (FileItem) itr.next();

						if (!item.isFormField()) {
							fileItem = item;
						}
						else {
							if (item.getFieldName().equals("attachmentFilename")) {
								filenameItem = item;
								log.debug("filenameItem name: " + filenameItem.getFieldName() + " valore: " + filenameItem.getString());
							}
						}
					}

					if (fileItem != null) {
						/* there is a file item in the request */
						String fileName = fileItem.getName();
						log.debug("fileItem name: " + fileName);

						if (fileItem.getName().contains("\\")) {
							log.debug("Windows file");

							/* windows file path */
							fileName = fileItem.getName().substring(fileItem.getName().lastIndexOf("\\") +1);
							log.debug("fileItem name: " + fileName);
						}

						File fullFile  = new File(fileName);
						File savedFile = new File(uploadDirFile, fileName);

						if (savedFile != null) {

							/* check file size */
							if (maxBytes != null) {
								if (fileItem.getSize() > maxBytes.longValue()) {
									FileTooBigException ftbe = new FileTooBigException();
									ftbe.setMaxSize(new Long(maxBytes.longValue()/1024/1024).toString());
									throw ftbe;
								}
							}

							if (savedFile.exists()) {
								/* we need to create a file variant, save it and send it to the user */
								String fileNameWithoutExtension = savedFile.getName().substring(0, savedFile.getName().lastIndexOf("."));
								originalFilename = fileNameWithoutExtension;
								String suffix = savedFile.getName().substring(savedFile.getName().lastIndexOf(".") + 1);

								File newFile = File.createTempFile(fileNameWithoutExtension + "_", "." + suffix, uploadDirFile);
								fileItem.write(newFile);

								log.debug("newFile: " + newFile.getAbsolutePath());
								status = "true";
								message = "OK " + newFile.length() + " byte salvati";

								/* relative file path */
								savedfilename = uploadDirFileRelativePath + newFile.getName();
								String filenameWithExt =  extractFilenameWithExtensionFromPath(savedfilename);
								attachmentname = extractFilename(filenameWithExt);
							}
							else {
								log.debug("writing file to: " + savedFile.getAbsolutePath());
								originalFilename = extractFilename(extractFilenameWithExtensionFromPath(savedFile.getAbsolutePath()));
								fileItem.write(savedFile);

								status = "true";
								message = "OK " + savedFile.length() + " byte salvati";

								/* relative file path */
								savedfilename = uploadDirFileRelativePath + fullFile.getName();
								String filenameWithExt =  extractFilenameWithExtensionFromPath(savedfilename);
								attachmentname = extractFilename(filenameWithExt);
							}
						}
						else {
							log.error("cannot create file");
							status = "false";
							message = "Errore generico di salvataggio";
						}
					}

				}
				else {
					log.debug("no item to be saved");
				}
			}
			catch (FileTooBigException ftbe) {
				status = "false";
				message = "File troppo grande, dimensione massima (Mb): " + ftbe.getMaxSize();
			}
			catch (Exception e1) {
				e1.printStackTrace();
				log.error("error in uploading");

				status = "false";
				message = "Errore generico di salvataggio";
			}
		}

		PrintWriter out = response.getWriter();

		String responseMessage = "{\"success\":" + status + ",\"message\":\"" + message + "\",\"savedfilename\":\"" + savedfilename + "\",\"attachmentname\":\"" + attachmentname + "\",\"originalfilename\":\"" + originalFilename + "\"}";
		log.debug("responseMessage: " + responseMessage);
	    out.println(responseMessage);
	}

	/**
	 * This method extract filename (with extension) from filepath
	 *
	 * @param filepath
	 * @return filename without extension
	 */
	public static String extractFilenameWithExtensionFromPath(String filepath) {
		if (filepath != null) {
			int index = filepath.lastIndexOf("/");

			if (index > 0 && index < (filepath.length() -1)) {
				return filepath.substring(index + 1);
			}
			else return null;
		}
		else {
			return null;
		}
	}

	/**
	 * This method extract filename (without extension) from filename with extension
	 *
	 * @param filepath
	 * @return filename without extension
	 */
	public static String extractFilename(String filenameWithExtension) {
		if (filenameWithExtension != null) {
			int index = filenameWithExtension.lastIndexOf(".");

			if (index > 0) {
				return filenameWithExtension.substring(0, index);
			}
			else return filenameWithExtension;
		}
		else {
			return null;
		}
	}

	class FileTooBigException extends Exception {
		private static final long serialVersionUID = 1L;

		private String maxSize = null;

		public String getMaxSize() {
			return maxSize;
		}

		public void setMaxSize(String maxSize) {
			this.maxSize = maxSize;
		}

		public FileTooBigException() {
			super();
		}

		public FileTooBigException(String message) {
			super(message);
		}
	}

}

Nel sito del plugin trovate anche una demo completa e funzionante di AJAX upload.

Comprimere il codice Javascript con YUI Compressor

Postato da ROb | nella categoria Sviluppo web | mercoledì, 17 febbraio 2010

0

Molte librerie javascript vengono distribuite in un formato compresso (o minimizzato).

Se aprite i file in questo formato non riuscirete a leggere granché per via del fatto che tutti gli spazi e gli a capo sono stati sacrificati per risparmiare byte preziosi.

Compressione librerie Javascript

Mi sono sempre chiesto come fossero riusciti a realizzare tali file.
Beh la risposta è molto semplice: ci sono programmi appositi per farlo.

Uno di questi è YUI Compressor, un tool sviluppato dal YUI Team.
YUI Compressor è stato scritto in java e il suo utilizzo è veramente immediato.

Dopo aver scaricato la distribuzione (la versione attuale è la 2.4.2) e ipotizzando di averla scompattata nella directory /opt/ , potete avviare la minimizzazione del vostro codice attraverso questo comando:

java -jar /opt/yuicompressor-2.4.2/yuicompressor-2.4.2.jar --type js vostrofilejavascript.js

Il codice minimizzato verrà stampato a video. A questo punto potete salvarlo in un file.

Se volete invece salvarlo in un file minimizzato potete redirezionare direttamente lo standard output in questo modo:

java -jar /opt/yuicompressor-2.4.2/yuicompressor-2.4.2.jar --type js vostrofilejavascript.js > vostrofilejavascript.min.js