1717package cn .enaium .joe .service .decompiler ;
1818
1919import cn .enaium .joe .JavaOctetEditor ;
20- import cn .enaium .joe .jar .Jar ;
21- import cn .enaium .joe .util .config .util .CachedGlobalValue ;
2220import cn .enaium .joe .util .MessageUtil ;
2321import cn .enaium .joe .util .classes .ClassNode ;
24- import org .jetbrains .java .decompiler .main .Fernflower ;
22+ import cn .enaium .joe .util .classes .JarHelper ;
23+ import cn .enaium .joe .util .config .util .CachedGlobalValue ;
24+ import org .jetbrains .java .decompiler .main .decompiler .BaseDecompiler ;
2525import org .jetbrains .java .decompiler .main .extern .IContextSource ;
2626import org .jetbrains .java .decompiler .main .extern .IFernflowerLogger ;
2727import org .jetbrains .java .decompiler .main .extern .IResultSaver ;
2828import org .tinylog .Logger ;
2929
30+
3031import java .io .ByteArrayInputStream ;
31- import java .io .IOException ;
3232import java .io .InputStream ;
3333import java .util .*;
3434import java .util .jar .Manifest ;
3737 * @author Enaium
3838 * @since 1.0.0
3939 */
40- public class VineFlowerDecompiler implements IDecompiler {
41-
40+ public class VineFlowerDecompiler extends IFernflowerLogger implements IDecompiler , IResultSaver , IContextSource , IContextSource .IOutputSink {
41+ private String returned ;
42+ private HashMap <String , ClassNode > activeClass ;
4243 public static final CachedGlobalValue <Map <String , Object >> customProperties = new CachedGlobalValue <>(config -> {
4344 Map <String , String > map = JavaOctetEditor .getInstance ().CONFIG .getConfigMapStrings (config );
4445 HashMap <String , Object > hashMap = new HashMap <>(map .size ());
@@ -49,224 +50,103 @@ public class VineFlowerDecompiler implements IDecompiler{
4950 } else if (v .equals ("false" )) {
5051 v = "0" ;
5152 }
52- hashMap .put (entry .getKey (). replace ( '_' , '-' ) , v );
53+ hashMap .put (entry .getKey (), v );
5354 }
5455 return Collections .unmodifiableMap (hashMap );});
5556
56-
5757 @ Override
5858 public String decompile (final ClassNode classNode ) {
59- try (SingleClassResultSaver saver = new SingleClassResultSaver (classNode .getCanonicalName ())){
60- Fernflower fernflower = new Fernflower (saver , customProperties .getValue (), CustomLogger .LOGGER );
61-
62- fernflower .addLibrary (new JarContextSource (JavaOctetEditor .getInstance ().getJar ()));
63- fernflower .addSource (new SingleClassContextSource (classNode ));
64- fernflower .addWhitelist (classNode .getInternalName ());
65- try {
66- fernflower .decompileContext ();
67- } finally {
68- fernflower .clearContext ();
69- }
70- return saver .saved ;
71- } catch (IOException e ) {
72- return "Decompile Failed \n " + e ;
73- }
59+ returned = null ;
60+ activeClass = JarHelper .getAllNodes (classNode );
61+ BaseDecompiler baseDecompiler = new BaseDecompiler (this , customProperties .getValue (), this );
62+ baseDecompiler .addSource (this );
63+ baseDecompiler .decompileContext ();
64+ return returned ;
7465 }
7566
76- private static class JarContextSource implements IContextSource {
77-
78- Jar jar ;
79-
80- public JarContextSource (Jar jar ){
81- this .jar = jar ;
82- }
83-
84- @ Override
85- public String getName () {
86- return "Jar" ;
87- }
88-
89- @ Override
90- public Entries getEntries () {
91- return new Entries (jar .getClasses ().stream ().map (ClassNode ::getInternalName ).map (name -> name + ".class" ).map (Entry ::atBase ).toList (), Collections .emptyList (), Collections .emptyList ());
92- }
93-
94- @ Override
95- public boolean isLazy () {
96- return true ;
97- }
98-
99- @ Override
100- public InputStream getInputStream (String resource ) {
101- String className = resource .endsWith (".class" ) ? resource .substring (0 , resource .length () - 6 ) : resource ;
102- return hasClass (className ) ? new ByteArrayInputStream (getClassBytes (className )) : null ;
103- }
104-
105- @ Override
106- public byte [] getClassBytes (String resource ) {
107- String className = resource .endsWith (".class" ) ? resource .substring (0 , resource .length () - 6 ) : resource ;
108- return jar .getClassNode (className ).getClassBytes ();
109- }
110-
111- @ Override
112- public boolean hasClass (String resource ) {
113- String className = resource .endsWith (".class" ) ? resource .substring (0 , resource .length () - 6 ) : resource ;
114- return jar .hasClass (className );
115- }
116-
117- @ Override
118- public IOutputSink createOutputSink (IResultSaver saver ) {
119- return new IOutputSink () {
120- @ Override
121- public void begin () {
122-
123- }
124-
125- @ Override
126- public void acceptClass (String s , String s1 , String s2 , int [] ints ) {
127-
128- }
129-
130- @ Override
131- public void acceptDirectory (String s ) {
132-
133- }
134-
135- @ Override
136- public void acceptOther (String s ) {
137-
138- }
139-
140- @ Override
141- public void close () {
142-
143- }
144- };
67+ @ Override
68+ public void saveClassFile (String path , String qualifiedName , String entryName , String content , int [] mapping ) {
69+ if (returned == null ){
70+ returned = content ;
14571 }
14672 }
14773
148- private record SingleClassContextSource (ClassNode targetClasses ) implements IContextSource {
149- @ Override
150- public String getName () {
151- return JavaOctetEditor .TITLE ;
152- }
153-
154- @ Override
155- public Entries getEntries () {
156- return new Entries (List .of (Entry .atBase (targetClasses .getInternalName () + ".class" )), Collections .emptyList (), Collections .emptyList ());
157- }
158-
159- @ Override
160- public boolean isLazy () {
161- return true ;
162- }
163-
164- @ Override
165- public InputStream getInputStream (String resource ) {
166- String className = resource .endsWith (".class" )
167- ? resource .substring (0 , resource .length () - 6 ).replace ('/' , '.' )
168- : resource .replace ('/' , '.' );
169- return hasClass (className ) ? new ByteArrayInputStream (Objects .requireNonNull (getClassBytes (className ))) : null ;
170- }
171-
172- @ Override
173- public byte [] getClassBytes (String className ) {
174- if (className .equals (targetClasses .getInternalName ())) {
175- return targetClasses .getClassBytes ();
176- } else return null ;
177- }
74+ @ Override
75+ public void writeMessage (String message , Throwable t ) {
76+ Logger .info (t , message );
77+ }
17878
179- @ Override
180- public boolean hasClass (String className ) {
181- return className .equals (targetClasses .getInternalName ());
79+ @ Override
80+ public void writeMessage (String message , Severity severity ) {
81+ switch (severity ){
82+ case INFO -> Logger .info (message );
83+ case WARN -> Logger .warn (message );
84+ case TRACE -> Logger .trace (message );
85+ case ERROR -> MessageUtil .error (message );
18286 }
87+ }
18388
184- @ Override
185- public IOutputSink createOutputSink (IResultSaver saver ) {
186- SingleClassResultSaver singleClassResultSaver = saver instanceof SingleClassResultSaver ? (SingleClassResultSaver ) saver : null ;
187- return new IOutputSink () {
188- @ Override
189- public void begin () {
190-
191- }
192-
193- @ Override
194- public void acceptClass (String s , String s1 , String s2 , int [] ints ) {
195- if (singleClassResultSaver != null ) {
196- singleClassResultSaver .saveClassFile (null , s , s1 , s2 , ints );
197- }
198- }
199-
200- @ Override
201- public void acceptDirectory (String s ) {
202-
203- }
204-
205- @ Override
206- public void acceptOther (String s ) {
207-
208- }
209-
210- @ Override
211- public void close () {
212-
213- }
214- };
89+ @ Override
90+ public void writeMessage (String message , Severity severity , Throwable t ) {
91+ switch (severity ){
92+ case INFO -> Logger .info (t , message );
93+ case WARN -> Logger .warn (t , message );
94+ case TRACE -> Logger .trace (t , message );
95+ case ERROR -> MessageUtil .error (message , t );
21596 }
21697 }
21798
218- private static class SingleClassResultSaver implements IResultSaver {
219- public final String targetClassName ;
220- public String saved ;
221-
222- public SingleClassResultSaver (String targetClassName ) {
223- this .targetClassName = targetClassName ;
224- this .saved = null ;
225- }
99+ @ Override
100+ public String getName () {
101+ return JavaOctetEditor .TITLE ;
102+ }
226103
227- @ Override
228- public void saveClassFile (String path , String qualifiedName , String entryName , String content , int [] mapping ) {
229- if (qualifiedName .equals (targetClassName ) && saved == null ) {
230- saved = content ;
231- }
232- }
104+ @ Override
105+ public Entries getEntries () {
106+ return new Entries (activeClass .keySet ().stream ().map (Entry ::atBase ).toList (), List .of (), List .of ());
107+ }
233108
234- @ Override public void saveFolder (String path ) {}
235- @ Override public void copyFile (String source , String path , String entryName ) {}
236- @ Override public void createArchive (String path , String archiveName , Manifest manifest ) {}
237- @ Override public void saveDirEntry (String path , String archiveName , String entryName ) {}
238- @ Override public void copyEntry (String source , String path , String archiveName , String entry ) {}
239- @ Override public void saveClassEntry (String path , String archiveName , String qualifiedName , String entryName , String content ) {}
240- @ Override public void closeArchive (String path , String archiveName ) {}
109+ @ Override
110+ public boolean isLazy () {
111+ return true ;
241112 }
242113
243- private static class CustomLogger extends IFernflowerLogger {
114+ @ Override
115+ public InputStream getInputStream (String resource ) {
116+ if (activeClass .containsKey (resource )) return new ByteArrayInputStream (activeClass .get (resource ).getClassBytes ());
117+ return null ;
118+ }
244119
245- private static final CustomLogger LOGGER = new CustomLogger ();
120+ @ Override
121+ public byte [] getClassBytes (String className ) {
122+ if (activeClass .containsKey (className )) return activeClass .get (className ).getClassBytes ();
123+ return null ;
124+ }
246125
247- @ Override
248- public void writeMessage (String message , Throwable t ) {
249- Logger . info ( t , message );
250- }
126+ @ Override
127+ public boolean hasClass (String className ) {
128+ return activeClass . containsKey ( className );
129+ }
251130
252- @ Override
253- public void writeMessage (String message , Severity severity ) {
254- switch (severity ){
255- case INFO -> Logger .info (message );
256- case WARN -> Logger .warn (message );
257- case TRACE -> Logger .trace (message );
258- case ERROR -> MessageUtil .error (message );
259- }
260- }
131+ @ Override
132+ public IOutputSink createOutputSink (IResultSaver saver ) {
133+ return this ;
134+ }
261135
262- @ Override
263- public void writeMessage (String message , Severity severity , Throwable t ) {
264- switch (severity ){
265- case INFO -> Logger .info (t , message );
266- case WARN -> Logger .warn (t , message );
267- case TRACE -> Logger .trace (t , message );
268- case ERROR -> MessageUtil .error (message , t );
269- }
270- }
136+ @ Override
137+ public void acceptClass (String qualifiedName , String fileName , String content , int [] mapping ) {
138+ this .saveClassFile (null , null , null , content , mapping );
271139 }
272- }
140+
141+ @ Override public void begin () {}
142+ @ Override public void close () {}
143+ @ Override public void acceptDirectory (String s ) {}
144+ @ Override public void acceptOther (String s ) {}
145+ @ Override public void saveFolder (String path ) {}
146+ @ Override public void copyFile (String source , String path , String entryName ) {}
147+ @ Override public void createArchive (String path , String archiveName , Manifest manifest ) {}
148+ @ Override public void saveDirEntry (String path , String archiveName , String entryName ) {}
149+ @ Override public void copyEntry (String source , String path , String archiveName , String entry ) {}
150+ @ Override public void saveClassEntry (String path , String archiveName , String qualifiedName , String entryName , String content ) {}
151+ @ Override public void closeArchive (String path , String archiveName ) {}
152+ }
0 commit comments