[ 
https://issues.apache.org/jira/browse/MRESOLVER-94?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=16945661#comment-16945661
 ] 

Bence Sipka commented on MRESOLVER-94:
--------------------------------------

The code doesn't have packages in a way, that the ClassLoader that loads the 
maven-resolves classes, doesn't call ClassLoader.definePackage for the loaded 
classes. This will result in getClass().getPackage() to return null. Therefore, 
 this.getClass().getPackage().getImplementationVersion() will result in a NPE.

According to the documentation of Class.getPackage(), the method can return 
null, however the implementations in DefaultSuperPomProvider and 
DefaultReportingConverter doesn't handle this scenario.

I don't use the default packages.

An example for reproducing this:
{code:java}
public static void main(String[] args) throws Exception {
        Path jarpath = Paths.get("maven-resolver-fat-jar.jar");
        try (JarFile jar = new JarFile(jarpath.toFile())) {
                ClassLoader cl = new ClassLoader(null) {
                        @Override
                        protected Class<?> findClass(String name) throws 
ClassNotFoundException {
                                ZipEntry entry = jar.getEntry(name.replace('.', 
'/') + ".class");
                                if (entry != null) {
                                        try (InputStream is = 
jar.getInputStream(entry)) {
                                                ByteArrayOutputStream baos = 
new ByteArrayOutputStream();
                                                byte[] buf = new byte[4096];
                                                for (int read; (read = 
is.read(buf)) > 0;) {
                                                        baos.write(buf, 0, 
read);
                                                }
                                                byte[] classbytes = 
baos.toByteArray();
                                                return defineClass(name, 
classbytes, 0, classbytes.length);
                                        } catch (IOException e) {
                                        }
                                }
                                return super.findClass(name);
                        }
                };
                Class<?> defaultreportinconverterclass = 
cl.loadClass("org.apache.maven.model.plugin.DefaultReportingConverter");
                System.out.println("App.main() " + 
defaultreportinconverterclass);
                System.out.println("App.main() " + 
defaultreportinconverterclass.getPackage());
                defaultreportinconverterclass.getConstructor().newInstance();
        }
}
{code}
Minimal example for loading an affected class via a custom classloader from a 
fat JAR. The maven-resolver-fat-jar.jar contains all classes required by the 
maven-resolver to operate.

The anonymous ClassLoader inner class loads the classes from the appropriate 
JAR entries.

The program will produce the following output:
{code:java}
App.main() class org.apache.maven.model.plugin.DefaultReportingConverter
App.main() null
Exception in thread "main" java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at 
sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
        at 
sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at example.saker.maven.support.App.main(App.java:191)
Caused by: java.lang.NullPointerException
        at 
org.apache.maven.model.plugin.DefaultReportingConverter.<init>(DefaultReportingConverter.java:56)
        ... 5 more
{code}
As you can see, a NullPointerException occurs when the 
DefaultReportingConverter class is being instantiated, as it will call 
this.getClass().getPackage().getImplementationVersion(). But due to the fact, 
that no definePackage is called by the ClassLoader, it throws a NPE.

The same kind of error occurs when using DefaultSuperPomProvider.

> NullPointerException if no Package is defined for the current class
> -------------------------------------------------------------------
>
>                 Key: MRESOLVER-94
>                 URL: https://issues.apache.org/jira/browse/MRESOLVER-94
>             Project: Maven Resolver
>          Issue Type: Bug
>          Components: resolver
>    Affects Versions: 1.4.1
>         Environment: Windows 10, Java 8, custom classloading
>            Reporter: Bence Sipka
>            Priority: Minor
>
> When the maven-resolver and related classes are used with a {{ClassLoader}} 
> that doesn't define a java.lang.Package object for the loaded classes, the 
> library throws a {{NullPointerException}}.
> Scenario: I'm using the maven-resolver classes to resolver artifacts from 
> various repositories. I package the app, and deploy it to a custom 
> environment where the {{ClassLoader}} for the app doesn't define a 
> {{Package}} for the loaded classes. In these cases, when the maven-resolver 
> library calls {{this.getClass().getPackage().getImplementationVersion()}} 
> then a {{NullPointerException}} will occurr.
>  The following classes are affected:
>  {{DefaultSuperPomProvider.getSuperModel():81}}
>  {{DefaultReportingConverter.<init>:56}}
> Code around the locations:
> {code:java}
> String modelId = "org.apache.maven:maven-model-builder:"
>     + this.getClass().getPackage().getImplementationVersion() + ":super-pom";
> InputSource inputSource = new InputSource();
> inputSource.setModelId( modelId );
> {code}
> This exception makes the library unportable to different environments.
> Workaround:
> Implement a custom variant of the above classes that circumvent these parts 
> of the code.
> Possible solution:
> Null checks, and hard coding the version number.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to