66import com .ss .editor .FileExtensions ;
77import com .ss .editor .annotation .FromAnyThread ;
88import com .ss .editor .config .EditorConfig ;
9+ import com .ss .rlib .classpath .ClassPathScanner ;
10+ import com .ss .rlib .classpath .ClassPathScannerFactory ;
911import com .ss .rlib .manager .InitializeManager ;
12+ import com .ss .rlib .plugin .PluginContainer ;
1013import com .ss .rlib .util .FileUtils ;
1114import com .ss .rlib .util .Utils ;
1215import com .ss .rlib .util .array .Array ;
1922import java .nio .file .DirectoryStream ;
2023import java .nio .file .Files ;
2124import java .nio .file .Path ;
25+ import java .nio .file .Paths ;
2226
2327/**
24- * The class to manage custom classpath.
28+ * The class to manage classpath.
2529 *
2630 * @author JavaSaBr
2731 */
28- public class CustomClasspathManager {
32+ public class ClasspathManager {
2933
3034 @ NotNull
3135 private static final EditorConfig EDITOR_CONFIG = EditorConfig .getInstance ();
@@ -34,22 +38,37 @@ public class CustomClasspathManager {
3438 private static final String [] JAR_EXTENSIONS = toArray (FileExtensions .JAVA_LIBRARY );
3539
3640 @ NotNull
37- private static final String [] CLASSES_EXTENSIONS = toArray (FileExtensions .JAVA_CLASS );
41+ public static final Array <String > CORE_LIBRARIES_NAMES = ArrayFactory .asArray (
42+ "jme3-core" , "jme3-terrain" , "jme3-effects" ,
43+ "jme3-testdata" , "jme3-plugins" , "tonegod"
44+ );
3845
3946 @ Nullable
40- private static CustomClasspathManager instance ;
47+ private static ClasspathManager instance ;
4148
4249 /**
4350 * Gets instance.
4451 *
4552 * @return the instance
4653 */
4754 @ NotNull
48- public static CustomClasspathManager getInstance () {
49- if (instance == null ) instance = new CustomClasspathManager ();
55+ public static ClasspathManager getInstance () {
56+ if (instance == null ) instance = new ClasspathManager ();
5057 return instance ;
5158 }
5259
60+ /**
61+ * The core classpath scanner.
62+ */
63+ @ NotNull
64+ private final ClassPathScanner coreScanner ;
65+
66+ /**
67+ * The custom classpath scanner.
68+ */
69+ @ Nullable
70+ private volatile ClassPathScanner customScanner ;
71+
5372 /**
5473 * The libraries class loader.
5574 */
@@ -62,20 +81,86 @@ public static CustomClasspathManager getInstance() {
6281 @ Nullable
6382 private volatile URLClassLoader classesLoader ;
6483
65-
66- private CustomClasspathManager () {
84+ private ClasspathManager () {
6785 InitializeManager .valid (getClass ());
6886
87+ coreScanner = ClassPathScannerFactory .newManifestScanner (Editor .class , "Class-Path" );
88+ coreScanner .setUseSystemClasspath (true );
89+ coreScanner .scan (path -> {
90+
91+ if (CORE_LIBRARIES_NAMES .search (path , (pattern , pth ) -> pth .contains (pattern )) == null ) {
92+ return false ;
93+ } else if (path .contains ("natives" )) {
94+ return false ;
95+ } else if (path .contains ("sources" ) || path .contains ("javadoc" )) {
96+ return false ;
97+ }
98+
99+ return true ;
100+ });
101+
69102 final ExecutorManager executorManager = ExecutorManager .getInstance ();
70- executorManager .addJMETask (this ::updateLibraries );
71- executorManager .addJMETask (this ::updateClasses );
103+ executorManager .addJMETask (this ::reload );
104+ }
105+
106+ /**
107+ * Get all available resources from classpath.
108+ *
109+ * @return the list of resources.
110+ */
111+ @ NotNull
112+ public Array <String > getAllResources () {
113+ final Array <String > result = ArrayFactory .newArray (String .class );
114+ coreScanner .getAllResources (result );
115+ return result ;
116+ }
117+
118+ /**
119+ * Reload custom classes and libraries.
120+ */
121+ public synchronized void reload () {
122+ updateLibraries ();
123+ updateClasses ();
124+
125+ final URLClassLoader librariesLoader = getLibrariesLoader ();
126+ final URLClassLoader classesLoader = getClassesLoader ();
127+ final ClassLoader classLoader = classesLoader == null ? librariesLoader : classesLoader ;
128+
129+ final ClassPathScanner scanner = classesLoader == null ? ClassPathScannerFactory .newDefaultScanner () :
130+ ClassPathScannerFactory .newDefaultScanner (classLoader );
131+
132+ if (librariesLoader == null && classesLoader == null ) {
133+ this .customScanner = scanner ;
134+ return ;
135+ }
136+
137+ final Array <URL > urls = ArrayFactory .newArray (URL .class );
138+
139+ if (librariesLoader != null ) {
140+ urls .addAll (librariesLoader .getURLs ());
141+ }
142+
143+ if (classesLoader != null ) {
144+ urls .addAll (classesLoader .getURLs ());
145+ }
146+
147+ final String [] paths = urls .stream ().map (url -> Utils .get (url , URL ::toURI ))
148+ .map (Paths ::get )
149+ .map (Path ::toString )
150+ .toArray (String []::new );
151+
152+ scanner .addAdditionalPaths (paths );
153+ scanner .setUseSystemClasspath (false );
154+ scanner .scan (path -> true );
155+
156+ this .customScanner = scanner ;
72157 }
73158
74159 /**
75160 * Update libraries loader.
76161 */
77162 @ FromAnyThread
78- public synchronized void updateLibraries () {
163+ private void updateLibraries () {
79164
80165 final Editor editor = Editor .getInstance ();
81166 final AssetManager assetManager = editor .getAssetManager ();
@@ -104,7 +189,7 @@ public synchronized void updateLibraries() {
104189 * Update compiled classes loader.
105190 */
106191 @ FromAnyThread
107- public synchronized void updateClasses () {
192+ private void updateClasses () {
108193
109194 final Editor editor = Editor .getInstance ();
110195 final AssetManager assetManager = editor .getAssetManager ();
@@ -178,4 +263,26 @@ private void setClassesLoader(@Nullable final URLClassLoader classesLoader) {
178263 private URLClassLoader getClassesLoader () {
179264 return classesLoader ;
180265 }
266+
267+ /**
268+ * Find all implementations of the interface class.
269+ *
270+ * @return the list of all available implementations.
271+ */
272+ @ NotNull
273+ public <T > Array <Class <T >> findImplements (@ NotNull final Class <T > interfaceClass ) {
274+
275+ final Array <Class <T >> result = ArrayFactory .newArray (Class .class );
276+
277+ coreScanner .findImplements (result , interfaceClass );
278+ customScanner .findImplements (result , interfaceClass );
279+
280+ final PluginManager pluginManager = PluginManager .getInstance ();
281+ pluginManager .handlePlugins (plugin -> {
282+ final PluginContainer container = plugin .getContainer ();
283+ container .getScanner ().findImplements (result , interfaceClass );
284+ });
285+
286+ return result ;
287+ }
181288}
0 commit comments