View Javadoc
1   /**
2    *
3    * Copyright 2004 The Apache Software Foundation
4    *
5    * Licensed under the Apache License, Version 2.0 (the "License");
6    * you may not use this file except in compliance with the License.
7    * You may obtain a copy of the License at
8    *
9    * http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.codehaus.plexus.archiver;
18  
19  import java.io.File;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import javax.annotation.Nonnull;
23  import org.codehaus.plexus.archiver.resources.PlexusIoVirtualSymlinkResource;
24  import org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributes;
25  import org.codehaus.plexus.components.io.functions.ResourceAttributeSupplier;
26  import org.codehaus.plexus.components.io.resources.PlexusIoFileResource;
27  import org.codehaus.plexus.components.io.resources.PlexusIoResource;
28  import org.codehaus.plexus.components.io.resources.PlexusIoResourceCollection;
29  import org.codehaus.plexus.components.io.resources.ResourceFactory;
30  import static org.codehaus.plexus.components.io.resources.ResourceFactory.createResource;
31  
32  public class ArchiveEntry
33  {
34  
35      public static final String ROLE = ArchiveEntry.class.getName();
36  
37      public static final int FILE = 1;
38  
39      public static final int DIRECTORY = 2;
40  
41      public static final int SYMLINK = 3;
42  
43      @Nonnull private PlexusIoResource resource;
44  
45      private final String name;
46  
47      private final int type;
48  
49      private final int mode;
50  
51      private final int defaultDirMode;  // Sometimes a directory needs to be created. Which mode should it be ?
52      // this mode is at the time of the creation of the archive entry, which is an important distinction
53  
54      private PlexusIoResourceAttributes attributes;
55  
56      private final boolean addSynchronously;
57  
58      /**
59       * @param name the filename as it will appear in the archive. This is platform-specific
60       * normalized with File.separatorChar
61       * @param resource original filename
62       * @param type FILE or DIRECTORY
63       * @param mode octal unix style permissions
64       * @param collection
65       * @param defaultDirMode
66       */
67      private ArchiveEntry( String name, @Nonnull PlexusIoResource resource, int type, int mode,
68                            PlexusIoResourceCollection collection, int defaultDirMode )
69      {
70          try
71          {
72              this.name = name;
73              this.defaultDirMode = defaultDirMode;
74              this.resource = collection != null ? collection.resolve( resource ) : resource;
75              this.attributes = ( resource instanceof ResourceAttributeSupplier )
76                                    ? ( (ResourceAttributeSupplier) resource ).getAttributes() : null;
77              this.type = type;
78              int permissions = mode;
79  
80              if ( mode == PlexusIoResourceAttributes.UNKNOWN_OCTAL_MODE && this.attributes == null )
81              {
82                  permissions = resource.isFile()
83                                    ? Archiver.DEFAULT_FILE_MODE
84                                    : resource.isSymbolicLink()
85                                          ? Archiver.DEFAULT_SYMLILNK_MODE
86                                          : Archiver.DEFAULT_DIR_MODE;
87  
88              }
89  
90              this.mode = permissions == PlexusIoResourceAttributes.UNKNOWN_OCTAL_MODE
91                              ? permissions
92                              : ( permissions & UnixStat.PERM_MASK ) | ( type == FILE
93                                                                         ? UnixStat.FILE_FLAG
94                                                                         : type == SYMLINK
95                                                                           ? UnixStat.LINK_FLAG
96                                                                           : UnixStat.DIR_FLAG );
97  
98              this.addSynchronously = ( collection != null && !collection.isConcurrentAccessSupported() );
99          }
100         catch ( IOException e )
101         {
102             throw new ArchiverException( "Error resolving resource " + resource.getName(), e );
103         }
104     }
105 
106     /**
107      * @return the filename of this entry in the archive.
108      */
109     public String getName()
110     {
111         return name;
112     }
113 
114     /**
115      * @return The original file that will be stored in the archive.
116      *
117      * @deprecated As of 1.0-alpha-10, file entries are no longer backed
118      * by files, but by instances of {@link PlexusIoResource}.
119      * Consequently, you should use {@link #getInputStream()}-
120      */
121     @Deprecated
122     public File getFile()
123     {
124         if ( resource instanceof PlexusIoFileResource )
125         {
126             return ( (PlexusIoFileResource) resource ).getFile();
127         }
128         return null;
129     }
130 
131     /**
132      * @return The resource contents.
133      */
134     public InputStream getInputStream()
135         throws IOException
136     {
137         return resource.getContents();
138     }
139 
140     /**
141      * @return FILE or DIRECTORY
142      */
143     public int getType()
144     {
145         return type;
146     }
147 
148     /**
149      * @return octal user/group/other unix like permissions.
150      */
151     public int getMode()
152     {
153         if ( mode != -1 )
154         {
155             return mode;
156         }
157 
158         if ( attributes != null && attributes.getOctalMode() > -1 )
159         {
160             return attributes.getOctalMode();
161         }
162 
163         return ( ( type == FILE
164                    ? Archiver.DEFAULT_FILE_MODE
165                    : type == SYMLINK
166                      ? Archiver.DEFAULT_SYMLILNK_MODE
167                      : Archiver.DEFAULT_DIR_MODE ) & UnixStat.PERM_MASK )
168                    | ( type == FILE
169                        ? UnixStat.FILE_FLAG
170                        : type == SYMLINK
171                          ? UnixStat.LINK_FLAG
172                          : UnixStat.DIR_FLAG );
173 
174     }
175 
176     /**
177      * Indicates if this entry should be added to the archive synchronously
178      * before adding the next entry and/or accessing the next entry of {@link ResourceIterator}.
179      *
180      * @return {@code true} if this entry should be added synchronously
181      */
182     public boolean shouldAddSynchronously()
183     {
184         return addSynchronously;
185     }
186 
187     public static ArchiveEntry createFileEntry( String target, PlexusIoResource resource, int permissions,
188                                                 PlexusIoResourceCollection collection, int defaultDirectoryPermissions )
189         throws ArchiverException
190     {
191         if ( resource.isDirectory() )
192         {
193             throw new ArchiverException( "Not a file: " + resource.getName() );
194         }
195         final int type = resource.isSymbolicLink() ? SYMLINK : FILE;
196         return new ArchiveEntry( target, resource, type, permissions, collection, defaultDirectoryPermissions );
197     }
198 
199     public static ArchiveEntry createFileEntry( String target, File file, int permissions,
200                                                 int defaultDirectoryPermissions )
201         throws ArchiverException, IOException
202     {
203         if ( !file.isFile() )
204         {
205             throw new ArchiverException( "Not a file: " + file );
206         }
207 
208         final PlexusIoResource res = ResourceFactory.createResource( file );
209 
210         final int type;
211         if ( res.isSymbolicLink() )
212         {
213             type = SYMLINK;
214             permissions = permissions & ~( UnixStat.FILE_FLAG ); // remove file flag again .doh.
215         }
216         else
217         {
218             type = FILE; // File flag was there already. This is a bit of a mess !
219         }
220 
221         return new ArchiveEntry( target, res, type, permissions, null, defaultDirectoryPermissions );
222     }
223 
224     public static ArchiveEntry createDirectoryEntry( String target, @Nonnull PlexusIoResource resource, int permissions,
225                                                      int defaultDirectoryPermissions )
226         throws ArchiverException
227     {
228         if ( !resource.isDirectory() )
229         {
230             throw new ArchiverException( "Not a directory: " + resource.getName() );
231         }
232         final int type;
233         if ( resource.isSymbolicLink() )
234         {
235             type = SYMLINK;
236             permissions = permissions & ~( UnixStat.DIR_FLAG ); // remove dir flag again .doh.
237         }
238         else
239         {
240             type = DIRECTORY; // Dir flag was there already. This is a bit of a mess !
241 
242         }
243         return new ArchiveEntry( target, resource, type, permissions, null, defaultDirectoryPermissions );
244     }
245 
246     public static ArchiveEntry createDirectoryEntry( String target, final File file, int permissions,
247                                                      int defaultDirMode1 )
248         throws ArchiverException, IOException
249     {
250         if ( !file.isDirectory() )
251         {
252             throw new ArchiverException( "Not a directory: " + file );
253         }
254 
255         final PlexusIoResource res = createResource( file );
256         return new ArchiveEntry( target, res, DIRECTORY, permissions, null, defaultDirMode1 );
257     }
258 
259     public static ArchiveEntry createSymlinkEntry( String symlinkName, int permissions, String symlinkDestination,
260                                                    int defaultDirectoryPermissions )
261     {
262         final ArchiveEntry archiveEntry = new ArchiveEntry(
263             symlinkName, new PlexusIoVirtualSymlinkResource( new File( symlinkName ), symlinkDestination ), SYMLINK,
264             permissions, null, defaultDirectoryPermissions );
265 
266         return archiveEntry;
267     }
268 
269     public PlexusIoResourceAttributes getResourceAttributes()
270     {
271         return attributes;
272     }
273 
274     public void setResourceAttributes( PlexusIoResourceAttributes attributes )
275     {
276         this.attributes = attributes;
277     }
278 
279     public @Nonnull
280     PlexusIoResource getResource()
281     {
282         return resource;
283     }
284 
285     public int getDefaultDirMode()
286     {
287         return defaultDirMode;
288     }
289 
290 }