Skip to content

Commit 7f3f13a

Browse files
committed
add functionality to scan classes
add functionalities to progress add reverse order iterators to sorted collections add RenameFileTask improve DirectoryReader add functionalities to OutputToInput to know if the full data is already available serialization of byte array is done by default using the one of a stream instead of an array improve IDManager and add IDManagerRandomLong
1 parent 08b5c20 commit 7f3f13a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+1284
-124
lines changed

net.lecousin.core/src/main/java/net/lecousin/framework/application/SplashScreen.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,20 @@ public void unlisten(Runnable onchange) {
389389
}
390390
}
391391

392+
private boolean eventInterrupted;
393+
394+
@Override
395+
public void interruptEvents() {
396+
eventInterrupted = true;
397+
}
398+
399+
@Override
400+
public void resumeEvents(boolean trigger) {
401+
eventInterrupted = false;
402+
if (trigger)
403+
updateProgress();
404+
}
405+
392406
private void updateProgress() {
393407
if (subText.length() == 0) {
394408
progressText.setText("");
@@ -399,8 +413,9 @@ private void updateProgress() {
399413
}
400414
progressBar.setValue((int)(50 + (10000 * worked / amount)));
401415
bottom.invalidate();
402-
synchronized (this) {
403-
if (event != null) event.fire();
404-
}
416+
if (!eventInterrupted)
417+
synchronized (this) {
418+
if (event != null) event.fire();
419+
}
405420
}
406421
}

net.lecousin.core/src/main/java/net/lecousin/framework/application/launcher/DynamicLibrariesManager.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
import net.lecousin.framework.concurrent.synch.JoinPoint;
4040
import net.lecousin.framework.concurrent.synch.SynchronizationPoint;
4141
import net.lecousin.framework.concurrent.tasks.drives.FullReadFileTask;
42+
import net.lecousin.framework.event.Listener;
4243
import net.lecousin.framework.exception.NoException;
4344
import net.lecousin.framework.io.IO;
4445
import net.lecousin.framework.io.IO.Readable;
@@ -51,6 +52,7 @@
5152
import net.lecousin.framework.plugins.ExtensionPoints;
5253
import net.lecousin.framework.progress.FakeWorkProgress;
5354
import net.lecousin.framework.progress.WorkProgress;
55+
import net.lecousin.framework.util.Filter;
5456
import net.lecousin.framework.util.Pair;
5557
import net.lecousin.framework.util.Triple;
5658

@@ -939,4 +941,12 @@ public void run() {
939941
return task;
940942
}
941943

944+
@Override
945+
public void scanLibraries(
946+
String rootPackage, boolean includeSubPackages, Filter<String> packageFilter, Filter<String> classFilter,
947+
Listener<Class<?>> classScanner
948+
) {
949+
appClassLoader.scanLibraries(rootPackage, includeSubPackages, packageFilter, classFilter, classScanner);
950+
}
951+
942952
}

net.lecousin.core/src/main/java/net/lecousin/framework/application/libraries/LibrariesManager.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
import net.lecousin.framework.application.Application;
77
import net.lecousin.framework.application.ApplicationClassLoader;
88
import net.lecousin.framework.concurrent.synch.ISynchronizationPoint;
9+
import net.lecousin.framework.event.Listener;
910
import net.lecousin.framework.io.IO;
11+
import net.lecousin.framework.util.Filter;
1012

1113
/** Allows to load libraries and get information about loaded ones. */
1214
public interface LibrariesManager {
@@ -26,4 +28,8 @@ public interface LibrariesManager {
2628
/** Return the list of libraries loaded. Each File may be a file in case of a JAR, or a directory. */
2729
List<File> getLibrariesLocations();
2830

31+
/** Go through each library to scan its content. */
32+
void scanLibraries(String rootPackage, boolean includeSubPackages,
33+
Filter<String> packageFilter, Filter<String> classFilter, Listener<Class<?>> classScanner);
34+
2935
}

net.lecousin.core/src/main/java/net/lecousin/framework/application/libraries/classloader/AbstractClassLoader.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,12 @@
1515
import net.lecousin.framework.collections.CompoundCollection;
1616
import net.lecousin.framework.concurrent.synch.ISynchronizationPoint;
1717
import net.lecousin.framework.concurrent.synch.JoinPoint;
18+
import net.lecousin.framework.event.Listener;
1819
import net.lecousin.framework.exception.NoException;
1920
import net.lecousin.framework.io.IO;
2021
import net.lecousin.framework.io.provider.IOProvider;
2122
import net.lecousin.framework.io.provider.IOProviderFrom;
23+
import net.lecousin.framework.util.Filter;
2224
import net.lecousin.framework.util.Pair;
2325

2426
/**
@@ -58,6 +60,9 @@ public Application getApplication() {
5860

5961
protected abstract IO.Readable openResourcePointer(Object pointer, byte priority) throws IOException;
6062

63+
protected abstract void scan(String rootPackage, boolean includeSubPackages,
64+
Filter<String> packageFilter, Filter<String> classFilter, Listener<Class<?>> classScanner);
65+
6166
private List<AbstractClassLoader> subLoaders = null;
6267

6368
/** Add a class loader from a resource contained by this class loader, for example an inner jar file. */

net.lecousin.core/src/main/java/net/lecousin/framework/application/libraries/classloader/AppClassLoader.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
import net.lecousin.framework.collections.CompoundCollection;
1515
import net.lecousin.framework.concurrent.Task;
1616
import net.lecousin.framework.concurrent.Threading;
17+
import net.lecousin.framework.event.Listener;
1718
import net.lecousin.framework.io.IO;
1819
import net.lecousin.framework.io.IOAsInputStream;
1920
import net.lecousin.framework.io.IOFromInputStream;
2021
import net.lecousin.framework.io.provider.FileIOProvider;
2122
import net.lecousin.framework.io.provider.IOProvider;
2223
import net.lecousin.framework.io.provider.IOProviderFromPathUsingClassloader;
24+
import net.lecousin.framework.util.Filter;
2325

2426
/**
2527
* Used to aggregate class loaders for an application.
@@ -252,4 +254,14 @@ public Class<?> loadClass(String className) throws ClassNotFoundException {
252254
public URL getResource(String filename) {
253255
return getResourceFrom(filename, null);
254256
}
257+
258+
/** Scan libraries to find classes. */
259+
public void scanLibraries(
260+
String rootPackage, boolean includeSubPackages,
261+
Filter<String> packageFilter, Filter<String> classFilter, Listener<Class<?>> classScanner
262+
) {
263+
for (AbstractClassLoader cl : libs)
264+
cl.scan(rootPackage, includeSubPackages, packageFilter, classFilter, classScanner);
265+
}
266+
255267
}

net.lecousin.core/src/main/java/net/lecousin/framework/application/libraries/classloader/DirectoryClassLoader.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,11 @@
77
import java.net.MalformedURLException;
88
import java.net.URL;
99

10+
import net.lecousin.framework.application.libraries.classpath.DefaultLibrariesManager;
11+
import net.lecousin.framework.event.Listener;
1012
import net.lecousin.framework.io.FileIO;
1113
import net.lecousin.framework.io.IO;
14+
import net.lecousin.framework.util.Filter;
1215

1316
/**
1417
* Class loader from a directory containing class files.
@@ -77,4 +80,12 @@ protected Object getResourcePointer(String path) {
7780
protected IO.Readable openResourcePointer(Object pointer, byte priority) {
7881
return new FileIO.ReadOnly((File)pointer, priority);
7982
}
83+
84+
@Override
85+
protected void scan(
86+
String rootPackage, boolean includeSubPackages,
87+
Filter<String> packageFilter, Filter<String> classFilter, Listener<Class<?>> classScanner
88+
) {
89+
DefaultLibrariesManager.scanDirectoryLibrary(this, dir, rootPackage, includeSubPackages, packageFilter, classFilter, classScanner);
90+
}
8091
}

net.lecousin.core/src/main/java/net/lecousin/framework/application/libraries/classloader/ZipClassLoader.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@
1212
import java.util.zip.ZipEntry;
1313
import java.util.zip.ZipFile;
1414

15+
import net.lecousin.framework.application.libraries.classpath.DefaultLibrariesManager;
1516
import net.lecousin.framework.concurrent.CancelException;
1617
import net.lecousin.framework.concurrent.Task;
1718
import net.lecousin.framework.concurrent.Threading;
19+
import net.lecousin.framework.event.Listener;
1820
import net.lecousin.framework.io.FileIO;
1921
import net.lecousin.framework.io.IO;
2022
import net.lecousin.framework.io.IOFromInputStream;
@@ -23,6 +25,7 @@
2325
import net.lecousin.framework.io.provider.IOProvider;
2426
import net.lecousin.framework.memory.IMemoryManageable;
2527
import net.lecousin.framework.memory.MemoryManager;
28+
import net.lecousin.framework.util.Filter;
2629

2730
/**
2831
* JAR class loader.
@@ -211,5 +214,18 @@ public InputStream getInputStream() throws IOException {
211214
return zip.getInputStream(entry);
212215
}
213216
}
217+
218+
@Override
219+
protected void scan(
220+
String rootPackage, boolean includeSubPackages,
221+
Filter<String> packageFilter, Filter<String> classFilter, Listener<Class<?>> classScanner
222+
) {
223+
try {
224+
DefaultLibrariesManager.scanJarLibrary(this, getZip(),
225+
rootPackage, includeSubPackages, packageFilter, classFilter, classScanner);
226+
} catch (Throwable t) {
227+
// ignore
228+
}
229+
}
214230

215231
}

net.lecousin.core/src/main/java/net/lecousin/framework/application/libraries/classpath/DefaultLibrariesManager.java

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,26 @@
99
import java.util.Enumeration;
1010
import java.util.LinkedList;
1111
import java.util.List;
12+
import java.util.zip.ZipEntry;
13+
import java.util.zip.ZipFile;
1214

1315
import net.lecousin.framework.application.Application;
16+
import net.lecousin.framework.application.ApplicationClassLoader;
1417
import net.lecousin.framework.application.libraries.LibrariesManager;
1518
import net.lecousin.framework.concurrent.Task;
1619
import net.lecousin.framework.concurrent.TaskManager;
1720
import net.lecousin.framework.concurrent.Threading;
1821
import net.lecousin.framework.concurrent.synch.ISynchronizationPoint;
1922
import net.lecousin.framework.concurrent.synch.JoinPoint;
2023
import net.lecousin.framework.concurrent.synch.SynchronizationPoint;
24+
import net.lecousin.framework.event.Listener;
2125
import net.lecousin.framework.exception.NoException;
2226
import net.lecousin.framework.io.IO;
2327
import net.lecousin.framework.io.IOFromInputStream;
2428
import net.lecousin.framework.io.text.BufferedReadableCharacterStream;
2529
import net.lecousin.framework.plugins.CustomExtensionPoint;
2630
import net.lecousin.framework.plugins.ExtensionPoints;
31+
import net.lecousin.framework.util.Filter;
2732

2833
/**
2934
* Default implementation of LibrariesManager.
@@ -260,4 +265,99 @@ private void loadPlugins(Enumeration<URL> urls, SynchronizationPoint<Exception>
260265
loadPlugins(urls, sp);
261266
}, sp);
262267
}
268+
269+
@Override
270+
public void scanLibraries(
271+
String rootPackage, boolean includeSubPackages,
272+
Filter<String> packageFilter, Filter<String> classFilter, Listener<Class<?>> classScanner
273+
) {
274+
List<File> files = getLibrariesLocations();
275+
for (File f : files) {
276+
if (f.isDirectory())
277+
scanDirectoryLibrary(app.getClassLoader(), f, rootPackage,
278+
includeSubPackages, packageFilter, classFilter, classScanner);
279+
else
280+
scanJarLibrary(app.getClassLoader(), f, rootPackage, includeSubPackages, packageFilter, classFilter, classScanner);
281+
}
282+
}
283+
284+
/** Scan a directory looking for class files. */
285+
public static void scanDirectoryLibrary(
286+
ApplicationClassLoader classLoader, File dir, String rootPackage, boolean includeSubPackages,
287+
Filter<String> packageFilter, Filter<String> classFilter, Listener<Class<?>> classScanner
288+
) {
289+
String pkgPath = rootPackage.replace('.', '/');
290+
File rootDir = new File(dir, pkgPath);
291+
if (!rootDir.exists()) return;
292+
scanClasses(classLoader, rootDir, rootPackage, includeSubPackages, packageFilter, classFilter, classScanner);
293+
}
294+
295+
private static void scanClasses(
296+
ApplicationClassLoader classLoader, File dir, String pkgName, boolean includeSubPackages,
297+
Filter<String> packageFilter, Filter<String> classFilter, Listener<Class<?>> classScanner
298+
) {
299+
File[] files = dir.listFiles();
300+
if (files == null) return;
301+
boolean filtered = packageFilter != null && !packageFilter.accept(pkgName);
302+
for (File f : files) {
303+
if (f.isDirectory()) {
304+
if (!includeSubPackages) continue;
305+
scanClasses(classLoader, f, pkgName + '.' + f.getName(), true, packageFilter, classFilter, classScanner);
306+
} else if (!filtered) {
307+
if (f.getName().endsWith(".class")) {
308+
String name = pkgName + '.' + f.getName().substring(0, f.getName().length() - 6);
309+
if (classFilter == null || classFilter.accept(name)) {
310+
try {
311+
Class<?> cl = classLoader.loadClass(name);
312+
classScanner.fire(cl);
313+
} catch (Throwable t) {
314+
// ignore
315+
}
316+
}
317+
}
318+
}
319+
}
320+
}
321+
322+
/** Scan a JAR looking for class files. */
323+
public static void scanJarLibrary(
324+
ApplicationClassLoader classLoader, File file, String rootPackage, boolean includeSubPackages,
325+
Filter<String> packageFilter, Filter<String> classFilter, Listener<Class<?>> classScanner
326+
) {
327+
try (ZipFile jar = new ZipFile(file)) {
328+
scanJarLibrary(classLoader, jar, rootPackage, includeSubPackages, packageFilter, classFilter, classScanner);
329+
} catch (Throwable t) {
330+
// ignore
331+
}
332+
}
333+
334+
/** Scan a JAR looking for class files. */
335+
public static void scanJarLibrary(
336+
ApplicationClassLoader classLoader, ZipFile jar, String rootPackage, boolean includeSubPackages,
337+
Filter<String> packageFilter, Filter<String> classFilter, Listener<Class<?>> classScanner
338+
) {
339+
String pkgPath = rootPackage.length() > 0 ? rootPackage.replace('.', '/') + '/' : "";
340+
Enumeration<? extends ZipEntry> entries = jar.entries();
341+
while (entries.hasMoreElements()) {
342+
ZipEntry f = entries.nextElement();
343+
if (f.isDirectory()) continue;
344+
String name = f.getName();
345+
if (!name.startsWith(pkgPath)) continue;
346+
if (!name.endsWith(".class")) continue;
347+
name = name.substring(0, name.length() - 6);
348+
name = name.replace('/', '.');
349+
int i = name.lastIndexOf('.');
350+
String pkg = i > 0 ? name.substring(0, i) : "";
351+
if (includeSubPackages || pkg.equals(rootPackage)) {
352+
if (packageFilter != null && !packageFilter.accept(pkg)) continue;
353+
if (classFilter != null && !classFilter.accept(name)) continue;
354+
try {
355+
Class<?> cl = classLoader.loadClass(name);
356+
classScanner.fire(cl);
357+
} catch (Throwable t) {
358+
// ignore
359+
}
360+
}
361+
}
362+
}
263363
}

0 commit comments

Comments
 (0)