I need to ensure that a method from a class is only executed by selected methods from different packages.
package myApp.security;
public class SecurityStuff{
public static final SecurityStuff security = new SecurityStuff();
public KeyStore getKeyStore(){
//if invoked by MySock.getTLSServerSocket()
return keyStore;
//if not, should return null
}
}
package myApp.socks;
public class MySock{
public void getTLSServerSocket(){
KeyStore keyStore = SecurityStuff.security.getKeyStore();
}
}
With the 2 classes above, how do I ensure that SecurityStuff.getKeyStore() would return the KeyStore iff it is from the classes & methods that I allow?
Please take into account that the jar would be obfuscated later.
You can request the sender's object:
public KeyStore getKeyStore(Object obj){
if (!obj instanceof MyClassThatIsAllowedToCall) return;
//execute code
}
And when you call getKeyStore always provide the parameter:
getKeyStore(this);
This seems to be what you want, but it is NOT secure! You could easily fake the sender. So if you are actually handling confidential data, this won't be the way to go.
Take a look at StakTraceElement . You can get stacktrace like :
StackTraceElement[] stack = Thread.currentThread().getStackTrace();
Then you can get the calling method name using getMethodName(). So, probably you can whitelist the methods you want access to and return keystore for them. For all other cases, you can return null. Hope this helps.
I'm going mad with an error non error on my web-app Flex 3.6 based (using BlazeDS). I try to describe my issue: I have a java class:
public class User {...}
and the binding one in .as:
[Bindable]
[RemoteClass(alias="it.dto.User")]
public class User {...}
I also have a DataManager.as to do the Async call like this:
public function getUser():void {
var token:AsyncToken = _service.getUser();
token.addResponder(new AsyncResponder(userOnResult,userOnFault));
}
private function userOnFault(event:FaultEvent,token:Object):void {
var _fail:String = "Error";
}
private function socOnResult(event:ResultEvent,token:Object):void {
_resUser = event.result as ArrayCollection;
dispatchEvent(new MyEvent("USER_EVENT",_resUser));
}
Now I implemented the following code in two different .as file (different package), which refers to two different .mxml:
var data:DataManager = new DataManager;
....
data.addEventListener("USER_EVENT",userResult);
....
data.getUser();
....
private function userResult(dataEvent:MyEvent):void {
var user:ArrayCollection = new ArrayCollection;
user = dataEvent.result as ArrayCollection;
for (var i:int = 0;i<user.length; i++) {
var u:User = new User;
u = (User)(user.getItemAt(i));
}
_dm.removeEventListener("USER_EVENT",userResult);
}
The drama is that in the first .as it works perfectly, and in the second .as give me a Error of coercion failed. In the second file seems how it can't recognize the User class.
Do you have any idea?? I'm going mad!!
Thank you
#Stacktrace error:
TypeError: Error #1034: Type Coercion failed: cannot convert appcode.dto::SocietaDTO#b4dbfc1 to appcode.dto.SocietaDTO.
at modules::ReportIspezioni/onSocResult()[D:\workspace\maga\aga\flex_src\modules\ReportIspezioni_src.as:80]
at flash.events::EventDispatcher/dispatchEventFunction()
at flash.events::EventDispatcher/dispatchEvent()
at appcode.dao::DataManager/socOnResult()[D:\workspace\maga\aga\flex_src\appcode\dao\DataManager.as:180]
at mx.rpc::AsyncResponder/result()[C:\autobuild\3.x\frameworks\projects\rpc\src\mx\rpc\AsyncResponder.as:82]
at mx.rpc::AsyncToken/http://www.adobe.com/2006/flex/mx/internal::applyResult()[C:\autobuild\3.x\frameworks\projects\rpc\src\mx\rpc\AsyncToken.as:199]
at mx.rpc.events::ResultEvent/http://www.adobe.com/2006/flex/mx/internal::callTokenResponders()[C:\autobuild\3.x\frameworks\projects\rpc\src\mx\rpc\events\ResultEvent.as:172]
at mx.rpc::AbstractOperation/http://www.adobe.com/2006/flex/mx/internal::dispatchRpcEvent()[C:\autobuild\3.x\frameworks\projects\rpc\src\mx\rpc\AbstractOperation.as:199]
at mx.rpc::AbstractInvoker/http://www.adobe.com/2006/flex/mx/internal::resultHandler()[C:\autobuild\3.x\frameworks\projects\rpc\src\mx\rpc\AbstractInvoker.as:263]
at mx.rpc::Responder/result()[C:\autobuild\3.x\frameworks\projects\rpc\src\mx\rpc\Responder.as:46]
at mx.rpc::AsyncRequest/acknowledge()[C:\autobuild\3.x\frameworks\projects\rpc\src\mx\rpc\AsyncRequest.as:74]
at NetConnectionMessageResponder/resultHandler()[C:\autobuild\3.x\frameworks\projects\rpc\src\mx\messaging\channels\NetConnectionChannel.as:524]
at mx.messaging::MessageResponder/result()[C:\autobuild\3.x\frameworks\projects\rpc\src\mx\messaging\MessageResponder.as:199]
Obviusly the User class written above is just for example, to understand the code logic. The real class is a DTO calls SocietaDTO.
N.B: The code works perfectly in another module of my project.. I don't understand why here it doesn't work.
Thanks a lot
I never save browser cache when developing.. Anyway I solve the Issue by adding this:
registerClassAlias("it.mec.dto.SocietaDTO", SocietaDTO);
In the class were exception launch.
Thanks anyway
I have a custom Properties class extending java.util.Properties and overriding getProperty using Jasypt.
I have placed Jasypt and MyProperties jar files under the lib folder of Liquibase.
I am trying to run it with Liquibase-CLI:
liquibase --defaultsFile=my.properties --propertyProviderClass=info.farhdine.MyProperties validate
But, I am always getting an error:
java.sql.SQLException: ORA-01017: invalid username/password; logon denied
In my.properties file, even if nothing is encrypted, I am always getting the same error as far as I use propertyProviderClass.
Does anyone already managed to make it work?
Thanks.
Problem solved!
I was overriding the get() method instead of put() :)
public class MyProperties extends java.util.Properties {
private static final long serialVersionUID = -207802321379271320L;
public MyProperties() {
StandardPBEStringEncryptor encryptor = new StandardPBEStringEncryptor();
encryptor.setPassword("jasypt");
super.defaults = new EncryptableProperties(encryptor);
}
#Override
public synchronized Object put(Object paramK, Object paramV) {
return super.defaults.put(paramK, paramV);
}
}
It seems like my RealmObject values are being hidden by the RealmProxy class, but can be set from the proxyclass.
My model is pretty straight forward as you can see.
public class GroupRealm extends RealmObject {
#PrimaryKey
public String id;
#Index
public String name;
public String imageUrl;
public int order;
public GroupRealm parent;
public RealmList<GroupRealm> children;
public RealmList<ContentRealm> contents;
}
This is how i am setting the values(db is a valid Realm, and everything is in a transaction that commits fine):
GroupRealm gr = db.where(GroupRealm.class).equalTo("id",g.GroupID).findFirst();
if(gr==null){
gr = db.createObject(GroupRealm.class,g.GroupID);
}
gr.imageUrl = g.GlyphUrl;
gr.name = g.Title;
gr.order = g.OrderNum;
The image below is what I get when i query the db latter on.(same variable name not same place in code)
In my android.library where my RealmObjects are defined project I have the necessary plugins.
apply plugin: 'com.android.library'
apply plugin: 'realm-android'
and on the project level I am setting the correct dependencies:
dependencies {
classpath 'com.android.tools.build:gradle:2.1.0'
classpath "io.realm:realm-gradle-plugin:0.90.1"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
I am out of ideas. If I try to access anything I retrieve the GroupRealm as expected but all of the public properties exposed through the proxy class return null!
Relevant FAQ in documentation: https://realm.io/docs/java/latest/#debugging
Realm uses Android Gradle Transform API. It gives a possibility to manipulate compiled class files before they are converted to dex files.
More details inside io.realm.transformer.RealmTransformer and io.realm.transformer. BytecodeModifier classes which can be found in the realm's github.
What RealmTransformer does, among others, is:
replacing all accesses to fields of user's RealmObjects with the appropriate Realm accessors.
You can also check result classes inside folder app/build/intermediates/transforms/RealmTransformer/
Example of setter:
Line of your code:
gr.imageUrl = g.GlyphUrl;
will be replaced with something like this:
String var5 = g.GlyphUrl;
gr.realmSet$imageUrl(var5);
Example of getter:
String url = gr.imageUrl;
will be replaced with something like this:
String url = gr.realmGet$imageUrl();
Example use case
You have created class GroupRealm. Realm using Transform API generates GroupRealmRealmProxy. This proxy class looks like this:
public class GroupRealmRealmProxy extends GroupRealm implements RealmObjectProxy, GroupRealmRealmProxyInterface {
private final GroupRealmRealmProxy.GroupRealmColumnInfo columnInfo;
private final ProxyState proxyState;
private RealmList<GroupRealm> childrenRealmList;
private RealmList<ContentRealm> contentsRealmList;
private static final List<String> FIELD_NAMES;
GroupRealmRealmProxy(ColumnInfo columnInfo) {
...
}
public String realmGet$id() {
this.proxyState.getRealm$realm().checkIfValid();
return this.proxyState.getRow$realm().getString(this.columnInfo.idIndex);
}
public void realmSet$id(String value) {
this.proxyState.getRealm$realm().checkIfValid();
if(value == null) {
this.proxyState.getRow$realm().setNull(this.columnInfo.idIndex);
} else {
this.proxyState.getRow$realm().setString(this.columnInfo.idIndex, value);
}
}
public String realmGet$name() {
this.proxyState.getRealm$realm().checkIfValid();
return this.proxyState.getRow$realm().getString(this.columnInfo.nameIndex);
}
public void realmSet$name(String value) {
this.proxyState.getRealm$realm().checkIfValid();
if(value == null) {
this.proxyState.getRow$realm().setNull(this.columnInfo.nameIndex);
} else {
this.proxyState.getRow$realm().setString(this.columnInfo.nameIndex, value);
}
}
...
}
You can observe that methods realmSet$name and realmGet$name don't have access to field name declared in the class GroupRealm. They use proxyState.
Now, let's back to the usage of GroupRealm. When you debug your code:
GroupRealm gr = db.where(GroupRealm.class).equalTo("id",g.GroupID).findFirst();
if(gr==null){
gr = db.createObject(GroupRealm.class,g.GroupID);
}
gr.imageUrl = g.GlyphUrl;
gr.name = g.Title;
gr.order = g.OrderNum;
in a reality it's decompiled version looks like this:
GroupRealm gr = (GroupRealm)realm.where(GroupRealm.class).equalTo("id", g.GroupId).findFirst();
if(gr == null) {
gr = (GroupRealm)realm.createObject(GroupRealm.class, g.GroupId);
}
String var7 = g.GlyphUrl;
gr.realmSet$imageUrl(var7);
var7 = g.Title;
gr.realmSet$name(var7);
int var8 = g.OrderNum;
gr.realmSet$order(var8);
First of all, gr is the instance of GroupRealmRealmProxy class. As you can see, setting of gr.name is replaced by gr.realmSet$name(var7). It means that the field name of GroupRealm is never used. The situation is analogous in the case of realmGet$.
While debugging you see your version of source code but actually you're using a modified version with injected methods realmSet$ and realmGet$.
The fields are null. You access the properties through a native method that replaces all field access. Previously (before 0.88.0) it used to create a dynamic proxy that overrode your getters and setters to use their native proxy implementation.
The fields don't have values. But as you can see, the Realm object has the values just fine: it says so in the toString() value.
There is nothing to be done about this. Because of the "clever" thing that Realm is doing, the debugger is completely prevented from doing what it is supposed to. You'll have to rely on a lot of Log.d statements.
I'm sorry. That's just the reality of it.
This is because of the Realm proxies model which is zero-copy storage.
You can use Kotlin Realm extension, Vicpinm library https://github.com/vicpinm/Kotlin-Realm-Extensions
If you still want to use in Java then you achieve it by:-
Realm.getDefaultInstance().copyFromRealm(realmObject)
The answers above are all right if you directly use an RealmObject retrieved from your Realm. With Managed RealmObject (Objects "directly" connected with your Realm, so the "Real Instance" of the object inside your Realm which you can Modify only inside RealmTransaction and which changes will affect all other Managed RealmInstance instantly) you can't see their values inside of the debugger because of the proxy.
Anyway you can work around this by using a NO MANAGED object, so by COPYING the RealmObject from the realm:
MyRealmObject obj = getRealmObjectFromRealm();
if(obj != null){
obj = mRealm.copyFromRealm(obj);
}
This way you will see all properties of your realm object inside the debugger.
Obviously if you need to use a Managed Realm Object inside your code, when you are debugging you need to change your code by creating another "MyRealmObject" instance which is a copy from the Realm of the other "MyRealmObject".
This way you will see all objects properties inside the debugger (:
Hope this is helpful,
Greetings & have a nice coding!
:D
How does one go about and try to find all subclasses of a given class (or all implementors of a given interface) in Java?
As of now, I have a method to do this, but I find it quite inefficient (to say the least).
The method is:
Get a list of all class names that exist on the class path
Load each class and test to see if it is a subclass or implementor of the desired class or interface
In Eclipse, there is a nice feature called the Type Hierarchy that manages to show this quite efficiently.
How does one go about and do it programmatically?
Scanning for classes is not easy with pure Java.
The spring framework offers a class called ClassPathScanningCandidateComponentProvider that can do what you need. The following example would find all subclasses of MyClass in the package org.example.package
ClassPathScanningCandidateComponentProvider provider = new ClassPathScanningCandidateComponentProvider(false);
provider.addIncludeFilter(new AssignableTypeFilter(MyClass.class));
// scan in org.example.package
Set<BeanDefinition> components = provider.findCandidateComponents("org/example/package");
for (BeanDefinition component : components)
{
Class cls = Class.forName(component.getBeanClassName());
// use class cls found
}
This method has the additional benefit of using a bytecode analyzer to find the candidates which means it will not load all classes it scans.
There is no other way to do it other than what you described. Think about it - how can anyone know what classes extend ClassX without scanning each class on the classpath?
Eclipse can only tell you about the super and subclasses in what seems to be an "efficient" amount of time because it already has all of the type data loaded at the point where you press the "Display in Type Hierarchy" button (since it is constantly compiling your classes, knows about everything on the classpath, etc).
This is not possible to do using only the built-in Java Reflections API.
A project exists that does the necessary scanning and indexing of your classpath so you can get access this information...
Reflections
A Java runtime metadata analysis, in the spirit of Scannotations
Reflections scans your classpath, indexes the metadata, allows you to query it on runtime and may save and collect that information for many modules within your project.
Using Reflections you can query your metadata for:
get all subtypes of some type
get all types annotated with some annotation
get all types annotated with some annotation, including annotation parameters matching
get all methods annotated with some
(disclaimer: I have not used it, but the project's description seems to be an exact fit for your needs.)
Try ClassGraph. (Disclaimer, I am the author). ClassGraph supports scanning for subclasses of a given class, either at runtime or at build time, but also much more. ClassGraph can build an abstract representation of the entire class graph (all classes, annotations, methods, method parameters, and fields) in memory, for all classes on the classpath, or for classes in selected packages, and you can query this class graph however you want. ClassGraph supports more classpath specification mechanisms and classloaders than any other scanner, and also works seamlessly with the new JPMS module system, so if you base your code on ClassGraph, your code will be maximally portable. See the API here.
Don't forget that the generated Javadoc for a class will include a list of known subclasses (and for interfaces, known implementing classes).
I know I'm a few years late to this party, but I came across this question trying to solve the same problem. You can use Eclipse's internal searching programatically, if you're writing an Eclipse Plugin (and thus take advantage of their caching, etc), to find classes which implement an interface. Here's my (very rough) first cut:
protected void listImplementingClasses( String iface ) throws CoreException
{
final IJavaProject project = <get your project here>;
try
{
final IType ifaceType = project.findType( iface );
final SearchPattern ifacePattern = SearchPattern.createPattern( ifaceType, IJavaSearchConstants.IMPLEMENTORS );
final IJavaSearchScope scope = SearchEngine.createWorkspaceScope();
final SearchEngine searchEngine = new SearchEngine();
final LinkedList<SearchMatch> results = new LinkedList<SearchMatch>();
searchEngine.search( ifacePattern,
new SearchParticipant[]{ SearchEngine.getDefaultSearchParticipant() }, scope, new SearchRequestor() {
#Override
public void acceptSearchMatch( SearchMatch match ) throws CoreException
{
results.add( match );
}
}, new IProgressMonitor() {
#Override
public void beginTask( String name, int totalWork )
{
}
#Override
public void done()
{
System.out.println( results );
}
#Override
public void internalWorked( double work )
{
}
#Override
public boolean isCanceled()
{
return false;
}
#Override
public void setCanceled( boolean value )
{
}
#Override
public void setTaskName( String name )
{
}
#Override
public void subTask( String name )
{
}
#Override
public void worked( int work )
{
}
});
} catch( JavaModelException e )
{
e.printStackTrace();
}
}
The first problem I see so far is that I'm only catching classes which directly implement the interface, not all their subclasses - but a little recursion never hurt anyone.
I did this several years ago. The most reliable way to do this (i.e. with official Java APIs and no external dependencies) is to write a custom doclet to produce a list that can be read at runtime.
You can run it from the command line like this:
javadoc -d build -doclet com.example.ObjectListDoclet -sourcepath java/src -subpackages com.example
or run it from ant like this:
<javadoc sourcepath="${src}" packagenames="*" >
<doclet name="com.example.ObjectListDoclet" path="${build}"/>
</javadoc>
Here's the basic code:
public final class ObjectListDoclet {
public static final String TOP_CLASS_NAME = "com.example.MyClass";
/** Doclet entry point. */
public static boolean start(RootDoc root) throws Exception {
try {
ClassDoc topClassDoc = root.classNamed(TOP_CLASS_NAME);
for (ClassDoc classDoc : root.classes()) {
if (classDoc.subclassOf(topClassDoc)) {
System.out.println(classDoc);
}
}
return true;
}
catch (Exception ex) {
ex.printStackTrace();
return false;
}
}
}
For simplicity, I've removed command line argument parsing and I'm writing to System.out rather than a file.
Keeping in mind the limitations mentioned in the other answers, you can also use openpojo's PojoClassFactory (available on Maven) in the following manner:
for(PojoClass pojoClass : PojoClassFactory.enumerateClassesByExtendingType(packageRoot, Superclass.class, null)) {
System.out.println(pojoClass.getClazz());
}
Where packageRoot is the root String of the packages you wish to search in (e.g. "com.mycompany" or even just "com"), and Superclass is your supertype (this works on interfaces as well).
Depending on your particular requirements, in some cases Java's service loader mechanism might achieve what you're after.
In short, it allows developers to explicitly declare that a class subclasses some other class (or implements some interface) by listing it in a file in the JAR/WAR file's META-INF/services directory. It can then be discovered using the java.util.ServiceLoader class which, when given a Class object, will generate instances of all the declared subclasses of that class (or, if the Class represents an interface, all the classes implementing that interface).
The main advantage of this approach is that there is no need to manually scan the entire classpath for subclasses - all the discovery logic is contained within the ServiceLoader class, and it only loads the classes explicitly declared in the META-INF/services directory (not every class on the classpath).
There are, however, some disadvantages:
It won't find all subclasses, only those that are explicitly declared. As such, if you need to truly find all subclasses, this approach may be insufficient.
It requires the developer to explicitly declare the class under the META-INF/services directory. This is an additional burden on the developer, and can be error-prone.
The ServiceLoader.iterator() generates subclass instances, not their Class objects. This causes two issues:
You don't get any say on how the subclasses are constructed - the no-arg constructor is used to create the instances.
As such, the subclasses must have a default constructor, or must explicity declare a no-arg constructor.
Apparently Java 9 will be addressing some of these shortcomings (in particular, the ones regarding instantiation of subclasses).
An Example
Suppose you're interested in finding classes that implement an interface com.example.Example:
package com.example;
public interface Example {
public String getStr();
}
The class com.example.ExampleImpl implements that interface:
package com.example;
public class ExampleImpl implements Example {
public String getStr() {
return "ExampleImpl's string.";
}
}
You would declare the class ExampleImpl is an implementation of Example by creating a file META-INF/services/com.example.Example containing the text com.example.ExampleImpl.
Then, you could obtain an instance of each implementation of Example (including an instance of ExampleImpl) as follows:
ServiceLoader<Example> loader = ServiceLoader.load(Example.class)
for (Example example : loader) {
System.out.println(example.getStr());
}
// Prints "ExampleImpl's string.", plus whatever is returned
// by other declared implementations of com.example.Example.
It should be noted as well that this will of course only find all those subclasses that exist on your current classpath. Presumably this is OK for what you are currently looking at, and chances are you did consider this, but if you have at any point released a non-final class into the wild (for varying levels of "wild") then it is entirely feasible that someone else has written their own subclass that you will not know about.
Thus if you happened to be wanting to see all subclasses because you want to make a change and are going to see how it affects subclasses' behaviour - then bear in mind the subclasses that you can't see. Ideally all of your non-private methods, and the class itself should be well-documented; make changes according to this documentation without changing the semantics of methods/non-private fields and your changes should be backwards-compatible, for any subclass that followed your definition of the superclass at least.
The reason you see a difference between your implementation and Eclipse is because you scan each time, while Eclipse (and other tools) scan only once (during project load most of the times) and create an index. Next time you ask for the data it doesn't scan again, but look at the index.
I'm using a reflection lib, which scans your classpath for all subclasses: https://github.com/ronmamo/reflections
This is how it would be done:
Reflections reflections = new Reflections("my.project");
Set<Class<? extends SomeType>> subTypes = reflections.getSubTypesOf(SomeType.class);
You can use org.reflections library and then, create an object of Reflections class. Using this object, you can get list of all subclasses of given class.
https://www.javadoc.io/doc/org.reflections/reflections/0.9.10/org/reflections/Reflections.html
Reflections reflections = new Reflections("my.project.prefix");
System.out.println(reflections.getSubTypesOf(A.class)));
Add them to a static map inside (this.getClass().getName()) the parent classes constructor (or create a default one) but this will get updated in runtime. If lazy initialization is an option you can try this approach.
I just write a simple demo to use the org.reflections.Reflections to get subclasses of abstract class:
https://github.com/xmeng1/ReflectionsDemo
I needed to do this as a test case, to see if new classes had been added to the code. This is what I did
final static File rootFolder = new File(SuperClass.class.getProtectionDomain().getCodeSource().getLocation().getPath());
private static ArrayList<String> files = new ArrayList<String>();
listFilesForFolder(rootFolder);
#Test(timeout = 1000)
public void testNumberOfSubclasses(){
ArrayList<String> listSubclasses = new ArrayList<>(files);
listSubclasses.removeIf(s -> !s.contains("Superclass.class"));
for(String subclass : listSubclasses){
System.out.println(subclass);
}
assertTrue("You did not create a new subclass!", listSubclasses.size() >1);
}
public static void listFilesForFolder(final File folder) {
for (final File fileEntry : folder.listFiles()) {
if (fileEntry.isDirectory()) {
listFilesForFolder(fileEntry);
} else {
files.add(fileEntry.getName().toString());
}
}
}
If you intend to load all subclassess of given class which are in the same package, you can do so:
public static List<Class> loadAllSubClasses(Class pClazz) throws IOException, ClassNotFoundException {
ClassLoader classLoader = pClazz.getClassLoader();
assert classLoader != null;
String packageName = pClazz.getPackage().getName();
String dirPath = packageName.replace(".", "/");
Enumeration<URL> srcList = classLoader.getResources(dirPath);
List<Class> subClassList = new ArrayList<>();
while (srcList.hasMoreElements()) {
File dirFile = new File(srcList.nextElement().getFile());
File[] files = dirFile.listFiles();
if (files != null) {
for (File file : files) {
String subClassName = packageName + '.' + file.getName().substring(0, file.getName().length() - 6);
if (! subClassName.equals(pClazz.getName())) {
subClassList.add(Class.forName(subClassName));
}
}
}
}
return subClassList;
}
find all classes in classpath
public static List<String> getClasses() {
URLClassLoader urlClassLoader = (URLClassLoader) Thread.currentThread().getContextClassLoader();
List<String> classes = new ArrayList<>();
for (URL url : urlClassLoader.getURLs()) {
try {
if (url.toURI().getScheme().equals("file")) {
File file = new File(url.toURI());
if (file.exists()) {
try {
if (file.isDirectory()) {
for (File listFile : FileUtils.listFiles(file, new String[]{"class"}, true)) {
String classFile = listFile.getAbsolutePath().replace(file.getAbsolutePath(), "").replace(".class", "");
if (classFile.startsWith(File.separator)) {
classFile = classFile.substring(1);
}
classes.add(classFile.replace(File.separator, "."));
}
} else {
JarFile jarFile = new JarFile(file);
if (url.getFile().endsWith(".jar")) {
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
JarEntry jarEntry = entries.nextElement();
if (jarEntry.getName().endsWith(".class")) {
classes.add(jarEntry.getName().replace(".class", "").replace("/", "."));
}
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
} catch (URISyntaxException e) {
e.printStackTrace();
}
}
return classes;
}
enter link description hereService Manager in java will get all implementing classes for an interface in J