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 04:03  |
Eclipse User |
|
|
|
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 #1438753 is a reply to message #1438572] |
Mon, 06 October 2014 08:48   |
Eclipse User |
|
|
|
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...
|
|
| | | |
Re: How to load EClasses of a certain subtype [message #1439694 is a reply to message #1439579] |
Tue, 07 October 2014 08:07  |
Eclipse User |
|
|
|
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.
|
|
|
Goto Forum:
Current Time: Wed Jul 23 08:29:50 EDT 2025
Powered by FUDForum. Page generated in 1.06838 seconds
|