@@ -3,9 +3,7 @@ package manifest
3
3
import (
4
4
"context"
5
5
"encoding/xml"
6
- "errors"
7
6
"fmt"
8
- "os"
9
7
"path/filepath"
10
8
11
9
"deps.dev/util/maven"
@@ -15,17 +13,11 @@ import (
15
13
"github.com/google/osv-scanner/internal/resolution/client"
16
14
"github.com/google/osv-scanner/internal/resolution/datasource"
17
15
"github.com/google/osv-scanner/internal/resolution/util"
16
+ mavenutil "github.com/google/osv-scanner/internal/utility/maven"
18
17
"github.com/google/osv-scanner/pkg/lockfile"
19
18
"golang.org/x/exp/maps"
20
19
)
21
20
22
- const (
23
- OriginManagement = "management"
24
- OriginParent = "parent"
25
- OriginPlugin = "plugin"
26
- OriginProfile = "profile"
27
- )
28
-
29
21
type MavenResolverExtractor struct {
30
22
client.DependencyClient
31
23
datasource.MavenRegistryAPIClient
@@ -43,7 +35,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD
43
35
return []lockfile.PackageDetails {}, fmt .Errorf ("could not extract from %s: %w" , f .Path (), err )
44
36
}
45
37
// Merging parents data by parsing local parent pom.xml or fetching from upstream.
46
- if err := MergeMavenParents (ctx , e .MavenRegistryAPIClient , & project , project .Parent , 1 , f .Path (), true ); err != nil {
38
+ if err := mavenutil . MergeParents (ctx , e .MavenRegistryAPIClient , & project , project .Parent , 1 , f .Path (), true ); err != nil {
47
39
return []lockfile.PackageDetails {}, fmt .Errorf ("failed to merge parents: %w" , err )
48
40
}
49
41
// Process the dependencies:
@@ -53,7 +45,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD
53
45
project .ProcessDependencies (func (groupID , artifactID , version maven.String ) (maven.DependencyManagement , error ) {
54
46
root := maven.Parent {ProjectKey : maven.ProjectKey {GroupID : groupID , ArtifactID : artifactID , Version : version }}
55
47
var result maven.Project
56
- if err := MergeMavenParents (ctx , e .MavenRegistryAPIClient , & result , root , 0 , f .Path (), false ); err != nil {
48
+ if err := mavenutil . MergeParents (ctx , e .MavenRegistryAPIClient , & result , root , 0 , f .Path (), false ); err != nil {
57
49
return maven.DependencyManagement {}, err
58
50
}
59
51
@@ -97,7 +89,7 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD
97
89
VersionType : resolve .Requirement ,
98
90
Version : string (d .Version ),
99
91
},
100
- Type : resolve .MavenDepType (d , OriginManagement ),
92
+ Type : resolve .MavenDepType (d , mavenutil . OriginManagement ),
101
93
}
102
94
}
103
95
overrideClient .AddVersion (root , reqs )
@@ -133,112 +125,6 @@ func (e MavenResolverExtractor) Extract(f lockfile.DepFile) ([]lockfile.PackageD
133
125
return maps .Values (details ), nil
134
126
}
135
127
136
- // MaxParent sets a limit on the number of parents to avoid indefinite loop.
137
- const MaxParent = 100
138
-
139
- // MergeMavenParents parses local accessible parent pom.xml or fetches it from
140
- // upstream, merges into root project, then interpolate the properties.
141
- // result holds the merged Maven project.
142
- // current holds the current parent project to merge.
143
- // start indicates the index of the current parent project, which is used to
144
- // check if the packaging has to be `pom`.
145
- // allowLocal indicates whether parsing local parent pom.xml is allowed.
146
- // path holds the path to the current pom.xml, which is used to compute the
147
- // relative path of parent.
148
- func MergeMavenParents (ctx context.Context , mavenClient datasource.MavenRegistryAPIClient , result * maven.Project , current maven.Parent , start int , path string , allowLocal bool ) error {
149
- currentPath := path
150
- visited := make (map [maven.ProjectKey ]bool , MaxParent )
151
- for n := start ; n < MaxParent ; n ++ {
152
- if current .GroupID == "" || current .ArtifactID == "" || current .Version == "" {
153
- break
154
- }
155
- if visited [current .ProjectKey ] {
156
- // A cycle of parents is detected
157
- return errors .New ("a cycle of parents is detected" )
158
- }
159
- visited [current .ProjectKey ] = true
160
-
161
- var proj maven.Project
162
- parentFound := false
163
- if parentPath := MavenParentPOMPath (currentPath , string (current .RelativePath )); allowLocal && parentPath != "" {
164
- currentPath = parentPath
165
- f , err := os .Open (parentPath )
166
- if err != nil {
167
- return fmt .Errorf ("failed to open parent file %s: %w" , parentPath , err )
168
- }
169
- if err := xml .NewDecoder (f ).Decode (& proj ); err != nil {
170
- return fmt .Errorf ("failed to unmarshal project: %w" , err )
171
- }
172
- if MavenProjectKey (proj ) == current .ProjectKey && proj .Packaging == "pom" {
173
- // Only mark parent is found when the identifiers and packaging are exptected.
174
- parentFound = true
175
- }
176
- }
177
- if ! parentFound {
178
- // Once we fetch a parent pom.xml from upstream, we should not
179
- // allow parsing parent pom.xml locally anymore.
180
- allowLocal = false
181
-
182
- var err error
183
- proj , err = mavenClient .GetProject (ctx , string (current .GroupID ), string (current .ArtifactID ), string (current .Version ))
184
- if err != nil {
185
- return fmt .Errorf ("failed to get Maven project %s:%s:%s: %w" , current .GroupID , current .ArtifactID , current .Version , err )
186
- }
187
- if n > 0 && proj .Packaging != "pom" {
188
- // A parent project should only be of "pom" packaging type.
189
- return fmt .Errorf ("invalid packaging for parent project %s" , proj .Packaging )
190
- }
191
- if MavenProjectKey (proj ) != current .ProjectKey {
192
- // The identifiers in parent does not match what we want.
193
- return fmt .Errorf ("parent identifiers mismatch: %v, expect %v" , proj .ProjectKey , current .ProjectKey )
194
- }
195
- }
196
- // Empty JDK and ActivationOS indicates merging the default profiles.
197
- if err := proj .MergeProfiles ("" , maven.ActivationOS {}); err != nil {
198
- return err
199
- }
200
- result .MergeParent (proj )
201
- current = proj .Parent
202
- }
203
- // Interpolate the project to resolve the properties.
204
- return result .Interpolate ()
205
- }
206
-
207
- // MavenProjectKey returns a project key with empty groupId/version
208
- // filled by corresponding fields in parent.
209
- func MavenProjectKey (proj maven.Project ) maven.ProjectKey {
210
- if proj .GroupID == "" {
211
- proj .GroupID = proj .Parent .GroupID
212
- }
213
- if proj .Version == "" {
214
- proj .Version = proj .Parent .Version
215
- }
216
-
217
- return proj .ProjectKey
218
- }
219
-
220
- // Maven looks for the parent POM first in 'relativePath',
221
- // then the local repository '../pom.xml',
222
- // and lastly in the remote repo.
223
- func MavenParentPOMPath (currentPath , relativePath string ) string {
224
- if relativePath == "" {
225
- relativePath = "../pom.xml"
226
- }
227
- path := filepath .Join (filepath .Dir (currentPath ), relativePath )
228
- if info , err := os .Stat (path ); err == nil {
229
- if ! info .IsDir () {
230
- return path
231
- }
232
- // Current path is a directory, so look for pom.xml in the directory.
233
- path = filepath .Join (path , "pom.xml" )
234
- if _ , err := os .Stat (path ); err == nil {
235
- return path
236
- }
237
- }
238
-
239
- return ""
240
- }
241
-
242
128
func ParseMavenWithResolver (depClient client.DependencyClient , mavenClient datasource.MavenRegistryAPIClient , pathToLockfile string ) ([]lockfile.PackageDetails , error ) {
243
129
f , err := lockfile .OpenLocalDepFile (pathToLockfile )
244
130
if err != nil {
0 commit comments