Mezclé las respuestas de @Grodriguez y @bemace y agregué mi propia estrategia para llegar a una solución de mejor esfuerzo. Esta solución imita en el tiempo de ejecución la función de importación automática disponible en tiempo de compilación.
El código completo de my solution is here. Dado un nombre simple, los pasos principales son:
- obtener una lista de paquetes accesibles desde el cargador de clases actual.
- Para cada paquete, intente cargar el nombre completo calificado obtenido del paquete + nombre simple.
Paso 2 es fácil:
public List<String> getFQNs(String simpleName) {
if (this.packages == null) {
this.packages = getPackages();
}
List<String> fqns = new ArrayList<String>();
for (String aPackage : packages) {
try {
String fqn = aPackage + "." + simpleName;
Class.forName(fqn);
fqns.add(fqn);
} catch (Exception e) {
// Ignore
}
}
return fqns;
}
Paso 1 es más difícil y depende de su aplicación/medio ambiente por lo que he implementado diversas estrategias para obtener diferentes listas de paquetes.
cargador de clases actual (puede ser útil para detectar clases generadas dinámicamente)
public Collection<String> getPackages() {
Set<String> packages = new HashSet<String>();
for (Package aPackage : Package.getPackages()) {
packages.add(aPackage.getName());
}
return packages;
}
Classpath (lo suficientemente bueno para aplicaciones que se cargan por completo de la ruta de clase. No es bueno para aplicaciones complejas como Eclipse)
public Collection<String> getPackages() {
String classpath = System.getProperty("java.class.path");
return getPackageFromClassPath(classpath);
}
public static Set<String> getPackageFromClassPath(String classpath) {
Set<String> packages = new HashSet<String>();
String[] paths = classpath.split(File.pathSeparator);
for (String path : paths) {
if (path.trim().length() == 0) {
continue;
} else {
File file = new File(path);
if (file.exists()) {
String childPath = file.getAbsolutePath();
if (childPath.endsWith(".jar")) {
packages.addAll(ClasspathPackageProvider
.readZipFile(childPath));
} else {
packages.addAll(ClasspathPackageProvider
.readDirectory(childPath));
}
}
}
}
return packages;
}
Bootstrap ruta de clase (por ejemplo, java.lang)
public Collection<String> getPackages() {
// Even IBM JDKs seem to use this property...
String classpath = System.getProperty("sun.boot.class.path");
return ClasspathPackageProvider.getPackageFromClassPath(classpath);
}
paquetes Eclipse (proveedor de paquetes de dominio específico)
// Don't forget to add "Eclipse-BuddyPolicy: global" to MANIFEST.MF
public Collection<String> getPackages() {
Set<String> packages = new HashSet<String>();
BundleContext context = Activator.getDefault().getBundle()
.getBundleContext();
Bundle[] bundles = context.getBundles();
PackageAdmin pAdmin = getPackageAdmin(context);
for (Bundle bundle : bundles) {
ExportedPackage[] ePackages = pAdmin.getExportedPackages(bundle);
if (ePackages != null) {
for (ExportedPackage ePackage : ePackages) {
packages.add(ePackage.getName());
}
}
}
return packages;
}
public PackageAdmin getPackageAdmin(BundleContext context) {
ServiceTracker bundleTracker = null;
bundleTracker = new ServiceTracker(context,
PackageAdmin.class.getName(), null);
bundleTracker.open();
return (PackageAdmin) bundleTracker.getService();
}
ejemplos de preguntas y respuestas en mi entorno Eclipse:
- del archivo: [java.io.File, org.eclipse.core.internal.resources.File]
- Lista: [java.awt.List, org.eclipse.swt.widgets.List, com.sun.xml.internal.bind.v2.schemage n.xmlschema.List, java.util.List, org.hibernate.mapping.List]
- IResource: [org.eclipse.core.resources.IResource]
Ni siquiera estoy seguro de que pueda enumera las clases cargadas desde un cargador de clases. Esto podría ayudarlo http://media.techtarget.com/tss/static/articles/content/dm_loadedClasses/executing.pdf –
@ Colin: incluso entonces, esto le permitiría encontrar clases que ya han sido cargadas por un cargador de clases, pero no las clases que están "disponibles en tiempo de ejecución". AFAIK no hay manera de saber si una clase determinada está disponible sin intentar cargarla. – Grodriguez
@Grodriguez: tienes razón en que no hay forma de saberlo. Considere los cargadores de clase que generan bytecode sobre la marcha en tiempo de ejecución. –