giovedì 28 novembre 2013

Tomcat 7 personalizzare parametri allo start up

Per modificare dei parametri specifici per un singolo Tomcat (es per cambiare il path oppure per definire una variabile di utilità) occorre modificare lo script startup.bat inserendo all'inizio istruzioni di questo tipo. Qui cambiamo la CATALINA_HOME, inseriamo un percorso diverso dallo standard nel path e definiamo una variabile di ambiente valida solo per questo tomcat senza definirla sul S.O.:


set CATALINA_HOME=d:\prove\apache-tomcat-7.0.39
set path=d:\miaDirectory;%path%
set @TESTVARIABILE=c:\pippo 

sabato 23 novembre 2013

Tomcat 7 settare connessione HTTPS

In questo post vediamo come:
  1. Creare un certificato per l'https;
  2. Visionare le caratteristiche del certificato;
  3. Configurare Tomcat 7 in modo da poter rispondere in https.
CREARE UN CERTIFICATO PER L'HTTPS

 Per effettuare questa operazione si utilizza la JDK 1.6, in particolare il programma keytool.
L'opzione -keystore consente di specificare dove creare il file. Attenzione è obbligatorio specificare un nome di file; va bene anche se non esistente, l'importante è che non sia  una directory la procedura va in errore dicendo "Errore keytool: java.lang.Exception: Il file keystore esiste ma Þ vuoto: c:\lav\certificati"

Da cmd:

C:\lav\ApplicationServers\apache-tomcat-7.0.23\bin>keytool -genkey -alias carlo
-keyalg RSA -keystore c:\lav\certificati\certificato.txt
Immettere la password del keystore:
Immettere nuovamente la nuova password:
Specificare nome e cognome
 [Unknown]:  MARIO BREGA
Specificare il nome dell'unitÓ aziendale
 [Unknown]:  AZIENDA ABC
Specificare il nome dell'azienda
 [Unknown]:  AZIENDA TEST
Specificare la localitÓ
 [Unknown]:  ROMA
Specificare la provincia
 [Unknown]:  RM
Specificare il codice a due lettere del paese in cui si trova l'unitÓ
 [Unknown]:  IT
Il dato CN=MARIO BREGA, OU=AZIENDA ABC, O=AZIENDA TEST, L=ROMA, ST=RM, C=IT Þ co
rretto?
 [no]:  s

Immettere la password della chiave per <carlo>
        (INVIO se corrisponde alla password del keystore):


VISIONARE LE CARATTERISTICHE DEL CERTIFICATO

Sempre utilizzando la keytool con l'opzione -list e specificando il keystore è possibile visionare le caratteristiche del certificato appena creato:


C:\lav\ApplicationServers\apache-tomcat-7.0.23\bin>keytool -list -keystore c:\la
v\certificati\certificato.txt
Immettere la password del keystore:

Tipo keystore: JKS
Provider keystore: SUN

Il keystore contiene 1 entry

carlo, 23-nov-2013, PrivateKeyEntry,
Impronta digitale certificato (MD5): F5:F9:15:AB:98:31:2D:19:C3:65:5C:EF:EA:7E:4
8:B1


CONFIGURARE TOMCAT7 IN HTTPS

Per configurare Tomcat7 in modo da essere raggiungibile in HTTPS con il certificato appena creato è sufficiente agire sul file server.xml presente nella directory conf dell'application server.
Bisogna scommentare il nodo Connector dove troviamo il commento:
Define a SSL HTTP/1.1 Connector on port 8443 e modificarlo nel nostro caso così:

 <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" keystorePass="xxxx" keystoreFile="c:\lav\certificati\certificato.txt "
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" />


aggiungendo le opzioni keystoreFile e keystorePass.

Per testare il tutto è sufficiente andare via browser all'indirizzo https://localhost:8443. Il certificato ovviamente non è trusted e quindi dovremmo aggiungere una eccezione di sicurezza al browser per accettarlo.

mercoledì 20 novembre 2013

Passare più di 9 parametri ad un file .bat

Se passiamo più di 9 parametri ad un .bat ci sono dei problemi.
Infatti scrivendo %10 in realtà prende il parametro 1 (%1) e poi vede uno zero.
Per gestire più parametri occorre usare l'operatore shift che trasla la lista di parametri.
Nell'esempio riportato sotto vogliamo passare 11 parametri e quindi, dopo aver letto il parametro 9,con un doppio shift "perdiamo" i valori 1 e 2 e quindi i valori %8 e %9 letti dopo saranno il decimo e undicesimo parametro inviato.
L'esempio seguente scrive questi parametri su di un file txt.

set arg1=%1
set arg2=%2
set arg3=%3
set arg4=%4
set arg5=%5
set arg6=%6
set arg7=%7
set arg8=%8
set arg9=%9
shift
shift
set arg10=%8
set arg11=%9
set
echo Utente %arg1% ci invia i parametri %arg2% %arg3% %arg4% %arg5% %arg6% %arg7% %arg8% %arg9% %arg10% %arg11% > risultato.txt


lunedì 18 novembre 2013

Java invocare bat file passando parametri

Supponiamo di voler invocare un semplic bat di questo tipo:

echo %1 %2
echo Ciao %1 %2 > pippo.txt

Quindi un bat che prende in input dei parametri e li scrive su un file (creandolo ex novo), in un path RELATIVO rispetto alla posizione del path.

Via java è possibile utilizzare la seguente istruzione:

Runtime.getRuntime().exec("cmd /c start  C:\\excel\\test.bat ciao sam");


E in effetti funziona ma il file non viene creato nella directory relativa c:excel bensì in quella dove stiamo eseguendo il nostro pgm Java.

Non sono riuscito a capire come fare (sicuramente ci deve essere un modo) per fare in modo che non scrivesse il file nel percorso relativo al pgm Java ma inutilmente.
Ho provato anche a fare una cosa del tipo:

System.setProperty("user.dir","c:\\excel");

ma niente da fare.

Per risolvere ho utilizzato la libreria commons-exec-1.1.jar.

DefaultExecutor df=new DefaultExecutor();
df.setWorkingDirectory(new File("c:\\excel"));
CommandLine cl=new CommandLine("c:\\excel\\test.bat");
cl.addArgument("uno");
cl.addArgument("due");
df.execute(cl)

Si noti che se si commenta il rigo 2 (il setWorkingDirectory) torniamo alla situazione precedente, mentre se non si specifica nel CommandLine il percorso assoluto e si mette quello relativo comunque non funziona (nonostante abbia settata la working directory) e da proprio errore lamentando la mancanza del file bat.

sabato 16 novembre 2013

Java7 watch service

Una feature molto utile è quella del WatchService, che consente di registrare una directory e notificare ogni evento che viene compiuto su di essa (es. inserimento nuovi file, cancellazioni file,modifiche eccetera).
Si ottiene questo risultato seguendo la seguente serie di passaggi logici:
  1. Ottenere un'istanza del WatchService dalla classe FileSystem;
  2. Registrare la directory di interesse, specificando nei varargs tutti gli eventi per cui si vuole registrarla;
  3. Effettuare un loop infinito dove si attendono gli eventi. Si utilizza il metodo take() per ottenere l'evento appena disponibile. La chiamata a take() è bloccante, se si vuole invece la versione non bloccante bisogna invocare il poll();
  4. Una volta ottenuto l'evento di tipo WatchKey si cicla tra tutti gli eventi disponibili per ottenere quello di interesse;
  5. Una volta processato l'evento si resetta la chiave (key.reset() nel codice), senza questo passaggio soltanto il primo evento nella directory sarà registrato.
Vediamo il codice:

package it.test;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardWatchEventKinds;
import java.nio.file.WatchEvent;
import java.nio.file.WatchKey;
import java.nio.file.WatchService;
public class ObserveDirChanges {

 public static void main(String[] args) {
  Path p=Paths.get("c:\\excel");
  WatchService ws=null;
  try
  {
ws=p.getFileSystem().newWatchService();
p.register(ws, StandardWatchEventKinds.ENTRY_CREATE,StandardWatchEventKinds.ENTRY_DELETE,StandardWatchEventKinds.ENTRY_MODIFY,StandardWatchEventKinds.OVERFLOW);
for(;;){
WatchKey key=null;
try
{
key=ws.take();
}
catch(InterruptedException ex){
ex.printStackTrace();
}
for(WatchEvent<?> event:key.pollEvents()){
switch(event.kind().name()){
 case "OVERFLOW":
 System.out.println("Attenzione è andato perduto un evento");
 break;
 case "ENTRY_MODIFY":
 System.out.println("File "+event.context()+" modificato");
 break;
 case "ENTRY_CREATE":
 System.out.println("File "+event.context()+" creato");
 break;
 case "ENTRY_DELETE":
 System.out.println("File "+event.context()+" cancellato");
 break;
 }
 key.reset();
    }
      }
  }
  catch(IOException e){
   e.printStackTrace();
  }

 }

}


JAVA 7 ottenere informazioni su data creazione file

Con le nuove API è possibile ottenere semplicemente molte informazioni sulla natura dei file.
Nel seguente esempio vediamo come ottenere queste informazioni utilizzando l'interfaccia java.nio.file.attribute.BasicFileAttributes.


package it.test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.BasicFileAttributes;
public class CheckAttributiFile {
 public static void main(String[] args) {
  Path p=Paths.get("c:\\excel\\2_BAHIA.xls");
  try
  {
BasicFileAttributes fileAttributes=Files.readAttributes(p, BasicFileAttributes.class);
System.out.println("Size: "+fileAttributes.size());
System.out.println("Directory: "+fileAttributes.isDirectory());
System.out.println("File normale: "+fileAttributes.isRegularFile());;
System.out.println("Link simbolico: "+fileAttributes.isSymbolicLink());
System.out.println("Ultima modifica: "+fileAttributes.lastModifiedTime());
System.out.println("Ultimo accesso:"+fileAttributes.lastAccessTime());
System.out.println("Data creazione file: "+fileAttributes.creationTime());
  }
  catch (IOException e) {
   e.printStackTrace();
  }
 }
}


 Il risultato è il seguente:

Size: 5120
Directory: false
File normale: true
Link simbolico: false
Ultima modifica: 2013-08-08T09:04:30.744618Z
Ultimo accesso:2013-04-04T06:56:47.668827Z
Data creazione file: 2013-04-04T06:56:47.668827Z

Java 7 classe java.nio.file.Files esempio creazione link simbolico

Con  la classe Files si può fare praticamente di tutto a livello di file system con semplici ed intuitivi metodi.
Vediamo come creare e testare la creazione di un link simbolico:

package it.test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FilesExample {
 public static void main(String[] args) throws IOException{
  Path p3=Paths.get("C:\\lav\\testFile\\simbolicLink.txt");
  Path p4=Paths.get("C:\\lav\\testFile\\fileReale.txt");
  System.out.println(Files.createFile(p4));
  Files.createSymbolicLink(p3, p4);
  System.out.println(Files.isSymbolicLink(p3));
  
 }
 
}


Andando sulla directory del filesystem via dos vedremo quindi:

JAVA NIO package interfaccia Path

Con java 7 abbiamo un package java.nio.file con interessanti feature per lo scandagliamento del file System.
Una di queste è rappresentato dall'interfaccia java.nio.Path che consente di ottenere molte informazioni con metodi semplici ed intuitivi.
Si crea una implementazione di tale interfaccia chiamando il metodo statico get sulla classe Paths.
Esempio:

package it.test;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathExample {
public static void main(String[] args) {
  Path p=Paths.get("c:\\lav\\trash\\prof");
  System.out.println(p.getFileName());
        System.out.println(p.getRoot());
        System.out.println(p.getParent());
        for(Path element:p){
         System.out.println(element.toString());
        }
 }

}



Ci fornisce l'output seguente:

prof
c:\
c:\lav\trash
lav
trash
prof

In questo altro esempio ho preso il path relativo al progetto Java di test, utilizzando anche ulteriori metodi dell'interfaccia come il toAbsolutePath() o il toUri().

package it.test;
import java.io.IOException;
import java.nio.file.LinkOption;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathExample {
public static void main(String[] args) throws IOException {
  Path p=Paths.get("src");
  System.out.println("File name: "+p.getFileName());
        System.out.println("Root: "+p.getRoot());
        System.out.println("Parent: "+p.getParent());
        for(Path element:p){
         System.out.println(element.toString());
        }
        System.out.println("Absolute path: "+p.toAbsolutePath());
        System.out.println("Uri: "+p.toUri());
        System.out.println("Path normalized:"+p.normalize().toString());
        System.out.println("Real path: "+p.toRealPath(LinkOption.NOFOLLOW_LINKS));
        
 }

}


Risultato:

File name: src
Root: null
Parent: null
src
Absolute path: C:\lav\workspace\wsTest\Java7Cert\src
Uri: file:///C:/lav/workspace/wsTest/Java7Cert/src/
Path normalized:src
Real path: C:\lav\workspace\wsTest\Java7Cert\src

In particolare:
  • toUri() ritorna un path che può essere aperto da un browser ;
  • toAbsolutePath() ritorna il path assoluto dato un path relativo;
  • normalize() rimuove simboli non necessari (es. "." e "..");
  • toRealPath() ritona il path assoluto e normalizzato e può risolvere anche i symbolic link (nel caso in esame usando l'opzione NOFOLLOWLINKS è stato scelto di non considerare i link simbolici. A differenza degli altri metodi esposti però se il file non esiste fisicamente lancia una eccezione tipo IOException.
E' possibile anche effettuare delle comparazioni tra path, ed esistono 2 metodi:
  • compareTo che effettua un confronto puramente lessicografico e torna 0 se i path sono uguali;
  • equals() che effettua un confronto reale tra i path (ma bisogna accertarsi che i percorsi di entrambi i path siano percorsi assoluti).
Esempio:

 // comparing paths
        Path p2=Paths.get("C:\\lav\\workspace\\wsTest\\Java7Cert\\src");
        System.out.println(p.compareTo(p2)==0?"OK":"KO");
        System.out.println(p.equals(p2));
        System.out.println(p.toAbsolutePath().equals(p2));

In questo caso ci torna prima KO, poi false e poi true (quando si confrontano i path entrambi assoluti).

mercoledì 13 novembre 2013

Primefaces p:dialog problemi nel submit ajax

Utilizzando primefaces 3.5 ho avuto il seguente problema.
Avevo un form principale che richiamava un p:dialog.
Il p:dialog si vedeva sempre con i campi in grigetto e non riuscivo quindi ad effettuare l'update.
Ho usato quindi la proprietà appendToBody="true" che effettivamente consentiva la visualizzazione corretta del form ma i valori dei campi non passavano in request (il bean aveva scope di tipo view).
A questo punto per risolvere il tutto ho messo tutto il p:dialog all'interno di un form separato e fuori dal form principale (occhio che definire form innestati provoca problemi in alcuni browser) e a questo punto tutto ho potuto rimettere il valore di default appendToBody e tutto ha funzionato correttmaente.
Incollo sotto l'xhtml del p:dialog:

<ui:composition xmlns="http://www.w3.org/1999/xhtml"  
    xmlns:h="http://java.sun.com/jsf/html"  
    xmlns:f="http://java.sun.com/jsf/core"   
    xmlns:p="http://primefaces.org/ui"
    xmlns:ui="http://java.sun.com/jsf/facelets">  
 <h:form id="ghersi">
    <p:dialog id="parametrizzazioneGi" widgetVar="par020WidgetVar" appendToBody="false"
       closable="true" resizable="true" draggable="true" modal="true" 
                width="600" height="250" header = "#{msg['paramGi']}" dynamic="true">
              <table>
              <tr><td>#{msg['codInt']}</td>
              <td> 
              <p:inputText id="codiceInterno" value="#{par020.codiceInterno}" maxlength="5" size="10"></p:inputText>
              </td>
              </tr>
              <tr><td>#{msg['codOgg']}</td>
              <td> 
              <p:inputText id="codiceOggetto" value="#{par020.codiceOggetto}" maxlength="30" size="40"></p:inputText>
              </td>
              </tr>
               <tr><td>#{msg['dtUltElabor']}</td>
              <td> 
              <p:inputText id="dtUltElab" value="#{par020.dataUltimaElaborazione}" maxlength="9" size="18"></p:inputText>
              </td>
              </tr>
               <tr><td>#{msg['schedPar']}</td>
              <td> 
              <p:inputText id="schedaParam" value="#{par020.schedaParametro}" maxlength="80" size="45"></p:inputText>
              </td>
              </tr>
              <tr>
              <td colspan="2">
              <p:commandButton id="insertParam" value="Inserimento" icon="ui-icon-arrowreturnthick-1-w"  
          actionListener="#{par020.insert}"   
             style="margin-top:15px;margin-right:5px;color:white;background:#868686;"
             update=":mainForm:parametri :mainForm:messages " oncomplete="par020WidgetVar.hide()" /> 
              </td>
              </tr>
              </table>
              
  </p:dialog>
    </h:form>
    </ui:composition>


lunedì 11 novembre 2013

Internet Explorer evitare messaggio sul window.close()

Con questo javascript si riesce ad evitare che richiamando il window.close() sia chiesta conferma all'utente della volontà di chiudere la finestra.
Il messaggio di conferma viene richiesto perchè c'è solo una finestra di tipo parent, per cui si avvisa in quanto chiuderla significa praticamente chiudere il browser.
Per evitare il problema ho trovato qui un trucco utile.
La funzione window.open ha la seguente firma:
window.open(URL,name,specs,replace)
I valori di name possono essere:
    _blank - Il caricamento dell'URL avviene in una nuova finestra
    _parent - Il caricamento dell'URL avviene nel frame parent
    _self - Il caricamento dell'url rimpiazza l'url corrente
    _top - Il caricamento dell'url rimpiazza qualsiasi frameset caricato
    name - il nome della finestra
Si imbroglia IE aprendo una pagina vuota superiore nella stessa pagina e quindi richiudendola.
Il valore true nel parametro replace indica che sostituisce il valore nella history.
Il parametro specs, qui lasciato vuoto, serve a specificare eventuali caratteristiche grafiche della finestra.
Così:

var win=window.open("","_top","","true");
win.opener=true;
win.close(); 


giovedì 7 novembre 2013

Determinare data creazione di un file

Dalla versione JDK 7 ci sono le API apposite di java.nio.
Con la jdk 1.6 si può procedere così (funziona in sistemi windows non l'ho testato su linux):


File f=new File("c:\\lav\\popso.txt");
SimpleDateFormat sdf=new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
Date d=new Date(f.lastModified());
System.out.println(sdf.format(d));