07 dicembre 2010

URLConnection : richiesta http + login

E' da tanto tempo che non scrivo un post sul mio blog, trovo l'occasione grazie ad un client che stò sviluppando che permette di eseguire il login su un sito mediante classi standard java.net, anzichè utilizzare librerie note come quella di apache.

In particolare in questo post vedremo come creare un wrapper per eseguire connessioni tramite l'oggetto URLConnection.
Quella che vedremo di seguito è una classe di utilità per la gestione delle richieste http con parametri post e/o invio delle informazioni presenti nei cookies.

Ecco il codice sorgente della classe :
package util;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.URL;
import java.io.OutputStreamWriter;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import util.entity.ResponseWrapper;

/***
* Classe di utilità per l'utilizzo delle connessioni mediante UrlConnection del package java.net
*
*/
public class ConnectionUtils {

/***
* Metodo per eseguire una chiamata http.
* Il metodo richiama un link, passandogli nell'header del pacchetto le informazioni sui parametri
* e le informazioni sui cookies.
* Dopo la chiamata http, recupera le informazioni dei cookies ed il contenuto html della risposta
* e li restituisce in un oggetto modellato per contenere tali informazioni.
*
* @param link : link da chiamare
* @param params : parametri post da passare
* @param cookiesToSend : cookies da inviare nell'header
* @return
*/
public static ResponseWrapper downloadPagePost(String link, Map params,List cookiesToSend) {

ResponseWrapper ouputRequest = null;
try {
URL url = new URL(link);
URLConnection conn = url.openConnection();
// mantiene la connessione anche dopo la richiesta
conn.setDoOutput(true);
conn.setRequestProperty("User-Agent","Java1.6 / "+System.getProperty("os.name")+" ("+System.getProperty("os.version")+")");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Cookie", CookiesUtils.getMyCookiesString(cookiesToSend));

OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
String paramsEncoded = RequestUtils.getEncodedParameters(params);
wr.write(paramsEncoded);
wr.flush();

System.out.println("Call page : "+link);
String headerName = null;
List cookiesretrieved = new ArrayList();

for (int i = 1; (headerName = conn.getHeaderFieldKey(i)) != null; i++) {
// System.out.println("------------------");
// System.out.println("header : "+headerName);
// System.out.println("Content : "+conn.getHeaderField(i));

if (headerName.equals("Set-Cookie")) {
String cookie = conn.getHeaderField(i);
//System.out.println("cookie : "+cookie);
// Estraggo il cookie corrente e lo metto nella lista per il wrapper
String currCook = cookie.substring(0, cookie.indexOf(";"));
cookiesretrieved.add(currCook);
} //end if
}

StringBuffer output = new StringBuffer();
BufferedReader rd = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = rd.readLine()) != null) {
output.append(line);
}

ouputRequest = new ResponseWrapper(output,cookiesretrieved);

} catch (Exception e) {
e.printStackTrace();
}
return ouputRequest;
}
}


In dipendenza a questa classe è necessario definire la classe ResponseWrapper :
package util.entity;

import java.io.FileWriter;
import java.io.IOException;
import java.util.List;

public class ResponseWrapper {
private List cookies;
private StringBuffer content;

public ResponseWrapper(StringBuffer acontent,List cookin){
cookies = cookin;
content = acontent;
}

public List getCookies() {
return cookies;
}

public void setCookies(List cookies) {
this.cookies = cookies;
}

public StringBuffer getContent() {
return content;
}

public void setContent(StringBuffer content) {
this.content = content;
}

public boolean writeToFile(String fileName){
FileWriter out;
try {
out = new FileWriter(fileName);
out.write(getContent().toString());
out.close();
} catch (IOException e) {
return false;
}

return true;
}
}


Questa classe è ha il compito di incapsulare le informazioni recuperate mediante la richiesta http, in particolare l'html contenuto e la lista di cookies generati dal sito.

Definiamo adesso un metodo per eseguire il login a cui passiamo username, password e cookies generati dal sito

 public static boolean login(String username, String password,List cookies){
Map parametri = new HashMap();
parametri.put("username",username);
parametri.put("password",password);
parametri.put("otherParam","param");

ResponseWrapper responseLogin = ConnectionUtils.downloadPagePost("mysite.org/login.php", parametri,cookies);

boolean loggedin = true ;// Here we can check login

// write html content to a file named checklogin.html
responseLogin.writeToFile("checklogin.html");

return loggedin;
}


Come utilizzare questo metodo ? Semplice :
List cookies = new ArrayList();
cookies.add("PHPSESSID=asd5nkl4nmnskdfjsidd=");
MySampleLogin.login("myUsr","myPasw",cookies);


Spero che la classe vi possa rendere le cose più semplici.
Alla prossima!

10 maggio 2010

Browser.Engine : distinguere i Browser con mootools

I mootools tra la miriade di funzionalità, ci permette di individuare la versione del browser mediante la classe Browser.

Un classico esempio di distinzione tra i browser possiamo vederla nel seguente esempio.


var BE = Browser.Engine;
if (!this.BE.webkit && !this.BE.gecko && !this.BE.trident){
// firefox 3.6 bug
BE = Browser.Engines;
}
if (BE.webkit) {
alert ("webkit : Safari, Google Chrome, Konqueror";
}
if (BE.gecko) {
alert ("gecko : Firefox, or any Mozilla Browser";
}
if (BE.trident) {
alert ("trident : Internet Explorer";
}

Come potete vedere nell'esempio nel caso in cui si tratti di firefox 3.6, visto che l'oggetto Broser.Engine.gecko non è definito (undefined), è stato fixato con un workaround, utilizzando l'oggetto Browser.Engines.gecko per intercettare il browser.

17 marzo 2010

Risolvere il problema 80048051 di msn

Tra tutti gli errori derivanti dall'utilizzo di un OS Windows, ve ne segnalo uno in cui mi imbatto diverse volte a lavoro, specialmente quando interrompo la connessione di rete del mio pc e lo metto in standBy.
Nel momento in cui tento di riconnettermi a MSN ottengo un magnifico errore 80048051.



Per poterlo risolvere non è necessario come al solito chiudere e riaprire il programma, ma è necessario eseguire i seguenti passi :

- Aprire il broswer;
- Selezionare il menù "file", posto in alto a sinistra e vi si aprirà un ulteriore menù;
- Togliere la spunta (ovvero la v), dalla modalità "non in linea".

Alla prossima!!

26 febbraio 2010

FileUtils : funzionalità aggiuntive per la gestione dei files in Java

Tramite questo post metto a disposizione l'implementazione di una classe di utilità che implementa alcune funzionalità per la gestione dei Files in Java.

In dettagli le funzionalità implementate sono le seguenti :

- Cancellare i files più vecchi di un certo numero di giorni da una cartella
- Creare una cartella nel caso in cui non esista
- Recuperare l'elenco dei files da una cartella ordinandoli per data crescente / decrescente.

Il codice qui di seguito :
package it.fritzzz.utils;

import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

/***
* Classe di utilità per la gestione dei files
* @author a.franzi
*
*/
public class FileUtils {

/***
* Ordina e restituisce i files per data di ultima modifica
* @param directory : directory su cui eseguire il list del files
* @param asc : boolean (true = dal più lontano al più recente ; false = il contrario)
* @return : List di nomi files
*/
public static List listFilesOfDirOrderByLastModifiedDate(final File directory,boolean asc){
if (directory!=null && directory.isDirectory()) {
String[] children = directory.list();
if (children!=null && children.length>0){
List childList = Arrays.asList(children);
Collections.sort(childList,new Comparator() {

public int compare(Object o1, Object o2) {
if (o1 !=null && o2 !=null){
File file1 = new File(directory, (String)o1);
File file2 = new File(directory, (String)o2);

if (file1.lastModified()==file2.lastModified()){
return 0;
}else if (file1.lastModified()>file2.lastModified()){
return 1;
}else if (file1.lastModified()<file2.lastModified()){
return -1;
}
}
return 0;
}
});
return childList;
}
}
return null;
}


/***
* Metodo per rimuovere i files troppo vecchi da una determinata cartella
* @param folderName : nome della cartella
* @param numberOfDays : numero di giorni di tolleranza
* @return : boolean true se tutto è andato a buon fine
*/
public static boolean removeTooOldFilesFromDir(String folderName, int numberOfDays){
boolean ok = true;

try{
File dir = new File(folderName);

if (dir.isDirectory()){
File[] filesIntoDir = dir.listFiles();
if (filesIntoDir!=null && filesIntoDir.length> 0){
for (int i = 0 ; i < filesIntoDir.length; i++){
if (filesIntoDir[i].isFile()){
long lastUpdateOfFile = filesIntoDir[i].lastModified();
Calendar cal = Calendar.getInstance();
cal.setTimeInMillis(lastUpdateOfFile);
Calendar today = Calendar.getInstance();
today.add(Calendar.DAY_OF_YEAR, -numberOfDays);
if (cal.before(today)){
boolean currDelete = filesIntoDir[i].delete();
if (!currDelete){
System.out.println("Problem removing too old file : "+filesIntoDir[i].getAbsolutePath());
ok = false;
}else{
System.out.println("Removed too old file : "+filesIntoDir[i].getAbsolutePath());
}
}
}
}
}else{
throw new IOException("nessun file presente nella cartella : "+folderName);
}

}else{
throw new IOException("il path : "+folderName+" non è una directory");
}
}catch(IOException ex){
System.out.println("Eccezione : "+ex.getMessage());
ok = false;
}


return ok;
}

/***
* Metodo per creare una cartella nel caso non esiste gia'
* @param path : path
* @return : boolean
*/
public static boolean createFolderIfNotExits(String path){
File folder = new File(path);
if (!folder.exists()){
return folder.mkdirs();
}else{
System.out.println("la cartella : "+path+" esiste gia'");
}
return false;
}
}

22 febbraio 2010

ORACLE : Visualizzare lista di job in esecuzione

Per poter visualizzare l'elenco dei job in esecuzione la query da eseguire è la seguente :
SELECT r.sid,r.job,r.this_date,r.this_sec,SUBSTR(what,1,40),total_time
FROM dba_jobs_running r,dba_jobs j
WHERE r.job = j.job

19 febbraio 2010

Eseguire il redirect degli output di un batch in un file di log su Windows

Qualche semplice suggerimento per eseguire il redirect degli output dell'esecuzione di un file batch su windows.

E' necessario sapere che ci sono 2 livelli di output in maniera analoga ai sistemi Linux/Unix, il primo livello è lo STANDARD OUTPUT mentre il secondo livello è lo STANDARD ERROR.
Per cui le applicazioni ridirezionano gli output su questi 2 livelli a seconda delle esigenze.

Come è possibile salvare gli output dell'esecuzione di un batch?

Per poter eseguire delle prove creare con blocco note un nuovo di nome "test.bat" e copiare al suo interno i seguenti comandi :


@ECHO OFF
ECHO This text goes to Standard Output
ECHO This text goes to Standard Error 1>&2


Eseguendo il file "test.bat" da riga di comando (Start->Esegui..->cmd) otterremo il seguente risultato :

C:\>test.bat
This text goes to Standard Output
This text goes to Standard Error


REDIRECT DEGLI STANDARD OUTPUT SU FILE DI LOG

Eseguendo il comando "test.bat > logFile.log" otterremo il seguente risultato :
C:\>test.bat > logFile.log
This text goes to Standard Error


nel file di log logFile.log il contenuto sarà il seguente :
This text goes to Standard Output



REDIRECT DEGLI STANDARD ERORR SU FILE DI LOG

Eseguendo il comando "test.bat 2> logFile.log" otterremo il seguente risultato :
C:\>test.bat 2> logFile.log
This text goes to Standard Output


nel file di log logFile.log il contenuto sarà il seguente :
This text goes to Standard Error


REDIRECT DI TUTTI GLI OUTPUT SU UN UNICO FILE DI LOG

Eseguendo il comando "test.bat > logFile.log 2>&1" otterremo il seguente risultato :
C:\>test.bat > logFile.log 2>&1


nel file di log logFile.log il contenuto sarà il seguente :
This text goes to Standard Output
This text goes to Standard Error


N.B : è possibile loggare separatamente errori e output su 2 files differenti con il comando "test.bat > logFile.log 2> logFile.2.log"

E' possibile anche evitare che errori o output non siano visualizzati nè loggati. Nel seguente esempio verranno visualizzati solo gli errori tramite il comando "test.bat > NUL"

C:\>test.bat > NUL
This text goes to Standard Error

14 febbraio 2010

Usare JDBC per connettersi a Mysql da Java

Introduzione
Lo scopo di questo tutorial è quello di eseguire i seguenti passi :
- Scaricare e installare un database MySQL
- Preparare il database per essere usato tramite i JDBC
- Scrivere e testare la nostra prima applicazione che usa i JDBC

Che cosa è JDBC ?
JDBC (Java DataBase Connectivity), è un connettore per database che consente l'accesso alle basi di dati da qualsiasi programma scritto con il linguaggio di programmazione Java, indipendentemente dal tipo di DBMS utilizzato. È costituita da una API, raggruppata nel package java.sql, che serve ai client per connettersi a un database. Fornisce metodi per interrogare e modificare i dati. È orientata ai database relazionali ed è Object Oriented. La piattaforma Java 2 Standard Edition contiene le API JDBC, insieme all'implementazione di un bridge JDBC-ODBC, che permette di connettersi a database relazionali che supportino ODBC. Questo driver è in codice nativo e non in Java.

Per poter utilizzare MySQL dalle vostre applicazioni Java è necessario scaricare il Connector/J dal seguente link.

Cosa è MySQL ?
MySQL è un Relational database management system (RDBMS), composto da un client con interfaccia a caratteri e un server, entrambi disponibili sia per sistemi Unix come GNU/Linux che per Windows, anche se prevale un suo utilizzo in ambito Unix.
Dal 1996 supporta la maggior parte della sintassi SQL e si prevede in futuro il pieno rispetto dello standard ANSI. Possiede delle interfacce per diversi linguaggi, compreso un driver ODBC, due driver Java e un driver per Mono e .NET.

Per poter installare MySQL è necessario scaricare il pacchetto adatto al vostro Sistema Operativo dal seguente link.

Adesso abbiamo tutto il necessario per poter utilizzare MySQL all' interno della nostra applicazione java.


CONFIGURARE TOMCAT e MYSQL per il recupero della connessione

Prima di procedere, è necessario copiare il Driver JDBC (Connector) nella cartella : $CATALINA_HOME/lib.

In secondo luogo nel caso si tratti di un applicazione WEB è possibile definire un datasource nel file di configurazione del server context.xml:
<Resource name="jdbc/TestDB" auth="Container" type="javax.sql.DataSource"
maxActive="100" maxIdle="30" maxWait="10000"
username="javauser" password="javadude" driverClassName="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost:3306/javatest?autoReconnect=true"/>


Adesso tramite l'applicazione ed in particolare con il seguente pezzo di codice sarà possibile recuperare una connessione :

/***
* Classe di utilità per gestione connessioni
* @author alessandrofranzi
*
*/
public class DBAccess {
private static Logger logger = Logger.getRootLogger();

public DBAccess() {
}

/***
* Recupera la connessione
* @return : connessione
* @throws DatabaseException : eccezione personalizzata
*/
public static Connection getConnection() throws DatabaseException{
try {
InitialContext ic = new InitialContext();
DataSource ds = (DataSource) ic.lookup("java:comp/env/jdbc/TestDB");
return ds.getConnection();
} catch (NamingException e){
System.out.println("Eccezione : "+e.getMessage());
} catch (SQLException e){
System.out.println("Eccezione : "+e.getMessage());
} catch (Exception e){
System.out.println("Eccezione : "+e.getMessage());
}
}
}