1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.codehaus.plexus.archiver.dir;
17  
18  import javax.inject.Named;
19  
20  import java.io.File;
21  import java.io.IOException;
22  import java.io.InputStream;
23  import java.nio.file.Files;
24  import java.nio.file.attribute.FileTime;
25  import java.util.ArrayList;
26  import java.util.List;
27  
28  import org.codehaus.plexus.archiver.AbstractArchiver;
29  import org.codehaus.plexus.archiver.ArchiveEntry;
30  import org.codehaus.plexus.archiver.ArchiverException;
31  import org.codehaus.plexus.archiver.ResourceIterator;
32  import org.codehaus.plexus.archiver.exceptions.EmptyArchiveException;
33  import org.codehaus.plexus.archiver.util.ArchiveEntryUtils;
34  import org.codehaus.plexus.archiver.util.ResourceUtils;
35  import org.codehaus.plexus.components.io.attributes.SymlinkUtils;
36  import org.codehaus.plexus.components.io.functions.SymlinkDestinationSupplier;
37  import org.codehaus.plexus.components.io.resources.PlexusIoResource;
38  
39  
40  
41  
42  @Named("dir")
43  public class DirectoryArchiver extends AbstractArchiver {
44  
45      private final List<Runnable> directoryChmods = new ArrayList<>();
46      private long filesCopied;
47  
48      
49  
50  
51      public DirectoryArchiver() {
52          
53          setForced(false);
54      }
55  
56      public void resetArchiver() throws IOException {
57          cleanUp();
58      }
59  
60      @Override
61      public void execute() throws ArchiverException, IOException {
62          
63          
64          final ResourceIterator iter = getResources();
65          if (!iter.hasNext()) {
66              throw new EmptyArchiveException("archive cannot be empty");
67          }
68  
69          final File destDirectory = getDestFile();
70          if (destDirectory == null) {
71              throw new ArchiverException("You must set the destination directory.");
72          }
73          if (destDirectory.exists() && !destDirectory.isDirectory()) {
74              throw new ArchiverException(destDirectory + " is not a directory.");
75          }
76          if (destDirectory.exists() && !destDirectory.canWrite()) {
77              throw new ArchiverException(destDirectory + " is not writable.");
78          }
79  
80          getLogger().info("Copying files to {}", destDirectory.getAbsolutePath());
81  
82          try {
83              while (iter.hasNext()) {
84                  final ArchiveEntry f = iter.next();
85                  
86                  if (ResourceUtils.isSame(f.getResource(), destDirectory)) {
87                      throw new ArchiverException("The destination directory cannot include itself.");
88                  }
89                  String fileName = f.getName();
90                  final String destDir = destDirectory.getCanonicalPath();
91                  fileName = destDir + File.separator + fileName;
92                  PlexusIoResource resource = f.getResource();
93                  if (resource instanceof SymlinkDestinationSupplier) {
94                      String dest = ((SymlinkDestinationSupplier) resource).getSymlinkDestination();
95                      File target = new File(dest);
96                      File symlink = new File(fileName);
97                      makeParentDirectories(symlink);
98                      SymlinkUtils.createSymbolicLink(symlink, target);
99                  } else {
100                     copyFile(f, fileName);
101                 }
102             }
103 
104             directoryChmods.forEach(Runnable::run);
105             directoryChmods.clear();
106 
107             if (filesCopied > 0) {
108                 getLogger()
109                         .info(
110                                 "{} file{} copied to {}",
111                                 filesCopied,
112                                 filesCopied > 0 ? "s" : "",
113                                 destDirectory.getAbsolutePath());
114             } else {
115                 getLogger().info("All files are uptodate in {}", destDirectory.getAbsolutePath());
116             }
117 
118             filesCopied = 0;
119 
120         } catch (final IOException ioe) {
121             final String message = "Problem copying files : " + ioe.getMessage();
122             throw new ArchiverException(message, ioe);
123         }
124     }
125 
126     
127 
128 
129 
130 
131 
132 
133 
134 
135     protected void copyFile(final ArchiveEntry entry, final String vPath) throws ArchiverException, IOException {
136         
137         if (vPath.length() <= 0) {
138             return;
139         }
140 
141         final PlexusIoResource in = entry.getResource();
142         final File outFile = new File(vPath);
143 
144         final long inLastModified = in.getLastModified();
145 
146         if (!isForced()) {
147             final long outLastModified = outFile.lastModified();
148             if (ResourceUtils.isUptodate(inLastModified, outLastModified)) {
149                 return;
150             }
151         }
152 
153         if (!in.isDirectory()) {
154             makeParentDirectories(outFile);
155             try (InputStream input = entry.getInputStream()) {
156                 ResourceUtils.copyFile(input, outFile);
157             }
158             filesCopied++;
159             setFileModes(entry, outFile, inLastModified);
160         } else { 
161             if (outFile.exists()) {
162                 if (!outFile.isDirectory()) {
163                     
164                     
165                     throw new ArchiverException("Expected directory and found file at copy destination of "
166                             + in.getName() + " to " + outFile);
167                 }
168             } else if (!outFile.mkdirs()) {
169                 
170                 throw new ArchiverException("Unable to create directory or parent directory of " + outFile);
171             }
172 
173             directoryChmods.add(() -> {
174                 try {
175                     setFileModes(entry, outFile, inLastModified);
176                 } catch (IOException e) {
177                     throw new ArchiverException("Failed setting file attributes", e);
178                 }
179             });
180         }
181     }
182 
183     private static void makeParentDirectories(File file) {
184         if (!file.getParentFile().exists()) {
185             
186             if (!file.getParentFile().mkdirs()) {
187                 
188                 throw new ArchiverException("Unable to create directory or parent directory of " + file);
189             }
190         }
191     }
192 
193     private void setFileModes(ArchiveEntry entry, File outFile, long inLastModified) throws IOException {
194         if (!isIgnorePermissions()) {
195             ArchiveEntryUtils.chmod(outFile, entry.getMode());
196         }
197 
198         if (getLastModifiedTime() == null) {
199             FileTime fromMillis = FileTime.fromMillis(
200                     inLastModified == PlexusIoResource.UNKNOWN_MODIFICATION_DATE
201                             ? System.currentTimeMillis()
202                             : inLastModified);
203             Files.setLastModifiedTime(outFile.toPath(), fromMillis);
204         } else {
205             Files.setLastModifiedTime(outFile.toPath(), getLastModifiedTime());
206         }
207     }
208 
209     @Override
210     protected void cleanUp() throws IOException {
211         super.cleanUp();
212         setIncludeEmptyDirs(false);
213         setIncludeEmptyDirs(true);
214     }
215 
216     @Override
217     protected void close() throws IOException {}
218 
219     @Override
220     protected String getArchiveType() {
221         return "directory";
222     }
223 
224     @Override
225     public boolean isSupportingForced() {
226         return true;
227     }
228 }