77import java .io .IOException ;
88import java .io .InputStream ;
99import java .lang .reflect .InvocationTargetException ;
10+ import java .net .JarURLConnection ;
1011import java .net .MalformedURLException ;
1112import java .net .URL ;
1213import java .net .URLClassLoader ;
14+ import java .net .URLConnection ;
15+ import java .security .CodeSigner ;
1316import java .security .CodeSource ;
1417import java .security .ProtectionDomain ;
15- import java .security .cert .Certificate ;
1618import java .util .ArrayList ;
1719import java .util .Enumeration ;
1820import java .util .HashMap ;
1921import java .util .HashSet ;
2022import java .util .List ;
2123import java .util .Map ;
2224import java .util .Set ;
25+ import java .util .jar .JarEntry ;
26+ import java .util .jar .JarFile ;
27+ import java .util .jar .Manifest ;
2328
2429import org .mcphackers .launchwrapper .Launch ;
2530import org .mcphackers .launchwrapper .tweak .Tweaker ;
@@ -44,6 +49,7 @@ public class LaunchClassLoader extends URLClassLoader implements ClassNodeSource
4449 protected HighPriorityClassLoader urlClassLoader ;
4550 protected List <Tweaker > tweaks ;
4651 protected Set <String > exclusions = new HashSet <String >();
52+ protected Set <String > transformerExclusions = new HashSet <String >();
4753 /**
4854 * Keys should contain dots
4955 */
@@ -221,6 +227,12 @@ public Class<?> findClass(String name) throws ClassNotFoundException {
221227 return parent .loadClass (name );
222228 }
223229 }
230+
231+ for (String prefix : transformerExclusions ) {
232+ if (name .startsWith (prefix )) {
233+ return super .findClass (name );
234+ }
235+ }
224236 return redefineClass (name );
225237 }
226238
@@ -330,7 +342,7 @@ protected Class<?> redefineClass(String name) throws ClassNotFoundException {
330342 if (data == null ) {
331343 throw new ClassNotFoundException (transformedName );
332344 }
333- return defineClass (transformedName , data );
345+ return defineClass (transformedName , data , getProtectionDomain ( name ) );
334346 } catch (IOException e ) {
335347 throw new ClassNotFoundException (transformedName , e );
336348 }
@@ -376,44 +388,79 @@ public void setLoaderTweakers(List<Tweaker> classLoaderTweaks) {
376388 }
377389
378390 private Class <?> defineClass (String name , byte [] classData ) {
391+ return defineClass (name , classData , getProtectionDomain (name ));
392+ }
393+
394+ private Class <?> defineClass (String name , byte [] classData , ProtectionDomain protectionDomain ) {
379395 int i = name .lastIndexOf ('.' );
380396 if (i != -1 ) {
381397 String pkgName = name .substring (0 , i );
382398 if (getPackage (pkgName ) == null ) {
383399 definePackage (pkgName , null , null , null , null , null , null , null );
384400 }
385401 }
386- return defineClass (name , classData , 0 , classData .length , getProtectionDomain ( name ) );
402+ return defineClass (name , classData , 0 , classData .length , protectionDomain );
387403 }
388404
389405 private ProtectionDomain getProtectionDomain (String name ) {
390406 final URL resource = getResource (classResourceName (name ));
391407 if (resource == null ) {
392408 return null ;
393409 }
394- CodeSource codeSource = null ;
395- Certificate [] certificates = useDummyCert ? new Certificate [0 ] : null ;
410+
411+ CodeSigner [] signers = null ;
412+ int i = name .lastIndexOf ('.' );
413+
414+ // TODO avoid explicit net.minecraft comparison. Removing this condition breaks forge atm.
415+ if (i != -1 && !name .startsWith ("net.minecraft." )) {
416+ try {
417+ URLConnection urlConnection = resource .openConnection ();
418+ if (urlConnection instanceof JarURLConnection ) {
419+ final JarURLConnection jarURLConnection = (JarURLConnection )urlConnection ;
420+ JarFile jarFile ;
421+ jarFile = jarURLConnection .getJarFile ();
422+
423+ if (jarFile != null && jarFile .getManifest () != null ) {
424+ final Manifest manifest = jarFile .getManifest ();
425+ final JarEntry entry = jarFile .getJarEntry (classResourceName (name ));
426+ String pkgName = name .substring (0 , i );
427+
428+ Package pkg = getPackage (pkgName );
429+ // getClassBytes(name);
430+ if (entry != null ) {
431+ signers = entry .getCodeSigners ();
432+ }
433+ if (pkg == null ) {
434+ pkg = definePackage (pkgName , manifest , jarURLConnection .getJarFileURL ());
435+ }
436+ }
437+ }
438+ } catch (IOException e ) {
439+ e .printStackTrace ();
440+ }
441+ }
442+ URL newResource = resource ;
443+
444+ CodeSource codeSource ;
445+ // ModLoader fix
396446 if (resource .getProtocol ().equals ("jar" )) {
397447 String path = resource .getPath ();
398448 if (path .startsWith ("file:" )) {
399449 path = path .substring ("file:" .length ());
400- int i = path .lastIndexOf ('!' );
401- if (i != -1 ) {
402- path = path .substring (0 , i );
450+ int j = path .lastIndexOf ('!' );
451+ if (j != -1 ) {
452+ path = path .substring (0 , j );
403453 }
404454 }
405455 if (overridenSource .containsKey (name )) {
406456 path = overridenSource .get (name );
407457 }
408458 try {
409- URL newResource = new URL ("file" , "" , path );
410- codeSource = new CodeSource (newResource , certificates );
459+ newResource = new URL ("file" , "" , path );
411460 } catch (MalformedURLException e ) {
412- codeSource = new CodeSource (resource , certificates );
413461 }
414- } else {
415- codeSource = new CodeSource (resource , certificates );
416462 }
463+ codeSource = new CodeSource (newResource , signers );
417464 return new ProtectionDomain (codeSource , null );
418465 }
419466
0 commit comments