[Java] Minecraft - Automatically load your modules!


SUBMITTED BY: Guest

DATE: Feb. 10, 2014, 10:31 p.m.

FORMAT: Java

SIZE: 6.9 kB

HITS: 884

  1. // Class you need
  2. package com.luna.lib.reflection;
  3. import java.io.File;
  4. import java.io.IOException;
  5. import java.net.MalformedURLException;
  6. import java.net.URI;
  7. import java.net.URISyntaxException;
  8. import java.net.URL;
  9. import java.net.URLClassLoader;
  10. import java.util.ArrayList;
  11. import java.util.Enumeration;
  12. import java.util.List;
  13. import java.util.jar.JarEntry;
  14. import java.util.jar.JarFile;
  15. import com.luna.lib.loggers.BasicLogger;
  16. import com.luna.lib.loggers.enums.EnumLogType;
  17. public class ClassEnumerator {
  18. /**
  19. * Singleton instance
  20. */
  21. private static volatile ClassEnumerator instance;
  22. /**
  23. * Returns the singleton instance creates one if the instance is null
  24. *
  25. * @return instance
  26. */
  27. public static ClassEnumerator getInstance() {
  28. if( instance == null ) {
  29. BasicLogger.getInstance().setDebug( true );
  30. instance = new ClassEnumerator();
  31. }
  32. return instance;
  33. }
  34. /**
  35. * Parses a directory for jar files and class files
  36. *
  37. * Recurses through if necessary
  38. *
  39. * @param directory
  40. * directory to parse
  41. * @return class array
  42. */
  43. public List< Class< ? >> getClassesFromExternalDirectory( final File directory ) {
  44. final List< Class< ? >> classes = new ArrayList< Class< ? >>();
  45. for( final File file : directory.listFiles() ) {
  46. try {
  47. final ClassLoader classLoader = new URLClassLoader( new URL[ ] {
  48. file.toURI().toURL()
  49. }, /* this */directory.getClass().getClassLoader() );
  50. if( file.getName().toLowerCase().trim().endsWith( ".class" ) ) {
  51. BasicLogger.getInstance().log( EnumLogType.DEBUG, file.getName() );
  52. classes.add( classLoader.loadClass( file.getName().replace( ".class", "" )
  53. .replace( "/", "." ) ) );
  54. }
  55. if( file.getName().toLowerCase().trim().endsWith( ".jar" ) ) {
  56. classes.addAll( getClassesFromJar( file, classLoader ) );
  57. }
  58. if( file.isDirectory() ) {
  59. classes.addAll( getClassesFromExternalDirectory( file ) );
  60. }
  61. } catch( final MalformedURLException e ) {
  62. e.printStackTrace();
  63. } catch( final ClassNotFoundException e ) {
  64. e.printStackTrace();
  65. }
  66. }
  67. return classes;
  68. }
  69. /**
  70. * Returns the class array of all classes within a package
  71. *
  72. * @param classe
  73. * class to get code source location for
  74. *
  75. * @return class array
  76. */
  77. public Class< ? >[ ] getClassesFromPackage( final Class< ? > classe ) {
  78. final List< Class< ? >> classes = new ArrayList< Class< ? >>();
  79. URI uri = null;
  80. try {
  81. uri = classe.getProtectionDomain().getCodeSource().getLocation().toURI();
  82. } catch( final URISyntaxException e ) {
  83. e.printStackTrace();
  84. }
  85. if( uri == null ) {
  86. throw new RuntimeException( "No uri for "
  87. + classe.getProtectionDomain().getCodeSource().getLocation() );
  88. }
  89. BasicLogger.getInstance().log( EnumLogType.DEBUG, "URI: " + uri.toString() );
  90. classes.addAll( processDirectory( new File( uri ), "" ) );
  91. return classes.toArray( new Class[ classes.size() ] );
  92. }
  93. /**
  94. * Returns all class files inside a jar
  95. *
  96. * @param file
  97. * jar file
  98. * @param classLoader
  99. * classloader created previously using the jar file
  100. * @return class list
  101. */
  102. public List< Class< ? >> getClassesFromJar( final File file, final ClassLoader classLoader ) {
  103. final List< Class< ? >> classes = new ArrayList< Class< ? >>();
  104. try {
  105. final JarFile jarFile = new JarFile( file );
  106. final Enumeration< JarEntry > enumeration = jarFile.entries();
  107. while( enumeration.hasMoreElements() ) {
  108. final JarEntry jarEntry = enumeration.nextElement();
  109. if( jarEntry.isDirectory() || !jarEntry.getName().toLowerCase().trim().endsWith( ".class" ) ) {
  110. continue;
  111. }
  112. classes.add( classLoader.loadClass( jarEntry.getName().replace( ".class", "" )
  113. .replace( "/", "." ) ) );
  114. }
  115. jarFile.close();
  116. } catch( final IOException e ) {
  117. e.printStackTrace();
  118. } catch( final ClassNotFoundException e ) {
  119. e.printStackTrace();
  120. }
  121. return classes;
  122. }
  123. /**
  124. * Processes a directory and retrieves all classes from it and its
  125. * subdirectories
  126. *
  127. * Recurses if necessary
  128. *
  129. * @param directory
  130. * directory file to traverse
  131. * @return list of classes
  132. */
  133. private List< Class< ? >> processDirectory( final File directory, final String append ) {
  134. final List< Class< ? >> classes = new ArrayList< Class< ? >>();
  135. final String[ ] files = directory.list();
  136. for( final String fileName : files ) {
  137. String className = null;
  138. if( fileName.endsWith( ".class" ) ) {
  139. className = append + '.' + fileName.replace( ".class", "" );
  140. }
  141. if( className != null ) {
  142. classes.add( loadClass( className.substring( 1 ) ) );
  143. }
  144. final File subdir = new File( directory, fileName );
  145. if( subdir.isDirectory() ) {
  146. classes.addAll( processDirectory( subdir, append + "." + fileName ) );
  147. }
  148. }
  149. return classes;
  150. }
  151. /**
  152. * Loads a class based upon the name
  153. *
  154. * @param className
  155. * name of class (.class is pre removed)
  156. * @return Class if it was loaded properly
  157. */
  158. private Class< ? > loadClass( final String className ) {
  159. try {
  160. return Class.forName( className );
  161. } catch( final ClassNotFoundException e ) {
  162. throw new RuntimeException( "Error loading class '" + className + "'" );
  163. }
  164. }
  165. }
  166. // In your Module Manager class, use this to get the list of classes that are modules
  167. /**
  168. * Parses the class code source to get modules from the retrieved classes
  169. *
  170. * @param classe
  171. * class to get code source for
  172. * @return module array from package
  173. */
  174. private Module[ ] getModulesFromPackage( final Class< ? > classe ) {
  175. final List< Module > modules = new ArrayList<>();
  176. final Class< ? >[ ] classes = ClassEnumerator.getInstance().getClassesFromPackage( classe );
  177. for ( final Class< ? > c : classes ) {
  178. if ( Module.class.isAssignableFrom( c ) && !c.equals( Module.class ) ) {
  179. try {
  180. modules.add( ( Module ) c.newInstance() );
  181. } catch ( final InstantiationException e ) {
  182. e.printStackTrace();
  183. } catch ( final IllegalAccessException e ) {
  184. e.printStackTrace();
  185. }
  186. }
  187. }
  188. return modules.toArray( new Module[ modules.size() ] );
  189. }
  190. // And then use the returned array to load your modules!

comments powered by Disqus