lunedì 14 luglio 2014

Sql per calcolare prodotto matriciale

Una matrice sparsa (cioè con molti zeri), può essere rappresentata nel formato (i,j,value)
dove i= riga j=colonna e value=il valore != 0 della matrice.
Esempio una matrice del tipo
0 0 1
1 0 0
5 5 0
sarà rappresentata dai seguenti record:
0 2 1
1 0 1
2 0 5
2 1 5

Per effettuare il prodotto matriciale si può utilizzare una join di questo tipo:


SELECT a.row_num, b.col_num, SUM(a.value*b.value) from a,b 
on a.col_num=b.row_num group by a.row_num,b.col_num;


martedì 8 luglio 2014

Java copiare un file pre java 7

Nelle versioni precedenti a Java 7 per copiare un file occorre scriversi un metodo di questo tipo:


public void copia(String in,String out) throws Exception{
 BufferedWriter bw=new BufferedWriter(new FileWriter(in));
 BufferedReader br = new BufferedReader(new FileReader(out));
 String line;
 while ((line = br.readLine()) != null) {
   bw.write(line);
   bw.newLine();
 }
 br.close();
 bw.flush();
 bw.close();
}


sabato 14 giugno 2014

Tomcat7 cifrare password per autenticazione basic web application

Per abilitare l'autenticazione BASIC (con prompt del browser per username e password) in una web application occorre agire sul web.xml e quindi sull'application server.
In Tomcat è possibile utilizzare il file tomcat-users.xml presente nella directory conf di Tomcat.
Ad esempio supponiamo di avere il seguente codice nel web.xml della nostra web app:

 <login-config>
    <auth-method>BASIC</auth-method>
    <realm-name>Richiesta autenticazione per gestione utenze</realm-name>
  </login-config>
  <security-constraint>
    <web-resource-collection>
      <web-resource-name>restricted methods</web-resource-name>
      <url-pattern>/index.jsf</url-pattern>
      <http-method>GET</http-method>
      <http-method>POST</http-method>
    </web-resource-collection>
    <auth-constraint>
      <role-name>APP_ADMIN</role-name>
    </auth-constraint>
  </security-constraint>
  <security-role>
    <role-name>APP_ADMIN</role-name>
  </security-role>


Quindi nel Tomcat devono essere definite le credenziali dell'utente APP_ADMIN.

Tipicamente nel file tomcat-users.xml si inseriranno le seguenti indicazioni:


<role rolename="LEASING_ADMIN"/>
  <user password="qawsedrf" roles="APP_ADMIN" username="master"/>


Come possiamo vedere l'inconveniente di questo approccio è che la password è memorizzata in chiaro dentro Tomcat.

E' possibile cifrare la password utilizzando i seguenti algoritmi di cifratura
  • SHA;
  • MD2;
  • MD5 
Si può utilizzare l'utility digest.bat per cifrare la password (digest.sh su sistemi linux).
Digitando quindi da prompt di dos il comando

digest.bat -a md5 qawsedrf  

premendo invio si ottiene la risposta

qawsedrf:d1c2dcfcbfd41ce1103a25475b64f7a5

Quindi dobbiamo inserire la password cifrata al posto di quella in chiaro nel tomcat-users.xml.

Ora dobbiamo comunicare a Tomcat che la modalità di controllo password deve passare per un hash md5 della password digitata dall'utente.

Nel file conf/server.xml occorre cercare il Realm UserDataBaseRealm ed inserire l'attributo digest="md5" in questo modo:

<Realm className="org.apache.catalina.realm.LockOutRealm">
    <!-- This Realm uses the UserDatabase configured in the global JNDI
         resources under the key "UserDatabase".  Any edits
         that are performed against this UserDatabase are immediately
         available for use by the Realm.  -->
    <Realm className="org.apache.catalina.realm.UserDatabaseRealm" resourceName="UserDatabase" digest="md5"/>
</Realm>



domenica 8 giugno 2014

Gestire sessione non valida con JSF 2.0

Quando in JSF la sessione scade si incappa nella tipica eccezione di tipo

javax.faces.application.ViewExpiredException

Questo errore si verifica quando l'utente richiede una pagina ma la sessione è ormai scaduta, per cui non si riesce a ricostruire l'alberatura degli oggetti propria di JSF.

Un modo molto semplice per ovviare a questa eccezione è quello di dichiararla nel web.xml in questo modo:

<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/viewExpired.xhtml</location>
</error-page>


Il problema di questo approccio è che non gestisce i casi di chiamate ajax, ed essendo ormai il supporto di ajax il comportamento base di tutti i componenti di JSF 2.0 la dichiarazione nel web.xml non basta.

E' necessario quindi creare una classe che estenda

javax.faces.context.ExceptionHandlerWrapper

in questo modo


package it.exceptionHandler;
import it.util.Costanti;
import it.util.Utility;
import java.io.IOException;
import java.util.Iterator;
import javax.faces.FacesException;
import javax.faces.application.ViewExpiredException;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerWrapper;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.event.ExceptionQueuedEvent;
import org.apache.log4j.Logger;
public class ViexExpiredExceptionHandler extends ExceptionHandlerWrapper {
 private static final Logger log=Logger.getLogger(Costanti.LOGGER);
 private ExceptionHandler parent;
 public ViexExpiredExceptionHandler(ExceptionHandler parent){
  this.parent=parent;
 }

 @Override
 public ExceptionHandler getWrapped() {
  return this.parent;
 }
 @Override
 public void handle() throws FacesException{
   FacesContext facesContext = FacesContext.getCurrentInstance();
         for (Iterator<ExceptionQueuedEvent> iter = getUnhandledExceptionQueuedEvents().iterator(); iter.hasNext();) {
           Throwable exception = iter.next().getContext().getException();

if (exception instanceof ViewExpiredException) {


    final ExternalContext externalContext = facesContext
            .getExternalContext();

    try {


        facesContext.setViewRoot(facesContext.getApplication()
                .getViewHandler()
                .createView(facesContext, "/viewExpired.jsf"));     
        externalContext.redirect("viewExpired.jsf");             
        facesContext.getPartialViewContext().setRenderAll(true);
        facesContext.renderResponse();

    } 
    catch(IOException ioex){
     log.error(Utility.stackToString(ioex));
    }
    finally {
        iter.remove();
    }
}

}

getWrapped().handle();
 }

}


Quindi occorre creare una classe che estenda

javax.faces.context.ExceptionHandlerFactory e che faccia l'override del metodo getExceptionHandler tornando il nostro Handler personalizzato che gestisce la ViewExpiredException.


package it.exceptionHandler;
import javax.faces.context.ExceptionHandler;
import javax.faces.context.ExceptionHandlerFactory;
public class MyExceptionHandlerFactory extends ExceptionHandlerFactory {
    private ExceptionHandlerFactory parent;
    public MyExceptionHandlerFactory(ExceptionHandlerFactory parent){
     this.parent=parent;
    }
 @Override
 public ExceptionHandler getExceptionHandler() {
  ExceptionHandler result=parent.getExceptionHandler();
  result=new ViexExpiredExceptionHandler(result);
  return result;
 }

}


Quindi nel faces-config.xml dobbiamo dichiarare questa factory in questo modo:


<factory>
<exception-handler-factory>it.exceptionHandler.MyExceptionHandlerFactory</exception-handler-factory>
</factory>


giovedì 15 maggio 2014

Aggiungere repository Maven prime faces

Di seguito la struttura di un file pom utilizzato per utilizzare:
  • jsf 2.0;
  • primefaces 3.5;
  • spring 3.0;
  • javamail

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>test</groupId>
  <artifactId>webProva</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <name>test</name>
 <repositories>
  <repository>
<id>prime-repo</id>
<name>Prime Repo</name>
<url>http://repository.primefaces.org</url>
</repository>
</repositories>
  <dependencies>
  <dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>3.5</version>
</dependency>
<dependency>
   <groupId>com.sun.faces</groupId>
   <artifactId>jsf-api</artifactId>
   <version>2.1.11</version>
  </dependency>
  <dependency>
   <groupId>com.sun.faces</groupId>
   <artifactId>jsf-impl</artifactId>
   <version>2.1.11</version>
  </dependency>
 

   <dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-core</artifactId>
    <version>3.0.5.RELEASE</version>
   </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-context</artifactId>
        <version>3.0.5.RELEASE</version>
    </dependency>
     <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-expression</artifactId>
        <version>3.0.5.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework</groupId>
        <artifactId>spring-beans</artifactId>
        <version>3.0.5.RELEASE</version>
    </dependency>
    <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
            <version>3.0.5.RELEASE</version>
        </dependency>
        <dependency>
 <groupId>org.springframework</groupId>
 <artifactId>spring-web</artifactId>
 <version>3.0.5.RELEASE</version>
</dependency>
        <dependency> 
        <groupId>org.springframework</groupId> 
        <artifactId>spring-webmvc</artifactId> 
        <version>3.0.5.RELEASE</version>
         </dependency>
        <dependency>
 <groupId>javax.mail</groupId>
 <artifactId>mail</artifactId>
 <version>1.4</version>
</dependency>

  </dependencies>
</project>

domenica 4 maggio 2014

Caricamento Combo via Ajax tramite Json

Spesso capita di dover effettuare evolutive/manutenzioni su progetti vecchi, realizzati ad esempio Struts 1.3.
Qui metto un esempio di una classica combo a cascata (provincia comune) realizzata utilizzando Ajax e Json.
Ho utilizzato la libreria json-simple-1.1.1.jar per la creazione dell'oggetto Json lista dei comuni italiani ottenuto filtrando per provincia.
Come framework Javascript ho utilizzato Jquery versione 1.7.2.

JSP

<%@ page language="java" contentType="text/html; charset=ISO-8859-1"
    pageEncoding="ISO-8859-1"%>
    <%@taglib uri="http://struts.apache.org/tags-html" prefix="html"%>
<%@taglib uri="http://struts.apache.org/tags-bean" prefix="bean"%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<script src="js/jquery-1.7.2.js"></script>
<script src="js/jquery-ui-1.8.22.custom.min.js"></script>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>TEST</title>
<script>
//js function per caricare via ajax i comuni
function caricaComboComuni(){
 $("#loading").show();
  $("#loaded").hide();
 $.ajax({
   url: "caricaComune.do?cdProv="+document.getElementById("cdProv").value,
   dataType: "json",
   success:
    function (data){
    $("select#idComuni option").remove();
    $("#loading").hide();
    $("#loaded").show();
         $.each(data.listaComuni, function(key, val){
          $("select#idComuni").append('<option value="' + val.codice + '">' + val.descrizione + '</option>');
         })
       ;
    },
    error:  function (data){
     alert(data);
     }
  })
}

</script>
</head>
<body>
<html:form action="/goToHello">
<html:select property="descrizione" styleId="cdProv" onchange="caricaComboComuni()" >
<html:optionsCollection  property="listaDati" label="descrizione" value="codice" />
</html:select>
<br/>
<div id="loading" style="display:none;"> 
<img src="img/ajax-loader.gif"/>
 </div>
 <div id="loaded">
<html:select property="comune" styleId="idComuni"></html:select>
</div>
<br/>
<input type="submit" value="go" />
</html:form>
</body>
</html>


ACTION

package it.action;
import it.beans.ComuneBean;
import java.io.PrintWriter;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
public class SelectComune extends Action {
 public static JSONObject getJsonFromMyFormObject(List<ComuneBean> form)
   {
     JSONObject responseDetailsJson = new JSONObject();
     JSONArray jsonArray = new JSONArray();

     for (int i = 0; i < form.size(); i++)
     {
       JSONObject formDetailsJson = new JSONObject();
       formDetailsJson.put("codice", form.get(i).getCodice()+"-"+form.get(i).getDescrizione());
       formDetailsJson.put("descrizione", form.get(i).getDescrizione());
       jsonArray.add(formDetailsJson);
     }
     responseDetailsJson.put("listaComuni", jsonArray);
     return responseDetailsJson;
   }
 
 
 
 
 public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response)throws Exception
    {
     String codiceProv=request.getParameter("cdProv");
     List<ComuneBean> listaComuni=getComuneByProv(codiceProv);
     PrintWriter out = response.getWriter();
  out.write(getJsonFromMyFormObject(listaComuni).toJSONString());
   out.close();
  return null;
    }
 
 private List<ComuneBean> getComuneByProv(String codProv) throws Exception{
  String query="SELECT cd_catastale,descrizione FROM S_COMUNE where PROVINCIA_ID=? order by DESCRIZIONE";
  List<ComuneBean> l=new ArrayList<ComuneBean>();
  Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
  Connection conn=DriverManager.getConnection("jdbc:odbc:mydb","test","test");
  PreparedStatement pst=conn.prepareStatement(query);
  pst.setString(1, codProv);
  ResultSet rs=pst.executeQuery();
  while(rs.next()){
   ComuneBean c=new ComuneBean();
   c.setCodice(rs.getString("cd_catastale"));
   c.setDescrizione(rs.getString("descrizione").trim());
   l.add(c);
  }
  //Thread.sleep(3000);
  rs.close();
  pst.close();
  conn.close();
  return l;
 }

}


 

giovedì 24 aprile 2014

Query per trovare tabelle e righe totali in un db


Con questa query possiamo trovare tutte le tabelle con il numero di righe ordinate per tabella con più dati

select so.name as NomeTabella,max(si.rows) as righe from sysobjects as so
inner join sysindexes as si
on si.id=so.id and so.xtype='U'
group by so.name
order by 2 desc;