]> source.dussan.org Git - archiva.git/blob
a0094407c4022581821ab6e0aac323923595af03
[archiva.git] /
1 package org.apache.archiva.repository.storage;
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.filelock.FileLockException;
23 import org.apache.archiva.common.filelock.FileLockManager;
24 import org.apache.archiva.common.filelock.Lock;
25 import org.slf4j.Logger;
26 import org.slf4j.LoggerFactory;
27
28 import java.io.IOException;
29 import java.nio.channels.FileChannel;
30 import java.nio.file.*;
31 import java.util.HashSet;
32
33 /**
34  *
35  * Utility class for assets. Allows to copy, move between different storage instances and
36  * recursively consume the tree.
37  *
38  * @author Martin Stockhammer <martin_s@apache.org>
39  */
40 public class FsStorageUtil
41 {
42     private static final Logger log = LoggerFactory.getLogger( FsStorageUtil.class);
43
44     /**
45      * Copies the source asset to the target. The assets may be from different RepositoryStorage instances.
46      * If you know that source and asset are from the same storage instance, the copy method of the storage
47      * instance may be faster.
48      *
49      * @param source The source asset
50      * @param target The target asset
51      * @param locked If true, a readlock is set on the source and a write lock is set on the target.
52      * @param copyOptions Copy options
53      * @throws IOException
54      */
55     public static final void copyAsset( final StorageAsset source,
56                                         final StorageAsset target,
57                                         boolean locked,
58                                         final CopyOption... copyOptions ) throws IOException
59     {
60         if (source.isFileBased() && target.isFileBased()) {
61             // Short cut for FS operations
62             final Path sourcePath = source.getFilePath();
63             final Path targetPath = target.getFilePath( );
64             if (locked) {
65                 final FileLockManager lmSource = ((FilesystemStorage)source.getStorage()).getFileLockManager();
66                 final FileLockManager lmTarget = ((FilesystemStorage)target.getStorage()).getFileLockManager();
67                 Lock lockRead = null;
68                 Lock lockWrite = null;
69                 try {
70                     lockRead = lmSource.readFileLock(sourcePath);
71                 } catch (Exception e) {
72                     log.error("Could not create read lock on {}", sourcePath);
73                     throw new IOException(e);
74                 }
75                 try {
76                     lockWrite = lmTarget.writeFileLock(targetPath);
77                 } catch (Exception e) {
78                     log.error("Could not create write lock on {}", targetPath);
79                     throw new IOException(e);
80                 }
81                 try {
82                     Files.copy(sourcePath, targetPath, copyOptions);
83                 } finally {
84                     if (lockRead!=null) {
85                         try {
86                             lmSource.release(lockRead);
87                         } catch (FileLockException e) {
88                             log.error("Error during lock release of read lock {}", lockRead.getFile());
89                         }
90                     }
91                     if (lockWrite!=null) {
92                         try {
93                             lmTarget.release(lockWrite);
94                         } catch (FileLockException e) {
95                             log.error("Error during lock release of write lock {}", lockWrite.getFile());
96                         }
97                     }
98                 }
99             } else
100             {
101                 Files.copy( sourcePath, targetPath, copyOptions );
102             }
103         } else {
104             try {
105                 final RepositoryStorage sourceStorage = source.getStorage();
106                 final RepositoryStorage targetStorage = target.getStorage();
107                 sourceStorage.consumeDataFromChannel( source, is -> org.apache.archiva.repository.storage.util.StorageUtil.wrapWriteFunction( is, targetStorage, target, locked ), locked);
108             }  catch (IOException e) {
109                 throw e;
110             }  catch (Throwable e) {
111                 Throwable cause = e.getCause();
112                 if (cause instanceof IOException) {
113                     throw (IOException)cause;
114                 } else
115                 {
116                     throw new IOException( e );
117                 }
118             }
119         }
120     }
121
122
123     public static final void copyToLocalFile(StorageAsset asset, Path destination, CopyOption... copyOptions) throws IOException {
124         if (asset.isFileBased()) {
125             Files.copy(asset.getFilePath(), destination, copyOptions);
126         } else {
127             try {
128
129                 HashSet<OpenOption> openOptions = new HashSet<>();
130                 for (CopyOption option : copyOptions) {
131                     if (option == StandardCopyOption.REPLACE_EXISTING) {
132                         openOptions.add(StandardOpenOption.CREATE);
133                         openOptions.add(StandardOpenOption.TRUNCATE_EXISTING);
134                         openOptions.add(StandardOpenOption.WRITE);
135                     } else {
136                         openOptions.add(StandardOpenOption.WRITE);
137                         openOptions.add(StandardOpenOption.CREATE_NEW);
138                     }
139                 }
140                 asset.getStorage().consumeDataFromChannel(asset, channel -> {
141                     try {
142                         FileChannel.open(destination, openOptions).transferFrom(channel, 0, Long.MAX_VALUE);
143                     } catch (IOException e) {
144                         throw new RuntimeException(e);
145                     }
146                 }, false);
147             } catch (Throwable e) {
148                 if (e.getCause() instanceof IOException) {
149                     throw (IOException)e.getCause();
150                 } else {
151                     throw new IOException(e);
152                 }
153             }
154         }
155     }
156
157     public static class PathInformation {
158         final Path path ;
159         final boolean tmpFile;
160
161         PathInformation(Path path, boolean tmpFile) {
162             this.path = path;
163             this.tmpFile = tmpFile;
164         }
165
166         public Path getPath() {
167             return path;
168         }
169
170         public boolean isTmpFile() {
171             return tmpFile;
172         }
173
174     }
175
176     public static final PathInformation getAssetDataAsPath(StorageAsset asset) throws IOException {
177         if (!asset.exists()) {
178             throw new IOException("Asset does not exist");
179         }
180         if (asset.isFileBased()) {
181             return new PathInformation(asset.getFilePath(), false);
182         } else {
183             Path tmpFile = Files.createTempFile(asset.getName(), org.apache.archiva.repository.storage.util.StorageUtil.getExtension(asset));
184             copyToLocalFile(asset, tmpFile, StandardCopyOption.REPLACE_EXISTING);
185             return new PathInformation(tmpFile, true);
186         }
187     }
188
189 }