View Full Version : [JAVA] classe Java per scrivere Java
sto cercando di fare un programma, questo programma dovrebbe servire a scrivere un programma java completo secondo alcuni automatismi definiti, in pratica vorrei creare un programma in java che mi sappia creare il programma
software_automaticamente_generato.java
( la compilazione non dovrebbe essere un problema dato che tratterò il compilatore come qualsiasi eseguibile ) secondo dettami specifici come il nome della classe che conterrà l'entry point, variabili di tipo e nome predefinito, etc etc; possibilmente vorrei fare questa in una forma "comoda", nel senso che vorrei mantenere un certo livello di astrazione e non fare solamente un programma che crei un file nuovo, ci butti dentro delle righe di codice e lo rinomini in .java, ad esempio io gli setto il nome ed il tipo di una variabile come attributi e poi la classe saprà come scrivere questo nel file, oppure io gli setto il nome della classe e il mio programma saprà da solo dove aprire e chiudere le parentesi graffe.
in pratica la mia difficoltà è nel trovare una classe che mantenga un certo livello di astrazione su queste cose che è però una cosa molto comoda.
aggiungo una piccola grande cosa, l'intero processo deve essere trasparente all'utente, nessun file scritto da nessuna parte, l'utente riceve solo il compilato.
Deve essere possibile usare un compilatore indicato a scelta dall'utente e non necessariamente quello ufficiale ( javac ).
Non so se è proprio quello che ti serve, ma di solito per la generazione automatizzata di sorgenti (di qualunque tipo, non solo Java, al peggio anche solo dei semplici testi fatti in un certo modo) si ricorre a dei Template Engine.
Prova a dare un'occhiata a FreeMarker e StringTemplate
http://freemarker.sourceforge.net/
http://www.stringtemplate.org/
tomminno
02-10-2011, 15:16
Il tuo obiettivo è praticamente quello che viene realizzato negli editor UML che trasformano i diagrammi in codice.
Potresti provare a vedere i sorgenti di qualche progetto open source.
se non mi produce solo il compilato per l'utente mi è inutile, l'utente deve solo inserire qualche dato in una maschera ed avere il bytecode, nessun codice sorgente deve risiedere neanche temporaneamente sul filesystem della macchina
Provato con l'interfaccia JavaCompiler (http://download.oracle.com/javase/6/docs/api/javax/tools/JavaCompiler.html)?
in pratica la mia difficoltà è nel trovare una classe che mantenga un certo livello di astrazione su queste cose che è però una cosa molto comoda.
Non ho esattamente capito che intendi con questo. Nel senso che in generale nessuno ti vieta di inventarti un linguaggio intermedio nel quale l'interfaccia grafica scrive i comandi, e poi ci sarà un'interprete che traduce in java ciò che ti serve.
Puoi sare roba come SableCC e affini per questo.
se non mi produce solo il compilato per l'utente mi è inutile, l'utente deve solo inserire qualche dato in una maschera ed avere il bytecode, nessun codice sorgente deve risiedere neanche temporaneamente sul filesystem della macchina
Il template engine per forza di cose produce sorgenti, ma la generazione non necessariamente deve coinvolgere il file system.
Il template ed il data model possono benissimo essere presenti solo in ram (alias generati dal tuo codice e non caricati dal disco o da una fonte dati), così come lo sarà il sorgente (output) generato.
Dopo di che ti serve una libreria che permetta la compilazione di sorgenti presenti in variabili buffer.
E qui ti direi di guardare oltre all'interfaccia che già ti hanno suggerito anche al progetto Janino : http://xircles.codehaus.org/projects/janino
non so se una interfaccia da sola mi basti o comunque mi possa alleggerire il carico di lavoro.
io devo generare del bytecode ( un programma java classico, un file.class ), per farlo metto insieme del codice preparato da me e qualche pezzettino incluso "on-the-fly" secondo delle scelte dell'utente che avvengono tramite un mio programma ( non necessariamente scritto in java ), chiedo al framework/classe/linguaggio di offrirmi queste 2 possibilità:
- compilatore a scelta dell'utente
- nessun file scritto da nessuna parte e la mia parte di sorgente protetta da eventuali accessi di qualunque genere
esempio:
io scrivo del codice, dichiaro 2 variabili X ed Y e dei metodi, ora l'utente sceglie tra i miei metodi una somma, il programma mi deve generare del bytecode che dichiari X e Y e ne faccia solo la somma compilando il tutto con il compilatore scelto dall'utente, cioé nient'altro al di fuori della logica di ciò che richiede l'utente e deve occuparsi anche della sintassi per evitare noie con il compilatore.
Il template engine per forza di cose produce sorgenti, ma la generazione non necessariamente deve coinvolgere il file system.
Il template ed il data model possono benissimo essere presenti solo in ram (alias generati dal tuo codice e non caricati dal disco o da una fonte dati), così come lo sarà il sorgente (output) generato.
Dopo di che ti serve una libreria che permetta la compilazione di sorgenti presenti in variabili buffer.
E qui ti direi di guardare oltre all'interfaccia che già ti hanno suggerito anche al progetto Janino : http://xircles.codehaus.org/projects/janino
ok, se questa è la via più sicura per il mio codice darò una occhiata, grazie :)
Ok, ma Janino è un compilatore a parte, così tolgo la possibilità di scelta, i 2 punti che ho descritto sono fondamentali da rispettare altrimenti non mi conviene.
Sicuro che vuoi fare le cose in Java ?
Primo parli di dare al cliente solo il bytecode risultante, ma poi chiedi che il cliente deve scegliersi liberamente il compilatore.
Scusa ma quale compilatore ?
Java di solito si compila con Javac del pacchetto JDK o al più con librerie come Janino
Avendo tu parlato di bytecode come risultato ho escluso l'uso di GJC, Android o il compilatore bytecode to clr (di cui ora mi sfugge il nome).
Cosa intendi quindi con la tua affermazione ?
Secondo parli di scegliere solo dei metodi.
Insomma sembra che tu abbia una mega classe che fa un sacco di cose e che il cliente sceglierà, come da un menu, solo le funzioni che desidera (e che ti pagherà) ed il software dovrà derivare (o meglio creare exnovo) una classe che faccia solo quello chiesto (e pagato) ma non il resto.
Ti serve davvero una cosa del genere ?
Perché in tal caso suppongo ci siano anche altre soluzioni oltre alla generazione di nuove classi a runtime.
Terzo parli di totale sicurezza dei tuoi sorgenti.
Ma sai che un eseguibile (inteso come file .class) Java è facilmente decompilabile ?
Ed a meno di usare offuscatori di codice (es. ProGuard) spesso (almeno per progetti non troppo complessi) da un file .class (bytecode) si può riottenere un sorgente molto leggibile (anche se privo dei commenti) e sopratutto ricompilabile
Sicuro che vuoi fare le cose in Java ?
Primo parli di dare al cliente solo il bytecode risultante, ma poi chiedi che il cliente deve scegliersi liberamente il compilatore.
Scusa ma quale compilatore ?
Java di solito si compila con Javac del pacchetto JDK o al più con librerie come Janino
Avendo tu parlato di bytecode come risultato ho escluso l'uso di GJC, Android o il compilatore bytecode to clr (di cui ora mi sfugge il nome).
Cosa intendi quindi con la tua affermazione ?
Secondo parli di scegliere solo dei metodi.
Insomma sembra che tu abbia una mega classe che fa un sacco di cose e che il cliente sceglierà, come da un menu, solo le funzioni che desidera (e che ti pagherà) ed il software dovrà derivare (o meglio creare exnovo) una classe che faccia solo quello chiesto (e pagato) ma non il resto.
Ti serve davvero una cosa del genere ?
Perché in tal caso suppongo ci siano anche altre soluzioni oltre alla generazione di nuove classi a runtime.
Terzo parli di totale sicurezza dei tuoi sorgenti.
Ma sai che un eseguibile (inteso come file .class) Java è facilmente decompilabile ?
Ed a meno di usare offuscatori di codice (es. ProGuard) spesso (almeno per progetti non troppo complessi) da un file .class (bytecode) si può riottenere un sorgente molto leggibile (anche se privo dei commenti) e sopratutto ricompilabile
1) per compilatore intendo "qualsiasi eseguibile", l'utente indica il percorso e si usa quell'eseguibile, potrei comunque "filtrare" quell'eseguibile prima di darlo in pasto all'esecuzione, oppure semplicemente farci un test, del resto se quello è un reale compilatore da codice java mi deve generare sempre e comunque file class, giusto?
2) non ho detto che la mia soluzione sia fattibile e perfetta, difatti scrivo su un forum per chiedere consiglio su alcune cose che magari in teoria saprei fare ma poi nella pratica, almeno iniziale, necessitano di qualche avviso e suggerimento.
Voglio semplicemente generare un programma che generi un programma "cucito su misura", non mi sembra tanto arcana e strana la cosa, cercando un po' per la rete si trovano progetti molto più ambiziosi del mio.
Se ci sono altre soluzioni tolte le classi a runtime postale, io sono qui per questo, mi documento e leggo libri ma non posso sapere tutto di tutti come qualsiasi essere umano, non credo che sia strano sbagliare, il problema è trovare la soluzione adatta.
3) chi ti ha detto che non conosca ProGuard? io ho parlato specificatamente di sorgenti scritti sul filesystem, e penso che un semplice copia e incolla lo sappia fare pure un bimbo di 2 anni, quindi potrei anche usare ProGuard ma se poi lascio tutto in balia di un CTRL+C e CTRL+V, la magia di ProGuard va a farsi benedire.
rileggi con calma e considera le eventuali variabili, vedrai che il mio progetto non è così strano, forse complicato, ma leggendo il tuo post sembra quasi che tu abbia determinato il futuro del mio software :)
1) per compilatore intendo "qualsiasi eseguibile", l'utente indica il percorso e si usa quell'eseguibile, potrei comunque "filtrare" quell'eseguibile prima di darlo in pasto all'esecuzione, oppure semplicemente farci un test, del resto se quello è un reale compilatore da codice java mi deve generare sempre e comunque file class, giusto?
L'utente deve indicare il percorso ed anche la command line (il suo compilatore potrebbe necessitare di determinate opzioni o comandi per funzionare).
Ma cmq se tu vuoi dare al cliente solo il bytecode non capisco perché vuoi dargli l'opzione di poter scegliere con cosa compilare.
Lui potrebbe benissimo scegliere cose come:
BeanShell (che non è un compilatore) per eseguire i sorgenti senza compilarli
Convertire in codice nativo con GCJ. Ma ho letto che non c'è il 100% di compatibilità con le ultime versioni di Java
Convertire i sorgenti in C++ (+ librerie C++ di emulazione framework Java) per una successiva compilazione da C++ a codice nativo.
Ci sono almeno 2 ottimi prodotti commerciali che lo fanno.
In pratica sono come il GCJ ma con 100% di compatibilità Java 6.0 (e mi sa presto 7.0)
Compilare in bytecode e subito dopo convertire in CLR (DotNet) o DEX (Android)
Convertire i sorgenti in C# + framework DotNet (senza l'uso del framework Java). Anche qui ci sono dei tool automatici ma non so quanto siano affidabili
Se a te interessa che lui faccia solo il bytecode, non capisco perché DEVI usare un suo compilatore e non il tuo (es. Janino).
Inoltre non capisco come fai a chiedere di vietare l'uso del filesystem.
E se lui sceglie un compilatore che vuole (tra l'altro cosa normalissima) i sorgenti scritti su filesystem per poterli compilare che si fa ?
2) non ho detto che la mia soluzione sia fattibile e perfetta, difatti scrivo su un forum per chiedere consiglio su alcune cose che magari in teoria saprei fare ma poi nella pratica, almeno iniziale, necessitano di qualche avviso e suggerimento.
Voglio semplicemente generare un programma che generi un programma "cucito su misura", non mi sembra tanto arcana e strana la cosa, cercando un po' per la rete si trovano progetti molto più ambiziosi del mio.
Se ci sono altre soluzioni tolte le classi a runtime postale, io sono qui per questo, mi documento e leggo libri ma non posso sapere tutto di tutti come qualsiasi essere umano, non credo che sia strano sbagliare, il problema è trovare la soluzione adatta.
Beh non si capisce esattamente cosa devi fare e quindi proporti soluzioni non è facile (sempre ammesso di essere in grado di suggerirle, cosa mica scontata).
Se tutte le funzionalità sono note a priori e non c'è eccessiva flessibilità, direi di realizzare le funzionalità come moduli caricabili (e già compilati) ed ai clienti dai soli i pezzi che scelgono (e suppongo paghino).
In pratica facendo l'ipotesi di una calcolatrice avresti 5 classi.
La classe calcolatrice che non fa molto se non da interfaccia verso il cliente
Le quattro classi Addizione, Sottrazione, Moltiplicazione e Divisione che implementano le varie funzionalità
Il cliente che compra solo Addizione + Sottrazione avrà solo 3 classi su 5 e quando schiaccerà il pulsante Moltiplicazione otterrà un errore gestito che gli dirà "Funzione non disponibile" (o funzione non acquistata).
Se non vuoi che il cliente veda anche le funzioni non scelte (e non funzionanti) allora ci sono altre strade.
Esempio rimanendo nel caso di classi generate a runtime, direi di generare solo delle classi proxy verso le classi dei moduli funzionali.
Ossia nell'esempio precedente sarebbe generare al volo una classe MiaCalcolatrice che richiama (e quindi mostra) solo le funzioni scelte.
In questo caso potresti anche rischiare di lasciare i sorgenti (temporaneam.) sul filesystem perché anche se intercettati non direbbero molto del tuo programma (visto che non ci sarebbero mai i sorgenti dei moduli, il vero codice da proteggere).
3) chi ti ha detto che non conosca ProGuard? io ho parlato specificatamente di sorgenti scritti sul filesystem, e penso che un semplice copia e incolla lo sappia fare pure un bimbo di 2 anni, quindi potrei anche usare ProGuard ma se poi lascio tutto in balia di un CTRL+C e CTRL+V, la magia di ProGuard va a farsi benedire.
Tu hai apertamente detto che non ti sta bene il file system neanche per uso temporaneo.
Quindi una cosa del tipo
Scrivo i sorgenti in una cartella Temp magari poco visibile
Li compilo con il compilatore del cliente
Cancello i sorgenti
non ti sta bene.
Bene se il tuo cliente è in grado di recuperare i sorgenti da una soluzione del genere, non è un bimbo di 2 anni e non è tanto lontano dal essere in grado di recuperare i sorgenti dai binari (.class) non offuscati tramite decompilazione.
Come già detto sopra le scelte "no filesystem" e "compilatore scelto dal cliente" fanno un po' a pugni tra loro ed inoltre dargli la scelta del compilatore di per sé abbassa quasi tutte le tue difese.
Ossia se io fossi il cliente e volessi i tuoi sorgenti allora ti passerei come compilatore un qualcosa (magari un semplice batch) che fa:
Fai una copia privata del sorgente
Compila il sorgente
E qui non vedo molte tecniche per difendersi.
vBulletin® v3.6.4, Copyright ©2000-2026, Jelsoft Enterprises Ltd.