Convertit une Chaîne de Code
Je veux savoir si il existe un moyen de convertir un String
à Java code compilable.
J'ai une expression comparative enregistré dans un champ de base de données. Je veux le récupérer à partir de la base de données, puis de l'évaluer à l'intérieur d'une structure conditionnelle.
Est-il possible de faire cela?
- Analyse et évaluation de la comparaison vous-même pas une option? L'exécution de code arbitraire introduit souvent des risques de sécurité.
- Pour une bibliothèque à faire ce que rodion suggère, voir ma réponse ci-dessous.
- En plus de ma réponse: Il y a aussi un
InMemoryJavaCompiler
dans le cas de tests de l'OpenJDK. Voir hg.openjdk.java.net/jdk7u/jdk7u/hotspot/file/f547ab7c2681/test/... , les fichiersInMemoryJavaCompiler.java
etByteCodeLoader.java
Vous devez vous connecter pour publier un commentaire.
Si vous utilisez la version 6 de Java, vous pouvez essayer de le Compilateur Java de l'API. Au cœur de la JavaCompiler classe. Vous devriez être en mesure de construire le code source de votre
Comparator
objet en mémoire.Avertissement: je n'ai pas réellement essayé le code ci-dessous que la JavaCompiler objet n'est pas disponible sur ma plate-forme, pour une raison étrange...
Avertissement: Compilation arbitraire de code Java peut être dangereux pour votre santé.
Considérez-vous avertis...
Après cela, il vous suffit de stocker la appropriée de l'expression de Java dans votre champ de base de données, référencement
a
etb
.Utiliser Groovy!
Vous ne pouvez pas parce que java est un langage compilé.
Cependant, vous devez utiliser un
javax.script
api afin d'exécuter du code lors de l'exécution.JVM6 livré avec Rhino (interpréteur javascript) disponible via
javax.script
.http://java.sun.com/javase/6/docs/api/javax/script/package-summary.html
Il y a
javax.script
-compatible java interprètes (et de haricots de la coquille) est disponible.https://scripting.dev.java.net/
Vous pouvez en utilisant quelque chose comme BeanShell.
Vous pouvez utiliser BeanShell.
La clé de la classe est
bsh.Interpreter
.Voici un exemple simple:
Il est même possible de définir l'ensemble de la classe au lieu d'une seule expression.
Il n'est pas juste de dire que c'est impossible. C'est un problème très similaire au problème de Java Server Pages (Jsp) - dans leur cas, il y a le code incorporé dans des fichiers HTML qui doit être compilé dans un servlet et exécuté. Si vous avez vraiment envie d'utiliser ce mécanisme, je suis relativement sûr que vous pourriez creuser par le biais de la source pour un conteneur de servlet et de comprendre comment ils ont fait (probablement même la réutilisation de leur mécanisme, à un certain degré.)
; Cependant, il n'est pas un problème facile à résoudre (une fois que vous résoudre à l'évidence, problème immédiat, vous finissez par avoir à composer avec des problèmes avec classloading et les problèmes connexes.)
Il aurait certainement semblent être une meilleure idée pour aller avec le Java Plate-Forme De Script dans JDK6.
Apparemment Java Plate-Forme De Script est mieux pour ce genre de situation, mais Vous pouvez également utiliser Compilateur Java Api. Il fournit des méthodes pour compiler les fichiers source java à partir de dans du code java. Dans votre cas vous pouvez faire un fichier temporaire contenant une classe avec votre expression comparative ensuite, vous pouvez charger ce fichier et l'utiliser. Bien sûr ce n'est pas très élégant. Découvrez http://www.juixe.com/techknow/index.php/2006/12/13/java-se-6-compiler-api/ pour plus de détails sur l'utilisation d'un Compilateur Java Api
Groovy pourrait également être une option pour vous.
Il intègre proprement avec le Bean Script Cadre, peut être directement intégré assez facilement et peut être ok, syntaxe-sage, pour vous.
StringEscapeUtils.escapeJava de Commons Lang peuvent vous aider si vous souhaitez obtenir un morceau de code compilable et vidage d'une chaîne de caractères qui existe.
Un moyen simple d'obtenir des extraits de code exécutable du byte-code est le Javassist bibliothèque.
Vous pouvez éventuellement adapter les techniques décrites dans http://www.ibm.com/developerworks/java/library/j-dyn0610/ pour s'adapter à vos besoins.
Si vous avez de l'état à partir d'une base de données, je parie, il ya une bonne chance que vous pourriez vouloir utiliser cette condition pour accès les données dans la base de données.
Si vous utilisez un ORM comme Hibernate JPA ou (traditionnel ou JPA), vous pourriez être en mesure de formuler une requête dynamique de l'expression que vous auriez du passer à la createQuery() la méthode. Ce n'est pas aussi bon que d'être capable de faire un à la volée de la compilation de l'arbitraire de code Java, mais peut-être que c'est tout ce dont vous avez besoin, et cette solution ne nécessite pas de toute spéciale des inclusions ou des actions, puisque la requête compilateur de langage est une partie de l'ORM système lui-même.
Bien sûr, si vous FAITES des requêtes dynamiques de cette façon, je vous recommande de journalisation eux d'une certaine façon, car il peut être une vraie douleur pour comprendre ce qui s'est passé après le fait, si votre chaîne de requête est maintenant dans le garbage collector.
Vous ne devriez pas. Vraiment!
Êtes-vous inventer un autre l'entreprise de moteur de règles?. Vous pourriez lire ces liens.
Tenir compte du fait que les seules personnes qui est assez habile pour écrire du code, puis l'insérer dans une base de données, sont probablement d'avoir un éditeur de texte et un compilateur de toute façon...
Le compilateur va attraper tous ces satanés les erreurs de syntaxe et vous pouvez même tester le code! Rappelez-vous que les éditeurs et les compilateurs, et même des langages informatiques ont été inventés pour aider le programmeur à écrire confortablement compréhensible code avec un effort raisonnable.
Pendant que j'y suis: lisez à propos de la complicators gants trop!
Si tout ce que vous devez faire est d'évaluer une expression stockées dans une base de données, vous voudrez peut-être regarder à JEP (Java Analyseur d'Expression)
La dernière (commercial) de la version est ici.
Un peu plus âgés, la version de la GPL est ici
Quelques exemples d'utilisation.
Si vous êtes prêt à sacrifier le "code Java" partie de votre condition, vous pouvez utiliser le Java Mathématiques Évaluateur D'Expression de la bibliothèque. Il vous permet de spécifier une expression mathématique (comme java.lang.Chaîne de caractères), ajouter des valeurs pour les variables, et d'en évaluer l'expression.
Je l'ai utilisé dans la production de code avec un grand succès.
Oui, il est possible dans de nombreuses façons.
Comme certains l'ont mentionné ci-dessus, la version 6 de Java vous permet d'analyser, de les manipuler et de réécrire le code comme il est chargé!
La solution peut varier:
Vous pourriez, par exemple, écrire votre DB expression comme une classe Java et insérez votre classe sérialisée dans la DB comme un glob ou blob ou quel que soit son nom.
Ou, vous pouvez utiliser un modèle pour écrire une classe Java dans un fichier et insérez votre expression en elle. Ensuite compiler la classe au moment de l'exécution (comme une JSP pour Servlet) et puis charger dynamiquement la classe.
Bien sûr, vous voulez mettre en cache vos classes compilées pour une utilisation future si elles n'ont pas été modifiés dans la base de données.
Puis il y a aussi la possibilité d'utiliser un intégré le moteur de script tels que la plupart des réponses ont mentionné.
Tout ce que vous choisissez, vous pouvez être en mesure de mettre à jour ce post avec les détails de votre choix, la mise en œuvre, des problèmes, des notes, des commentaires, etc.
Vous feriez beaucoup mieux de la cartographie de votre base de données condition d'info à un objet et soit mise en œuvre d'une méthode equals que vous pouvez utiliser avec BeanPropertyValueEqualsPredicate de l'apache commons beanutils ou de mettre en œuvre Comparable à la place.
Ceci devrait faire ce que vous êtes après, sans toute la magie du compilateur de la malveillance ou à la sécurité de la conversion de chaînes de code.
J'ai utilisé les deux BeanShell et GroovyShell mais la performance sage, GroovyShell est plus rapide si vous prase et cache le script.