Permalink
Browse files

[PLXCOMP-156] Poor performance in DirectoryArchiver due to unnecessar…

…y native chmod calls.

use dynamically if available file permission mode with jvm 1.6 methods in File
  • Loading branch information...
olamy
olamy committed Sep 24, 2010
1 parent 04af56c commit aa74285f7a0cc87054e0ce2b0920916bda18299d
@@ -1,19 +1,21 @@
package org.codehaus.plexus.archiver.util;
import java.io.File;
import java.lang.reflect.Method;
import org.codehaus.plexus.archiver.ArchiverException;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.Os;
import org.codehaus.plexus.util.cli.CommandLineException;
import org.codehaus.plexus.util.cli.CommandLineUtils;
import org.codehaus.plexus.util.cli.Commandline;
import java.io.File;
public final class ArchiveEntryUtils
{
private ArchiveEntryUtils()
{
// no op
}
public static void chmod( File file, int mode, Logger logger )
@@ -26,12 +28,21 @@ public static void chmod( File file, int mode, Logger logger )
String m = Integer.toOctalString( mode & 0xfff );
if ( isJvmFilePermAvailable() )
{
applyPermissionsWithJvm( file, m, logger );
return;
}
try
{
Commandline commandline = new Commandline();
commandline.setWorkingDirectory( file.getParentFile().getAbsolutePath() );
logger.info( "mode " + mode + ", chmod " + m );
commandline.setExecutable( "chmod" );
commandline.createArg().setValue( m );
@@ -70,5 +81,54 @@ public static void chmod( File file, int mode, Logger logger )
throw new ArchiverException( "Error while executing chmod.", e );
}
}
/**
*
* @return true if file permissions for JVM are available ie is 1.6
*/
private static boolean isJvmFilePermAvailable()
{
try
{
return File.class.getMethod( "setReadable", new Class[] { Boolean.class } ) != null;
}
catch ( Exception e )
{
return false;
}
}
private static void applyPermissionsWithJvm( File file, String mode, Logger logger )
{
FilePermission filePermission = FilePermissionUtils.getFilePermissionFromMode( mode, logger );
Method method;
try
{
method = File.class.getMethod( "setReadable", new Class[] { Boolean.class, Boolean.class } );
method.invoke( file,
new Object[] {
Boolean.valueOf( filePermission.isReadable() ),
Boolean.valueOf( filePermission.isOwnerOnlyReadable() ) } );
method = File.class.getMethod( "setExecutable", new Class[] { Boolean.class, Boolean.class } );
method.invoke( file,
new Object[] {
Boolean.valueOf( filePermission.isExecutable() ),
Boolean.valueOf( filePermission.isOwnerOnlyExecutable() ) } );
method = File.class.getMethod( "setWritable", new Class[] { Boolean.class, Boolean.class } );
method.invoke( file,
new Object[] {
Boolean.valueOf( filePermission.isWritable() ),
Boolean.valueOf( filePermission.isOwnerOnlyWritable() ) } );
}
catch ( Exception e )
{
logger.error( "error calling dynamically file permissons with jvm " + e.getMessage(), e );
throw new RuntimeException( "error calling dynamically file permissons with jvm " + e.getMessage(), e );
}
}
}
@@ -0,0 +1,120 @@
package org.codehaus.plexus.archiver.util;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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.
*/
/**
* @author Olivier Lamy
* @since 1.0.1
*
*/
public class FilePermission
{
private boolean executable;
private boolean ownerOnlyExecutable;
private boolean ownerOnlyReadable;
private boolean readable;
private boolean ownerOnlyWritable;
private boolean writable;
public FilePermission( boolean executable, boolean ownerOnlyExecutable, boolean ownerOnlyReadable,
boolean readable, boolean ownerOnlyWritable, boolean writable )
{
this.executable = executable;
this.ownerOnlyExecutable = ownerOnlyExecutable;
this.ownerOnlyReadable = ownerOnlyReadable;
this.readable = readable;
this.ownerOnlyWritable = ownerOnlyWritable;
this.writable = writable;
}
public boolean isExecutable()
{
return executable;
}
public void setExecutable( boolean executable )
{
this.executable = executable;
}
public boolean isOwnerOnlyExecutable()
{
return ownerOnlyExecutable;
}
public void setOwnerOnlyExecutable( boolean ownerOnlyExecutable )
{
this.ownerOnlyExecutable = ownerOnlyExecutable;
}
public boolean isOwnerOnlyReadable()
{
return ownerOnlyReadable;
}
public void setOwnerOnlyReadable( boolean ownerOnlyReadable )
{
this.ownerOnlyReadable = ownerOnlyReadable;
}
public boolean isReadable()
{
return readable;
}
public void setReadable( boolean readable )
{
this.readable = readable;
}
public boolean isOwnerOnlyWritable()
{
return ownerOnlyWritable;
}
public void setOwnerOnlyWritable( boolean ownerOnlyWritable )
{
this.ownerOnlyWritable = ownerOnlyWritable;
}
public boolean isWritable()
{
return writable;
}
public void setWritable( boolean writable )
{
this.writable = writable;
}
public String toString()
{
return "FilePermission [executable=" + executable + ", ownerOnlyExecutable=" + ownerOnlyExecutable
+ ", ownerOnlyReadable=" + ownerOnlyReadable + ", readable=" + readable + ", ownerOnlyWritable="
+ ownerOnlyWritable + ", writable=" + writable + "]";
}
}
@@ -0,0 +1,163 @@
package org.codehaus.plexus.archiver.util;
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 java.util.ArrayList;
import java.util.List;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.StringUtils;
/**
* @author Olivier Lamy
* @since 1.0.1
*
*/
public class FilePermissionUtils
{
private FilePermissionUtils()
{
// no op
}
/**
* @param mode file mode "a la" unix ie 664, 440, etc
* @return FilePermission associated to the mode (group permission are ignored here)
*/
public static FilePermission getFilePermissionFromMode( String mode, Logger logger )
{
if ( StringUtils.isBlank( mode ) )
{
throw new IllegalArgumentException( " file mode cannot be empty" );
}
// 4 characters works on some unix (ie solaris)
if ( mode.length() != 3 && mode.length() != 4 )
{
throw new IllegalArgumentException( " file mode must be 3 or 4 characters" );
}
List modes = new ArrayList(mode.length());
for (int i = 0,size = mode.length();i<size;i++)
{
modes.add( String.valueOf( mode.charAt( i ) ) );
}
boolean executable = false, ownerOnlyExecutable = true, ownerOnlyReadable = true, readable = false, ownerOnlyWritable = true, writable = false;
// handle user perm
try
{
int userMode = Integer.valueOf( (String) modes.get( mode.length() == 4 ? 1 : 0 ) ).intValue();
switch ( userMode )
{
case 0 :
break;
case 1:
executable = true;
break;
case 2:
writable = true;
break;
case 3:
writable = true;
executable = true;
break;
case 4:
readable = true;
break;
case 5:
readable = true;
executable = true;
break;
case 7:
writable = true;
readable = true;
executable = true;
break;
default:
logger.warn( "ignore file mode " + userMode );
}
}
catch ( NumberFormatException e )
{
throw new IllegalArgumentException( " file mode must contains only number " + mode );
}
// handle all perm
try
{
int allMode = Integer.valueOf( (String) modes.get( mode.length() == 4 ? 3 : 2 ) ).intValue();
switch ( allMode )
{
case 0 :
break;
case 1:
executable = true;
ownerOnlyExecutable = false;
break;
case 2:
writable = true;
ownerOnlyWritable = false;
break;
case 3:
writable = true;
executable = true;
ownerOnlyExecutable = false;
ownerOnlyWritable = false;
break;
case 4:
readable = true;
ownerOnlyReadable = false;
break;
case 5:
readable = true;
executable = true;
ownerOnlyReadable = false;
ownerOnlyExecutable = false;
break;
case 7:
writable = true;
readable = true;
executable = true;
ownerOnlyReadable = false;
ownerOnlyExecutable = false;
ownerOnlyWritable = false;
break;
default:
logger.warn( "ignore file mode " + allMode );
}
}
catch ( NumberFormatException e )
{
throw new IllegalArgumentException( " file mode must contains only number " + mode );
}
return new FilePermission( executable, ownerOnlyExecutable, ownerOnlyReadable, readable, ownerOnlyWritable,
writable );
}
}
Oops, something went wrong.

0 comments on commit aa74285

Please sign in to comment.