Visualizzazione post con etichetta java generale. Mostra tutti i post
Visualizzazione post con etichetta java generale. Mostra tutti i post

lunedì 29 settembre 2014

Carattere fine riga (CRLF LF)

Il carattere di fine riga su file di testo è diverso a seconda del sistema operativo.
Su windows abbiamo CRLF dove CR ('\r') sta per Carriage Return e LF ('\n') per Line Feed.
Invece per Linux abbiamo solo LF.
In Java se utilizziamo il metodo newLine() della classe java.io.BufferedWriter questo si comporta in maniere platform dependant, ossia inserisce CRLF su Windows e LF su Linux.
Se da una programma Java su Windows si vuole creare un file di testo con carattere di fine riga compatibile con sistemi Linux allora invece di usare il metodo newLine() occorre esplicitamente fare la write del carattere \n.
In questo modo:


BufferedWriter bw=new BufferedWriter(new FileWriter(percorsoFileCopiato));
BufferedReader br = new BufferedReader(new FileReader(percorsoFileDaCopiare));
String line;
 while ((line = br.readLine()) != null) {
        bw.write(line);
      //  bw.newLine();
        bw.write("\n");
   }
 br.close();
 bw.flush();
 bw.close();


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();
}


mercoledì 9 aprile 2014

Log4j utilizzo di MDC (Mapped Diagnostic Context)

Utilizzando la classe org.apache.log4j.MDC è possibile inserire dei parametri in una mappa e poi riutilizzarli nei nostri appender, sfruttando il conversion pattern dell'appender.

Vediamo un esempio.

Per prima cosa dobbiamo definire un Filtro Http che inserisca nella mappa i valori, supponiamo di voler inserire l'indirizzo IP del chiamante.

Filtro


import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.log4j.MDC;
public class MyMdcFilter implements Filter {
    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException {
     Utente utente = null;
        try {
         
         String ip = request.getRemoteAddr();
         
         MDC.put("ipHost",ip);
          
            chain.doFilter(request, response);
 
        } finally {
           
      MDC.remove("ipHost");
        }
 
    }

 public void destroy() {
 }

 public void init(FilterConfig arg0) throws ServletException {
 }
 
}


Impostazioni log4j.properties

si noti in particolare la riga in grassetto, che consente di recuperare il valore presente nell'MDC


##############################################################
################### DEFINIZIONE DEI LOGGER ###################
##############################################################



log4j.rootLogger=DEBUG
#Gestione log4j riguardante esclusivamente la comunicazione del Datagroup del log garante.
log4j.logger.MyLogger.logIp=INFO, LogIp


log4j.appender.LogIp=org.apache.log4j.DailyRollingFileAppender
## Inserire il percorso assoluto del file        "
log4j.appender.LogIp.File=
log4j.appender.LogIp.layout=org.apache.log4j.PatternLayout
log4j.appender.LogIp.layout.ConversionPattern=%d{dd-MM-yyyy HH\:mm\:ss} %X{ipHost}  %m%n
log4j.appender.LogIp.DatePattern='.'yyyy-MM-dd'.log'

Caricamento lato web del log4j.properties

Il log4j.properties si può caricare in una Servlet con parametro load on startup pari a 0, ossia una servlet il cui metodo init è richiamato allo start up della Web App


File log4jAppl = new File( PATH_FILE );
// da gestire nel caso in cui il file non sia indicato, si potrebbe loggare internamente 
PropertyConfigurator.configure(log4jProp); 

Utilizzo del logger

Come al solito si utilizzerà il logger richiamandolo così nei punti di interesse:


private static Logger myLog= Logger.getLogger("MyLogger.logIp");


Risultato nel file di log

08-04-2014 19:02:00 10.249.232.187  dati loggati.....;

sabato 5 aprile 2014

Callable vs Runnable

In Java dalla versione 1.0 è presente l'interfaccia java.lang.Runnable, che come sappiamo deve essere implementata da quelle classi che si vuole eseguire come Thread separati.
Nell'interfaccia è dichiarato un solo metodo

void run()

Dalla versione 1.5 invece è stata creata una nuova interfaccia java.util.concurrent.Callable che per certi versi può essere vista come una estensione dell'interfaccia Runnable. Lo scopo dei progettisti è sempre quello di mantenere la retrocompatibilità, e questo è il motivo per cui non hanno modificato l'interfaccia Runnable ma ne hanno creata una nuova.

L'unico metodo definito dall'interfaccia Callable è:

V call() throws Exception

Il vantaggio di utilizzare Callable è che consente di ottenere indietro il risultato dell'esecuzione del task nel thread separato, cosa che tramite Runnable non è possibile.
In generale le differenze tra le 2 interfacce sono le seguenti:

  1. Un oggetto che implementa Callable non può essere utilizzato direttamente per costruire un Thread, mentre un oggetto che implementa Runnable può farlo;
  2. Un oggetto che implementa  Callable torna un risultato mentre un oggetto che implementa Runnable no;
  3. Un  oggetto che implementa Callable può rilanciare al chiamante una eccezione di tipo checked, mentre un oggetto che implementa Runnable può lanciare soltanto unchecked exceptions.
Vediamo un esempio di utilizzo di Callable.
Per utilizzare un oggetto che implementa un Callable dobbiamo necessariamente utilizzare un ExecutorService.

CALLABLE

import java.util.concurrent.Callable;
public class Fattoriale implements Callable<Long> {
 private long n;
 public Fattoriale(long n){
 this.n=n; 
 }
 @Override
 public Long call() throws Exception {
  
  if(n<=0) throw new Exception("Attenzione inserire un valore positivo!!");
  long f=1;
  for(long i=1;i<=n;i++){
   f*=i;
  }
  return f;
 }
}

EXECUTORSERVICE

import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class FattorialeTest {
 public static void main(String[] args) throws Exception {
       long N=5;
       Callable<Long> c=new Fattoriale(N);
       ExecutorService es=Executors.newSingleThreadExecutor();
       Future<Long> f=es.submit(c);
       System.out.println(String.format("Il fattoriale di %d è %d",N,f.get()));
       es.shutdown();
 }
}


Si noti che l'executor service funziona anche con oggetti di tipo Runnable ma, poichè questi non tornano un risultato, il Future associato tornerà null se il processo è terminato correttamente.

giovedì 6 marzo 2014

Java leggere file di properties

Utilizzando un file di properties in formato CHIAVE=VALORE è possibile leggere a runtime gli elementi presenti in questo modo


Properties p=new Properties();
p.load(new FileInputStream(new File("log.properties")));
        Set<Entry<Object, Object>> s=p.entrySet();
       Iterator<Entry<Object,Object>> it= s.iterator();
       while(it.hasNext()){
     Entry<Object,Object> e=it.next();
     String chiave=(String)e.getKey();
     String valore=(String)e.getValue();
     System.out.println("Chiave: "+chiave);
     System.out.println("Valore: "+ valore);
   }

martedì 4 febbraio 2014

Crivello di Eratostene

Di seguito una implementazione in Java del metodo del crivello di Eratostene per trovare dato un numero n la lista dei numeri primi fino ad n (http://it.wikipedia.org/wiki/Crivello_di_Eratostene ).

package it.test;
import java.util.*;
public class CrivelloEratostene {
 public static void main(String[] args) {
   System.out.println("Inserire il numero di interi desiderato: ");
         Scanner scan = new Scanner(System.in);
         int num = scan.nextInt();
         List<Integer> listNumbers=new ArrayList<Integer>();
         List<Integer> numbersToExclude=new ArrayList<Integer>();
         for(int i=2;i<num;i++){
          int mul=i;
          if(numbersToExclude.contains(i))
        break;
          if(i==2 || !isPrime(i)){
           for(int j=i;j<num;){
            numbersToExclude.add(j);
            j=j+mul;
           }
          }
         }
         for(int i=2;i<num;i++){
          if(!numbersToExclude.contains(i)){
           listNumbers.add(i);
          }
         }
         System.out.println(String.format("Lista numeri primi fino ad %d  : %s", num,listNumbers));
 }
 public static boolean isPrime(int n){
    for(int i=2;i<n;i++) {
          if(n%i==0)
              return false;
      }
      return true;
 }

}




martedì 28 gennaio 2014

Errore CertificateException : No subject alternative names present in chiamata HTTPS

Ho passato un pomeriggio a dannarmi per questo errore, ottenuto in fase di chiamata ad un Web Service in HTTPS sulla mia macchina.
Lo scenario è il seguente:
  1. Ho creato un certificato HTTPS;
  2. Lo ho inserito in Tomcat per fare in modo che un mio web service rispondesse in HTTPS;
  3. Ho scritto un client JAVA per il servizio
Il client Java è stato generato con JAX-WS, con il comando wsimport prima che fosse messo in HTTPS il servizio.
L'unica modifica al client fatta è stata quella di creare un costruttore ulteriore che prendesse in input l'url del servizio come Stringa, in modo da poterlo invocare a runtime con il percorso in https.
Cercando quindi l'errore su Internet ho letto che il problema era dato dalla presenza nel CN del certificato di un nome diverso da quello del server invocato lato client; ho letto anche che tale problema si verifica soltanto in caso di certificati self signed.
Ho provato a rigenerare il certificato mettendo nel CN (il primo campo richiesto dalla procedura keytool) l'indirizzo 127.0.0.1 oppure localhost ma nulla da fare, sempre lo stesso errore.
Ho risolto così:
  1. Nel file hosts della mia macchina ho aggiunto un nome XXX mappandolo a 127.0.0.1;
  2. Ho rigenerato il certificato mettendo come nome nel CN lo stesso del punto 1;
  3. Ho effettuato la chiamata client con l'indirizzo http://XXX:8080/URL_WSDL.

Cosìfacendo ha funzionato, anche se non capisco perchè...

domenica 19 gennaio 2014

Esempio utilizzo java.util.concurrent.Future, Callable e ExecutorService

L'interfaccia java.util.concurrent.Future schematizza un oggetto che dovrà tornare in futuro il risultato di una operazione asincrona.
L'interfaccia java.util.concurrent.Executor dichiara un solo metodo, void execute(Runnable)
L'interfaccia java.util.concurrent.ExecutorService estende l'interfaccia Executor aggiungendo funzionalità che consentono il termine dei thread e la produzione di oggetti Future.
L'interfaccia java.util.concurrent.Callable dichiara invece un solo metodo V call() throws Exception

Vediamo un esempio di una classe che implementa Callable e utilizza un ExecutorService per creare un oggetto Future passando il Callable.


package it.threads;
import java.util.concurrent.Callable;
public class OperazioneAsincrona implements Callable<String> {
 @Override
 public String call() throws Exception {
  System.out.println("Simulo lavorazione.....");
  Thread.sleep(3000);
  return "Lavorazione eseguita.....";
 }
}



Vediamo ora come richiamare il callable utilizzando ExecutorService e Future.

package it.threads;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class OperazioneAsincronaTest {
 public static void main(String[] args) throws InterruptedException, ExecutionException {
       Callable<String> task=new OperazioneAsincrona();
       ExecutorService es=Executors.newSingleThreadExecutor();
       Future<String> f=es.submit(task);
       System.out.println(f.get());
       System.out.println("Esco dall'executor...");
       es.shutdown();
 }
}


Si può anche istanziare un ThradPool con l' ExecutorService, usando invece del newSingleThreadExecutor il metodo newFixedThreadPool che accetta come parametro in input un intero.

Esempio utilizzo AtomicInteger

La classe AtomicInteger si trova nel package java.util.concurrent.atomic.
Si utilizza per evitare i problemi di tipo data race nel caso di operazioni multi-thread, quindi garantisce che nel caso di accessi ad un contatore una sincronizzazione sulla variabile da incrementare.
Vediamo un esempio classico di utilizzo di variabili intere in un ambiente multi thread.


package it.threads;
public class ClassicIntTest extends Thread {
 private static Integer intero=new Integer(0);
 public void run(){
  System.out.println("CLASSICO: Incremento 
                e recupero il valore "+ ++intero);
 }
}


Se lanciamo il Thread per 10 volte in questo modo:

public static void main(String[] args) {
  for(int i=0;i<10;i++){
    new ClassicIntTest().start();
  }
 }

Lanciando il main può accadere di avere il seguente output:

CLASSICO: Incremento e recupero il valore 1
CLASSICO: Incremento e recupero il valore 2
CLASSICO: Incremento e recupero il valore 3
CLASSICO: Incremento e recupero il valore 4
CLASSICO: Incremento e recupero il valore 5
CLASSICO: Incremento e recupero il valore 6
CLASSICO: Incremento e recupero il valore 7
CLASSICO: Incremento e recupero il valore 8
CLASSICO: Incremento e recupero il valore 8
CLASSICO: Incremento e recupero il valore 9


Come possiamo vedere il risultato non è quello che ci attenderemmo, in quanto non essendoci sincronizzazione sulla variabile intera (che è statica) capita che 2 thread leggano lo stesso valore in quanto accedono nel medesimo istante al metodo.

Se utilizziamo invece l'AtomicInteger questo non accade.
Esempio:

package it.threads;
import java.util.concurrent.atomic.AtomicInteger;
public class AtomicIntTest extends Thread {
 private static AtomicInteger intero=new AtomicInteger(0);
 public void run(){
  System.out.println("ATOMIC: Incrementa e recupera il valore "+intero.incrementAndGet());
 }
}


Se nel main precedente sostituiamo la classe ClassicIntTest con la AtomicIntTest avremo invece sempre l'output atteso, ossia:

ATOMIC: Incrementa e recupera il valore 1
ATOMIC: Incrementa e recupera il valore 2
ATOMIC: Incrementa e recupera il valore 3
ATOMIC: Incrementa e recupera il valore 4
ATOMIC: Incrementa e recupera il valore 5
ATOMIC: Incrementa e recupera il valore 6
ATOMIC: Incrementa e recupera il valore 8
ATOMIC: Incrementa e recupera il valore 7
ATOMIC: Incrementa e recupera il valore 9
ATOMIC: Incrementa e recupera il valore 10

mercoledì 8 gennaio 2014

Java stampare tutti i get di un oggetto

Un metodo per avere in stampa tutte i getter di un oggetto:


public static String getRappresentazioneStringa(Object o) throws Exception{
   StringBuffer sb=new StringBuffer();
   Method[] listaMetodi= o.getClass().getMethods();
   for(int i=0;i<listaMetodi.length;i++){
    Method m=listaMetodi[i];
    if(m.getName().startsWith("get") && !"getClass".equals(m.getName())){
     // è un getter stampo il valore
     sb.append(m.getName().substring(3).toUpperCase());
     sb.append(" = ");
     sb.append(m.invoke(o)!=null?m.invoke(o).toString():"");
     sb.append("#");
    }
   }
   return sb.toString();
}


domenica 22 dicembre 2013

Java implementazione pattern observer

Il pattern OBSERVER rientra nella categoria dei pattern "comportamentali".
Esistono 3 categorie principali di pattern:
  • CREAZIONALI ( es. SINGLETON, FACTORY, ABSTRACT FACTORY)
  • STRUTTURALI  (es. DECORATOR, PROXY, FACADE)
  • COMPORTAMENTALI (es. OBSERVER, STATE,STRATEGY)
Per realizzare questo pattern la classe che deve "segnalare" le modifiche agli osservatori dovrà estendere la classe java.util.Observable, mentre le classi che ricevono la segnalazione dovranno implementare l'interfaccia java.util.Observer che definisce il metodo  update.

Vediamo un semplice esempio.

CLASSE OBSERVABLE


package it.pattern;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
public class Lista extends Observable {
 private List<String> lista=new ArrayList<>();
 public List<String> getLista() {
  return lista;
 }
 public void addString(String elemento){
  setChanged();
  notifyObservers(elemento);
  lista.add(elemento);
 }
}


CLASSE OBSERVER

package it.pattern;
import java.util.Observable;
import java.util.Observer;
public class ListaObserver implements Observer {
 @Override
 public void update(Observable o, Object arg) {
  System.out.println("Aggiunto elemento "+arg);
 }
}


Vediamo di seguito un esempio di utilizzo:

package it.pattern;

public class Test {
 public static void main(String[] args) {
  Lista l=new Lista();
  l.addObserver(new ListaObserver());
  l.addString("dsjksdkjd");
  l.addString("dsddsds");

 }

}


Il risultato dell'esecuzione del codice sarà il seguente:

Aggiunto elemento dsjksdkjd
Aggiunto elemento dsddsds


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.

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));


domenica 27 ottobre 2013

Trovare tutti i numeri lunghi x-cifre in un campo di testo

Questo metodino cerca in una stringa tutti i valori numerici di 5 cifre in un campo di testo.


String testo2=" cerchiamo i cap 00175 oppure anche 03029, so si 234 09909 carlo";
  Pattern pt=Pattern.compile("\\b\\d{5}\\b");
  Matcher mc=pt.matcher(testo2);
  while(mc.find()){
   System.out.println(mc.group());
  }



Il separatore \b indica il termine parola , quindi becca e riconosce anche le virgole immediatamente dopo, se avessimo usato una espressione regolare del tipo \D\d{5}\D (ossia un qualsiasi carattere non numerico + 5 numeri + qualsiasi carattere non numerico) avremmo preso ad esempio 03029, con la virgola eccetera.

Differenze tra uso dei generics e il tipo object

C'è una sottile differenza tra la notazione con i generics e quella con il tipo generico java.lang.Object
Infatti se scriviamo questo metodo:

public static void stampa(List<?> lista){
  for(Object o:lista){
   System.out.println("["+o+"]");
  }
 }


Possiamo passare ad esso qualsiasi struttura dati ed avere l'output in stampa.
Es:

List<String> ls=new ArrayList<>();
  ls.add("uno");
  ls.add("due");
  ls.add("tre");
  stampa(ls);
  List<Integer> lista=new ArrayList<>();
  lista.add(5);
  lista.add(7);
  lista.add(9);
  stampa(lista);




Se invece proviamo a cambiare la firma del metodo da List<?> a List<Object> il
codice non compila più, il messaggio è "The method stampa(List<Object>) in the type xxxxx is not applicable for the arguments (List<String>) "

dove xxx è il nome della classe da cui invochiamo il metodo.
La differenza quindi tra i due approcci è che usando List<Object>  si incappa nel problema del subtyping, ossia il tipo List<String> poichè String è sottoclasse di object non va bene per invocare il metodo, bisognerà esplicitamente castare il parametro.
La notazione ? ci evita di effettuare cast e il nostro metodo funzionerà con Liste di qualsiasi tipo.

mercoledì 23 ottobre 2013

Java, invocare tutti i set di un metodo con input di tipo Stringa

Un metodo utile per istanziare al volo un oggetto e settare tutte le sue proprietà con input una stringa casuale

public Object getOggettoIstanziato(String nomeClasse) throws Throwable {
Class dynamicClass = null;
dynamicClass = Class.forName(nomeClasse);
Object iClass = dynamicClass.newInstance();
Method[] listaMetodi = dynamicClass.getMethods();
for (Method m : listaMetodi)
{
if (m.getName().startsWith("set")
&& m.getGenericParameterTypes()[0].toString().equals("class java.lang.String"))
{
 int numeroCaratteri = RandomUtils.nextInt(20) + 1;
 m.invoke(iClass,new Object[] { getRandomString(numeroCaratteri) });
   }
  }
  return iClass;
 }

giovedì 10 ottobre 2013

Java creare Url da Stringa



 private static URL getUrlFromWsdl(String wsdl) {
     URL baseUrl=null;
        try {
            baseUrl = new URL(wsdl);
        } catch (MalformedURLException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return baseUrl;
 }

mercoledì 9 ottobre 2013

Differenze conteggio caratteri tra javascript e java lato server

Con un formato testo libero (es. textarea) mi è capitato il seguente problema.
Il codice javascript lato client effettua un controllo sulla numerosità dei caratteri e lato server allo stesso modo si verifica di non eccedere la quota per evitare problemi sul db.
Il massimo impostabile è 1000 caratteri.
Solo che i due valori non collimano sempre.
In presenza di testi copiati e incollati da fonti esterne (siti di giornali etc.) succede che il frontend passa 1000 caratteri ma il back end se ne trova di più.
Indagando un pò il problema ho visto che è dovuto ai caratteri di  a capo, che nella request http sono identificati dallo /r.
Quindi ogni carattere di a capo mi viene a contare per 2.
Ho risolto inserendo una replace lato java, in questo modo:

x.replaceAll("\r", "");

venerdì 20 settembre 2013

Export runnable jar in modalità package oppure extract

Nel caso in cui da Eclipse si voglia esportare in un unico jar sia il codice della nostra applicazione sia quello delle librerie utilizzate da essa, si può procedere in 3 modi:
  • Extract required libraries into generated jar;
  • Package required libraries into generated jar;
  • Copy required libraries into a sub-folder next to the generated JAR.
Il terzo modo è intuitivo, tutti i jar sono inseriti in una cartella a fianco del jar principale.

Nel primo caso (EXTRACT) il contenuto dei jar viene esploso dentro il jar (Eclipse correttamente avvisa che trattandosi di un repackaging di jar esterni potrebbero esserci problemi di licenza).
In questo caso nel manifest del jar abbiamo la seguente situazione:

Main-Class: classe con il nostro main

Nel secondo caso (package) i jar sono inseriti all'interno del jar esportato, e il manifest risulta modificato in questo modo:

Manifest-Version: 1.0
Rsrc-Class-Path: ./ logback-core-1.0.9.jar commons-lang-2.6.jar logbac
 k-classic-1.0.9.jar slf4j-api-1.7.2.jar log4j-1.2.17.jar commons-code
 c-1.6.jar....[lista di tutti i jar utilizzati]
Class-Path: .
Rsrc-Main-Class:classe con il nostro main
Main-Class: org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader


Le differenze principali tra i 2 approcci sono:
  1. Usando la modalità package crescono le dimensioni del jar ;
  2. Usando la modalità extract si potrebbe incappare in problemi di licenza sw;
  3. Usando la modalità extract se si aggiorna un jar esterno bisogna rieffettuare il pacchetto, nel caso invece della modalità package basta sostituire il jar interno. 






lunedì 22 luglio 2013

CamelCase di una stringa

Metodo per ottenere una stringa in formato camel case,

public static String toCamelCase(String s){
  StringBuffer sb=new StringBuffer();
  if(!isNullOrEmpty(s)){
   StringTokenizer st=new StringTokenizer(s," ");
   while(st.hasMoreElements()){
    String testo=st.nextToken();
    sb.append(testo.substring(0, 1).toUpperCase());
    sb.append(testo.substring(1).toLowerCase());
    sb.append(" ");
   }
  }
  else
  {
   sb.append("");
  }
  
  return sb.toString();
 }