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

kezhenxu94 pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/skywalking-eyes.git


The following commit(s) were added to refs/heads/main by this push:
     new 03dbef4  Add support for resolving jars' licenses (#53)
03dbef4 is described below

commit 03dbef403159bb04fa3247b5f125458d830d69ef
Author: MoGuGuai-hzr <[email protected]>
AuthorDate: Thu Aug 12 13:22:55 2021 +0800

    Add support for resolving jars' licenses (#53)
---
 pkg/deps/jar.go                         | 136 ++++++++++++++++++++++++++++++++
 pkg/deps/{maven_test.go => jar_test.go} | 103 +++++++++++++++---------
 pkg/deps/maven.go                       | 131 +-----------------------------
 pkg/deps/maven_test.go                  |  37 +++++++--
 4 files changed, 234 insertions(+), 173 deletions(-)

diff --git a/pkg/deps/jar.go b/pkg/deps/jar.go
new file mode 100644
index 0000000..d7b851d
--- /dev/null
+++ b/pkg/deps/jar.go
@@ -0,0 +1,136 @@
+//
+// Licensed to 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. Apache Software Foundation (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.
+package deps
+
+import (
+       "archive/zip"
+       "bufio"
+       "bytes"
+       "fmt"
+       "io"
+       "path/filepath"
+       "regexp"
+
+       "github.com/apache/skywalking-eyes/license-eye/internal/logger"
+       "github.com/apache/skywalking-eyes/license-eye/pkg/license"
+)
+
+type JarResolver struct{}
+
+func (resolver *JarResolver) CanResolve(jarFile string) bool {
+       return filepath.Ext(jarFile) == ".jar"
+}
+
+func (resolver *JarResolver) Resolve(jarFile string, report *Report) error {
+       state := NotFound
+       if err := resolver.ResolveJar(&state, jarFile, report); err != nil {
+               dep := filepath.Base(jarFile)
+               logger.Log.Warnf("Failed to resolve the license of <%s>: %v\n", 
dep, state.String())
+               report.Skip(&Result{
+                       Dependency:    dep,
+                       LicenseSpdxID: Unknown,
+               })
+       }
+
+       return nil
+}
+
+func (resolver *JarResolver) ResolveJar(state *State, jarFile string, report 
*Report) error {
+       dep := filepath.Base(jarFile)
+
+       compressedJar, err := zip.OpenReader(jarFile)
+       if err != nil {
+               return err
+       }
+       defer compressedJar.Close()
+
+       var manifestFile *zip.File
+
+       // traverse all files in jar
+       for _, compressedFile := range compressedJar.File {
+               archiveFile := compressedFile.Name
+               switch {
+               case reHaveManifestFile.MatchString(archiveFile):
+                       manifestFile = compressedFile
+
+               case possibleLicenseFileName.MatchString(archiveFile):
+                       *state |= FoundLicenseInJarLicenseFile
+                       buf, err := resolver.ReadFileFromZip(compressedFile)
+                       if err != nil {
+                               return err
+                       }
+
+                       return resolver.IdentifyLicense(jarFile, dep, 
buf.String(), report)
+               }
+       }
+
+       if manifestFile != nil {
+               buf, err := resolver.ReadFileFromZip(manifestFile)
+               if err != nil {
+                       return err
+               }
+               norm := regexp.MustCompile(`(?im)[\r\n]+ +`)
+               content := norm.ReplaceAllString(buf.String(), "")
+
+               r := reSearchLicenseInManifestFile.FindStringSubmatch(content)
+               if len(r) != 0 {
+                       report.Resolve(&Result{
+                               Dependency:      dep,
+                               LicenseFilePath: jarFile,
+                               LicenseContent:  r[1],
+                               LicenseSpdxID:   r[1],
+                       })
+                       return nil
+               }
+       }
+
+       return fmt.Errorf("cannot find license content")
+}
+
+func (resolver *JarResolver) ReadFileFromZip(archiveFile *zip.File) 
(*bytes.Buffer, error) {
+       file, err := archiveFile.Open()
+       if err != nil {
+               return nil, err
+       }
+
+       buf := bytes.NewBuffer(nil)
+       w := bufio.NewWriter(buf)
+       _, err = io.CopyN(w, file, int64(archiveFile.UncompressedSize64))
+       if err != nil {
+               return nil, err
+       }
+
+       w.Flush()
+       file.Close()
+       return buf, nil
+}
+
+func (resolver *JarResolver) IdentifyLicense(path, dep, content string, report 
*Report) error {
+       identifier, err := license.Identify(path, content)
+       if err != nil {
+               return err
+       }
+
+       report.Resolve(&Result{
+               Dependency:      dep,
+               LicenseFilePath: path,
+               LicenseContent:  content,
+               LicenseSpdxID:   identifier,
+       })
+       return nil
+}
diff --git a/pkg/deps/maven_test.go b/pkg/deps/jar_test.go
similarity index 51%
copy from pkg/deps/maven_test.go
copy to pkg/deps/jar_test.go
index d63d519..4d55f89 100644
--- a/pkg/deps/maven_test.go
+++ b/pkg/deps/jar_test.go
@@ -18,59 +18,80 @@
 package deps_test
 
 import (
-       "bufio"
+       "fmt"
+       "io/ioutil"
        "os"
+       "os/exec"
        "path/filepath"
        "testing"
 
+       "github.com/apache/skywalking-eyes/license-eye/internal/logger"
        "github.com/apache/skywalking-eyes/license-eye/pkg/deps"
 )
 
-func TestCanResolve(t *testing.T) {
-       resolver := new(deps.MavenPomResolver)
+func TestCanResolveJarFile(t *testing.T) {
+       resolver := new(deps.JarResolver)
        for _, test := range []struct {
                fileName string
                exp      bool
        }{
-               {"pom.xml", true},
-               {"POM.XML", false},
-               {"log4j-1.2.12.pom", false},
-               {".pom", false},
+               {"1.jar", true},
+               {"/tmp/1.jar", true},
+               {"1.jar2", false},
+               {"protobuf-java-3.13.0.jar", true},
+               {"slf4j-api-1.7.25.jar", true},
        } {
                b := resolver.CanResolve(test.fileName)
                if b != test.exp {
-                       t.Errorf("MavenPomResolver.CanResolve(\"%v\") = %v, 
want %v", test.fileName, b, test.exp)
+                       t.Errorf("JarResolver.CanResolve(\"%v\") = %v, want 
%v", test.fileName, b, test.exp)
                }
        }
 }
 
-func dump(fileName, content string) error {
-       file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 
0666)
-       if err != nil {
-               return err
+func copyJars(t *testing.T, pomFile, content string) ([]string, error) {
+       dir := filepath.Dir(pomFile)
+
+       if err := os.Chdir(dir); err != nil {
+               return nil, err
+       }
+
+       if err := dumpPomFile(pomFile, content); err != nil {
+               return nil, err
        }
-       defer file.Close()
 
-       write := bufio.NewWriter(file)
-       _, err = write.WriteString(content)
+       if _, err := exec.Command("mvn", "dependency:copy-dependencies", 
"-DoutputDirectory=./lib", "-DincludeScope=runtime").Output(); err != nil {
+               return nil, err
+       }
+
+       jars := []string{}
+       files, err := ioutil.ReadDir(filepath.Join(dir, "lib"))
        if err != nil {
-               return err
+               return nil, err
+       }
+
+       for _, file := range files {
+               if !file.IsDir() {
+                       jars = append(jars, filepath.Join(dir, "lib", 
file.Name()))
+               }
        }
 
-       write.Flush()
-       return nil
+       return jars, nil
 }
 
-func TestResolve(t *testing.T) {
-       resolver := new(deps.MavenPomResolver)
+func TestResolveJar(t *testing.T) {
+       if _, err := exec.Command("mvn", "--version").Output(); err != nil {
+               logger.Log.Warnf("Failed to find mvn, the test `TestResolveJar` 
was skipped")
+               return
+       }
+
+       resolver := new(deps.JarResolver)
 
-       tempDir := deps.NewTempDirGenerator()
-       path, err := tempDir.Create()
+       path, err := tmpDir()
        if err != nil {
                t.Error(err)
                return
        }
-       defer tempDir.Destroy()
+       defer destroyTmpDir(t, path)
 
        pomFile := filepath.Join(path, "pom.xml")
 
@@ -100,28 +121,34 @@ func TestResolve(t *testing.T) {
                                <artifactId>commons-logging</artifactId>
                                <version>1.2</version>
                        </dependency>
-                       <!-- 
https://mvnrepository.com/artifact/org.apache.skywalking/skywalking-sharing-server-plugin
 -->
+                       <!-- 
https://mvnrepository.com/artifact/org.apache.commons/commons-math3 -->
                        <dependency>
-                               <groupId>org.apache.skywalking</groupId>
-                               
<artifactId>skywalking-sharing-server-plugin</artifactId>
-                               <version>8.6.0</version>
+                               <groupId>org.apache.commons</groupId>
+                               <artifactId>commons-math3</artifactId>
+                               <version>3.6.1</version>
                        </dependency>
                </dependencies>
-       </project>`, 107},
+       </project>`, 4},
        } {
-               dump(pomFile, test.pomContent)
+               jars, err := copyJars(t, pomFile, test.pomContent)
+               if err != nil {
+                       t.Error(err)
+                       return
+               }
 
-               if resolver.CanResolve(pomFile) {
-                       report := deps.Report{}
-                       if err := resolver.Resolve(pomFile, &report); err != 
nil {
-                               t.Error(err)
-                               return
-                       }
+               report := deps.Report{}
+               for _, jar := range jars {
+                       if resolver.CanResolve(jar) {
+                               if err := resolver.Resolve(jar, &report); err 
!= nil {
+                                       t.Error(err)
+                                       return
+                               }
 
-                       if len(report.Resolved)+len(report.Skipped) != test.cnt 
{
-                               t.Errorf("the expected number of jar packages 
is: %d, but actually: %d. result:\n%v", test.cnt, 
len(report.Resolved)+len(report.Skipped), report.String())
                        }
-
                }
+               if len(report.Resolved)+len(report.Skipped) != test.cnt {
+                       t.Errorf("the expected number of jar packages is: %d, 
but actually: %d. result:\n%v", test.cnt, 
len(report.Resolved)+len(report.Skipped), report.String())
+               }
+               fmt.Println(report.String())
        }
 }
diff --git a/pkg/deps/maven.go b/pkg/deps/maven.go
index 4a6c476..7f9d05c 100644
--- a/pkg/deps/maven.go
+++ b/pkg/deps/maven.go
@@ -18,13 +18,11 @@
 package deps
 
 import (
-       "archive/zip"
        "bufio"
        "bytes"
        "encoding/xml"
        "fmt"
        "io"
-       "io/ioutil"
        "os"
        "os/exec"
        "path/filepath"
@@ -34,10 +32,10 @@ import (
        "golang.org/x/net/html/charset"
 
        "github.com/apache/skywalking-eyes/license-eye/internal/logger"
-       "github.com/apache/skywalking-eyes/license-eye/pkg/license"
 )
 
 type MavenPomResolver struct {
+       JarResolver
        maven string
        repo  string
 }
@@ -165,7 +163,7 @@ func (resolver *MavenPomResolver) ResolveDependencies(deps 
[]*Dependency, report
 
 // ResolveLicense search all possible locations of the license, such as pom 
file, jar package
 func (resolver *MavenPomResolver) ResolveLicense(state *State, dep 
*Dependency, report *Report) error {
-       err := resolver.ResolveLicenseFromJar(state, dep, report)
+       err := resolver.ResolveJar(state, filepath.Join(resolver.repo, 
dep.Path(), dep.Jar()), report)
        if err == nil {
                return nil
        }
@@ -183,7 +181,7 @@ func (resolver *MavenPomResolver) 
ResolveLicenseFromPom(state *State, dep *Depen
        } else if pom != nil && len(pom.Licenses) != 0 {
                report.Resolve(&Result{
                        Dependency:      dep.Jar(),
-                       LicenseFilePath: dep.Path(),
+                       LicenseFilePath: pomFile,
                        LicenseContent:  pom.Raw(),
                        LicenseSpdxID:   pom.AllLicenses(),
                })
@@ -196,7 +194,7 @@ func (resolver *MavenPomResolver) 
ResolveLicenseFromPom(state *State, dep *Depen
                return err
        } else if headerComments != "" {
                *state |= FoundLicenseInPomHeader
-               return resolver.IdentifyLicense(dep, headerComments, report)
+               return resolver.IdentifyLicense(pomFile, dep.Jar(), 
headerComments, report)
        }
 
        return fmt.Errorf("not found in pom file")
@@ -268,91 +266,6 @@ func SeemLicense(content string) bool {
        return reMaybeLicense.MatchString(content)
 }
 
-// ResolveLicenseFromJar search for the license in the jar package, and it may 
appear in MANIFEST.MF, LICENSE.txt, NOTICE.txt
-func (resolver *MavenPomResolver) ResolveLicenseFromJar(state *State, dep 
*Dependency, report *Report) (err error) {
-       jarPath := filepath.Join(resolver.repo, dep.Path(), dep.Jar())
-       compressedJar, err := zip.OpenReader(jarPath)
-       if err != nil {
-               return err
-       }
-       defer compressedJar.Close()
-
-       var manifestFile *zip.File
-
-       // traverse all files in jar
-       for _, compressedFile := range compressedJar.File {
-               archiveFile := compressedFile.Name
-               switch {
-               case reHaveManifestFile.MatchString(archiveFile):
-                       manifestFile = compressedFile
-
-               case possibleLicenseFileName.MatchString(archiveFile):
-                       *state |= FoundLicenseInJarLicenseFile
-                       buf, err := resolver.ReadFileFromZip(compressedFile)
-                       if err != nil {
-                               return err
-                       }
-
-                       return resolver.IdentifyLicense(dep, buf.String(), 
report)
-               }
-       }
-
-       if manifestFile != nil {
-               buf, err := resolver.ReadFileFromZip(manifestFile)
-               if err != nil {
-                       return err
-               }
-               norm := regexp.MustCompile(`(?im)[\r\n]+ +`)
-               content := norm.ReplaceAllString(buf.String(), "")
-
-               r := reSearchLicenseInManifestFile.FindStringSubmatch(content)
-               if len(r) != 0 {
-                       report.Resolve(&Result{
-                               Dependency:      dep.Jar(),
-                               LicenseFilePath: dep.Path(),
-                               LicenseContent:  r[1],
-                               LicenseSpdxID:   r[1],
-                       })
-                       return nil
-               }
-       }
-
-       return fmt.Errorf("cannot find license content")
-}
-
-func (resolver *MavenPomResolver) ReadFileFromZip(archiveFile *zip.File) 
(*bytes.Buffer, error) {
-       file, err := archiveFile.Open()
-       if err != nil {
-               return nil, err
-       }
-
-       buf := bytes.NewBuffer(nil)
-       w := bufio.NewWriter(buf)
-       _, err = io.CopyN(w, file, int64(archiveFile.UncompressedSize64))
-       if err != nil {
-               return nil, err
-       }
-
-       w.Flush()
-       file.Close()
-       return buf, nil
-}
-
-func (resolver *MavenPomResolver) IdentifyLicense(dep *Dependency, content 
string, report *Report) error {
-       identifier, err := license.Identify(dep.Path(), content)
-       if err != nil {
-               return err
-       }
-
-       report.Resolve(&Result{
-               Dependency:      dep.Jar(),
-               LicenseFilePath: dep.Path(),
-               LicenseContent:  content,
-               LicenseSpdxID:   identifier,
-       })
-       return nil
-}
-
 func LoadDependencies(data []byte) []*Dependency {
        depsTree := LoadDependenciesTree(data)
 
@@ -527,42 +440,6 @@ func (dep *Dependency) String() string {
        return buf.String()
 }
 
-// TempDirGenerator Create and destroy one temporary directory
-type TempDirGenerator interface {
-       Create() (string, error)
-       Destroy()
-}
-
-func NewTempDirGenerator() TempDirGenerator {
-       return new(TempDir)
-}
-
-// TempDir an implementation of the TempDirGenerator
-type TempDir struct {
-       dir string
-}
-
-func (t *TempDir) Create() (string, error) {
-       tmpDir, err := ioutil.TempDir("", "")
-       if err != nil {
-               return "", err
-       }
-       t.dir = tmpDir
-       return tmpDir, nil
-}
-
-func (t *TempDir) Destroy() {
-       if t.dir == "" {
-               logger.Log.Errorf("the temporary directory does not exist")
-               return
-       }
-
-       err := os.RemoveAll(t.dir)
-       if err != nil {
-               logger.Log.Errorln(err)
-       }
-}
-
 // PomFile is used to extract license from the pom.xml file
 type PomFile struct {
        XMLName  xml.Name      `xml:"project"`
diff --git a/pkg/deps/maven_test.go b/pkg/deps/maven_test.go
index d63d519..906f7a3 100644
--- a/pkg/deps/maven_test.go
+++ b/pkg/deps/maven_test.go
@@ -19,6 +19,8 @@ package deps_test
 
 import (
        "bufio"
+       "fmt"
+       "io/ioutil"
        "os"
        "path/filepath"
        "testing"
@@ -26,7 +28,7 @@ import (
        "github.com/apache/skywalking-eyes/license-eye/pkg/deps"
 )
 
-func TestCanResolve(t *testing.T) {
+func TestCanResolvePomFile(t *testing.T) {
        resolver := new(deps.MavenPomResolver)
        for _, test := range []struct {
                fileName string
@@ -44,7 +46,7 @@ func TestCanResolve(t *testing.T) {
        }
 }
 
-func dump(fileName, content string) error {
+func dumpPomFile(fileName, content string) error {
        file, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 
0666)
        if err != nil {
                return err
@@ -61,16 +63,35 @@ func dump(fileName, content string) error {
        return nil
 }
 
-func TestResolve(t *testing.T) {
+func tmpDir() (string, error) {
+       dir, err := ioutil.TempDir("", "")
+       if err != nil {
+               return "", err
+       }
+       return dir, nil
+}
+
+func destroyTmpDir(t *testing.T, dir string) {
+       if dir == "" {
+               t.Errorf("the temporary directory does not exist")
+               return
+       }
+
+       err := os.RemoveAll(dir)
+       if err != nil {
+               t.Error(err)
+       }
+}
+
+func TestResolveMaven(t *testing.T) {
        resolver := new(deps.MavenPomResolver)
 
-       tempDir := deps.NewTempDirGenerator()
-       path, err := tempDir.Create()
+       path, err := tmpDir()
        if err != nil {
                t.Error(err)
                return
        }
-       defer tempDir.Destroy()
+       defer destroyTmpDir(t, path)
 
        pomFile := filepath.Join(path, "pom.xml")
 
@@ -109,7 +130,7 @@ func TestResolve(t *testing.T) {
                </dependencies>
        </project>`, 107},
        } {
-               dump(pomFile, test.pomContent)
+               dumpPomFile(pomFile, test.pomContent)
 
                if resolver.CanResolve(pomFile) {
                        report := deps.Report{}
@@ -121,7 +142,7 @@ func TestResolve(t *testing.T) {
                        if len(report.Resolved)+len(report.Skipped) != test.cnt 
{
                                t.Errorf("the expected number of jar packages 
is: %d, but actually: %d. result:\n%v", test.cnt, 
len(report.Resolved)+len(report.Skipped), report.String())
                        }
-
+                       fmt.Println(report.String())
                }
        }
 }

Reply via email to