PHP Code metrics statistics

I believe doing statistics about the quality of the code it can be a good incentive for developers to improve their application and for new coming developers in the project to see a well structured program and put easily their hands on.

Sometime ago I started to verify the quality of the code of Drupal using PHPdepend in Jenkins a bit for fun, so every time there was a new commit pdepend was launched to analyze the code.

I noticed in the code that the threshold to identify max and min limits were based on Java threshold (these threshold have been published in the book “Object Oriented Metrics in Practice” which you can find also in slideshare (slide 12)) which of course cannot be a good comparison since PHP and Java are 2 different programming languages, so I started to analyze other software in order to calculate an average and defining new thresholds.

The comparison was done with pdepend 0.10.7 (I am aware of the version 1.0.0) on 60 php projects which I selected in different environments.

You can find the file at the link Comparison of php application to determine thresholds in pdepend.

Even though you can find a degree among all the applications, it could be more interesting doing  it between similar application (CMS, etc.) .

The summary is:
MIN – AVG – MAX
cyclo-loc:    0.16 – 0.20 – 0.24 (not changed)
loc-nom:        13 –    20 –    27 (doubled)
nom-noc:         5 –   12 –    18
noc-nop:          1 –   14 –    27
calls-nom:   2.66 – 3.68 – 4.69
fanout-calls: 0.01 – 0.06 – 0.11 (much lower)
andc:          0.27 – 0.52 – 0.76
ahh:            0.17 – 0.37 – 0.58

What it is interesting to see is that the line of code for each method is doubled and the fanout-calls is much lower (then the next question would be: why ?), it would be even more interesting to see how the new versions of each application change or with the new version of pdepend, If I had more time I would like to work on it but at least I shared this thought with you :-)

I hope this result can be of inspiration somebody else :-)

Advertisements

Selenium: testing PDF with Calibre

During my test activities I have arrived at the point that I need to test generated PDFs containing the same text that I have in a html page.

So I searched different PDF utilities that can be used through a command line to extract text out of a PDF, among these I found: pdftotext (a command line tool coming with xpdf), Calibre (an ebook manager/converter), Tika (used by Solr to index pdf content), pdfbox (a java application library that extract pdf).

Giving a better look Calibre is using poppler as library and pdftotext is using poppler as well while Tika is based on pdfbox library to extract text.

At the end I chose Calibre for different reasons:

  1. Calibre allows to extract hyperlinks from the pdf (main reason) when using a wiki syntax like textile (I didn’t find this possibility in pdftotext, tika or pdfbox) on the other side the generated text is with wiki syntax
  2. The development life cycle of Calibre is quite fast (compared with xpdf)
  3. Calibre points to release the application for Windows, Mac and Linux (with xpdf you can have different versions but the one for Mac is released on 2007)

Note that I don’t care the possibility to extract text from images, I know that with pdfimages command it is possible to extract them or other formats that tika can support.

I have to say that in terms of performance on the pdf I tested pdftotext is the fastest (0.01 sec), followed by pdfbox (1.7 sec), Calibre (2.3 sec) and then Tika (2.8 sec) on page , so if you don’t care about hyperlinks but just PDF text I would suggest to go to pdftotext.

After choosing Calibre I created a simple php application that:

  1. receives as parameter the URL of a PDF
  2. calls Calibre with different options on the PDF downloaded
  3. removes  some text (like empty lines, etc.)
  4. gives back an xml file with all the text generated.

I created then a selenium command that calls the php file (through an xmlhttp request) and search for a particular text (specified as input together with the url of the pdf file).

Php application (convert.php):

<?php
$content = file_get_contents($_GET['url']);
$filefrom = 'extract.pdf';
$fileto = preg_replace("/\.pdf$/","",$filefrom).".txt";
file_put_contents($filefrom,$content);
//$t_start = microtime(true);
//system("java -jar tika.jar -t ".escapeshellcmd($filefrom)." > ".escapeshellcmd($fileto),$ret);
system("ebook-convert ".escapeshellcmd($filefrom)." ".escapeshellcmd($fileto)."  >nul 2>&1",$ret);
//system("pdftotext -nopgbrk -raw ".escapeshellcmd($filefrom)." ".escapeshellcmd($fileto),$ret);
//system("java -jar pdfbox.jar ExtractText  ".escapeshellcmd($filefrom)." ".escapeshellcmd($fileto),$ret);
//$t_end = microtime(true);
if($ret==0){
  $value=file_get_contents($fileto);
  $value_empty_line=preg_replace("/(^[\r\n]*|[\r\n]+)[\s\t]*[\r\n]+/", "\n", $value);
  $text=preg_replace("/(\[.*\]\n)/","",$value_empty_line);
  unlink($fileto);
  header('Content-type: text/xml');
  echo "<result>".htmlspecialchars($text)."</result>";
}
else{
  header('Content-type: text/xml');
  echo "<result>Convertion failed</result>";
}
?>

Selenium command (assertSearhInPDF):

Selenium.prototype.assertSearchInPDF = function(uri,names){
  var baseurl = globalStoredVars['host'];
  var params = [{"param" : "url","value" : storedVars[uri],}];
  var lista = "";
  for(var i=0; i<params.length; i++){
    lista +="&" + params[i].param + "=" + encodeURIComponent(params[i].value);
  }
  var indirizzo = baseurl+"/test/convert.php?"+lista;
  LOG.info( 'indirizzo = ' + indirizzo);
  var responseXML = chiamaWebService(indirizzo);
  LOG.info( 'response = ' + responseXML);
  var text = responseXML.getElementsByTagName('result')[0].firstChild.nodeValue;
  text = text.replace(/(\n)/g, " ");
  var array = names.split('|');
  var result=0;
  var length=array.length;
  LOG.info( 'text = ' + text);
  for (var i = 0; i < length; i++){
    if(text.indexOf(array[i]) !==-1){
      LOG.info( 'Found = ' + array[i]);
      result=result+1;
      text=text.substring(text.indexOf(array[i]));
    }
    else{
      LOG.info( 'Element ' + array[i]+' not found');
      break;
    }
  }
  if(result!=length)
    Assert.fail("Not all the elements have been found");
};

In particular the selenium command can accept a list of elements (separated by “|”) to searched in the respective order, if they are not found the command fails.

Selenium e il controllo sul tipo di file

Come caso d’uso mi era stato chiesto di verificare che il tipo di file  generato da una pagina web fosse PDF (qualora si cliccasse sull’icona in alto a destra) , vedi: http://ec.europa.eu/ewsi/en/info_sheet.cfm?ID_CSHEET=53

Come forse già sapete non potete sapere via javascript il tipo di file (potete controllare l’estensione ma non è certamente la stessa cosa) però è possibile in PHP tramite le funzioni FileInfo (vedi: http://www.php.net/manual/en/ref.fileinfo.php).

Volevo quindi creare un comando di Selenium che dato l’url di un file mi verifica se questo è del tipo che mi interessa (nel mio caso PDF, ma l’ho generalizzato).

Guardiamo prima il test selenium:

test_pdf
open /ewsi/en/index.cfm
clickAndWait link=Country info >
clickAndWait link=Italy
storeAttribute //div[@id=’fontpriv’]/a[1]@href linkfile
checkFileType linkfile PDF

Dunque nella variabile linkfile è contenuto il link (relativo alla base url nel mio caso http://ec.europa.eu) al file generato, chiamo poi il mio comando checkFileType che controlla che a quel link (trasformandolo in indirizzo assoluto) ci sia un file di tipo PDF.

Andiamo a vedere il file javascript da usare come user extension:

Selenium.prototype.doCheckFileType = function(uri,filetype){

    var baseurl = "http://ec.europa.eu";

    var params = [
	 {
	 "param" : "url",
	 "value" : baseurl+storedVars[uri],
	 }
	 ];

     var lista = "";
	 for(var i=0; i<params.length; i++){
	 	lista +="&" + params[i].param + "=" + encodeURIComponent(params[i].value);
	 }

	proxytype = "http://localhost/tipo.php?";
	var indirizzo = proxytype+lista;
	LOG.info( 'indirizzo = ' + indirizzo);

	var responseXML = chiamaWebService(indirizzo);
	LOG.info( 'response = ' + responseXML);
	var valore = responseXML.getElementsByTagName('filetype')[0].firstChild.nodeValue;

    valore = valore.substring(0,3);

    Assert.matches(filetype, valore);
};

Vi manca la funzione chiamaWebService che potete trovare nell’articolo precedente.

Potete vedere che ho lasciato il tutto molto generico (ciclo for che non serve a molto):

  1. ho semplicemente aggiunto la base url ed estratto l’url dalla variabile uri memorizzata nell’array storedVars
  2. chiamo il web service all’indirizzo http://localhost/tipo.php (che andiamo a vedere dopo)
  3. salvo nella variabile valore la risposta XML (ed estraggo i primi 3 caratteri che contengono il tipo del file). Il contenuto della risposta si trova dentro il tag <filetype>.
  4. verifico che il contenuto della variabile valore corrisponda al tipo che ho richiesto con la Assert.matches (se corrisponde il comando passa altrimenti genera un errore del tipo: [error] Actual value ‘GIF’ did not match ‘PDF’).

Ovviamente se la variabile linkfile contiene un indirizzo assoluto potete lasciare vuota la variabile baseurl o rimuoverla.

Andiamo a vedere il codice del file tipo.php:

<?php
    $content = file_get_contents($_GET['url']);
    $finfo = new finfo;
    $fileinfo = $finfo->buffer($content);
    header('Content-type: text/xml');
    echo "<filetype>".$fileinfo."</filetype>";
?>

Come potete vedere il file php è molto semplice, prima otteniamo il contenuto del file con file_get_content dalla url passata per parametro (nota che la url passata da javascript è codificata, in questa maniera potete passare url con parametri) e poi con finfo->buffer otteniamo il tipo di file che scriviamo dentro il file xml che restituiamo.

Buon weekend !

Estendere Selenium per validare pagine web, parte 2

Nel precedente articolo abbiamo visto come sia semplice fare delle chiamate XmlhttpRequest da Selenium testando il tutto sul css validator.

In un’ottica di automatizzare i test di selenium con Hudson (vedi plugin), potremmo pensare anche di salvare o di inviare per email il report generato da guardare in un secondo momento.

Per fare ciò invece di chiamare direttamente il validator potremmo chiamare un proxy scritto in PHP (o in un altro linguaggio) che:

  1. prende in input l’indirizzo della pagina da validare, l’indirizzo email e il tipo di validazione (CSS21, CSS3 ecc)
  2. chiama il validator e ottiene il report in xml
  3. salva il report in html e invia l’html per email (usando un file xslt per fare la trasformazione da xml a html)
  4. restituisca il report xml.

Andiamo a vedere dunque il comando da selenium:

storeLocation entry
checkCss ${entry} validity, email=emidiostani@gmail.com, profile=CSS21
verifyExpression ${validity} true

Come potete vedere una volta memorizzato l’indirizzo della pagina corrente nella variable entry, passiamo tale indirizzo al comando checkCss che restituisce il valore della variabile validity e prende come opzioni l’email e il profile (magari è meglio spostarli nella colonna di centro in futuro). Verifichiamo alla fine che il valore della variabile validity sia true.

Andiamo a vedere il codice (vi risparmio la funzione chiama WebService che abbiamo già visto nel precedente articolo):

Selenium.prototype.doCheckCss = function( uri, names ){

 var email = "";
 var profile = "";
 var array = names.split(',');
 for (var i = 0; i < array.length; i++){
 var name = array[i].trim();
 if(name.substr(0,5)=="email"){
 LOG.info( 'email = ' + name);
 var email_array = name.split('=');
 email = email_array[1];
 }
 else if(name.substr(0,7)=="profile"){
 LOG.info( 'profile = ' + name);
 var profile_array = name.split('=');
 profile = profile_array[1];
 }
 }

 var params = [
 {
 "param" : "uri",
 "value" : uri,
 },
 {
 "param" : "email",
 "value" : email,
 },
 {
 "param" : "profile",
 "value" : profile,
 },
 ];

 var lista = "";
 for(var i=0; i<params.length; i++){
 lista +="&" + params[i].param + "=" + encodeURIComponent(params[i].value);
 }

 var proxycss ="http://192.39.226.51/proxycss.php?";
 var indirizzo = proxycss+lista;
 LOG.info( 'indirizzo = ' + indirizzo);

 var responseXML = chiamaWebService(indirizzo);
 LOG.info( 'response = ' + responseXML);

 for (var i = 0; i < array.length; i++){
 var name = array[i].trim();
 if(name.substr(0,5)!="email" && name.substr(0,7)!="profile"){
 var name2 = "m:"+name;
 LOG.info( 'name2 = ' + name2);
 storedVars[name] = responseXML.getElementsByTagName(name2)[0].firstChild.nodeValue;
 LOG.info( 'callWebService: returned [' + storedVars[name] + ']' );
 }
 }
};

Nella prima parte estraiamo le opzioni email e profile da inserire insieme all’indirizzo (uri) nell’array params.

Concateniamo poi i parametri all’inidirizzo del proxy che contattiamo con la chiamaWebService (notate l’indirizzo ip che ovviamente dovete cambiare).

Estraiamo infine dalla risposta xml i parametri che abbiamo passato (ad eccezione di email e profile) da memorizzare nell’array associativo storedVars (predefinito per Selenium).

Ci resta da vedere il proxy php che dunque deve ricevere uri, email e profile e intrinsecamente:

  1. l’indirizzo della css validator (più altri parametri impliciti)
  2. il path del file xslt da applicare
  3. il path del report da salvare

Ed ecco il codice:

<?php

$uri = trim($_REQUEST['uri']);
$profile = trim(strtolower($_REQUEST['profile']));
$email = trim(strtolower($_REQUEST['email']));
$css = "http://192.39.226.51:8081/css-validator/validator?";
$usermedium = "all";
$warning = "1";
$lang = "en";
$output = "soap12";

if($profile =='')
 $profile="css21";
$address = $css."uri=".$uri."&profile=".$profile."&usermedium=".$usermedium."&warning=".$warning."&lang=".$lang."&output=".$output;
$result = file_get_contents($address);

$XSL = new DOMDocument();
$XSL->load( '/var/www/rest_style_css.xslt', LIBXML_NOCDATA);
$xslt = new XSLTProcessor();
$xslt->importStylesheet( $XSL );
$XML = new DOMDocument();
$XML->loadXML( $result );
$html = $xslt->transformToXML( $XML );

$dir = "reports/css/";
$report = "css-report-". date("H:i:s").".html";
$pathmyFile = "/var/www/".$dir.$report;
$fh = fopen($pathmyFile, 'w') or die("can't open file");
fwrite($fh, $html);
fclose($fh);

if($email !=''){
 $to = $email;
 $subject = 'CSS validation';
 $addresstomyfile = "<a href=http://".$_SERVER['SERVER_ADDR']."/".$dir.$report.">".$report."</a>";
 $message = "Report generated: ".$addresstomyfile." on ".date("j F, Y, g:i a")."\n".$html;
 $headers  = "From: Selenium Server<selenium.server@gmail.com>\r\n";
 $headers .= 'MIME-Version: 1.0' . "\r\n";
 $headers .= 'Content-type: text/html; charset=iso-8859-1' . "\r\n";
 mail($to, $subject, $message, $headers);
}

header('Content-type: text/xml');
echo $result;
?>

Si suppone dunque che:

  1. avete  la libreria xml e xsl per php (riavviate apache dopo averla installata)
  2. avete creato la cartella reports/css sotto la var/www
  3. avete creato un file xslt (che trovate alla fine dell’articolo) nella var/www
  4. abbiate una applicazione come sendmail che è in ascolto per mandare email

Il codice è facile da leggere:

  • una volta estratti i parametri li concateniamo per chiamare il validator con il metodo file_get_content(),
  • convertiamo il file xml ottenuto in html tramite il file xslt
  • salviamo tale file nella cartella reports/css
  • se l’email era stata passata come opzione allora mandiamo email l’html ottenuto
  • restituiamo (possiamo vedere anche tramite browser) il risultato xml

Potremmo in futuro passare solo una parte del risultato xml per risparmiare banda usata.

Ora potete fare lo stesso con w3c validator (su Ubuntu installate w3c-markup-validator), rss validator (ho testato in remoto ma non installato), l’achecker per l’accessibilità (che potete traquillamente installare (vi consiglio da svn).

File xslt da usare:

<?xml version="1.0"?>
<xsl:stylesheet xmlns:m="http://www.w3.org/2005/07/css-validator" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 <xsl:output method="html" encoding="UTF-8"/>
 <xsl:template match="m:cssvalidationresponse">
 <html>
 <head>
 <title>CSS report</title>
 </head>
 <body>
 <table width="100%">
 <TR bgcolor="#f7f3fd">
 <TD colspan="6">Analyzed web page address:
 <a href="{m:uri}" onclick="popup('{m:uri}; return false;')" title="{m:uri}" target="_new">
 <xsl:value-of select="m:uri" />
 </a>
 </TD>
 </TR>
 <TR bgcolor="#f7f3fd">
 <TD colspan="3"><B>Errors</B></TD>
 </TR>
 <TR bgcolor="#f7f3fd">
 <TD><B>Line</B></TD>
 <TD><B>Error Type</B></TD>
 <TD><B>Context</B></TD>
 <TD><B>Error Subtype</B></TD>
 <TD><B>Skipped String</B></TD>
 <TD><B>Message</B></TD>
 </TR>
 <xsl:for-each select="m:result/m:errors/m:errorlist/m:error">
 <tr>
 <xsl:if test="(position() mod 2 = 1)">
 <xsl:attribute name="bgcolor">#EEEEFF</xsl:attribute>
 </xsl:if>
 <TD><xsl:value-of select="m:line" /></TD>
 <TD><xsl:value-of select="m:errortype" /></TD>
 <TD><xsl:value-of select="m:context" /></TD>
 <TD><xsl:value-of select="m:errorsubtype" /></TD>
 <TD><xsl:value-of select="m:skippedstring" /></TD>
 <TD><xsl:value-of select="m:message" /></TD>
 </tr>
 </xsl:for-each>
 </table>
 <br/>
 <table width="100%">
 <TR rowspan="4" bgcolor="#f7f3fd">
 <TD width="10%"><B>Warnings</B></TD>
 </TR>
 <TR bgcolor="#f7f3fd">
 <TD width="10%"><B>Line</B></TD>
 <TD width="10%"><B>Level</B></TD>
 <TD width="70%"><B>Message</B></TD>
 <TD width="10%"><B>Context</B></TD>
 </TR>
 <xsl:for-each select="m:result/m:warnings/m:warninglist/m:warning">
 <tr>
 <xsl:if test="(position() mod 2 = 1)">
 <xsl:attribute name="bgcolor">#EEEEFF</xsl:attribute>
 </xsl:if>
 <TD width="10%"><xsl:value-of select="m:line" /></TD>
 <TD width="10%"><xsl:value-of select="m:level" /></TD>
 <TD width="70%"><xsl:value-of select="m:message" /></TD>
 <TD width="10%"><xsl:value-of select="m:context" /></TD>
 </tr>
 </xsl:for-each>
 </table>
 </body>
 </html>
 </xsl:template>
</xsl:stylesheet>

TCExam: applicazione web per test on line

Sono stato alla ConfSL è ho assistito ad un software per fare test/quiz on line chiamato TCExam, realizzato in PHP e rilasciato con GPL 3 a cura di Nicola Asuni che ho conosciuto personalmente. Nicola, già autore di TCPDF, si è concentrato sull’aderenza agli standard (XHTML 1.0, CSS 2.0 e WAI-AAA) che all’uso di AJAX che eventualmente potete aggiungere (concordo con lui anche perchè questo tipo di software è generalmente inglobato in altri ed è preferibile avere l’aderenza agli standard).

L’installazione, la versione attuale è 9.0.017, è semplice basta estrarre il file zip e copiarlo ad esempio nella cartella htdocs di Xampp e andare all’indirizzo:

http://localhost/TCexam/install/install.php

dove dovrete mettere i parametri di connessione al vostro database MySQL (default) o PostgreSQL. La procedura creerà un database con una 15 di tabelle.

Fatto ciò finite nella schermata di login. Dovete sapere però che esiste sia il lato pubblico che quello amministrativo che trovate all’indirizzo:

http://localhost/TCexam/admin/code/

e inserire le credenziali di amministratore admin/1234.

Occorre dire che il sistema di autenticazione si può basare su CAS, LDAP, Radius; i file di configurazione li trovate nella cartella shared/config.

La cosa interessante è che il software è multilingua ed è disponibile in Arabo, Bulgaro, Portoghese brasiliano, Cinese, Tedesco, Greco, Inglese, Spagnolo, Francese, Hindi, Ebreo, Ungherese, Indonesiano, Italiano, Giapponese,Marathi, Malese, Olandese, Polacco, Russo, Turco, Vietnamita.
Le lingue sono in un unico file che trovate nel path shared/config/lang/language_tmx.xml

Dal pannello potete creare utenti e assegnare loro dei gruppi. Potete importare/esportare utenti in formato XML o CSV e vedere lo stato dei risultati.

Le domande sono strutturare in moduli e argomenti e possono essere di tipo a risposta singola, multipla, libera e ordinamento delle risposte.
L’editing delle domande e risposte è basato su un editor che permette l’aggiunta di formule e immagini in Latex (cosa ottima) tramite tag quindi non visuale, tuttavia si può vedere la preview. Le domande possono essere importate/esportare in XML mentre la lista si può esportare anche in PDF.

La creazione dei test è anch’essa semplice. Per ogni test potete specificare la data di inizio e fine (fa fede quella del server), i gruppi di utenti che possono partecipare, i punti da assegnare per risposta corretta, sbagliata o non data, i punti minimi per passare l’esame e che tipo di domande aggiungere.

E’ possibile esportare il test in PDF così magari da stamparlo. Sul PDF generato compare un logo e un’intestazione specificati nel file shared/config/tce_pdf.php mentre l’immagine si trova nella cartella images.

A questo punto non vi resta che augurarvi buon test e se avete bisogno di aiuto chiedete direttamente a lui che è molto disponibile !

BambooINVOICE: applicazione web per fatture

Qualche giorno fa avevo già parlato di Invoicex, un’applicazione java per la gestione di fatture.

Oggi ho provato ad installare BambooINVOICE, un sistema di gestione fatture scritto in PHP e rilasciato con licenza GPL. In particolare è basato su PHP5, realizzato con CodeIgniter (un web application framework basato per applicazion PHP) e usa i seguenti database MySQL e MySQLi 4.1 ma anche MSSQL, Postgre, OCI8, SQLite e ODBC.

La versione attuale 0.8.9, rilasciata il 15 aprile 2009 è basata su CodeIgniter 1.7.1

Per poterlo installare in locale su XAMPP, lo scaricate e lo estraete nella cartella htdocs di XAMPP dando il nome alla cartella bambooinvoice.

Dovete poi creare un database (dal nome bambooinvoice, che potete fare con PHPMyAdmin) ed eventualmente modificare i parametri contenuti ne file:

bambooinvoice/bamboo_system_files/application/config/database.php

Con il vostro browser andate poi all’indirizzo: http://localhost/bambooinvoice

La prima schermata che vi appare vi chiede il vostro indirizzo email, utente e password e premete il tasto Install.

Se non ci sono problemi, l’applicazione è già installata e non dovete fare altro che loggarvi con l’email e la password inseriti prima.

L’interfaccia di default è in inglese ma è disponibile anche in francese, tedesco, olandese, danese, rumeno, spagnolo, portoghese, bulgaro, svedese e italiano. Tutto cio’ è possible cambiando la proprietà:

$config[‘language’]    = ‘english’;

nel file:

bambooinvoice/bamboo_system_files/application/config/config.php

e sostituendo “english” con:  “french”, “german”, “dutch”, “danish”, “romanian”, “spanish”, “portuguese”, “bulgarian”, “swedish”,  “italian”.

Fate un refresh della pagina web e vedete che la lingua è cambiata (certo che sarebbe bello cambiare la lingua o configurare il database dall’interfaccia grafica).

Cmq l’interfaccia di per se è semplice, avete una barra laterale contestuale alle opzioni selezionate. Il menu principale è molto semplice, avete fatture, clienti, grafici, impostazioni, account e utilties (questi ultimi 3 servono solo per la configurazione).

Per creare una fattura dovete prima di tutto creare un cliente (o potete farlo in corso d’opera) e poi sul pulsante del menu laterale “Nuova fattura”, semplice ma per l’esportazione della fattura in PDF dovete configurare DOMPDF.

I grafici raggiungibili dal menu principale generano sono degli istogrammi del fatturato mese per mese ma non è possible esportarli in PDF tuttavia se andate nel menu utilities potete esportare l’elenco delle fatture in XML o Excel. Dallo stesso menu potete vedere se esiste una nuova versione.

Se avete dei problemi o segnalazioni potete rivolgervi al forum:  http://forums.bambooinvoice.org/

Glassfish 2.1, Quercus 3.2.1 e WordPress 2.7.1

Talvolta avevo pensato di migrare da PHP a JSP poichè Tomcat supporta nativamente JSP ma Tomcat non è un application server.

Ultimamente sto valutando di usare Glassfish o Jboss come application server per usarli come base per Hudson un continuous integration engine (vedete articolo precedente) invece di usare Winstone integrato al suo interno.

In particolar modo, siccome quelli di Glassifish con Metro affermano l’interoperabilità con .NET per i web service (a partire da Jax-WS più le implementazione degli stessi standard con .NET cosa che Axis2 fa ma più lentamente a mio parere), ho pensato di concentrarmi su Glassfish.

Per caso ho scoperto che esiste Quercus che è una libreria java che è una implementazione java di PHP, in pratica il codice PHP viene trasformato in Java, in pratica potete far girare le vostre applicazioni PHP.

Quercus viene rilasciato con licenza GPL 2 da Caucho Technology una azienda che ha realizzato Resin un java/php application server e Hessian un protocollo binario per web services che avevo già sentito nominare quando lavoravo sui web services.

Quelli di Caucho affermano che le prestazioni si vedono.

Presto detto quello che avete bisogno quindi è GlassFish, Quercus e i driver JDBC che dovete installare nel vostro application server e che Quercus farà uso e la vostra applicazione PHP ovviamente.

Ho scelto WordPress perchè ho trovato un tutorial e di conseguenza ho installato i driver JDBC per Mysql e Mysql stesso.

I tutorial che ho seguito sono:

  • http://blogs.steeplesoft.com/glassfish-php-and-wordpress/ (ma non spiega che bisogna creare un connection pool su glassfish ovvero la connessione tramite i driver JDBC). Dovete prima di tutto estrarre i 3 file (quercus.jar, resin-util.jar, javamail-141.jar) che si trovano nel file war di Quercus nella cartella lib di Glassfish o nella cartella di lib del vostro dominio (domain1 nel mio caso)  a seconda della visibilità che volete dare. Poi in pratica nella cartella del vostro dominio trovate il file config/default-web.xml e dovete inserirci la seguente configurazione:

<servlet>
<servlet-name>Quercus Servlet</servlet-name>
<servlet-class>com.caucho.quercus.servlet.QuercusServlet</servlet-class>
<init-param>
<param-name>ini-file</param-name>
<param-value>WEB-INF/php.ini</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>Quercus Servlet</servlet-name>
<url-pattern>*.php</url-pattern>
</servlet-mapping>

Dovete poi estrarre WordPress nella cartella docroot del vostro dominio.

Poi oggi rivedendo Quercus ho visto che la procedura è spiegata nel file readme :-) che trovate nel pacchetto e che vi consiglio a questo punto di leggere per prima.

Ora mi concentro anche su Jboss e vedo per qualche applicazione in PostGres.

Nota: vedere anche Php-Java bridge.