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.internal.transformation;
20  
21  import java.io.File;
22  import java.io.InputStream;
23  import java.nio.file.Files;
24  import java.nio.file.Path;
25  import java.security.MessageDigest;
26  import java.util.function.Supplier;
27  
28  import org.apache.maven.artifact.Artifact;
29  import org.apache.maven.artifact.DefaultArtifact;
30  import org.apache.maven.artifact.handler.ArtifactHandler;
31  
32  import static java.util.Objects.requireNonNull;
33  
34  /**
35   * Transformed artifact is derived with some transformation from source artifact.
36   *
37   * @since TBD
38   */
39  abstract class TransformedArtifact extends DefaultArtifact {
40  
41      private final OnChangeTransformer onChangeTransformer;
42  
43      TransformedArtifact(
44              Artifact source, Supplier<Path> sourcePathProvider, String classifier, String extension, Path targetPath) {
45          super(
46                  source.getGroupId(),
47                  source.getArtifactId(),
48                  source.getVersionRange(),
49                  source.getScope(),
50                  extension,
51                  classifier,
52                  new TransformedArtifactHandler(
53                          classifier, extension, source.getArtifactHandler().getPackaging()));
54          this.onChangeTransformer =
55                  new OnChangeTransformer(sourcePathProvider, targetPath, TransformedArtifact::sha1, this::transform);
56      }
57  
58      @Override
59      public boolean isResolved() {
60          return getFile() != null;
61      }
62  
63      @Override
64      public void setFile(File file) {
65          throw new IllegalStateException("transformed artifact file cannot be set");
66      }
67  
68      @Override
69      public File getFile() {
70          Path result = onChangeTransformer.get();
71          if (result == null) {
72              return null;
73          }
74          return result.toFile();
75      }
76  
77      private static final int BUFFER_SIZE = 8192;
78  
79      private static String sha1(Path path) {
80          try {
81              MessageDigest md = MessageDigest.getInstance("SHA-1");
82              try (InputStream fis = Files.newInputStream(path)) {
83                  byte[] buffer = new byte[BUFFER_SIZE];
84                  int read;
85                  while ((read = fis.read(buffer)) != -1) {
86                      md.update(buffer, 0, read);
87                  }
88              }
89              StringBuilder result = new StringBuilder();
90              for (byte b : md.digest()) {
91                  result.append(String.format("%02x", b));
92              }
93              return result.toString();
94          } catch (Exception e) {
95              throw new RuntimeException(e);
96          }
97      }
98  
99      protected abstract void transform(Path src, Path dst);
100 
101     private static class TransformedArtifactHandler implements ArtifactHandler {
102         private final String classifier;
103 
104         private final String extension;
105 
106         private final String packaging;
107 
108         private TransformedArtifactHandler(String classifier, String extension, String packaging) {
109             this.classifier = classifier;
110             this.extension = requireNonNull(extension);
111             this.packaging = requireNonNull(packaging);
112         }
113 
114         public String getClassifier() {
115             return classifier;
116         }
117 
118         public String getDirectory() {
119             return null;
120         }
121 
122         public String getExtension() {
123             return extension;
124         }
125 
126         public String getLanguage() {
127             return "none";
128         }
129 
130         public String getPackaging() {
131             return packaging;
132         }
133 
134         public boolean isAddedToClasspath() {
135             return false;
136         }
137 
138         public boolean isIncludesDependencies() {
139             return false;
140         }
141     }
142 }