Newsgroup: it.comp.java
Titolo: Problema avvio generica applicazione

salve a tutti,
vorrei sapere come conoscere se la mia applicazione è già avviata oppure
no. Se fosse già avviata vorrei passarle il controllo invece che
allocare un'altra istanza. Voglio che ad ogni istante ci sia solo
un'istanza della mia applicazione e che l'utente richiami sempre quella,
anche se tenti di avviarne altre.
ringrazio anticipatamente,
GiGi
-- 
Posted via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Potresti aprire un socket (su porta tcp o x unix su disco).
In questo modo potresti addirittura comunicare con l'applicazione 
running (ad esempio puoi chiedergli di aprire una nuova finestra con
parametri opportuni).
Putroppo dopo dovrai gestire il protocollo di comunicazione
(per fare in fretta, potresti usare RMI, ma anche WebService o (peggio) 
qualcosa di custom) e la sicurezza x l'accesso all'applicazione (chi, da 
dove, etc.).


Qualcosa di più semplice :)? Per esempio, controllare tra la lista dei
processi in memoria?


 processi in memoria?
E' un po' stiracchiato e non ho idea se funzioni: dichiari la classe
principale della tua applicazione come estensione di Thread. A questo punto
tramite getThreadGroup dovresti poter accedere al gruppo di thread avviati
dal class loader della jvm, tra i quali eventuali altre istanze
dell'applicazione. Usi enumerate di ThreadGroup per avere tale lista e
controlli che esista un unico thread con quel nome. Se ce n'è più d'uno a
questo punto però puoi solo dire all'utente che c'è già un'istanza aperta,
non hai modo di "passarle il controllo".
Ovviamente nell'ipotesi che non venga avviata una nuova jvm ad ogni istanza,
che le varie istanze delle applicazioni appartengano effettivamente al thrad
group principale e non ad un suo figlio (non è possibile leggere le
informazioni del parent...), che questa consegni senza fiatare il
ThreadGroup principale, che ti dia il permesso di leggerci, ecc....
Il metodo che ti hanno suggerito di usare un socket in ascolto e di testarne
la presenza tuttavia mi sembra decisamente quello migliore.
Del resto l'operazione che chiedi è molto platform-dependent: Sotto windows
un'applicazione può controllare se c'è in giro una sua simile controllando
se tra i figli del desktop ce n'è un'altro con la stessa window-class per
poi mandargli 
p.es
. un WM_USER per avvertirla. Nei vari *nix dovresti
ravanare nella lista dei processi vedendo se ce ne sono per quell'utente che
hanno il tuo stesso eseguibile e quindi gli mandi magari un SIGUSR, ecc..
IG

Ok, ho aperto una porta utilizzando SockectServer e sono riuscito a
controllare se
esiste o meno un'istanza della mia applicazione. Ora il problema diventa
più difficile..
Come faccio a passare il controllo all'istanza già presente?
grazie,


 processi in memoria?
Puoi provare. 
http://sourceforge.net/projects/processmonitor/
 ti aiuta
ad accedere ai processi di sistema

 Come faccio a passare il controllo all'istanza già presente?
L'applicazione "abusiva" crea un socket da connettere a quello in ascolto e
usa l'OutputStream per scriverci dentro. L'altra applicazione avrà un thread
in funzione che esegue continuamente accept() sul ServerSocket (funzione
bloccante, occhio...) e che legge i dati in arrivo dal suo InputStream. A
seconda di quello che il chiamante manda al chiamato l'applicazione
principale fa qualcosa (a tua scelta: passa in primo piano, usa i dati
arrivati via socket per aprire un file, apre una nuova finestra se funziona
in MDI, ecc...). Il chiamante inviata la sua richiesta chiude il socket e si
quitta.
Suggerisco la lettura di esaustiva documentazione sul funzionamento generale
dei socket e non solo per l'implementazione java. Google: network socket
IG

Secondo voi questo è il modo corretto di procedere? C'e' un pattern che
definisce il problema? Inoltre... se quando creo la ServerSocket su una
porta
e la porta è allocata ad un altro processo diverso dalla mia
applicazione..
non funzionerà nulla, giusto? Esempio..
Siano A e B due istanze della mia applicazione, A la prima e B la
seconda rispettivamente.
Nel caso fortunato abbiamo:
passo 1. A tenta di aprire la porta 1234. Ci riesce (non ci sono altre
istanze della mia applicazione)
e rimane in ascolto.
passo 2. B tenta di aprire la porta 1234. non ci riesce (c'e' A) e
quindi passa il controllo
tramite la socket ad A.
Nel caso sfortunato...(puo' accadere?) in cui la porta è già assegnata
ad un processo generico.
passo 1. A tenta di aprire la porta 1234. Non ci riesce. A "Pensa" che
ci
sia un'altra istanza dell'applicazione e cerca di passarle il controllo,
ma non ci riesce perchè l'applicazione che gestisce la porta "non
capisce"
che cavolo vuole A..:)
e quindi? :)


 ad un processo generico.
Può accadere tranquillamente, chi primo arriva meglio alloggia. Però puoi
sempre verificare che ci c'è in ascolto sia davvero un'altra istanza
connettendoti, inviandogli una sequenza di controllo qualsiasi alla quale la
vera applicazione risponderebbe appropriatamente. Se l'altro chiude la
comunicazione, non risponde o risponde roba diversa da quella che ti aspetti
vuol dire che tu sei il primo, ma la porta è già occupata, e stamperai
qualcosa tipo "impossibile avviare l'applicazione perchè la porta XYZ è in
uso". Se poi vuoi puoi usare un range di porte, e se la prima è occupata
provi la seconda, sempre con la stessa procedura. In questo caso ad ogni
avvio le devi provare tutte... oppure potresti usare UPD (classe
DatagramSocket) invece di TCP, le probabilità che qualcuno stia facendone un
uso intenso sono abbastanza scarse.
Oppure ecco una soluzione finale: usi System.getProperty per farti dare la
directory home dell'utente, e li crei un file con nome talmente lungo e
incasinato da essere univoco nel quale scrivi la porta che hai aperto, così
non devi sapere qual'è in anticipo. Se quando avvii il programma il file c'è
vuol dire c'è già un'altra istanza e basta leggerne il contenuto per sapere
su che porta risponde per passarle il controllo, se no sei tu il primo e
apri la porta in ascolto e ne scrivi il numero nel file. Alla chiusura della
prima istanza il file viene cancellato.
IG