Follow me
RSS feed
My sources
My Viadeo

Ma (petite) console Java

Greg | 08 Aug 2011

Projets Quand j'ai commencé à développer en Java, parmi les choses qui me manquait le plus, une console, façon IRB, était dans le top 10. En effet, le problème avec les langages nécessitant une phase de compilation et que lorsque vous voulez tester rapidement un petit enchainement, vous avez l'impression de devoir sortir l'artillerie lourde. J'ai donc cherché s'il existait quelque chose pour m'aider, et je suis rapidement tombé sur BeanShell. Ce dernier, utilisé en ligne de commande, répond totalement à mon besoin. Cependant, je me suis également demandé si je ne pourrais pas mettre en place ma propre solution.

Je me suis donc tourné vers ce que je connais et j'ai essayé de mettre en place une solution à base de JRuby et java-inline. Le résultat n'est pas parfait, mais il répond au besoin de base.

Voici un example d'utilisation :

$ export CLASSPATH=commons-io-2.0.1.jar
$ ruby jconsole.rb
jConsole with Java 10.7
> \help
\import [PACKAGE]   : Import package PACKAGE or display imports if no package given
\unimport [PACKAGE] : Remove package PACKAGE import
\run                : Set auto-run on/off

\help               : Display help
\quit               : Quit jConsole

CLASSPATH set to : commons-io-2.0.1.jar
> \run
run OFF
> \import org.apache.commons.io.FileUtils
> \import java.io.File
> File temp = FileUtils.getTempDirectory();
> System.out.println("TEMP FILE = "+temp.getPath());
> \run
run ON
TEMP FILE = /var/folders/h3/x2n5fwvd2q955wyr1y8_87kr0000gn/T
>

Et voici le code de la chose :

#!jruby

unless RUBY_PLATFORM === "java"
   puts "jConsole only works with jRuby"
   puts "For more informations, see http://www.jruby.org/"
   exit 1
end

require 'readline'
require 'rubygems'
begin
require 'term/ansicolor'
rescue
   puts "please install term/ansicolor : "
   puts "  [sudo] gem install term-ansicolor"
   exit 1
end
require 'inline'
begin
require 'java_inline'
rescue
   puts "please install java-inline : "
   puts "  [sudo] gem install java-inline"
   exit 1
end
require 'java'

class JConsole 
   class Runner
      def initialize
         clean
      end
   
      def clean
         @complete_source = nil
         @imports = []
         @java_klass = nil
      end
   
      def unimport(packages) 
         @imports -= packages
      end
   
      def import(packages)
         if packages.size == 0
            @imports.each { |i| puts "\t#{i}" }
         else
            @imports += packages
         end
      end
   
      def uniline(data)
         methodName = create_uniline_method(data)
         compile
         @java_klass.send(methodName.to_sym)
      end
   
      private
   
      def compile
         source = @complete_source
         imp = @imports
         jKlass = Class.new do 
            inline :Java do |builder|
               imp.each { |i| 
                  builder.import i 
               }
               builder.java source
            end
         end
         @java_klass = jKlass.new
      end
   
      def create_uniline_method(data)
         methodName = "x"+Time.now.to_i.to_s
         @complete_source = "
public static void #{methodName}() { 
  #{data}
}
         "
         methodName
      end
   end

   def initialize
      @runner = Runner.new
      @runner.uniline("System.out.println(\"jConsole with Java \" + System.getProperty(\"os.version\"));")
      @run = true
      ENV['CLASSPATH'] = "." if ENV['CLASSPATH'].nil?
   end

   def jrun?(data)
      [["(", ")"], ["{", "}"], ["[", "]"]].each do |e|
         return false if data.count(e[0]) != data.count(e[1])
      end
      return true
   end

   def command(args)
      action = args.shift.to_sym
      run = false
      case action
      when :import
         @runner.import args
      when :unimport
         @runner.unimport args
      when :run
         @run = !@run
         print Term::ANSIColor.yellow, "run #{ @run ? 'ON' : 'OFF' }\n", Term::ANSIColor.clear
         run = true
      when :help
         help
      when :quit
         exit 0
      else 
         print Term::ANSIColor.red, "Command `\\#{action}' undefined! Try \\help\n", Term::ANSIColor.clear
      end

      return run
   end

   def help
      print Term::ANSIColor.blue
      puts "\\import [PACKAGE]   : Import package PACKAGE or display imports if no package given"
      puts "\\unimport [PACKAGE] : Remove package PACKAGE import"
      puts "\\run                : Set auto-run on/off"
      puts ""
      puts "\\help               : Display help"
      puts "\\quit               : Quit jConsole"
      puts ""
      puts "CLASSPATH set to : "+ENV['CLASSPATH']
      print Term::ANSIColor.clear
   end

   def run
      kode = ""
      print Term::ANSIColor.green
      while line = Readline.readline( "> ", true )
         run = true
         if line =~ /^\\/
            run = command line.chomp.gsub(/^\\/, "").split(" ")
            line = ""
         end

         print Term::ANSIColor.clear
         if run
            unless jrun?(kode+line) && @run
               kode += line
            else
               @runner.uniline(kode+line.chomp)
               kode = ""
            end
         end
         print Term::ANSIColor.green
      end
      print Term::ANSIColor.clear
   end
end

JConsole.new.run

A moins que vous soyez une peu téméraire, vous pouvez parfaitement utiliser jConsole. Cependant, BeanShell est une solution plus raisonnable ;)

Copyright © 2009 - 2011 Grégoire Lejeune.
All documents licensed under the Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License, except ones with specified licence.
Powered by Jekyll.