Newsgroup: it.comp.java
Titolo: Ricerca directory in java

Domanda stupida...
se io ho un file java, mettiamo prova.class che gira nella directory
c:\pippo, esiste una funzione che io possa chiamare all'interno del file
prova.class che mi ritorni c:\pippo e che quando sposto il file nella
directory c:\paperino e lo lancio da là, mi ritorni c:\paperino?
Grazie,
Fabrizio

...

Per evidenziare la presenza di un file prova con:
import java.io.*;
public class prova{
 public RicercaFile(){
  File f = new File("C:\pippo",  "prova.class");  
     if ( f.exists() ) {   //  se il file viene trovato questo metodo
      restituisce true
   System.out.println("Il file " + f.getName() + " è presente");
  }
else {
System.out.println("Il file " + f.getName() + " non è presente");
}
}
File originale=new File("C:\\cartella\\1\\sottocartella\\0001.jpg");
  File destinazione=new File("C:\\cartella\\1\\0001.jpg");
  originale.renameTo(destinazione);

...





Non è una domanda stupida, anzi... e la risposta non è da meno. Purtroppo
non c'è nessun metodo semplice che permetta ad una classe di conoscere il
proprio file di provenienza, perchè i bytecode possono provenire
letteralmente da OVUNQUE (dipende dalla capacità del classloader
corrispondente).
Ti faccio solo qualche esempio: con i classloader standard forniti "di
serie" con il JDK, una classe può essere caricata e allocata da
- singolo classfile
- archivio .jar
- risorsa in rete (vedi java.net.URLClassLoader), quindi di nuovo da un file
locale ("file://"), da un archivio su un webserver ("http://") o su un
ftpserver ("ftp://")
Se poi lo sviluppatore di turno ha tempo e voglia di fare le cose a modo
proprio, è possibile implementare diversi classloader che carichino le
classi da:
- una tabella su un database
- una connessione diretta TCP/IP
- direttamente dalla porta seriale standard o usb, o persino firewire (non
sto scherzando!)
- qualunque storage riconosciuto dal sistema operativo sottostante e per cui
sia possibile scrivere un'estensione nativa (.dll o .so) utilizzabile via
JNI
Quindi il problema si riconduce al poter rilevare qual'è il classloader da
cui è stata caricata la tua classe "prova", e comunicare con esso per
sapere:
1) se è un classloader file-based
2) qual'è il file da cui ha caricato la tua classe
Sapere il classloader di provenienza è estremamente facile, perfino
dall'interno della tua classe (occhio alle restrizioni di sicurezza!):
  ClassLoader classloader=this.getClass().getClassLoader();
Con il JDK standard, l'unico classloader basato su file che io conosca è
java.net.URLClassLoader, quindi potresti verificare tramite l'operatore
instanceof:
  URLClassLoader myclassloader=null;
  if (classloader instanceof URLClassLoader)
    myclassloader=(URLClassLoader)classloader;
Uscito da questo codice, se myclassloader è ancora null allora si tratta
probabilmente del classloader di sistema, che di default non permette di
rilevare l'origine delle classi da lui generate.
Se invece si tratta di un URLClassLoader, sei fortunato (oppure hai forzato
un po' la mano... chi ha orecchie per intendere, intenda!). A questo punto
puoi usare il metodo getURLs() per ottenere un array di URL in cui il
classloader esegue le sue ricerche (ti ricordo che un URL può riferirsi ad
un file presente su disco). Ti toccherà scandire ogni singolo oggetto URL
per vedere:
1) se il metodo getProtocol inizia con "file"
2) se il metodo getFile restituisce "prova.class"
Nel caso in cui l'URL scandita soddisfi questi due requisiti, puoi essere
certo che si tratta del file di provenienza che stai cercando. Ancora un
piccolo passaggio attraverso URI per arrivare al File (suppondendo che il
tuo oggetto URL trovato sia "foundurl"):
  File classfile=new File(new URI(foundurl.toString()));
beh... a questo punto puoi farci un po' quello che vuoi... mi sembra che tu
possa perfino cancellarlo (una classe suicida ROTFL!), rinominarlo,
spostarlo o modificarlo, dato che il bytecode della classe stessa è già in
memoria, ma mi sembra un operazione abbastanza pericolosa. Vedi un po' te
che esperimenti ti andrà fare ;)
Perdonami se mi sono dilungato, ma penso ne sia valsa la pena. In bocca al
lupo!
-- 
Fermiamo Scientology prima che sia troppo tardi!!!
http://xenu.com-it.net
 - 
http://xenu.freewinds.cx/
(per rispondere personalmente leva IlDitoDalCulo)

 ha scritto nel messaggio
news:c1uukv$1ne30b$1...@ID-200838.news.uni-berlin.de...


 Fabrizio
Il quoting ragazzo mio... il quoting... ;)
Come immaginavo, stai tentando di rilevare il percorso originario del
classfile tramite il classloader standard. Per poter utilizzare
URLClassLoader l'applicazione deve essere sviluppata seguendo alcune
premesse importanti. Ti do qualche suggerimento in più:
La classe principale della tua applicazione deve "preparare il terreno" per
poter utilizzare URLClassLoader, innanzi tutto deve sapere dove stanno tutti
i file ".class" . Ora mi dirai: "e grazie tante, se glie lo dico io dove
stanno i classfile a che serve tutta quella roba di prima?". Risposta: ti
ricordo che il classloader di sistema NON PERMETTE di rilevare la vera
origine delle classi caricate, quindi se vuoi sapere il percorso di queste
dovremmo fare tutto a "manina". Forza, su le maniche:
Supponiamo che tutti i classfile si trovino nella stessa directory dove si
troverà anche MainClass.class, e che essa sia anche la directory da cui
avvii l'interprete (cioè la directory corrente):
------------------------------------------------- MainClass.class
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
public class MainClass {
  public static void main(String[] args) {
    try {
      File currentDir=new File(System.getProperty("user.dir"));
      File[] classLoaderFiles=currentDir.listFiles();
      URL[] classLoaderUrls=new URL[classLoaderFiles.length];
      for(int i=0;i<classLoaderFiles.length;i++)
        classLoaderUrls[i]=classLoaderFiles[i].toURL();
      //Ottenuta tutta la lista dei classfile che compongono la tua
      //applicazione, creiamo un classloader adatto
      URLClassLoader myloader=new URLClassLoader(classLoaderUrls);
 
      //Adesso smanettiamo un po' con la Reflection per "riavviare"
      //la tua applicazione sotto l'ègida del nuovo classloader
      //1) ricarichiamo da zero la classe principale
      Class entryClass=myloader.loadClass(this.getClass().getName());
      //2) otteniamo accesso al metodo "xmain" (puoi scegliere quello che
      //vuoi, basta che sia definito e pubblicamente accessibile)
      Class[] signature=new Class[1];
      signature[0]=args.getClass();
      Method xmainMethod=entryClass.getMethod("xmain",signature);
      //3) richiamiamo il metodo "xmain" passandogli tutti gli argomenti
      xmainMethod.invoke(null, args);
 
    } catch (Exception ex) { //lo so, non è bello... ma avevo fretta...
      ex.printStackTrace();
    }
  }
  public static void xmain(String[] args) {
    //Questo metodo deve essere trattato come il punto d'ingresso
    //principale della tua applicazione, con la differenza che
    //da qua sarà possibile arrivare all'URLClassLoader che ha avviato
    //il tutto.
    Path pathobj=new Path();
    pathobj.testPath();
  }
}
---------------------------------------------fine MainClass.class
------------------------------------------------------ Path.class
import java.io.*;
import java.net.*;
import java.lang.reflect.*;
public class Path {
  public String testPath() {
    ClassLoader classloader=this.getClass().getClassLoader();
    URLClassLoader myclassloader=null;
    if (classloader instanceof URLClassLoader) {
      myclassloader=(URLClassLoader)classloader;
    } else {
      System.out.println("classloader non corretto");
      return;
    }
    for(int i=0; i<foundurl.length; i++) {
      System.out.println(foundUrl[i].toString());
      //Beh, non devo mica dirti tutto io :P
    }
  }
}
--------------------------------------------------fine Path.class


 --------------------------------------------------fine Path.class
Chiedo scusa a tutti :°


 ha scritto nel messaggio
news:c1v5or$1mtfqh$1...@ID-200838.news.uni-berlin.de...


 
Scherzi? Il tuo codice sara' utile a molti!
Grazie.
-- 
                Roberto Nunnari -software engineer-
                     mailto:
ro...@nunnisoft.ch
 
http://www.nunnisoft.ch
   Residenza Boschetto 12           tel/fax: 
+41-91-6046511
   6935 Bosco Luganese        """    mobile: 
+41-76-3208561
   Switzerland               (o o)
========================oOO==(_)==OOo========================