View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.maven.buildcache.artifact;
20  
21  import java.io.File;
22  import java.util.concurrent.CompletableFuture;
23  import java.util.concurrent.ExecutionException;
24  import java.util.concurrent.Future;
25  import java.util.concurrent.RunnableFuture;
26  
27  import org.apache.maven.artifact.Artifact;
28  import org.apache.maven.artifact.DefaultArtifact;
29  import org.apache.maven.artifact.InvalidArtifactRTException;
30  import org.apache.maven.artifact.handler.ArtifactHandler;
31  import org.slf4j.Logger;
32  import org.slf4j.LoggerFactory;
33  
34  import static java.util.Objects.requireNonNull;
35  
36  /**
37   * Overrides default file behavior with async file holder to restore files from cache lazy. Similar to {@link
38   * org.apache.maven.project.artifact.AttachedArtifact}
39   */
40  public class RestoredArtifact extends DefaultArtifact {
41  
42      private static final Logger LOGGER = LoggerFactory.getLogger(RestoredArtifact.class);
43      public static final String MSG_INTERRUPTED_WHILE_RETRIEVING_ARTIFACT_FILE =
44              "Interrupted while retrieving artifact file";
45      public static final String MSG_ERROR_RETRIEVING_ARTIFACT_FILE = "Error retrieving artifact file";
46  
47      private volatile Future<File> fileFuture;
48  
49      public RestoredArtifact(
50              Artifact parent, Future<File> fileFuture, String type, String classifier, ArtifactHandler handler) {
51          super(
52                  parent.getGroupId(),
53                  parent.getArtifactId(),
54                  parent.getVersionRange(),
55                  parent.getScope(),
56                  type,
57                  classifier,
58                  handler,
59                  parent.isOptional());
60          this.fileFuture = requireNonNull(fileFuture, "fileFuture == null");
61      }
62  
63      /**
64       * Returns file using caller thread to download it if necessary
65       */
66      @Override
67      public File getFile() {
68  
69          if (!fileFuture.isDone()) {
70              if (fileFuture instanceof RunnableFuture) {
71                  try {
72                      LOGGER.trace(
73                              "Artifact file {} is not yet retrieved, downloading directly", getDependencyConflictId());
74                      ((RunnableFuture<?>) fileFuture).run();
75                  } catch (RuntimeException e) {
76                      throw new InvalidArtifactRTException(
77                              getGroupId(),
78                              getArtifactId(),
79                              getVersion(),
80                              getType(),
81                              MSG_ERROR_RETRIEVING_ARTIFACT_FILE,
82                              e);
83                  }
84              } else {
85                  LOGGER.trace(
86                          "Artifact file {} is not yet retrieved, waiting for download to complete",
87                          getDependencyConflictId());
88              }
89          }
90  
91          try {
92              return fileFuture.get();
93          } catch (InterruptedException e) {
94              Thread.currentThread().interrupt();
95              throw new InvalidArtifactRTException(
96                      getGroupId(),
97                      getArtifactId(),
98                      getVersion(),
99                      getType(),
100                     MSG_INTERRUPTED_WHILE_RETRIEVING_ARTIFACT_FILE,
101                     e);
102         } catch (ExecutionException e) {
103             throw new InvalidArtifactRTException(
104                     getGroupId(),
105                     getArtifactId(),
106                     getVersion(),
107                     getType(),
108                     MSG_ERROR_RETRIEVING_ARTIFACT_FILE,
109                     e.getCause());
110         }
111     }
112 
113     @Override
114     public void setFile(File destination) {
115         this.fileFuture = CompletableFuture.completedFuture(destination);
116     }
117 }