package net.jhorstmann.i18n.xgettext.asm; import net.jhorstmann.i18n.I18N; import org.objectweb.asm.ClassReader; import org.objectweb.asm.tree.ClassNode; import org.objectweb.asm.tree.MethodNode; import org.objectweb.asm.tree.analysis.Analyzer; import org.objectweb.asm.tree.analysis.AnalyzerException; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; import net.jhorstmann.i18n.tools.MessageBundle; import net.jhorstmann.i18n.tools.xgettext.MessageExtractor; import net.jhorstmann.i18n.tools.xgettext.MessageExtractorException; import net.jhorstmann.i18n.tools.xgettext.MessageFunction; public class AsmMessageExtractor implements MessageExtractor { public static final List<MessageFunction> DEFAULT_MESSAGE_FUNCTIONS; static { List<MessageFunction> functions = new ArrayList<MessageFunction>(); String namespace = I18N.class.getName(); functions.add(MessageFunction.fromJava(namespace, "String tr(String message, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String tr(Locale, String message, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String tr(ResourceBundle, String message, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String trc(String context, String message, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String trc(Locale, String context, String message, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String trc(ResourceBundle, String context, String message, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String trn(String message, String plural, long, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String trn(Locale, String message, String plural, long, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String trn(ResourceBundle, String message, String plural, long, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String trnc(String context, String message, String plural, long, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String trnc(Locale, String context, String message, String plural, long, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String trnc(ResourceBundle, String context, String message, String plural, long, Object...)")); functions.add(MessageFunction.fromJava(namespace, "String mark(String message)")); DEFAULT_MESSAGE_FUNCTIONS = Collections.unmodifiableList(functions); } private ConstantTrackingInterpreter interpreter; public AsmMessageExtractor(MessageBundle bundle) { this(bundle, DEFAULT_MESSAGE_FUNCTIONS, true); } public AsmMessageExtractor(MessageBundle bundle, List<MessageFunction> functions, boolean srcRefPaths) { this.interpreter = new ConstantTrackingInterpreter(bundle, functions, srcRefPaths); } @Override public final void extractMessages(File file) throws IOException, MessageExtractorException { InputStream in = new FileInputStream(file); extractMessages(in, true); } public final void extractMessages(InputStream in, boolean close) throws IOException, MessageExtractorException { try { extractMessages(in); } finally { if (close) { try { in.close(); } catch (IOException ex) { } } } } public final void extractMessages(InputStream in) throws IOException, MessageExtractorException { ClassReader classReader = new ClassReader(in); ClassNode classNode = new ClassNode(); classReader.accept(classNode, 0); interpreter.setCurrentClass(classNode); Analyzer analyzer = new Analyzer(interpreter); try { for (Iterator it=classNode.methods.iterator(); it.hasNext(); ) { MethodNode methodNode = (MethodNode) it.next(); interpreter.setCurrentMethod(methodNode); analyzer.analyze(classNode.name, methodNode); } } catch (AnalyzerException ex) { throw new MessageExtractorException(ex); } } }