From 9338f9dc1dcb081e6a7b53673b13a6e6337bf609 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 18 Nov 2020 16:42:30 +0100 Subject: [PATCH 1/2] Use 0 sized arrays when using toArray --- .../plexus/components/io/resources/proxy/ProxyFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/codehaus/plexus/components/io/resources/proxy/ProxyFactory.java b/src/main/java/org/codehaus/plexus/components/io/resources/proxy/ProxyFactory.java index 15597b03..4b4bf9bd 100644 --- a/src/main/java/org/codehaus/plexus/components/io/resources/proxy/ProxyFactory.java +++ b/src/main/java/org/codehaus/plexus/components/io/resources/proxy/ProxyFactory.java @@ -40,7 +40,7 @@ public static PlexusIoResource createProxy( @Nonnull PlexusIoResource target, Ob interfaces.add( ResourceAttributeSupplier.class ); return (PlexusIoResource) Proxy.newProxyInstance( PlexusIoResource.class.getClassLoader(), - interfaces.toArray( new Class[interfaces.size()] ), + interfaces.toArray( new Class[0] ), new ResourceInvocationHandler( target, alternateSupplier ) ); } } From 3f3058978c2aaeb1e7b026ba2a92efdab92bd7e7 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 18 Nov 2020 16:45:44 +0100 Subject: [PATCH 2/2] Avoid multiple access to the file system The plexus DirectoryScanner usually access the file system multiple times for each file, so cache all attributes --- .../io/attributes/FileAttributes.java | 126 ++++++++++++------ .../PlexusIoResourceAttributeUtils.java | 116 ++++++++-------- .../attributes/SimpleResourceAttributes.java | 10 ++ .../UserGroupModeFileAttributes.java | 47 +++++++ .../io/resources/PlexusIoFileResource.java | 26 ++++ .../PlexusIoFileResourceCollection.java | 4 +- 6 files changed, 230 insertions(+), 99 deletions(-) create mode 100644 src/main/java/org/codehaus/plexus/components/io/attributes/UserGroupModeFileAttributes.java diff --git a/src/main/java/org/codehaus/plexus/components/io/attributes/FileAttributes.java b/src/main/java/org/codehaus/plexus/components/io/attributes/FileAttributes.java index d052d200..6b90fdff 100644 --- a/src/main/java/org/codehaus/plexus/components/io/attributes/FileAttributes.java +++ b/src/main/java/org/codehaus/plexus/components/io/attributes/FileAttributes.java @@ -22,6 +22,7 @@ import java.nio.file.LinkOption; import java.nio.file.Path; import java.nio.file.attribute.FileOwnerAttributeView; +import java.nio.file.attribute.FileTime; import java.nio.file.attribute.PosixFilePermission; import java.security.Principal; import java.util.Collections; @@ -52,62 +53,77 @@ public class FileAttributes private final boolean symbolicLink; + private final boolean regularFile; + + private final boolean directory; + + private final boolean other; + private final int octalMode; private final Set permissions; + private final long size; + + private final FileTime lastModifiedTime; + public FileAttributes( @Nonnull File file, @Nonnull Map userCache, @Nonnull Map groupCache ) throws IOException { Path path = file.toPath(); - if ( AttributeUtils.isUnix( path ) ) + Set views = path.getFileSystem().supportedFileAttributeViews(); + String names; + if ( views.contains( "unix" ) ) + { + names = "unix:*"; + } + else if ( views.contains( "posix" ) ) { - Map attrs = Files.readAttributes( path, "unix:permissions,gid,uid,isSymbolicLink,mode", LinkOption.NOFOLLOW_LINKS ); - this.permissions = (Set) attrs.get( "permissions" ); - - groupId = (Integer) attrs.get( "gid" ); - - String groupName = groupCache.get( groupId ); - if ( groupName != null ) - { - this.groupName = groupName; - } - else - { - Object group = Files.getAttribute( path, "unix:group", LinkOption.NOFOLLOW_LINKS ); - this.groupName = ( (Principal) group ).getName(); - groupCache.put( groupId, this.groupName ); - } - userId = (Integer) attrs.get( "uid" ); - String userName = userCache.get( userId ); - if ( userName != null ) - { - this.userName = userName; - } - else - { - Object owner = Files.getAttribute( path, "unix:owner", LinkOption.NOFOLLOW_LINKS ); - this.userName = ( (Principal) owner ).getName(); - userCache.put( userId, this.userName ); - } - octalMode = (Integer) attrs.get( "mode" ) & 0xfff; // Mask off top bits for compatibilty. Maybe check if we - // can skip this - symbolicLink = (Boolean) attrs.get( "isSymbolicLink" ); + names = "posix:*"; } else { - FileOwnerAttributeView fa = AttributeUtils.getFileOwnershipInfo( file ); - this.userName = fa.getOwner().getName(); - userId = null; - this.groupName = null; - this.groupId = null; - octalMode = PlexusIoResourceAttributes.UNKNOWN_OCTAL_MODE; - permissions = Collections.emptySet(); - symbolicLink = Files.isSymbolicLink( path ); + names = "basic:*"; } + Map attrs = Files.readAttributes( path, names, LinkOption.NOFOLLOW_LINKS); + if ( !attrs.containsKey( "group" ) && !attrs.containsKey( "owner" ) && views.contains( "owner" ) ) + { + Map ownerAttrs = Files.readAttributes( path, "owner:*", LinkOption.NOFOLLOW_LINKS); + Map newAttrs = new HashMap<>( attrs ); + newAttrs.putAll( ownerAttrs ); + attrs = newAttrs; + } + this.groupId = (Integer) attrs.get( "gid" ); + this.groupName = attrs.containsKey( "group" ) ? ((Principal) attrs.get( "group" ) ).getName() : null; + this.userId = (Integer) attrs.get( "uid" ); + this.userName = attrs.containsKey( "owner" ) ? ((Principal) attrs.get( "owner" ) ).getName() : null; + this.symbolicLink = (Boolean) attrs.get( "isSymbolicLink" ); + this.regularFile = (Boolean) attrs.get( "isRegularFile" ); + this.directory = (Boolean) attrs.get( "isDirectory" ); + this.other = (Boolean) attrs.get( "isOther" ); + this.octalMode = attrs.containsKey( "mode" ) ? (Integer) attrs.get( "mode" ) & 0xfff : PlexusIoResourceAttributes.UNKNOWN_OCTAL_MODE; + this.permissions = attrs.containsKey( "permissions" ) ? (Set) attrs.get( "permissions" ) : Collections.emptySet(); + this.size = (Long) attrs.get( "size" ); + this.lastModifiedTime = (FileTime) attrs.get( "lastModifiedTime" ); + } + public FileAttributes( @Nullable Integer userId, String userName, @Nullable Integer groupId, @Nullable String groupName, + int octalMode, boolean symbolicLink, boolean regularFile, boolean directory, boolean other, + Set permissions, long size, FileTime lastModifiedTime) { + this.userId = userId; + this.userName = userName; + this.groupId = groupId; + this.groupName = groupName; + this.octalMode = octalMode; + this.symbolicLink = symbolicLink; + this.regularFile = regularFile; + this.directory = directory; + this.other = other; + this.permissions = permissions; + this.size = size; + this.lastModifiedTime = lastModifiedTime; } public static @Nonnull @@ -290,4 +306,34 @@ public boolean isSymbolicLink() { return symbolicLink; } + + public boolean isRegularFile() + { + return regularFile; + } + + public boolean isDirectory() + { + return directory; + } + + public boolean isOther() + { + return other; + } + + public long getSize() + { + return size; + } + + public FileTime getLastModifiedTime() + { + return lastModifiedTime; + } + + protected Set getPermissions() + { + return permissions; + } } \ No newline at end of file diff --git a/src/main/java/org/codehaus/plexus/components/io/attributes/PlexusIoResourceAttributeUtils.java b/src/main/java/org/codehaus/plexus/components/io/attributes/PlexusIoResourceAttributeUtils.java index 526a7c2e..3e2c44b8 100644 --- a/src/main/java/org/codehaus/plexus/components/io/attributes/PlexusIoResourceAttributeUtils.java +++ b/src/main/java/org/codehaus/plexus/components/io/attributes/PlexusIoResourceAttributeUtils.java @@ -43,69 +43,71 @@ public static PlexusIoResourceAttributes mergeAttributes( PlexusIoResourceAttrib { return base; } - SimpleResourceAttributes result; if ( base == null ) { - result = new SimpleResourceAttributes(); + return new SimpleResourceAttributes( + override.getUserId() != null && override.getUserId() != -1 + ? override.getUserId() + : def != null && def.getUserId() != null && def.getUserId() != -1 + ? def.getUserId() + : null, + override.getUserName() != null + ? override.getUserName() + : def != null + ? def.getUserName() + : null, + override.getGroupId() != null && override.getGroupId() != -1 + ? override.getGroupId() + : def != null && def.getGroupId() != null && def.getGroupId() != -1 + ? def.getGroupId() + : null, + override.getGroupName() != null + ? override.getGroupName() + : def != null + ? def.getGroupName() + : null, + override.getOctalMode() ); } else { - result = new SimpleResourceAttributes( base.getUserId(), base.getUserName(), base.getGroupId(), - base.getGroupName(), base.getOctalMode() ); - result.setSymbolicLink( base.isSymbolicLink() ); + Integer uid = override.getUserId() != null && override.getUserId() != -1 + ? override.getUserId() + : base.getUserId() != null && base.getUserId() != -1 + ? base.getUserId() + : def.getUserId() != null && def.getUserId() != -1 + ? def.getUserId() + : null; + String uname = override.getUserName() != null + ? override.getUserName() + : base.getUserName() != null + ? base.getUserName() + : def.getUserName(); + Integer gid = override.getGroupId() != null && override.getGroupId() != -1 + ? override.getGroupId() + : base.getGroupId() != null && base.getGroupId() != -1 + ? base.getGroupId() + : def.getGroupId() != null && def.getGroupId() != -1 + ? def.getGroupId() + : null; + String gname = override.getGroupName() != null + ? override.getGroupName() + : base.getGroupName() != null + ? base.getGroupName() + : def.getGroupName(); + int mode = override.getOctalMode() > 0 + ? override.getOctalMode() + : base.getOctalMode() >= 0 + ? base.getOctalMode() + : def.getOctalMode(); + if ( base instanceof FileAttributes ) + { + return new UserGroupModeFileAttributes( uid, uname, gid, gname, mode, (FileAttributes) base ); + } + else + { + return new SimpleResourceAttributes( uid, uname, gid, gname, mode, base.isSymbolicLink() ); + } } - - if ( override.getGroupId() != null && override.getGroupId() != -1 ) - { - result.setGroupId( override.getGroupId() ); - } - - if ( def != null && def.getGroupId() >= 0 && ( result.getGroupId() == null || result.getGroupId() < 0 ) ) - { - result.setGroupId( def.getGroupId() ); - } - - if ( override.getGroupName() != null ) - { - result.setGroupName( override.getGroupName() ); - } - - if ( def != null && result.getGroupName() == null ) - { - result.setGroupName( def.getGroupName() ); - } - - if ( override.getUserId() != null && override.getUserId() != -1 ) - { - result.setUserId( override.getUserId() ); - } - - if ( def != null && def.getUserId() >= 0 && ( result.getUserId() == null || result.getUserId() < 0 ) ) - { - result.setUserId( def.getUserId() ); - } - - if ( override.getUserName() != null ) - { - result.setUserName( override.getUserName() ); - } - - if ( def != null && result.getUserName() == null ) - { - result.setUserName( def.getUserName() ); - } - - if ( override.getOctalMode() > 0 ) - { - result.setOctalMode( override.getOctalMode() ); - } - - if ( def != null && result.getOctalMode() < 0 ) - { - result.setOctalMode( def.getOctalMode() ); - } - - return result; } public static boolean isGroupExecutableInOctal( int mode ) diff --git a/src/main/java/org/codehaus/plexus/components/io/attributes/SimpleResourceAttributes.java b/src/main/java/org/codehaus/plexus/components/io/attributes/SimpleResourceAttributes.java index 301905e5..a92d7411 100644 --- a/src/main/java/org/codehaus/plexus/components/io/attributes/SimpleResourceAttributes.java +++ b/src/main/java/org/codehaus/plexus/components/io/attributes/SimpleResourceAttributes.java @@ -46,6 +46,16 @@ public SimpleResourceAttributes( Integer uid, String userName, Integer gid, Stri this.mode = mode; } + public SimpleResourceAttributes( Integer uid, String userName, Integer gid, String groupName, int mode, boolean isSymbolicLink ) + { + this.uid = uid; + this.userName = userName; + this.gid = gid; + this.groupName = groupName; + this.mode = mode; + this.isSymbolicLink = isSymbolicLink; + } + public static PlexusIoResourceAttributes lastResortDummyAttributesForBrokenOS() { return new SimpleResourceAttributes(); diff --git a/src/main/java/org/codehaus/plexus/components/io/attributes/UserGroupModeFileAttributes.java b/src/main/java/org/codehaus/plexus/components/io/attributes/UserGroupModeFileAttributes.java new file mode 100644 index 00000000..37984b17 --- /dev/null +++ b/src/main/java/org/codehaus/plexus/components/io/attributes/UserGroupModeFileAttributes.java @@ -0,0 +1,47 @@ +package org.codehaus.plexus.components.io.attributes; + +/* + * Copyright 2007 The Codehaus Foundation. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import javax.annotation.Nullable; + +/* + * A very simple pojo based PlexusIoResourceAttributes without any kind of backing + */ +public class UserGroupModeFileAttributes + extends FileAttributes +{ + + public UserGroupModeFileAttributes( Integer uid, String userName, Integer gid, String groupName, int mode, FileAttributes base ) + { + super( uid, userName, gid, groupName, mode, + base.isSymbolicLink(), base.isRegularFile(), base.isDirectory(), base.isOther(), + base.getPermissions(), base.getSize(), base.getLastModifiedTime() ); + } + + public String toString() + { + return String.format( + "%nResource Attributes:%n------------------------------%nuser: %s%ngroup: %s%nuid: %d%ngid: %d%nmode: %06o", + getUserName() == null ? "" : getUserName(), + getGroupName() == null ? "" : getGroupName(), + getUserId() != null ? getUserId() : 0, + getGroupId() != null ? getGroupId() : 0, + getOctalMode() ); + } + + +} diff --git a/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResource.java b/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResource.java index c8ca266b..c999a32c 100755 --- a/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResource.java +++ b/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResource.java @@ -22,10 +22,12 @@ import java.io.IOException; import java.io.InputStream; import java.net.URL; +import java.nio.file.attribute.FileTime; import org.apache.commons.io.IOUtils; import org.apache.commons.io.output.DeferredFileOutputStream; import org.codehaus.plexus.components.io.attributes.AttributeUtils; +import org.codehaus.plexus.components.io.attributes.FileAttributes; import org.codehaus.plexus.components.io.attributes.PlexusIoResourceAttributes; import org.codehaus.plexus.components.io.functions.ContentSupplier; import org.codehaus.plexus.components.io.functions.FileSupplier; @@ -157,6 +159,10 @@ public long getSize() { if ( dfos == null ) { + if ( attributes instanceof FileAttributes) + { + return ( ( FileAttributes ) attributes ).getSize(); + } return getFile().length(); } if ( dfos.isInMemory() ) @@ -171,16 +177,28 @@ public long getSize() public boolean isDirectory() { + if ( attributes instanceof FileAttributes ) + { + return ( ( FileAttributes ) attributes ).isDirectory(); + } return getFile().isDirectory(); } public boolean isExisting() { + if ( attributes instanceof FileAttributes ) + { + return true; + } return getFile().exists(); } public boolean isFile() { + if ( attributes instanceof FileAttributes ) + { + return ( ( FileAttributes ) attributes ).isRegularFile(); + } return getFile().isFile(); } @@ -192,6 +210,14 @@ public PlexusIoResourceAttributes getAttributes() public long getLastModified() { + if ( attributes instanceof FileAttributes ) + { + FileTime lastModified = ( ( FileAttributes ) attributes ).getLastModifiedTime(); + if ( lastModified != null ) + { + return lastModified.toMillis(); + } + } return AttributeUtils.getLastModified( getFile() ); } diff --git a/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollection.java b/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollection.java index 2293de96..75631f15 100644 --- a/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollection.java +++ b/src/main/java/org/codehaus/plexus/components/io/resources/PlexusIoFileResourceCollection.java @@ -159,8 +159,8 @@ private void addResources( List result, String[] resources ) String sourceDir = name.replace( '\\', '/' ); File f = new File( dir, sourceDir ); - PlexusIoResourceAttributes attrs = new FileAttributes( f, cache1, cache2 ); - attrs = mergeAttributes( attrs, f.isDirectory() ); + FileAttributes fattrs = new FileAttributes( f, cache1, cache2 ); + PlexusIoResourceAttributes attrs = mergeAttributes( fattrs, fattrs.isDirectory() ); String remappedName = getName( name );