Skip to content

Commit 46245e4

Browse files
committed
Cache another set of file attributes access
The PlexusIoFileResource constructor calls file.lastModified(), file.length(), file.isFile(), file.isDirectory() and file.exists() which is very inefficient
1 parent 89339a3 commit 46245e4

File tree

8 files changed

+135
-40
lines changed

8 files changed

+135
-40
lines changed

src/main/java/org/codehaus/plexus/components/io/attributes/FileAttributes.java

+12-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@
4040
public class FileAttributes
4141
implements PlexusIoResourceAttributes
4242
{
43+
public static final LinkOption[] FOLLOW_LINK_OPTIONS = new LinkOption[] { };
44+
45+
public static final LinkOption[] NOFOLLOW_LINK_OPTIONS = new LinkOption[] { LinkOption.NOFOLLOW_LINKS };
46+
4347
@Nullable
4448
private final Integer groupId;
4549

@@ -81,7 +85,13 @@ public FileAttributes( @Nonnull File file, @Nonnull Map<Integer, String> userCac
8185
public FileAttributes( @Nonnull File file )
8286
throws IOException
8387
{
88+
this( file, false );
89+
}
8490

91+
public FileAttributes( @Nonnull File file, boolean followLinks )
92+
throws IOException
93+
{
94+
LinkOption[] options = followLinks ? FOLLOW_LINK_OPTIONS : NOFOLLOW_LINK_OPTIONS;
8595
Path path = file.toPath();
8696
Set<String> views = path.getFileSystem().supportedFileAttributeViews();
8797
String names;
@@ -97,10 +107,10 @@ else if ( views.contains( "posix" ) )
97107
{
98108
names = "basic:*";
99109
}
100-
Map<String, Object> attrs = Files.readAttributes( path, names, LinkOption.NOFOLLOW_LINKS );
110+
Map<String, Object> attrs = Files.readAttributes( path, names, options );
101111
if ( !attrs.containsKey( "group" ) && !attrs.containsKey( "owner" ) && views.contains( "owner" ) )
102112
{
103-
Map<String, Object> ownerAttrs = Files.readAttributes( path, "owner:*", LinkOption.NOFOLLOW_LINKS );
113+
Map<String, Object> ownerAttrs = Files.readAttributes( path, "owner:*", options );
104114
Map<String, Object> newAttrs = new HashMap<>( attrs );
105115
newAttrs.putAll( ownerAttrs );
106116
attrs = newAttrs;

src/main/java/org/codehaus/plexus/components/io/attributes/PlexusIoResourceAttributeUtils.java

+17-2
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,13 @@ public static boolean isOctalModeEnabled( int mode, int targetMode )
162162
public static PlexusIoResourceAttributes getFileAttributes( File file )
163163
throws IOException
164164
{
165-
Map<String, PlexusIoResourceAttributes> byPath = getFileAttributesByPath( file, false );
165+
return getFileAttributes( file, false );
166+
}
167+
168+
public static PlexusIoResourceAttributes getFileAttributes( File file, boolean followLinks )
169+
throws IOException
170+
{
171+
Map<String, PlexusIoResourceAttributes> byPath = getFileAttributesByPath( file, false, followLinks );
166172
final PlexusIoResourceAttributes o = byPath.get( file.getAbsolutePath() );
167173
if ( o == null )
168174
{
@@ -183,6 +189,15 @@ public static Map<String, PlexusIoResourceAttributes> getFileAttributesByPath( F
183189
Map<String, PlexusIoResourceAttributes> getFileAttributesByPath( @Nonnull File dir,
184190
boolean recursive )
185191
throws IOException
192+
{
193+
return getFileAttributesByPath( dir, recursive, false );
194+
}
195+
196+
public static @Nonnull
197+
Map<String, PlexusIoResourceAttributes> getFileAttributesByPath( @Nonnull File dir,
198+
boolean recursive,
199+
boolean followLinks )
200+
throws IOException
186201
{
187202
final List<String> fileAndDirectoryNames;
188203
if ( recursive && dir.isDirectory() )
@@ -198,7 +213,7 @@ Map<String, PlexusIoResourceAttributes> getFileAttributesByPath( @Nonnull File d
198213

199214
for ( String fileAndDirectoryName : fileAndDirectoryNames )
200215
{
201-
attributesByPath.put( fileAndDirectoryName, new FileAttributes( new File( fileAndDirectoryName ) ) );
216+
attributesByPath.put( fileAndDirectoryName, new FileAttributes( new File( fileAndDirectoryName ), followLinks ) );
202217
}
203218
return attributesByPath;
204219
}

src/main/java/org/codehaus/plexus/components/io/attributes/PlexusIoResourceAttributes.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ public interface PlexusIoResourceAttributes
7474
*/
7575
int getOctalMode();
7676

77-
@Nonnull
77+
//@Nonnull
7878
//String getOctalModeString();
7979

8080
/**

src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResource.java

+40-27
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.io.InputStream;
2424
import java.net.URL;
2525
import java.nio.file.attribute.FileTime;
26+
import java.util.function.Supplier;
2627

2728
import org.apache.commons.io.IOUtils;
2829
import org.apache.commons.io.output.DeferredFileOutputStream;
@@ -50,6 +51,9 @@ public class PlexusIoFileResource
5051
@Nonnull
5152
private final PlexusIoResourceAttributes attributes;
5253

54+
@Nonnull
55+
private final FileAttributes fileAttributes;
56+
5357
private final ContentSupplier contentSupplier;
5458

5559
private final DeferredFileOutputStream dfos;
@@ -61,23 +65,41 @@ protected PlexusIoFileResource( @Nonnull File file, @Nonnull String name,
6165
this( file, name, attrs, null, null );
6266
}
6367

64-
@SuppressWarnings( "ConstantConditions" )
6568
PlexusIoFileResource( @Nonnull final File file, @Nonnull String name, @Nonnull PlexusIoResourceAttributes attrs,
6669
final ContentSupplier contentSupplier, final InputStreamTransformer streamTransformer )
6770
throws IOException
6871
{
69-
super( name, file.lastModified(), file.length(), file.isFile(), file.isDirectory(), file.exists() );
70-
this.file = file;
72+
this( file, name, attrs,
73+
new FileAttributes( file, true ),
74+
contentSupplier, streamTransformer );
75+
}
7176

77+
PlexusIoFileResource( @Nonnull final File file, @Nonnull String name,
78+
@Nonnull PlexusIoResourceAttributes attrs, @Nonnull FileAttributes fileAttributes,
79+
final ContentSupplier contentSupplier, final InputStreamTransformer streamTransformer )
80+
throws IOException
81+
{
82+
super( name, fileAttributes.getLastModifiedTime().toMillis(), fileAttributes.getSize(),
83+
fileAttributes.isRegularFile(), fileAttributes.isDirectory(),
84+
fileAttributes.isRegularFile() || fileAttributes.isDirectory() || fileAttributes.isSymbolicLink() || fileAttributes.isOther() );
85+
this.file = file;
86+
this.attributes = requireNonNull( attrs, "attributes is null for file " + file.getName() );
87+
this.fileAttributes = requireNonNull( fileAttributes, "fileAttributes is null for file " + file.getName() );
7288
this.contentSupplier = contentSupplier != null ? contentSupplier : getRootContentSupplier( file );
7389

7490
boolean hasTransformer = streamTransformer != null && streamTransformer != identityTransformer;
7591
InputStreamTransformer transToUse = streamTransformer != null ? streamTransformer : identityTransformer;
7692

7793
dfos = hasTransformer && file.isFile() ? asDeferredStream( this.contentSupplier, transToUse, this ) : null;
78-
if ( attrs == null )
79-
throw new IllegalArgumentException( "attrs is null for file " + file.getName() );
80-
this.attributes = attrs;
94+
}
95+
96+
private static <T> T requireNonNull( T t, String message )
97+
{
98+
if ( t == null )
99+
{
100+
throw new IllegalArgumentException( message );
101+
}
102+
return t;
81103
}
82104

83105
private static DeferredFileOutputStream asDeferredStream( @Nonnull ContentSupplier supplier,
@@ -159,11 +181,7 @@ public long getSize()
159181
{
160182
if ( dfos == null )
161183
{
162-
if ( attributes instanceof FileAttributes)
163-
{
164-
return ( ( FileAttributes ) attributes ).getSize();
165-
}
166-
return getFile().length();
184+
return fileAttributes.getSize();
167185
}
168186
if ( dfos.isInMemory() )
169187
{
@@ -177,11 +195,7 @@ public long getSize()
177195

178196
public boolean isDirectory()
179197
{
180-
if ( attributes instanceof FileAttributes )
181-
{
182-
return ( ( FileAttributes ) attributes ).isDirectory();
183-
}
184-
return getFile().isDirectory();
198+
return fileAttributes.isDirectory();
185199
}
186200

187201
public boolean isExisting()
@@ -195,11 +209,7 @@ public boolean isExisting()
195209

196210
public boolean isFile()
197211
{
198-
if ( attributes instanceof FileAttributes )
199-
{
200-
return ( ( FileAttributes ) attributes ).isRegularFile();
201-
}
202-
return getFile().isFile();
212+
return fileAttributes.isRegularFile();
203213
}
204214

205215
@Nonnull
@@ -208,15 +218,18 @@ public PlexusIoResourceAttributes getAttributes()
208218
return attributes;
209219
}
210220

221+
@Nonnull
222+
public FileAttributes getFileAttributes()
223+
{
224+
return fileAttributes;
225+
}
226+
211227
public long getLastModified()
212228
{
213-
if ( attributes instanceof FileAttributes )
229+
FileTime lastModified = fileAttributes.getLastModifiedTime();
230+
if ( lastModified != null )
214231
{
215-
FileTime lastModified = ( ( FileAttributes ) attributes ).getLastModifiedTime();
216-
if ( lastModified != null )
217-
{
218-
return lastModified.toMillis();
219-
}
232+
return lastModified.toMillis();
220233
}
221234
return AttributeUtils.getLastModified( getFile() );
222235
}

src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoSymlinkResource.java

+27-7
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,36 @@ public class PlexusIoSymlinkResource
1515
implements SymlinkDestinationSupplier
1616
{
1717
private final String symLinkDestination;
18-
private final PlexusIoResource targetResource;
18+
private final PlexusIoFileResource targetResource;
1919

2020
PlexusIoSymlinkResource( @Nonnull File symlinkfile, String name, @Nonnull PlexusIoResourceAttributes attrs )
21-
throws IOException
21+
throws IOException
22+
{
23+
this( symlinkfile, name, attrs, symlinkfile.toPath() );
24+
}
25+
26+
PlexusIoSymlinkResource( @Nonnull File symlinkfile, String name, @Nonnull PlexusIoResourceAttributes attrs,
27+
Path linkPath )
28+
throws IOException
29+
{
30+
this( symlinkfile, name, attrs, linkPath, java.nio.file.Files.readSymbolicLink( linkPath ) );
31+
}
32+
33+
private PlexusIoSymlinkResource( @Nonnull File symlinkfile, String name, @Nonnull PlexusIoResourceAttributes attrs,
34+
Path path, Path linkPath )
35+
throws IOException
36+
{
37+
this( symlinkfile, name, attrs, linkPath.toString(),
38+
( PlexusIoFileResource ) ResourceFactory.createResource( path.resolveSibling( linkPath ).toFile() ) );
39+
}
40+
41+
private PlexusIoSymlinkResource( @Nonnull File symlinkfile, String name, @Nonnull PlexusIoResourceAttributes attrs,
42+
String symLinkDestination, PlexusIoFileResource targetResource )
43+
throws IOException
2244
{
23-
super( symlinkfile, name, attrs );
24-
Path path = symlinkfile.toPath();
25-
Path linkPath = java.nio.file.Files.readSymbolicLink( path );
26-
symLinkDestination = linkPath.toString();
27-
targetResource = ResourceFactory.createResource( path.resolveSibling( linkPath ).toFile() );
45+
super( symlinkfile, name, attrs, targetResource.getFileAttributes(), null, null );
46+
this.symLinkDestination = symLinkDestination;
47+
this.targetResource = targetResource;
2848
}
2949

3050
public String getSymlinkDestination()

src/main/java/org/codehaus/plexus/components/io/resources/ResourceFactory.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package org.codehaus.plexus.components.io.resources;
22

3+
import org.codehaus.plexus.components.io.attributes.FileAttributes;
34
import org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributes;
45
import org.codehaus.plexus.components.io.functions.ContentSupplier;
56
import org.codehaus.plexus.components.io.functions.InputStreamTransformer;
@@ -54,7 +55,8 @@ public static PlexusIoResource createResource( File f, String name, final Conten
5455
{
5556
boolean symbolicLink = attributes.isSymbolicLink();
5657
return symbolicLink ? new PlexusIoSymlinkResource( f, name, attributes )
57-
: new PlexusIoFileResource( f, name, attributes, contentSupplier, inputStreamTransformer );
58+
: new PlexusIoFileResource( f, name, attributes,
59+
new FileAttributes( f, true ), contentSupplier, inputStreamTransformer );
5860
}
5961

6062
}

src/test/java/org/codehaus/plexus/components/io/resources/PlexusIoPlexusIoFileResourceTest.java

+34
Original file line numberDiff line numberDiff line change
@@ -27,4 +27,38 @@ public void testRealSymlink()
2727
final File target = SymlinkUtils.readSymbolicLink( file );
2828
assertTrue( target.getName().endsWith( "targetDir" ) );
2929
}
30+
31+
public void testSymSymlinkFile()
32+
throws IOException
33+
{
34+
if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
35+
return;
36+
final File file = new File( "src/test/resources/symlinks/src/symSymR" );
37+
PlexusIoResource r = ResourceFactory.createResource( file );
38+
assertTrue( r.isSymbolicLink() );
39+
assertEquals( 38, r.getSize() );
40+
PlexusIoResource rL = ( ( PlexusIoSymlinkResource ) r ).getLink();
41+
assertFalse( rL instanceof PlexusIoSymlinkResource );
42+
PlexusIoResource rT = ( ( PlexusIoSymlinkResource ) r ).getTarget();
43+
assertTrue( rT instanceof PlexusIoSymlinkResource );
44+
PlexusIoResource rTT = ( ( PlexusIoSymlinkResource ) rT ).getTarget();
45+
assertFalse( rTT instanceof PlexusIoSymlinkResource );
46+
}
47+
48+
public void testSymlinkFile()
49+
throws IOException
50+
{
51+
if ( Os.isFamily( Os.FAMILY_WINDOWS ) )
52+
return;
53+
final File file = new File( "src/test/resources/symlinks/src/symR" );
54+
PlexusIoResource r = ResourceFactory.createResource( file );
55+
assertTrue( r.isSymbolicLink() );
56+
assertEquals( 38, r.getSize() );
57+
58+
final File file2 = new File( "src/test/resources/symlinks/src/symSymR" );
59+
PlexusIoResource r2 = ResourceFactory.createResource( file2 );
60+
assertTrue( r2.isSymbolicLink() );
61+
assertEquals( 38, r2.getSize() );
62+
PlexusIoResource r3 = ( ( PlexusIoSymlinkResource ) r2 ).getTarget();
63+
}
3064
}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
symR

0 commit comments

Comments
 (0)