2010-01-08 15 views
6

Java 6'daki dinamik derlemem mükemmel çalışıyor. Ancak, çıkış yolunu değiştirmek istiyorum. Ben bir sürü şey denedim (seni ayıracağım). Neyse, burada çalışma koduDinamik Derleme için Çıkış Yolu Belirtme

String[] filesToCompile = { "testFiles/Something.java" }; 
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null); 
Iterable<? extends JavaFileObject> compilationUnits = fileManager.getJavaFileObjects(filesToCompile); 
CompilationTask task = compiler.getTask(null, fileManager, null,null, null, compilationUnits); 
System.out.println("Good? " + task.call()); 

var Ama çıkış ne istiyorum değil kaynak dizin gider. Yanıtın compiler.getTask'da bulunabileceğinden şüpheleniyorum, ancak API, bazı parametrelerin ne anlama gelebileceği konusunda çok açık değil. Ya da belki de FileManager ile bir şey. Ben tahmin muhtemelen iyi bir fikir değil, yine

fileManager.setLocation(StandardLocation.locationFor("testFiles2"), null); 

ama

denedim.

Teşekkürler!

Düzenleme: Bu (üzgün söz konusuysa ve bir daha kompakt bir şekilde) gibi de seçenekler kullanılarak denedim:

final List<String> optionsList = new ArrayList<String>(); 
    optionsList.add("-d what"); 
    Iterable<String> options = new Iterable<String>() {   
     public Iterator<String> iterator() { 
      return optionsList.iterator(); 
     } 
    }; 

ve sonra getTask için seçenekler geçen değil hata mesajı "geçersiz Bayrak."

+0

+1! –

+0

Her zaman vardı, şimdi yerleşik! –

+0

Cevabım güncellendi. –

cevap

5

Kod çalışacak ilk yazı, ancak aşağıdaki hata olsun en atılmış:

java.lang.IllegalArgumentException: invalid flag: -d folder 

Bunun nedeni geçen gereğidir "-d folder", ayrıştırıcıyı bir seçenek ayrıştırmayı düşünür. Seçenekler "-d", "folder" gibi ayrılmalıdır.

Çalışma örneği aşağıdaki gibidir: Beni haberdar olarak dinamik derleme şimdi böyle bir şey olduğunu yapmak için

JavaCompiler javaCompiler = ToolProvider.getSystemJavaCompiler(); 
StandardJavaFileManager sjfm = javaCompiler.getStandardFileManager(null, null, null); 

String[] options = new String[] { "-d", "output" }; 
File[] javaFiles = new File[] { new File("src/gima/apps/flip/TestClass.java") }; 

CompilationTask compilationTask = javaCompiler.getTask(null, null, null, 
     Arrays.asList(options), 
     null, 
     sjfm.getJavaFileObjects(javaFiles) 
); 
compilationTask.call(); 
+0

"c: \\ foo bar \\ foo" veya "c:/foo bar/foo" gibi yollardan ne haber? Beyaz boşluk veya eğik çizgi doğru şekilde ayrıştırılabilir mi? – Gobliins

+0

Bilmiyorum, ama argümanlar artık doğru bir şekilde aktarıldığından (ve asıl sorunun niteliği tam olarak ayrıştırılmayan parametrelerin tam olduğundan dolayı) kaçış gerekmez. Tekrar dene ve rapor et? – Gima

4

Java 6 dinamik derleyici araçlarıyla 0 deneyimim var. Ancak hiç kimse yanıt vermedi :)

Derleme görevi, FileManager nesnesini alır. Standart olanı kullanırsanız, kaynak dizin ağacında sınıflar oluşturulur. Yapabilecekleriniz, kendi FileManager alt sınıfınızı override getFileForOutput yöntemiyle sağlamaktır. GetFileForOutput öğesinin API açıklaması, bunun çıkış (= sınıf) dosyalarınızın nereye gideceğini etkileyeceğini gösterir.

Güncelleme

Nasıl kanca dosya yöneticileri

ForwardingJavaFileManager, ForwardingFileObject ve ForwardingJavaFileObject Subclassing bir çağrılarak oluşturulan gibi standart dosya yöneticisinin tutumu aşırı kullanılamaz Bir derleyicide yöntem, bir kurucu çağırmakla değil. Bunun yerine iletme (veya temsilci) kullanılmalıdır. Bu sınıflar, davranışların özelleştirilmesine izin verirken, çoğu çağrıyı belirli bir dosya yöneticisine veya dosya nesnesine iletmeyi kolaylaştırır. Örneğin, JavaFileManager.flush() için tüm aramaları günlüğe nasıl düşünün:

final Logger logger = ...; 
    Iterable<? extends JavaFileObject> compilationUnits = ...; 
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
    StandardJavaFileManager stdFileManager = compiler.getStandardFileManager(null, null, null); 
    JavaFileManager fileManager = new ForwardingJavaFileManager(stdFileManager) { 
     public void flush() { 
      logger.entering(StandardJavaFileManager.class.getName(), "flush"); 
      super.flush(); 
      logger.exiting(StandardJavaFileManager.class.getName(), "flush"); 
     } 
    }; 
    compiler.getTask(null, fileManager, null, null, null, compilationUnits).call(); 

Güncelleme 2

Ben dinamik derleme üzerinde okumak ve bunu yapmak için kendi uygulama oluşturduk. Bu kod biraz fazla tören içeriyor (yani basitleştirilebilir) ama işe yarıyor!

package yar; 

import javax.tools.JavaCompiler; 
import javax.tools.ToolProvider; 

public class DynamicCompiler { 

    JavaCompiler compiler; 

    public DynamicCompiler() { 
     this.compiler = ToolProvider.getSystemJavaCompiler(); 
     if (this.compiler == null) { 
     throw new NullPointerException("Cannot provide system compiler."); 
     } 
    } 

    public void compile() { 
     this.compiler.run(null, System.out, System.err, 
      "-d", "testFiles2", 
      "testFiles/Hello1.java", "testFiles/Hello2.java"); 
    } 

    /** 
    * @param args 
    */ 
    public static void main(String[] args) { 
     try { 
     DynamicCompiler dc = new DynamicCompiler(); 
     dc.compile(); 
     } catch (Exception e) { 
     System.err.println(e.getMessage()); 
     } 
    } 

} 

Java dosyaları dinamik olarak oluşturulmuş bir liste ile çalışmak için bu kodu nasıl emin değilim; Her kaynak dosyası için muhtemelen sadece compiler.run yapmalıyım.

+0

Bu doğru olabilir, ancak maalesefJavaFileObjects yalnızca StandardJavaFileManager'dadır .... Ne yapılabileceğini görüyorum. Bu Ruby olsaydı, cevabın maymun yama için yeterli olurdu ve bitmiş olacak :) –

+0

Java, gitmek için yol alt sınıflandırmadır ... 'ForwardingJavaFileManager'' StandardJavaFileManager' uygular ve bu kullanmakta olduğunuz. –

+0

Aslında, 'derleyiciden 'alacağınız FileManager'ın etrafına dolan bir kurucuya sahiptir. Elbette, bu kurucuyu türetilmiş sınıfınızda halka açmak isteyeceksiniz. –

8

Bugün aynı sorunla karşı karşıya kaldım.

fileManager.setLocation(StandardLocation.CLASS_OUTPUT, Arrays.asList(outputDir)); 

Ve işte bu !!:

cevap (yerine vadede `düzenli getTask yöntemini kullanarak) FileManager çıktı dir belirtmektir

Dokümantasyon biraz yanıltıcıdır, yani bir örnek çok kullanışlı olabilir. Ama sonunda o beni oraya aldı. İşte DÜZENLEME

çalışan bir örnek var:

// write the test class 
    File sourceFile = new File("First.java"); 
    FileWriter writer = new FileWriter(sourceFile); 

    writer.write(
      "package load.test;\n" + 
      "public class First{}" 
    ); 
    writer.close(); 

    // Get the java compiler for this platform 
    JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
    StandardJavaFileManager fileManager = compiler.getStandardFileManager(
      null, 
      null, 
      null); 

    //--   H E R E --// 
    // Specify where to put the genereted .class files 
    fileManager.setLocation(StandardLocation.CLASS_OUTPUT, 
          Arrays.asList(new File("/tmp"))); 
    // Compile the file 
    compiler 
     .getTask(null, 
       fileManager, 
       null, 
       null, 
       null, 
       fileManager.getJavaFileObjectsFromFiles(Arrays.asList(sourceFile))) 
     .call(); 
    fileManager.close(); 

    // delete the file 
    sourceFile.deleteOnExit(); 
+0

Bu soruna baktığımdan beri bir süredir. Yani cevabınızın cevabın tamamını çözdüğünü mi söylüyorsun? –

+0

Yeap !!!, oldukça fazla. Yanıtı, bir örnek – OscarRyz

+0

Works ile iyice güncelleyeceğim - getTask() seçeneklerinde "-d" parametresiyle aynı, ancak daha temiz. – Atorian

İlgili konular