DevBoost / JaMoPP

JaMoPP can parse Java source and byte code into EMF-based models and vice versa. It preserves source formatting and can be used for code analysis and refactoring.
17 stars 18 forks source link

NullPointerException in JavaClasspath.registerClassifier() #15

Closed BenjaminKlatt closed 10 years ago

BenjaminKlatt commented 10 years ago

From time to time, I receive a NullpointerException during JavaClasspath initialization (See stack trace below).

I use the following code to initialize a ResourceSet and an assigned JavaClasspath:

ResourceSet targetResourceSet = setUpResourceSet();
JavaClasspath cp = JavaClasspath.get(targetResourceSet);

with setUpRessourceSet() implemented as

    /**
     * Setup the JaMoPP resource set and prepare the parsing options for the java resource type.
     *
     * @return The initialized resource set.
     */
    private ResourceSet setUpResourceSet() {
        ResourceSet rs = new ResourceSetImpl();
        Map<Object, Object> options = rs.getLoadOptions();
        options.put(IJavaOptions.DISABLE_LAYOUT_INFORMATION_RECORDING, Boolean.FALSE);
        options.put(IJavaOptions.DISABLE_LOCATION_MAP, Boolean.FALSE);
        EPackage.Registry.INSTANCE.put("http://www.emftext.org/java", JavaPackage.eINSTANCE);

        Map<String, Object> factoryMap = rs.getResourceFactoryRegistry().getExtensionToFactoryMap();
        factoryMap.put("java", new JavaSourceOrClassFileResourceFactoryImpl());
        factoryMap.put(Resource.Factory.Registry.DEFAULT_EXTENSION, new XMIResourceFactoryImpl());
        return rs;
    }

The code is part of an Eclipse plugin. I run it within an Eclipse instance. Unfortunately, it does not occure everytime and restarting the Eclipse test instance solves the issue in most cases.

Is there anything wrong in how the RessourceSet and the classpath are initialized?

Thanks Benjamin

Stacktrace:

Caused by: java.lang.NullPointerException
    at org.eclipse.emf.common.util.BasicEMap.grow(BasicEMap.java:1487)
    at org.eclipse.emf.common.util.BasicEMap.doPut(BasicEMap.java:603)
    at org.eclipse.emf.common.util.BasicEMap$1.didAdd(BasicEMap.java:150)
    at org.eclipse.emf.common.util.BasicEMap$1.didAdd(BasicEMap.java:1)
    at org.eclipse.emf.common.util.BasicEList.addUnique(BasicEList.java:419)
    at org.eclipse.emf.common.util.AbstractEList.add(AbstractEList.java:301)
    at org.eclipse.emf.common.util.BasicEMap.put(BasicEMap.java:585)
    at org.eclipse.emf.common.util.BasicEMap$DelegatingMap.put(BasicEMap.java:793)
    at org.emftext.language.java.JavaClasspath.registerClassifier(JavaClasspath.java:515)
    at org.emftext.language.java.JavaClasspath.registerClassifierJar(JavaClasspath.java:414)
    at org.emftext.language.java.JavaClasspath.registerClassifierJar(JavaClasspath.java:378)
    at org.emftext.language.java.JavaClasspath.registerStdLib(JavaClasspath.java:366)
    at org.emftext.language.java.JavaClasspath.get(JavaClasspath.java:194)
    at org.emftext.language.java.JavaClasspath.get(JavaClasspath.java:272)
    at org.splevo.jamopp.extraction.JaMoPPSoftwareModelExtractor.extractSoftwareModel(JaMoPPSoftwareModelExtractor.java:51)
BenjaminKlatt commented 10 years ago

The issue resulted from a race condition in accessing a shared JavaClasspath. It is necessary to configure the ResourceSet to use a local JavaClasspath

ResourceSet rs = new ResourceSetImpl();

// further resource set enhancement for the extraction specific needs
Map<Object, Object> options = rs.getLoadOptions();
options.put(JavaClasspath.OPTION_USE_LOCAL_CLASSPATH, Boolean.TRUE);
...