You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by sj...@apache.org on 2022/01/02 16:27:52 UTC

[maven-invoker] 01/01: [MSHARED-649] Allow Pom file outside base directory

This is an automated email from the ASF dual-hosted git repository.

sjaranowski pushed a commit to branch MSHARED-649
in repository https://gitbox.apache.org/repos/asf/maven-invoker.git

commit 9ffc8fea34bb45c1e03e2dff4e7ac042440e3abe
Author: Slawomir Jaranowski <s....@gmail.com>
AuthorDate: Sun Jan 2 17:27:26 2022 +0100

    [MSHARED-649] Allow Pom file outside base directory
---
 .../maven/shared/invoker/DefaultInvoker.java       |  16 +--
 .../shared/invoker/MavenCommandLineBuilder.java    | 127 ++++++++++-----------
 .../maven/shared/invoker/DefaultInvokerTest.java   |  22 ++++
 .../invoker/MavenCommandLineBuilderTest.java       |  93 +++++++--------
 .../test-pom-outside-project/project/pom.xml       |  29 +++++
 .../test-pom-outside-project/temp/pom.xml          |  26 +++++
 6 files changed, 188 insertions(+), 125 deletions(-)

diff --git a/src/main/java/org/apache/maven/shared/invoker/DefaultInvoker.java b/src/main/java/org/apache/maven/shared/invoker/DefaultInvoker.java
index 6fa6ca8..b545466 100644
--- a/src/main/java/org/apache/maven/shared/invoker/DefaultInvoker.java
+++ b/src/main/java/org/apache/maven/shared/invoker/DefaultInvoker.java
@@ -68,37 +68,33 @@ public class DefaultInvoker
     {
         MavenCommandLineBuilder cliBuilder = new MavenCommandLineBuilder();
 
-        InvokerLogger logger = getLogger();
         if ( logger != null )
         {
-            cliBuilder.setLogger( getLogger() );
+            cliBuilder.setLogger( logger );
         }
 
-        File localRepo = getLocalRepositoryDirectory();
-        if ( localRepo != null )
+        if ( localRepositoryDirectory != null )
         {
-            cliBuilder.setLocalRepositoryDirectory( getLocalRepositoryDirectory() );
+            cliBuilder.setLocalRepositoryDirectory( localRepositoryDirectory );
         }
 
-        File mavenHome = getMavenHome();
         if ( mavenHome != null )
         {
-            cliBuilder.setMavenHome( getMavenHome() );
+            cliBuilder.setMavenHome( mavenHome );
         }
 
-        File mavenExecutable = getMavenExecutable();
         if ( mavenExecutable != null )
         {
             cliBuilder.setMavenExecutable( mavenExecutable );
         }
 
-        File workingDirectory = getWorkingDirectory();
         if ( workingDirectory != null )
         {
-            cliBuilder.setWorkingDirectory( getWorkingDirectory() );
+            cliBuilder.setBaseDirectory( workingDirectory );
         }
 
         Commandline cli;
+
         try
         {
             cli = cliBuilder.build( request );
diff --git a/src/main/java/org/apache/maven/shared/invoker/MavenCommandLineBuilder.java b/src/main/java/org/apache/maven/shared/invoker/MavenCommandLineBuilder.java
index a6e33fe..7376df8 100644
--- a/src/main/java/org/apache/maven/shared/invoker/MavenCommandLineBuilder.java
+++ b/src/main/java/org/apache/maven/shared/invoker/MavenCommandLineBuilder.java
@@ -43,7 +43,7 @@ public class MavenCommandLineBuilder
 
     private InvokerLogger logger = DEFAULT_LOGGER;
 
-    private File workingDirectory;
+    private File baseDirectory;
 
     private File localRepositoryDirectory;
 
@@ -89,10 +89,15 @@ public class MavenCommandLineBuilder
         // includes/excludes, etc.
         setReactorBehavior( request, cli );
 
-        // working directory and local repository location
-        setEnvironmentPaths( request, cli );
+        // discover value for working directory
+        setupBaseDirectory( request );
 
-        // pom-file and basedir handling
+        cli.setWorkingDirectory( baseDirectory );
+
+        // local repository location
+        setLocalRepository( request, cli );
+
+        // pom-file handling
         setPomLocation( request, cli );
 
         setSettingsLocation( request, cli );
@@ -296,52 +301,33 @@ public class MavenCommandLineBuilder
      */
     protected void setPomLocation( InvocationRequest request, Commandline cli )
     {
-        boolean pomSpecified = false;
-
         File pom = request.getPomFile();
         String pomFilename = request.getPomFileName();
-        File baseDirectory = request.getBaseDirectory();
 
-        if ( pom != null )
+        if ( pom == null )
         {
-            pomSpecified = true;
-        }
-        else if ( baseDirectory != null )
-        {
-            if ( baseDirectory.isDirectory() )
+            if ( pomFilename != null )
             {
-                if ( pomFilename != null )
-                {
-                    pom = new File( baseDirectory, pomFilename );
-
-                    pomSpecified = true;
-                }
-                else
-                {
-                    pom = new File( baseDirectory, "pom.xml" );
-                }
+                pom = new File( baseDirectory, pomFilename );
             }
             else
             {
-                logger.warn( "Base directory is a file. Using base directory as POM location." );
-
-                pom = baseDirectory;
-
-                pomSpecified = true;
+                pom = new File( baseDirectory, "pom.xml" );
             }
         }
 
-        if ( pomSpecified )
+        try
         {
-            try
-            {
-                pom = pom.getCanonicalFile();
-            }
-            catch ( IOException e )
-            {
-                logger.debug( "Failed to canonicalize the POM path: " + pom + ". Using as-is.", e );
-            }
+            pom = pom.getCanonicalFile();
+        }
+        catch ( IOException e )
+        {
+            logger.debug( "Failed to canonicalize the POM path: " + pom + ". Using as-is.", e );
+        }
 
+        if ( pom.getParentFile().equals( baseDirectory ) )
+        {
+            // pom in project workspace
             if ( !"pom.xml".equals( pom.getName() ) )
             {
                 logger.debug( "Specified POM file is not named 'pom.xml'. "
@@ -351,55 +337,64 @@ public class MavenCommandLineBuilder
                 cli.createArg().setValue( pom.getName() );
             }
         }
+        else
+        {
+            cli.createArg().setValue( "-f" );
+            cli.createArg().setValue( pom.getPath() );
+        }
     }
 
-    /**
-     * <p>setEnvironmentPaths.</p>
-     *
-     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
-     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
-     */
-    protected void setEnvironmentPaths( InvocationRequest request, Commandline cli )
+    void setupBaseDirectory( InvocationRequest request )
     {
-        File workingDirectory = request.getBaseDirectory();
-
-        if ( workingDirectory == null )
+        File baseDirectoryFromRequest = null;
+        if ( request.getBaseDirectory() != null )
+        {
+            baseDirectoryFromRequest = request.getBaseDirectory();
+        }
+        else
         {
             File pomFile = request.getPomFile();
             if ( pomFile != null )
             {
-                workingDirectory = pomFile.getParentFile();
+                baseDirectoryFromRequest = pomFile.getParentFile();
             }
         }
 
-        if ( workingDirectory == null )
+        if ( baseDirectoryFromRequest != null )
         {
-            workingDirectory = this.workingDirectory;
+            baseDirectory = baseDirectoryFromRequest;
         }
 
-        if ( workingDirectory == null )
+        if ( baseDirectory == null )
         {
-            workingDirectory = new File( System.getProperty( "user.dir" ) );
+            baseDirectory = new File( System.getProperty( "user.dir" ) );
         }
-        else if ( workingDirectory.isFile() )
+        else if ( baseDirectory.isFile() )
         {
-            logger.warn( "Specified base directory (" + workingDirectory + ") is a file."
+            logger.warn( "Specified base directory (" + baseDirectory + ") is a file."
                 + " Using its parent directory..." );
 
-            workingDirectory = workingDirectory.getParentFile();
+            baseDirectory = baseDirectory.getParentFile();
         }
 
         try
         {
-            cli.setWorkingDirectory( workingDirectory.getCanonicalPath() );
+            baseDirectory = baseDirectory.getCanonicalFile();
         }
         catch ( IOException e )
         {
-            logger.debug( "Failed to canonicalize base directory: " + workingDirectory + ". Using as-is.", e );
-
-            cli.setWorkingDirectory( workingDirectory.getAbsolutePath() );
+            logger.debug( "Failed to canonicalize base directory: " + baseDirectory + ". Using as-is.", e );
         }
+    }
 
+    /**
+     * <p>setLocalRepository.</p>
+     *
+     * @param request a {@link org.apache.maven.shared.invoker.InvocationRequest} object.
+     * @param cli a {@link org.apache.maven.shared.utils.cli.Commandline} object.
+     */
+    protected void setLocalRepository( InvocationRequest request, Commandline cli )
+    {
         File localRepositoryDirectory = request.getLocalRepositoryDirectory( this.localRepositoryDirectory );
 
         if ( localRepositoryDirectory != null )
@@ -708,23 +703,23 @@ public class MavenCommandLineBuilder
     }
 
     /**
-     * <p>Getter for the field <code>workingDirectory</code>.</p>
+     * <p>Getter for the field <code>baseDirectory</code>.</p>
      *
      * @return a {@link java.io.File} object.
      */
-    public File getWorkingDirectory()
+    public File getBaseDirectory()
     {
-        return workingDirectory;
+        return baseDirectory;
     }
 
     /**
-     * <p>Setter for the field <code>workingDirectory</code>.</p>
+     * <p>Setter for the field <code>baseDirectory</code>.</p>
      *
-     * @param workingDirectory a {@link java.io.File} object.
+     * @param baseDirectory a {@link java.io.File} object.
      */
-    public void setWorkingDirectory( File workingDirectory )
+    public void setBaseDirectory( File baseDirectory )
     {
-        this.workingDirectory = workingDirectory;
+        this.baseDirectory = baseDirectory;
     }
 
     /**
diff --git a/src/test/java/org/apache/maven/shared/invoker/DefaultInvokerTest.java b/src/test/java/org/apache/maven/shared/invoker/DefaultInvokerTest.java
index 70a4d6d..f6ce7c9 100644
--- a/src/test/java/org/apache/maven/shared/invoker/DefaultInvokerTest.java
+++ b/src/test/java/org/apache/maven/shared/invoker/DefaultInvokerTest.java
@@ -217,6 +217,28 @@ public class DefaultInvokerTest
         assertEquals( 0, result.getExitCode() );
     }
 
+    @Test
+    public void testPomOutsideProject() throws Exception
+    {
+        logTestStart();
+
+        File testDir = getBasedirForBuild();
+
+        File basedir = new File( testDir, "project" );
+        File pom = new File(testDir, "temp/pom.xml" );
+
+        Invoker invoker = newInvoker();
+
+        InvocationRequest request = new DefaultInvocationRequest();
+        request.setBaseDirectory( basedir );
+        request.setPomFile( pom );
+        request.setGoals( Collections.singletonList( "validate" ) );
+
+        InvocationResult result = invoker.execute( request );
+
+        assertEquals( 0, result.getExitCode() );
+    }
+
     private Invoker newInvoker()
     {
         Invoker invoker = new DefaultInvoker();
diff --git a/src/test/java/org/apache/maven/shared/invoker/MavenCommandLineBuilderTest.java b/src/test/java/org/apache/maven/shared/invoker/MavenCommandLineBuilderTest.java
index f019255..eee14a9 100644
--- a/src/test/java/org/apache/maven/shared/invoker/MavenCommandLineBuilderTest.java
+++ b/src/test/java/org/apache/maven/shared/invoker/MavenCommandLineBuilderTest.java
@@ -83,7 +83,7 @@ public class MavenCommandLineBuilderTest
 
         try
         {
-            mclb.setEnvironmentPaths( newRequest(), cli );
+            mclb.setLocalRepository( newRequest(), cli );
             fail( "Should not set local repo location to point to a file." );
         }
         catch ( IllegalArgumentException expected )
@@ -94,9 +94,10 @@ public class MavenCommandLineBuilderTest
     @Test
     public void testShouldFailToSetLocalRepoLocationFromRequestWhenItIsAFile()
     {
+        InvocationRequest request = newRequest().setLocalRepositoryDirectory( lrd );
         try
         {
-            mclb.setEnvironmentPaths( newRequest().setLocalRepositoryDirectory( lrd ), cli );
+            mclb.setLocalRepository( request, cli );
             fail( "Should not set local repo location to point to a file." );
         }
         catch ( IllegalArgumentException expected )
@@ -109,7 +110,7 @@ public class MavenCommandLineBuilderTest
     {
         File lrd = temporaryFolder.newFolder( "workdir" ).getCanonicalFile();
         mclb.setLocalRepositoryDirectory( lrd );
-        mclb.setEnvironmentPaths( newRequest(), cli );
+        mclb.setLocalRepository( newRequest(), cli );
 
         assertArgumentsPresentInOrder( cli, "-D", "maven.repo.local=" + lrd.getPath() );
     }
@@ -119,7 +120,7 @@ public class MavenCommandLineBuilderTest
         throws Exception
     {
         File lrd = temporaryFolder.newFolder( "workdir" ).getCanonicalFile();
-        mclb.setEnvironmentPaths( newRequest().setLocalRepositoryDirectory( lrd ), cli );
+        mclb.setLocalRepository( newRequest().setLocalRepositoryDirectory( lrd ), cli );
 
         assertArgumentsPresentInOrder( cli, "-D", "maven.repo.local=" + lrd.getPath() );
     }
@@ -132,7 +133,7 @@ public class MavenCommandLineBuilderTest
         File glrd = temporaryFolder.newFolder( "global-workdir" ).getCanonicalFile();
 
         mclb.setLocalRepositoryDirectory( glrd );
-        mclb.setEnvironmentPaths( newRequest().setLocalRepositoryDirectory( lrd ), cli );
+        mclb.setLocalRepository( newRequest().setLocalRepositoryDirectory( lrd ), cli );
 
         assertArgumentsPresentInOrder( cli, "-D", "maven.repo.local=" + lrd.getPath() );
     }
@@ -142,10 +143,11 @@ public class MavenCommandLineBuilderTest
         throws Exception
     {
         File wd = temporaryFolder.newFolder( "workdir" );
-        mclb.setWorkingDirectory( wd );
-        mclb.setEnvironmentPaths( newRequest(), cli );
 
-        assertEquals( cli.getWorkingDirectory(), wd.getCanonicalFile() );
+        mclb.setBaseDirectory( wd );
+        Commandline commandline = mclb.build( newRequest() );
+
+        assertEquals( commandline.getWorkingDirectory(), wd.getCanonicalFile() );
     }
 
     @Test
@@ -157,10 +159,9 @@ public class MavenCommandLineBuilderTest
         InvocationRequest req = newRequest();
         req.setBaseDirectory( wd );
 
+        mclb.setupBaseDirectory( req );
 
-        mclb.setEnvironmentPaths( req, cli );
-
-        assertEquals( cli.getWorkingDirectory(), wd.getCanonicalFile() );
+        assertEquals( mclb.getBaseDirectory(), wd.getCanonicalFile() );
     }
 
     @Test
@@ -170,15 +171,14 @@ public class MavenCommandLineBuilderTest
         File wd = temporaryFolder.newFolder( "workdir" );
         File gwd = temporaryFolder.newFolder( "global-workdir" );
 
-        mclb.setWorkingDirectory( gwd );
+        mclb.setBaseDirectory( gwd );
 
         InvocationRequest req = newRequest();
         req.setBaseDirectory( wd );
 
+        mclb.setupBaseDirectory( req);
 
-        mclb.setEnvironmentPaths( req, cli );
-
-        assertEquals( cli.getWorkingDirectory(), wd.getCanonicalFile() );
+        assertEquals( mclb.getBaseDirectory(), wd.getCanonicalFile() );
     }
 
     @Test
@@ -496,62 +496,61 @@ public class MavenCommandLineBuilderTest
 
         InvocationRequest req = newRequest().setPomFile( pomFile );
 
-        mclb.setEnvironmentPaths( req, cli );
-        mclb.setPomLocation( req, cli );
+        Commandline commandline = mclb.build( req );
 
-        assertEquals( projectDir.getCanonicalFile(), cli.getWorkingDirectory() );
+        assertEquals( projectDir.getCanonicalFile(), commandline.getWorkingDirectory() );
 
         Set<String> args = new HashSet<>();
         args.add( "-f" );
         args.add( "non-standard-pom.xml" );
 
-        assertArgumentsPresent( cli, args );
+        assertArgumentsPresent( commandline, args );
     }
 
     @Test
-    public void testShouldSpecifyFileOptionUsingNonStandardPomInBasedir()
+    public void testShouldNotSpecifyFileOptionUsingStandardPomFileLocation()
         throws Exception
     {
-        File projectDir = temporaryFolder.newFolder( "invoker-tests", "file-option-nonstd-basedir" );
+        File projectDir = temporaryFolder.newFolder( "invoker-tests", "std-pom-file-location" );
 
-        File basedir = createDummyFile( projectDir, "non-standard-pom.xml" ).getCanonicalFile();
+        File pomFile = createDummyFile( projectDir, "pom.xml" ).getCanonicalFile();
 
 
-        InvocationRequest req = newRequest().setBaseDirectory( basedir );
+        InvocationRequest req = newRequest().setPomFile( pomFile );
 
-        mclb.setEnvironmentPaths( req, cli );
-        mclb.setPomLocation( req, cli );
+        Commandline commandline = mclb.build( req );
 
-        assertEquals( projectDir.getCanonicalFile(), cli.getWorkingDirectory() );
+        assertEquals( projectDir.getCanonicalFile(), commandline.getWorkingDirectory() );
 
         Set<String> args = new HashSet<>();
         args.add( "-f" );
-        args.add( "non-standard-pom.xml" );
+        args.add( "pom.xml" );
 
-        assertArgumentsPresent( cli, args );
+        assertArgumentsNotPresent( commandline, args );
     }
 
     @Test
-    public void testShouldNotSpecifyFileOptionUsingStandardPomFileLocation()
+    public void testShouldSetPomForOutsideWorkspace()
         throws Exception
     {
         File projectDir = temporaryFolder.newFolder( "invoker-tests", "std-pom-file-location" );
 
-        File pomFile = createDummyFile( projectDir, "pom.xml" ).getCanonicalFile();
+        File outsidePom = temporaryFolder.newFile( "pom.xml" );
 
 
-        InvocationRequest req = newRequest().setPomFile( pomFile );
+        InvocationRequest req = newRequest()
+            .setBaseDirectory( projectDir )
+            .setPomFile( outsidePom );
 
-        mclb.setEnvironmentPaths( req, cli );
-        mclb.setPomLocation( req, cli );
+        Commandline commandline = mclb.build( req );
 
-        assertEquals( projectDir.getCanonicalFile(), cli.getWorkingDirectory() );
+        assertEquals( projectDir.getCanonicalFile(), commandline.getWorkingDirectory() );
 
         Set<String> args = new HashSet<>();
         args.add( "-f" );
-        args.add( "pom.xml" );
+        args.add( outsidePom.getCanonicalPath() );
 
-        assertArgumentsNotPresent( cli, args );
+        assertArgumentsPresent( commandline, args );
     }
 
     @Test
@@ -565,16 +564,15 @@ public class MavenCommandLineBuilderTest
 
         InvocationRequest req = newRequest().setBaseDirectory( basedir );
 
-        mclb.setEnvironmentPaths( req, cli );
-        mclb.setPomLocation( req, cli );
+        Commandline commandline = mclb.build( req );
 
-        assertEquals( projectDir.getCanonicalFile(), cli.getWorkingDirectory() );
+        assertEquals( projectDir.getCanonicalFile(), commandline.getWorkingDirectory() );
 
         Set<String> args = new HashSet<>();
         args.add( "-f" );
         args.add( "pom.xml" );
 
-        assertArgumentsNotPresent( cli, args );
+        assertArgumentsNotPresent( commandline, args );
     }
 
     @Test
@@ -586,16 +584,15 @@ public class MavenCommandLineBuilderTest
 
         InvocationRequest req = newRequest().setBaseDirectory( projectDir );
 
-        mclb.setEnvironmentPaths( req, cli );
-        mclb.setPomLocation( req, cli );
+        Commandline commandline = mclb.build( req );
 
-        assertEquals( projectDir.getCanonicalFile(), cli.getWorkingDirectory() );
+        assertEquals( projectDir.getCanonicalFile(), commandline.getWorkingDirectory() );
 
         Set<String> args = new HashSet<>();
         args.add( "-f" );
         args.add( "pom.xml" );
 
-        assertArgumentsNotPresent( cli, args );
+        assertArgumentsNotPresent( commandline, args );
     }
 
     @Test
@@ -604,19 +601,17 @@ public class MavenCommandLineBuilderTest
     {
         File projectDir = temporaryFolder.newFolder( "invoker-tests", "std-basedir-with-pom-filename" );
 
-
         InvocationRequest req = newRequest().setBaseDirectory( projectDir ).setPomFileName( "non-standard-pom.xml" );
 
-        mclb.setEnvironmentPaths( req, cli );
-        mclb.setPomLocation( req, cli );
+        Commandline commandline = mclb.build( req );
 
-        assertEquals( projectDir.getCanonicalFile(), cli.getWorkingDirectory() );
+        assertEquals( projectDir.getCanonicalFile(), commandline.getWorkingDirectory() );
 
         Set<String> args = new HashSet<>();
         args.add( "-f" );
         args.add( "non-standard-pom.xml" );
 
-        assertArgumentsPresent( cli, args );
+        assertArgumentsPresent( commandline, args );
     }
 
     @Test
diff --git a/src/test/resources/test-pom-outside-project/project/pom.xml b/src/test/resources/test-pom-outside-project/project/pom.xml
new file mode 100644
index 0000000..a0791f3
--- /dev/null
+++ b/src/test/resources/test-pom-outside-project/project/pom.xml
@@ -0,0 +1,29 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.maven.shared.invoker</groupId>
+  <artifactId>test-pom-outside-project</artifactId>
+  <packaging>jar</packaging>
+  <version>1</version>
+
+  <invalid-tag/>
+
+</project>
diff --git a/src/test/resources/test-pom-outside-project/temp/pom.xml b/src/test/resources/test-pom-outside-project/temp/pom.xml
new file mode 100644
index 0000000..635cc4b
--- /dev/null
+++ b/src/test/resources/test-pom-outside-project/temp/pom.xml
@@ -0,0 +1,26 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements.  See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership.  The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License.  You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied.  See the License for the
+specific language governing permissions and limitations
+under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <groupId>org.apache.maven.shared.invoker</groupId>
+  <artifactId>test-pom-outside-project</artifactId>
+  <packaging>jar</packaging>
+  <version>1</version>
+</project>