2012-05-26 8 views
10

Chcę skompilować źródło bez zależności obecnych na komputerze.
Przykład: File A.java:
JavaCompiler z niestandardową klasą ClassLoader i FileManager

import some.pkg.B; 
public class A extends B {...} 

nie mam źródłowy B prezent chciałbym zaczepić albo JavaFileManager lub niestandardową ClassLoader w celu uzyskania symboli w pytaniu (pakiet „trochę. pakiet i klasa B), a następnie użyj usługi, którą mam, która pobiera ciąg źródłowy.

Kod kompilacji: (inputFiles ma A.java)

JavaCompiler compiler = ToolProvider.getSystemJavaCompiler(); 
CustomClassLoader classLoader = new CustomClassLoader(); 
StandardJavaFileManager standardfileManager = compiler.getStandardFileManager(this, null, null); 
JavaFileManager fileManager = new CustomFileManager(standardfileManager, output, classLoader); 
CompilationTask task = compiler.getTask(null, fileManager, this, null, null, inputFiles); 
boolean result = task.call(); 

Haki na JavaFileManager (getFileForInput ..) i na moim classloader (findClass, loadClass ..) nie wyzwalane podczas kompilowania i ja dostaje komunikaty o błędach:

A.java:#: package some.pkg does not exist 
A.java:#: cannot find symbol 
symbol: class B 

EDIT

Po gry z API, podchodząc JavaCompiler (starsza wersja) s ource and reading Compilation Overview Nadal nie mogę znaleźć haka API, którego mogę używać do dostarczania mi symboli z drzew składniowych. Wygląda na to, że API musi uzyskać wszystkie zasoby w oparciu o nazwy pakietów, zgodnie z sugestią kschneid.
Jednym z obejść, o którym myślałem, jest uruchomienie JavaCompiler i analiza komunikatów o błędach brakujących symboli. W ten sposób dowiem się, które symbole są potrzebne, zdobądź je i przekompiluj.
Jakieś inne obejścia/rozwiązania?

+0

Co JDK wersja/kompilator i platformy używasz? – matts

+0

JavaCompiler (javac), JDK 1.6.30 x64 w systemie Windows. –

+0

Nie jestem całkowicie pewien. Ale czuję się tak, jakby to, co próbujesz zrobić, to dynamiczne ładowanie klasy. Nie możesz użytkownik 'Class.forname()' załadować klasy w czasie wykonywania. Proszę mnie poprawić, jeśli źle to zrozumiałem. – Ankit

Odpowiedz

4

(zakładam, że nie jesteś naprawdę stosując nazwę pakietu „pakietu”, ponieważ to będzie tylko nielegalne ...)

niestandardowego JavaFileManager powinny trafiać jego metoda list wywoływany. Mam nadzieję, że ten zapis ma sens, ale kombinacja args do tej metody powinny wyglądać następująco:

[PLATFORM_CLASS_PATH, some, [CLASS], false] 
[CLASS_PATH, some, [SOURCE, CLASS], false] 
[PLATFORM_CLASS_PATH, some.pkg, [CLASS], false] 
[CLASS_PATH, some.pkg, [SOURCE, CLASS], false] 

Nie jestem pewien, jak trudno będzie dla danego środowiska do tworzenia odpowiednich Iterable<JavaFileObject> instancje, ale myślę, to jest wymagane ...

+0

Dzięki za notatkę pakietu, poprawiłem pytanie. –

+0

Tęskniłem za tą funkcją, dobre połączenie.Jest to dobra ścieżka, ale nie chcę budować JavaFileObject na wszystkich klasach w pakiecie, tylko tych, które są używane w rzeczywistej kompilacji pliku Java, który próbuję skompilować. Czy istnieje sposób na uzyskanie rzeczywistych nazw klas, a nie tylko pakietów? –

+0

Oto świetna implementacja tego. http://atamur.blogspot.kr/2009/10/using-built-in-javacompiler-with-custom.html – zeodtr

1

Znalazłem, że fajny sposób na hakowanie klas podczas kompilacji jest z Groovy AST Transformation. Można spojrzeć na to, co można zrobić here

To nie jest zwykły stary java chociaż, ale może być przydatnym narzędziem do poznania

Powiązane problemy