Skip to main content


Eclipse Community Forums
Forum Search:

Search      Help    Register    Login    Home
Home » Modeling » EMF » How to load EClasses of a certain subtype
How to load EClasses of a certain subtype [message #1438567] Mon, 06 October 2014 08:03 Go to next message
Johannes Dorn is currently offline Johannes DornFriend
Messages: 61
Registered: June 2013
Member
In our project we want to be able to load multiple EClasses that are contributed via the extension point org.eclipse.emf.ecore.generated_package.

We use the following code to do this:

protected static List<SnippetRepositoryConfiguration> fetchDefaultConfigurations() {
        List<SnippetRepositoryConfiguration> defaultConfigurations = Lists.newArrayList();

        Registry instance = EPackage.Registry.INSTANCE;
        for (String key : instance.keySet()) {
            try {
                EPackage ePackage = instance.getEPackage(key);
                if (ePackage == null) {
                    continue;
                }
                List<EClass> subtypes = searchSubtypes(ePackage,
                        SnipmatchModelPackage.Literals.DEFAULT_SNIPPET_REPOSITORY_CONFIGURATION_PROVIDER);
                for (EClass eClass : subtypes) {
                    DefaultSnippetRepositoryConfigurationProvider configurationProvider = cast(instance
                            .getEFactory(key).create(eClass));

                    defaultConfigurations.addAll(configurationProvider.getDefaultConfiguration());
                }
            } catch (Exception e) {
                LOG.error("Exception while loading default configurations", e); //$NON-NLS-1$
            }
        }

    private static List<EClass> searchSubtypes(EPackage ePackage, EClass eClass) {
        List<EClass> subTypes = Lists.newArrayList();
        for (EClassifier eClassifier : ePackage.getEClassifiers()) {
            if (eClassifier instanceof EClass) {
                EClass otherEClass = (EClass) eClassifier;
                if (eClass.isSuperTypeOf(otherEClass) && eClass != otherEClass) {
                    if (!(otherEClass.isAbstract() || otherEClass.isInterface())) {
                        subTypes.add((EClass) eClassifier);
                    }
                }
            }
        }
        return subTypes;
    }


This code is executed during our bundle startup. Unfortunately, on some Eclipse installations (i.e. Luna for Java EE developers), we get a ConcurrentModificationException while iterating over the Registry instance's keySet(). Apparently, the EPackageRegistryImpl (which extends HashMap) is modified while we are trying to iterate over its entries.

An additional problem with this code is, that
instance.getEPackage(key);
can return null or throw a SAXParseException when XCore is installed.

This leads me to believe that there must be a better way to to get to the relevant classes. Is there some kind of mechanism in EMF for this?
Re: How to load EClasses of a certain subtype [message #1438572 is a reply to message #1438567] Mon, 06 October 2014 08:09 Go to previous messageGo to next message
Felix Dorner is currently offline Felix DornerFriend
Messages: 295
Registered: March 2012
Senior Member
On 06/10/2014 10:03, Johannes Dorn wrote:

>
> This code is executed during our bundle startup. Unfortunately, on some
> Eclipse installations (i.e. Luna for Java EE developers), we get a
> ConcurrentModificationException while iterating over the Registry
> instance's keySet(). Apparently, the EPackageRegistryImpl (which extends
> HashMap) is modified while we are trying to iterate over its entries.

Yes, you must iterate over a copy of the keySet. Iterating over it loads
packages on the fly and thus modifies the map by replacing a placeholder
(an EPackage.Descriptor i think) with the real package.

> An additional problem with this code is, that instance.getEPackage(key);
> can return null or throw a SAXParseException when XCore is installed.

That seems a different issue..

> This leads me to believe that there must be a better way to to get to
> the relevant classes. Is there some kind of mechanism in EMF for this?

Not that I know of.
Re: How to load EClasses of a certain subtype [message #1438753 is a reply to message #1438572] Mon, 06 October 2014 12:48 Go to previous messageGo to next message
Ed Merks is currently offline Ed MerksFriend
Messages: 33137
Registered: July 2009
Senior Member
Comments below.

On 06/10/2014 10:09 AM, Felix Dorner wrote:
> On 06/10/2014 10:03, Johannes Dorn wrote:
>
>>
>> This code is executed during our bundle startup. Unfortunately, on some
>> Eclipse installations (i.e. Luna for Java EE developers), we get a
>> ConcurrentModificationException while iterating over the Registry
>> instance's keySet(). Apparently, the EPackageRegistryImpl (which extends
>> HashMap) is modified while we are trying to iterate over its entries.
>
> Yes, you must iterate over a copy of the keySet. Iterating over it
> loads packages on the fly and thus modifies the map by replacing a
> placeholder (an EPackage.Descriptor i think) with the real package.
It's actually bad manners to iterator over this in general, because it
will activate all bundles containing generated models, which could be a
large fraction of the total number of bundles...
>
>> An additional problem with this code is, that instance.getEPackage(key);
>> can return null or throw a SAXParseException when XCore is installed.
>
> That seems a different issue..
It's possible for it to return null if the package class can't be loaded
at this time. E.g., if another thread is trying to load the same
class, the JVM prevents deadlock and can return classes that aren't
fully initialized...
>
>> This leads me to believe that there must be a better way to to get to
>> the relevant classes. Is there some kind of mechanism in EMF for this?
>
> Not that I know of.
No, better you define your own extension point for what you're trying to
make extensible...


Ed Merks
Professional Support: https://www.macromodeling.com/
Re: How to load EClasses of a certain subtype [message #1438850 is a reply to message #1438753] Mon, 06 October 2014 15:44 Go to previous messageGo to next message
Felix Dorner is currently offline Felix DornerFriend
Messages: 295
Registered: March 2012
Senior Member
Hi,

On 06/10/2014 14:48, Ed Merks wrote:
> It's actually bad manners to iterator over this in general, because it
> will activate all bundles containing generated models, which could be a
> large fraction of the total number of bundles...

I totally get that.

> No, better you define your own extension point for what you're trying to
> make extensible...
>

I had thought about it a few times it would be cool if the
generated_package/dynamic_package extensions would define an additional
attribute/key so clients could have any number of "named package
registries", rather than just a single global registry ready to use. The
global registry is just the one that's used if no key is specified,
totally backwards compatible ;)
Re: How to load EClasses of a certain subtype [message #1439563 is a reply to message #1438850] Tue, 07 October 2014 09:30 Go to previous messageGo to next message
Johannes Dorn is currently offline Johannes DornFriend
Messages: 61
Registered: June 2013
Member
Thanks for your input. As suggested, i now use an extension point to get the correct key. https://git.eclipse.org/r/#/c/34483

Felix Dorner wrote on Mon, 06 October 2014 11:44
I had thought about it a few times it would be cool if the
generated_package/dynamic_package extensions would define an additional
attribute/key so clients could have any number of "named package
registries", rather than just a single global registry ready to use. The
global registry is just the one that's used if no key is specified,
totally backwards compatible Wink


That sounds like a useful addition to me.
Re: How to load EClasses of a certain subtype [message #1439579 is a reply to message #1438850] Tue, 07 October 2014 09:49 Go to previous messageGo to next message
Andreas Sewe is currently offline Andreas SeweFriend
Messages: 111
Registered: June 2013
Senior Member
While I went through the EPackageRegistryImpl code together with Johannes, I noticed that the class is (under the hood) a plain old HashMap. This makes me wonder about its thread-safety.

To me, at least the IRegistryChangeListener registered in RegistryReader.readRegistry seems like if could, by way of GeneratedPackageRegistryReader.readElement, put things into EPackage.Registry.INSTANCE at any time. My question is thus: When is using EPackage.Registry.INSTANCE.get(...) save? I may be wrong, but can't the underlying HashMap be, e.g., rehashed during the get due to a new IRegistryChangeEvent?

How to query the Package.Registry singleton in a thread-safe manner?
Re: How to load EClasses of a certain subtype [message #1439694 is a reply to message #1439579] Tue, 07 October 2014 12:07 Go to previous message
Ed Merks is currently offline Ed MerksFriend
Messages: 33137
Registered: July 2009
Senior Member
Andreas,

Comments below.

On 07/10/2014 11:49 AM, Andreas Sewe wrote:
> While I went through the EPackageRegistryImpl code together with
> Johannes, I noticed that the class is (under the hood) a plain old
> HashMap. This makes me wonder about its thread-safety.
That's always difficult to achieve...
>
> To me, at least the IRegistryChangeListener registered in
> RegistryReader.readRegistry seems like if could, by way of
> GeneratedPackageRegistryReader.readElement, put things into
> EPackage.Registry.INSTANCE at any time.
Yes, in theory, but only if bundles are dynamically added, otherwise the
bundle activator causes all the reading to happen once and for all when
the Ecore bundle is started.
> My question is thus: When is using EPackage.Registry.INSTANCE.get(...)
> save?
Yes, barring class loader circularity, which is thread safe, but can
result in null being returned.
> I may be wrong, but can't the underlying HashMap be, e.g., rehashed
> during the get due to a new IRegistryChangeEvent?
Yes, but then adding locks could just deadlock, which is also highly
undesirable.
>
> How to query the Package.Registry singleton in a thread-safe manner?
I'd not worry about it. What could possibly add dynamic bundle to OSGi
while you're iterating? I've never heard of anyone ever having such a
problem.


Ed Merks
Professional Support: https://www.macromodeling.com/
Previous Topic:[Xcore] Basic Question
Next Topic:[CDO] Why we abandoned CDO
Goto Forum:
  


Current Time: Fri Apr 19 14:55:51 GMT 2024

Powered by FUDForum. Page generated in 0.02423 seconds
.:: Contact :: Home ::.

Powered by: FUDforum 3.0.2.
Copyright ©2001-2010 FUDforum Bulletin Board Software

Back to the top