]> source.dussan.org Git - archiva.git/blob
847dd7a6be7d589461949a8f3168bf24661bff6e
[archiva.git] /
1 package org.apache.archiva.repository.content.maven2;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  *  http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import org.apache.archiva.common.utils.PathUtil;
23 import org.apache.archiva.configuration.FileTypes;
24 import org.apache.archiva.metadata.repository.storage.maven2.ArtifactMappingProvider;
25 import org.apache.archiva.metadata.repository.storage.maven2.DefaultArtifactMappingProvider;
26 import org.apache.archiva.model.ArchivaArtifact;
27 import org.apache.archiva.model.ArtifactReference;
28 import org.apache.archiva.model.ProjectReference;
29 import org.apache.archiva.model.VersionedReference;
30 import org.apache.archiva.repository.ContentNotFoundException;
31 import org.apache.archiva.repository.ManagedRepositoryContent;
32 import org.apache.archiva.repository.RepositoryException;
33 import org.apache.archiva.repository.layout.LayoutException;
34 import org.apache.commons.lang.StringUtils;
35
36 import java.io.IOException;
37 import java.net.URI;
38 import java.nio.file.Files;
39 import java.nio.file.Path;
40 import java.nio.file.Paths;
41 import java.util.Collections;
42 import java.util.HashSet;
43 import java.util.List;
44 import java.util.Objects;
45 import java.util.Set;
46 import java.util.stream.Collectors;
47 import java.util.stream.Stream;
48
49 /**
50  * ManagedDefaultRepositoryContent
51  */
52 public class ManagedDefaultRepositoryContent
53     extends AbstractDefaultRepositoryContent
54     implements ManagedRepositoryContent
55 {
56
57     private FileTypes filetypes;
58
59     public void setFileTypes(FileTypes fileTypes) {
60         this.filetypes = fileTypes;
61     }
62
63
64
65     private org.apache.archiva.repository.ManagedRepository repository;
66
67     public ManagedDefaultRepositoryContent(FileTypes fileTypes) {
68         super(Collections.singletonList( new DefaultArtifactMappingProvider() ));
69         setFileTypes( fileTypes );
70     }
71     public ManagedDefaultRepositoryContent( List<? extends ArtifactMappingProvider> artifactMappingProviders, FileTypes fileTypes )
72     {
73         super(artifactMappingProviders==null ? Collections.singletonList( new DefaultArtifactMappingProvider() ) : artifactMappingProviders);
74         setFileTypes( fileTypes );
75     }
76
77     @Override
78     public void deleteVersion( VersionedReference reference )
79     {
80         String path = toMetadataPath( reference );
81         Path projectPath = Paths.get( getRepoRoot(), path );
82
83         Path projectDir = projectPath.getParent();
84         if ( Files.exists(projectDir) && Files.isDirectory(projectDir) )
85         {
86             org.apache.archiva.common.utils.FileUtils.deleteQuietly( projectDir );
87         }
88     }
89
90     @Override
91     public void deleteProject( String namespace, String projectId )
92         throws RepositoryException
93     {
94         ArtifactReference artifactReference = new ArtifactReference();
95         artifactReference.setGroupId( namespace );
96         artifactReference.setArtifactId( projectId );
97         String path = toPath( artifactReference );
98         Path directory = Paths.get( getRepoRoot(), path );
99         if ( !Files.exists(directory) )
100         {
101             throw new ContentNotFoundException( "cannot found project " + namespace + ":" + projectId );
102         }
103         if ( Files.isDirectory(directory) )
104         {
105             try
106             {
107                 org.apache.archiva.common.utils.FileUtils.deleteDirectory( directory );
108             }
109             catch ( IOException e )
110             {
111                 throw new RepositoryException( e.getMessage(), e );
112             }
113         }
114         else
115         {
116             log.warn( "project {}:{} is not a directory", namespace, projectId );
117         }
118
119     }
120
121     @Override
122     public void deleteArtifact( ArtifactReference artifactReference )
123     {
124         String path = toPath( artifactReference );
125         Path filePath = Paths.get( getRepoRoot(), path );
126
127         if ( Files.exists(filePath) )
128         {
129             org.apache.archiva.common.utils.FileUtils.deleteQuietly( filePath );
130         }
131
132         Path filePathmd5 = Paths.get( getRepoRoot(), path + ".md5" );
133
134         if ( Files.exists(filePathmd5) )
135         {
136             org.apache.archiva.common.utils.FileUtils.deleteQuietly( filePathmd5 );
137         }
138
139         Path filePathsha1 = Paths.get( getRepoRoot(), path + ".sha1" );
140
141         if ( Files.exists(filePathsha1) )
142         {
143             org.apache.archiva.common.utils.FileUtils.deleteQuietly( filePathsha1 );
144         }
145     }
146
147     @Override
148     public void deleteGroupId( String groupId )
149         throws ContentNotFoundException
150     {
151
152         String path = StringUtils.replaceChars( groupId, '.', '/' );
153
154         Path directory = Paths.get( getRepoRoot(), path );
155
156         if ( Files.exists(directory) )
157         {
158             try
159             {
160                 org.apache.archiva.common.utils.FileUtils.deleteDirectory( directory );
161             }
162             catch ( IOException e )
163             {
164                 log.warn( "skip error deleting directory {}:", directory, e );
165             }
166         }
167     }
168
169     @Override
170     public String getId()
171     {
172         return repository.getId();
173     }
174
175     @Override
176     public Set<ArtifactReference> getRelatedArtifacts( ArtifactReference reference )
177         throws ContentNotFoundException
178     {
179         Path artifactFile = toFile( reference );
180         Path repoBase = PathUtil.getPathFromUri(repository.getLocation()).toAbsolutePath();
181         Path repoDir = artifactFile.getParent().toAbsolutePath();
182
183         if ( !Files.exists(repoDir))
184         {
185             throw new ContentNotFoundException(
186                 "Unable to get related artifacts using a non-existant directory: " + repoDir.toAbsolutePath() );
187         }
188
189         if ( !Files.isDirectory( repoDir ) )
190         {
191             throw new ContentNotFoundException(
192                 "Unable to get related artifacts using a non-directory: " + repoDir.toAbsolutePath() );
193         }
194
195         Set<ArtifactReference> foundArtifacts;
196
197         // First gather up the versions found as artifacts in the managed repository.
198
199         try (Stream<Path> stream = Files.list(repoDir)) {
200             foundArtifacts = stream.filter(Files::isRegularFile).map(path -> {
201                 try {
202                     ArtifactReference artifact = toArtifactReference(repoBase.relativize(path).toString());
203                     if( artifact.getGroupId().equals( reference.getGroupId() ) && artifact.getArtifactId().equals(
204                             reference.getArtifactId() ) && artifact.getVersion().equals( reference.getVersion() )) {
205                         return artifact;
206                     } else {
207                         return null;
208                     }
209                 } catch (LayoutException e) {
210                     log.debug( "Not processing file that is not an artifact: {}", e.getMessage() );
211                     return null;
212                 }
213             }).filter(Objects::nonNull).collect(Collectors.toSet());
214         } catch (IOException e) {
215             log.error("Could not read directory {}: {}", repoDir, e.getMessage(), e);
216             return Collections.emptySet();
217         }
218         return foundArtifacts;
219     }
220
221     @Override
222     public String getRepoRoot()
223     {
224         return convertUriToPath( repository.getLocation() );
225     }
226
227     private String convertUriToPath( URI uri ) {
228         if (uri.getScheme()==null) {
229             return Paths.get(uri.getPath()).toString();
230         } else if ("file".equals(uri.getScheme())) {
231             return Paths.get(uri).toString();
232         } else {
233             return uri.toString();
234         }
235     }
236
237     @Override
238     public org.apache.archiva.repository.ManagedRepository getRepository()
239     {
240         return repository;
241     }
242
243     /**
244      * Gather the Available Versions (on disk) for a specific Project Reference, based on filesystem
245      * information.
246      *
247      * @return the Set of available versions, based on the project reference.
248      * @throws org.apache.archiva.repository.layout.LayoutException
249      * @throws org.apache.archiva.repository.layout.LayoutException
250      */
251     @Override
252     public Set<String> getVersions( ProjectReference reference )
253         throws ContentNotFoundException, LayoutException
254     {
255         String path = toMetadataPath( reference );
256
257         int idx = path.lastIndexOf( '/' );
258         if ( idx > 0 )
259         {
260             path = path.substring( 0, idx );
261         }
262
263         Path repoDir = PathUtil.getPathFromUri( repository.getLocation() ).resolve( path );
264
265         if ( !Files.exists(repoDir) )
266         {
267             throw new ContentNotFoundException(
268                 "Unable to get Versions on a non-existant directory: " + repoDir.toAbsolutePath() );
269         }
270
271         if ( !Files.isDirectory(repoDir) )
272         {
273             throw new ContentNotFoundException(
274                 "Unable to get Versions on a non-directory: " + repoDir.toAbsolutePath() );
275         }
276
277         final String groupId = reference.getGroupId();
278         final String artifactId = reference.getArtifactId();
279         try(Stream<Path> stream = Files.list(repoDir)) {
280             return stream.filter(Files::isDirectory).map(
281                     p -> newVersionedRef(groupId, artifactId, p.getFileName().toString())
282             ).filter(this::hasArtifact).map(ref -> ref.getVersion())
283                     .collect(Collectors.toSet());
284         } catch (IOException e) {
285             log.error("Could not read directory {}: {}", repoDir, e.getMessage(), e);
286         } catch (RuntimeException e) {
287             if (e.getCause()!=null && e.getCause() instanceof LayoutException) {
288                 throw (LayoutException)e.getCause();
289             } else {
290                 throw e;
291             }
292         }
293         return Collections.emptySet();
294     }
295
296     static final VersionedReference newVersionedRef(final String groupId, final String artifactId, final String version) {
297         VersionedReference ref = new VersionedReference();
298         ref.setGroupId(groupId);
299         ref.setArtifactId(artifactId);
300         ref.setVersion(version);
301         return ref;
302     }
303
304     @Override
305     public Set<String> getVersions( VersionedReference reference )
306         throws ContentNotFoundException
307     {
308         String path = toMetadataPath( reference );
309
310         int idx = path.lastIndexOf( '/' );
311         if ( idx > 0 )
312         {
313             path = path.substring( 0, idx );
314         }
315
316         Path repoBase = PathUtil.getPathFromUri(repository.getLocation());
317         Path repoDir = repoBase.resolve( path );
318
319         if ( !Files.exists(repoDir) )
320         {
321             throw new ContentNotFoundException(
322                 "Unable to get versions on a non-existant directory: " + repoDir.toAbsolutePath() );
323         }
324
325         if ( !Files.isDirectory(repoDir) )
326         {
327             throw new ContentNotFoundException(
328                 "Unable to get versions on a non-directory: " + repoDir.toAbsolutePath() );
329         }
330
331         Set<String> foundVersions = new HashSet<>();
332
333         try(Stream<Path> stream = Files.list(repoDir)) {
334             return stream.filter(Files::isRegularFile)
335                     .map(p -> repoBase.relativize(p).toString())
336                     .filter(p -> !filetypes.matchesDefaultExclusions(p))
337                     .filter(filetypes::matchesArtifactPattern)
338                     .map(path1 -> {
339                         try {
340                             return toArtifactReference(path1);
341                         } catch (LayoutException e) {
342                             log.debug( "Not processing file that is not an artifact: {}", e.getMessage() );
343                             return null;
344                         }
345                     }).filter(Objects::nonNull)
346                     .map(ar -> ar.getVersion())
347                     .collect(Collectors.toSet());
348         } catch (IOException e) {
349             log.error("Could not read directory {}: {}", repoDir, e.getMessage(), e);
350         }
351         return Collections.emptySet();
352     }
353
354     @Override
355     public boolean hasContent( ArtifactReference reference )
356     {
357         Path artifactFile = toFile( reference );
358         return Files.exists(artifactFile) && Files.isRegularFile( artifactFile );
359     }
360
361     @Override
362     public boolean hasContent( ProjectReference reference )
363     {
364         try
365         {
366             Set<String> versions = getVersions( reference );
367             return !versions.isEmpty();
368         }
369         catch ( ContentNotFoundException | LayoutException e )
370         {
371             return false;
372         }
373     }
374
375     @Override
376     public boolean hasContent( VersionedReference reference )
377     {
378         try
379         {
380             return ( getFirstArtifact( reference ) != null );
381         }
382         catch ( IOException | LayoutException e )
383         {
384             return false;
385         }
386     }
387
388     @Override
389     public void setRepository( org.apache.archiva.repository.ManagedRepository repository )
390     {
391         this.repository = repository;
392     }
393
394     /**
395      * Convert a path to an artifact reference.
396      *
397      * @param path the path to convert. (relative or full location path)
398      * @throws org.apache.archiva.repository.layout.LayoutException if the path cannot be converted to an artifact reference.
399      */
400     @Override
401     public ArtifactReference toArtifactReference( String path )
402         throws LayoutException
403     {
404         String repoPath = convertUriToPath( repository.getLocation() );
405         if ( ( path != null ) && path.startsWith( repoPath ) && repoPath.length() > 0 )
406         {
407             return super.toArtifactReference( path.substring( repoPath.length() + 1 ) );
408         }
409
410         return super.toArtifactReference( path );
411     }
412
413     // The variant with runtime exception for stream usage
414     private ArtifactReference toArtifactRef(String path) {
415         try {
416             return toArtifactReference(path);
417         } catch (LayoutException e) {
418             throw new RuntimeException(e);
419         }
420     }
421
422
423
424     @Override
425     public Path toFile( ArtifactReference reference )
426     {
427         return PathUtil.getPathFromUri( repository.getLocation()).resolve( toPath( reference ) );
428     }
429
430     @Override
431     public Path toFile( ArchivaArtifact reference )
432     {
433         return PathUtil.getPathFromUri( repository.getLocation()).resolve( toPath( reference ) );
434     }
435
436     /**
437      * Get the first Artifact found in the provided VersionedReference location.
438      *
439      * @param reference the reference to the versioned reference to search within
440      * @return the ArtifactReference to the first artifact located within the versioned reference. or null if
441      *         no artifact was found within the versioned reference.
442      * @throws java.io.IOException     if the versioned reference is invalid (example: doesn't exist, or isn't a directory)
443      * @throws org.apache.archiva.repository.layout.LayoutException
444      */
445     private ArtifactReference getFirstArtifact( VersionedReference reference )
446         throws LayoutException, IOException
447     {
448         String path = toMetadataPath( reference );
449
450         int idx = path.lastIndexOf( '/' );
451         if ( idx > 0 )
452         {
453             path = path.substring( 0, idx );
454         }
455
456         Path repoBase = PathUtil.getPathFromUri(repository.getLocation()).toAbsolutePath();
457         Path repoDir = repoBase.resolve( path );
458
459         if ( !Files.exists(repoDir) )
460         {
461             throw new IOException( "Unable to gather the list of snapshot versions on a non-existant directory: "
462                                        + repoDir.toAbsolutePath() );
463         }
464
465         if ( !Files.isDirectory(repoDir) )
466         {
467             throw new IOException(
468                 "Unable to gather the list of snapshot versions on a non-directory: " + repoDir.toAbsolutePath() );
469         }
470         try(Stream<Path> stream = Files.list(repoDir)) {
471             return stream.filter(Files::isRegularFile)
472                 .map(p -> repoBase.relativize(p).toString())
473                     .filter(filetypes::matchesArtifactPattern)
474                     .map(this::toArtifactRef).findFirst().orElse(null);
475         } catch (RuntimeException e) {
476             if (e.getCause()!=null && e.getCause() instanceof LayoutException) {
477                 throw (LayoutException)e.getCause();
478             } else {
479                 throw e;
480             }
481         }
482
483     }
484
485     private boolean hasArtifact( VersionedReference reference )
486
487     {
488         try
489         {
490             return ( getFirstArtifact( reference ) != null );
491         }
492         catch ( IOException e )
493         {
494             return false;
495         } catch (LayoutException e) {
496             // We throw the runtime exception for better stream handling
497             throw new RuntimeException(e);
498         }
499     }
500
501     public void setFiletypes( FileTypes filetypes )
502     {
503         this.filetypes = filetypes;
504     }
505 }