aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlivier Lamy <olamy@apache.org>2013-12-12 11:26:40 +0000
committerOlivier Lamy <olamy@apache.org>2013-12-12 11:26:40 +0000
commit6b23332e9def8fc0e75be883f8a18807f0fccbbd (patch)
tree96de94a165343d5f8a69abe6f2bdd3f580e2931a
parent074386d154d4134fbfae4bc7642cd72d58422313 (diff)
downloadarchiva-6b23332e9def8fc0e75be883f8a18807f0fccbbd.tar.gz
archiva-6b23332e9def8fc0e75be883f8a18807f0fccbbd.zip
add a new module for file locking
git-svn-id: https://svn.apache.org/repos/asf/archiva/trunk@1550396 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--archiva-modules/archiva-base/archiva-configuration/pom.xml80
-rw-r--r--archiva-modules/archiva-base/archiva-filelock/pom.xml134
-rw-r--r--archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/DefaultFileLockManager.java177
-rw-r--r--archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/FileLockException.java13
-rw-r--r--archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/FileLockManager.java18
-rw-r--r--archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java105
-rw-r--r--archiva-modules/archiva-base/archiva-filelock/src/main/resources/META-INF/spring-context.xml34
-rw-r--r--archiva-modules/archiva-base/archiva-filelock/src/test/cassandra-all-2.0.3.jarbin0 -> 3369436 bytes
-rw-r--r--archiva-modules/archiva-base/archiva-filelock/src/test/java/org/apache/archiva/common/filelock/DefaultFileLockManagerTest.java208
-rw-r--r--archiva-modules/archiva-base/archiva-filelock/src/test/resources/log4j2-test.xml44
-rw-r--r--archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyConnectors.java4
-rw-r--r--archiva-modules/archiva-base/pom.xml1
-rw-r--r--archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java1
-rw-r--r--pom.xml5
14 files changed, 789 insertions, 35 deletions
diff --git a/archiva-modules/archiva-base/archiva-configuration/pom.xml b/archiva-modules/archiva-base/archiva-configuration/pom.xml
index 94d3fa219..577e3a884 100644
--- a/archiva-modules/archiva-base/archiva-configuration/pom.xml
+++ b/archiva-modules/archiva-base/archiva-configuration/pom.xml
@@ -40,6 +40,16 @@
</exclusions>
</dependency>
<dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
<groupId>org.apache.archiva.redback.components.registry</groupId>
<artifactId>spring-registry-commons</artifactId>
<exclusions>
@@ -52,41 +62,41 @@
<dependency>
<groupId>commons-configuration</groupId>
<artifactId>commons-configuration</artifactId>
- <exclusions>
- <exclusion>
- <groupId>commons-beanutils</groupId>
- <artifactId>commons-beanutils-core</artifactId>
- </exclusion>
- <!-- targeting JDK 1.4, xml parser/apis not needed -->
- <exclusion>
- <groupId>xerces</groupId>
- <artifactId>xerces</artifactId>
- </exclusion>
- <exclusion>
- <groupId>xerces</groupId>
- <artifactId>xercesImpl</artifactId>
- </exclusion>
- <exclusion>
- <groupId>xalan</groupId>
- <artifactId>xalan</artifactId>
- </exclusion>
- <exclusion>
- <groupId>xml-apis</groupId>
- <artifactId>xml-apis</artifactId>
- </exclusion>
- <exclusion>
- <groupId>servletapi</groupId>
- <artifactId>servletapi</artifactId>
- </exclusion>
- <exclusion>
- <groupId>commons-logging</groupId>
- <artifactId>commons-logging</artifactId>
- </exclusion>
- <exclusion>
- <groupId>ant</groupId>
- <artifactId>ant-optional</artifactId>
- </exclusion>
- </exclusions>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils-core</artifactId>
+ </exclusion>
+ <!-- targeting JDK 1.4, xml parser/apis not needed -->
+ <exclusion>
+ <groupId>xerces</groupId>
+ <artifactId>xerces</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xalan</groupId>
+ <artifactId>xalan</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>xml-apis</groupId>
+ <artifactId>xml-apis</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>servletapi</groupId>
+ <artifactId>servletapi</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ <exclusion>
+ <groupId>ant</groupId>
+ <artifactId>ant-optional</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
<groupId>org.apache.ant</groupId>
diff --git a/archiva-modules/archiva-base/archiva-filelock/pom.xml b/archiva-modules/archiva-base/archiva-filelock/pom.xml
new file mode 100644
index 000000000..d8ab67df0
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-filelock/pom.xml
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ 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.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+ <parent>
+ <groupId>org.apache.archiva</groupId>
+ <artifactId>archiva-base</artifactId>
+ <version>2.0.0-SNAPSHOT</version>
+ </parent>
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>archiva-filelock</artifactId>
+ <packaging>bundle</packaging>
+ <name>Archiva Base :: FileLock</name>
+ <dependencies>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <exclusions>
+ <exclusion>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.inject</groupId>
+ <artifactId>javax.inject</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-jcl</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>com.googlecode.multithreadedtc</groupId>
+ <artifactId>multithreadedtc</artifactId>
+ <version>1.01</version>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-slf4j-impl</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Bundle-SymbolicName>org.apache.archiva.common</Bundle-SymbolicName>
+ <Bundle-Version>${project.version}</Bundle-Version>
+ <Export-Package>
+ org.apache.archiva.common*;version=${project.version}
+ </Export-Package>
+ <Import-Package>
+
+ </Import-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-surefire-plugin</artifactId>
+ <configuration>
+ <systemPropertyVariables>
+ <buildDirectory>${project.build.directory}</buildDirectory>
+ <java.io.tmpdir>${project.build.directory}</java.io.tmpdir>
+ </systemPropertyVariables>
+ </configuration>
+ </plugin>
+ </plugins>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.rat</groupId>
+ <artifactId>apache-rat-plugin</artifactId>
+ <configuration>
+ <excludes>
+ </excludes>
+ </configuration>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/DefaultFileLockManager.java b/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/DefaultFileLockManager.java
new file mode 100644
index 000000000..795760672
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/DefaultFileLockManager.java
@@ -0,0 +1,177 @@
+package org.apache.archiva.common.filelock;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+import java.io.File;
+import java.io.IOException;
+
+import java.nio.channels.OverlappingFileLockException;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author Olivier Lamy
+ */
+@Service("fileLockManager#default")
+public class DefaultFileLockManager
+ implements FileLockManager
+{
+ private static final ConcurrentMap<File, Lock> lockFiles = new ConcurrentHashMap<File, Lock>( 64 );
+
+ private boolean skipLocking = false;
+
+ private Logger log = LoggerFactory.getLogger( getClass() );
+
+ @Override
+ public Lock readFileLock( File file )
+ throws FileLockException
+ {
+ if ( skipLocking )
+ {
+ try
+ {
+ return new Lock( file, false );
+ }
+ catch ( IOException e )
+ {
+ throw new FileLockException( e.getMessage(), e );
+ }
+ }
+ Lock lock = lockFiles.get( file );
+ if ( lock == null )
+ {
+ try
+ {
+ lock = new Lock( file, false );
+ Lock current = lockFiles.putIfAbsent( file, lock );
+ if ( current != null )
+ {
+ lock = current;
+ }
+ return lock;
+ }
+ catch ( IOException e )
+ {
+ throw new FileLockException( e.getMessage(), e );
+ }
+ catch ( OverlappingFileLockException e )
+ {
+ log.debug( "OverlappingFileLockException: {}", e.getMessage() );
+ if ( lock == null )
+ {
+ lock = lockFiles.get( file );
+ }
+ }
+ }
+ // FIXME add a timeout on getting that!!!
+ while ( true )
+ {
+ log.debug( "wait read lock" );
+ synchronized ( lock )
+ {
+ if ( lock.getFileLock().isShared() || !lock.getFileLock().isValid() )
+ {
+ lock.addFileClient( Thread.currentThread() );
+ return lock;
+ }
+ }
+ }
+ //return lock;
+ }
+
+ @Override
+ public Lock writeFileLock( File file )
+ throws FileLockException
+ {
+ try
+ {
+ if ( skipLocking )
+ {
+ return new Lock( file, true );
+ }
+
+ // FIXME add a timeout on getting that!!!
+ while ( true )
+ {
+ Lock lock = lockFiles.get( file );
+ log.debug( "wait write lock" );
+ if ( lock != null )
+ {
+ synchronized ( lock )
+ {
+ if ( lock.getFileLock().isValid() || lock.getFileClients().size() > 0 )
+ {
+ continue;
+ }
+ return lock;
+ }
+ }
+ else
+ {
+ try
+ {
+ lock = new Lock( file, true );
+ }
+ catch ( OverlappingFileLockException e )
+ {
+ log.debug( "OverlappingFileLockException: {}", e.getMessage() );
+ if ( lock == null )
+ {
+ lock = lockFiles.get( file );
+ }
+
+ lock = lockFiles.get( file );
+ log.debug( "OverlappingFileLockException get: {}", lock );
+ }
+ Lock current = lockFiles.putIfAbsent( file, lock );
+ if ( current != null )
+ {
+ lock = current;
+ }
+ return lock;
+ }
+ }
+
+ }
+ catch ( IOException e )
+ {
+ throw new FileLockException( e.getMessage(), e );
+ }
+ }
+
+ @Override
+ public void release( Lock lock )
+ throws FileLockException
+ {
+ if ( lock == null )
+ {
+ log.debug( "skip releasing null" );
+ return;
+ }
+ if ( skipLocking )
+ {
+ return;
+ }
+ try
+ {
+ if ( lock.isWrite().get() )
+ {
+ lock.getFileLock().release();
+ }
+ synchronized ( lock )
+ {
+ lock.close();
+ if ( lock.getFileClients().size() < 1 )
+ {
+ lockFiles.remove( lock.getFile() );
+ }
+ }
+ }
+ catch ( IOException e )
+ {
+ throw new FileLockException( e.getMessage(), e );
+ }
+ }
+}
diff --git a/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/FileLockException.java b/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/FileLockException.java
new file mode 100644
index 000000000..2d14859c0
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/FileLockException.java
@@ -0,0 +1,13 @@
+package org.apache.archiva.common.filelock;
+
+/**
+ * @author Olivier Lamy
+ */
+public class FileLockException
+ extends Exception
+{
+ public FileLockException( String s, Throwable throwable )
+ {
+ super( s, throwable );
+ }
+}
diff --git a/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/FileLockManager.java b/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/FileLockManager.java
new file mode 100644
index 000000000..5f3832634
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/FileLockManager.java
@@ -0,0 +1,18 @@
+package org.apache.archiva.common.filelock;
+
+import java.io.File;
+
+/**
+ * @author Olivier Lamy
+ */
+public interface FileLockManager
+{
+ Lock writeFileLock( File file )
+ throws FileLockException;
+
+ Lock readFileLock( File file )
+ throws FileLockException;
+
+ void release( Lock lock )
+ throws FileLockException;
+}
diff --git a/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java b/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java
new file mode 100644
index 000000000..6baabbc05
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-filelock/src/main/java/org/apache/archiva/common/filelock/Lock.java
@@ -0,0 +1,105 @@
+package org.apache.archiva.common.filelock;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileLock;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * @author Olivier Lamy
+ */
+public class Lock
+{
+ private File file;
+
+ private AtomicBoolean write;
+
+ private final Map<Thread, AtomicInteger> fileClients = new HashMap<Thread, AtomicInteger>();
+
+ private FileLock fileLock;
+
+ public Lock( File file, boolean write )
+ throws FileNotFoundException, IOException
+ {
+ this.file = file;
+ this.write = new AtomicBoolean( write );
+ this.openLock( write );
+ }
+
+ public File getFile()
+ {
+ return file;
+ }
+
+ public AtomicBoolean isWrite()
+ {
+ return write;
+ }
+
+ public void setFile( File file )
+ {
+ this.file = file;
+ }
+
+ public void setWrite( boolean write )
+ {
+ this.write.set( write );
+ }
+
+ public FileLock getFileLock()
+ {
+ return fileLock;
+ }
+
+ public void setFileLock( FileLock fileLock )
+ {
+ this.fileLock = fileLock;
+ }
+
+ public Map<Thread, AtomicInteger> getFileClients()
+ {
+ return fileClients;
+ }
+
+ public void addFileClient( Thread thread )
+ {
+ this.fileClients.put( thread, new AtomicInteger( 1 ) );
+ }
+
+ public boolean removeFileClient( Thread thread )
+ {
+ return this.fileClients.remove( thread ) != null;
+ }
+
+ protected void close()
+ throws IOException
+ {
+ if ( this.write.get() )
+ {
+ this.fileLock.release();
+ fileClients.remove( Thread.currentThread() );
+ }
+ }
+
+ public void openLock( boolean write )
+ throws IOException
+ {
+ fileClients.put( Thread.currentThread(), new AtomicInteger( 1 ) );
+ RandomAccessFile raf = new RandomAccessFile( file, write ? "rw" : "r" );
+ this.fileLock = raf.getChannel().lock( 1, 1, !write );
+ }
+
+ @Override
+ public String toString()
+ {
+ final StringBuilder sb = new StringBuilder( "Lock{" );
+ sb.append( "file=" ).append( file );
+ sb.append( '}' );
+ return sb.toString();
+ }
+}
diff --git a/archiva-modules/archiva-base/archiva-filelock/src/main/resources/META-INF/spring-context.xml b/archiva-modules/archiva-base/archiva-filelock/src/main/resources/META-INF/spring-context.xml
new file mode 100644
index 000000000..944c8d606
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-filelock/src/main/resources/META-INF/spring-context.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0"?>
+
+<!--
+ ~ 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.
+ -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xsi:schemaLocation="http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context-3.0.xsd"
+ default-lazy-init="true">
+
+ <context:annotation-config/>
+ <context:component-scan base-package="org.apache.archiva.common.filelock"/>
+
+
+</beans> \ No newline at end of file
diff --git a/archiva-modules/archiva-base/archiva-filelock/src/test/cassandra-all-2.0.3.jar b/archiva-modules/archiva-base/archiva-filelock/src/test/cassandra-all-2.0.3.jar
new file mode 100644
index 000000000..0a4b1c542
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-filelock/src/test/cassandra-all-2.0.3.jar
Binary files differ
diff --git a/archiva-modules/archiva-base/archiva-filelock/src/test/java/org/apache/archiva/common/filelock/DefaultFileLockManagerTest.java b/archiva-modules/archiva-base/archiva-filelock/src/test/java/org/apache/archiva/common/filelock/DefaultFileLockManagerTest.java
new file mode 100644
index 000000000..86fb24dd3
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-filelock/src/test/java/org/apache/archiva/common/filelock/DefaultFileLockManagerTest.java
@@ -0,0 +1,208 @@
+package org.apache.archiva.common.filelock;
+
+import edu.umd.cs.mtc.MultithreadedTestCase;
+import edu.umd.cs.mtc.TestFramework;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.IOUtils;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * @author Olivier Lamy
+ */
+@RunWith( SpringJUnit4ClassRunner.class )
+@ContextConfiguration( locations = { "classpath*:/META-INF/spring-context.xml" } )
+public class DefaultFileLockManagerTest
+{
+
+ final Logger logger = LoggerFactory.getLogger( getClass() );
+
+ @Inject
+ @Named( value = "fileLockManager#default" )
+ FileLockManager fileLockManager;
+
+ class ConcurentFileWrite
+ extends MultithreadedTestCase
+ {
+
+ FileLockManager fileLockManager;
+
+ File file = new File( System.getProperty( "buildDirectory" ), "foo.txt" );
+
+ File largeJar = new File( System.getProperty( "basedir" ), "src/test/cassandra-all-2.0.3.jar" );
+
+ ConcurentFileWrite( FileLockManager fileLockManager )
+ throws IOException
+ {
+ this.fileLockManager = fileLockManager;
+ file.createNewFile();
+
+ }
+
+ @Override
+ public void initialize()
+ {
+
+ }
+
+ public void thread1()
+ throws FileLockException, IOException
+ {
+ logger.info( "thread1" );
+ Lock lock = fileLockManager.writeFileLock( this.file );
+ try
+ {
+ lock.getFile().delete();
+ FileUtils.copyFile( largeJar, lock.getFile() );
+ }
+ finally
+ {
+ fileLockManager.release( lock );
+ }
+ logger.info( "thread1 ok" );
+ }
+
+ public void thread2()
+ throws FileLockException, IOException
+ {
+ logger.info( "thread2" );
+ Lock lock = fileLockManager.writeFileLock( this.file );
+ try
+ {
+ lock.getFile().delete();
+ FileUtils.copyFile( largeJar, lock.getFile() );
+ }
+ finally
+ {
+ fileLockManager.release( lock );
+ }
+ logger.info( "thread2 ok" );
+ }
+
+ public void thread3()
+ throws FileLockException, IOException
+ {
+ logger.info( "thread3" );
+ Lock lock = fileLockManager.readFileLock( this.file );
+ try
+ {
+ IOUtils.copy( new FileInputStream( lock.getFile() ),
+ new FileOutputStream( File.createTempFile( "foo", ".jar" ) ) );
+ }
+ finally
+ {
+ fileLockManager.release( lock );
+ }
+ logger.info( "thread3 ok" );
+ }
+
+ public void thread4()
+ throws FileLockException, IOException
+ {
+ logger.info( "thread4" );
+ Lock lock = fileLockManager.writeFileLock( this.file );
+ try
+ {
+ lock.getFile().delete();
+ FileUtils.copyFile( largeJar, lock.getFile() );
+ }
+ finally
+ {
+ fileLockManager.release( lock );
+ }
+ logger.info( "thread4 ok" );
+ }
+
+ public void thread5()
+ throws FileLockException, IOException
+ {
+ logger.info( "thread5" );
+ Lock lock = fileLockManager.writeFileLock( this.file );
+ try
+ {
+ lock.getFile().delete();
+ FileUtils.copyFile( largeJar, lock.getFile() );
+ }
+ finally
+ {
+ fileLockManager.release( lock );
+ }
+ logger.info( "thread5 ok" );
+ }
+
+ public void thread6()
+ throws FileLockException, IOException
+ {
+ logger.info( "thread6" );
+ Lock lock = fileLockManager.readFileLock( this.file );
+ try
+ {
+ IOUtils.copy( new FileInputStream( lock.getFile() ),
+ new FileOutputStream( File.createTempFile( "foo", ".jar" ) ) );
+ }
+ finally
+ {
+ fileLockManager.release( lock );
+ }
+ logger.info( "thread6 ok" );
+ }
+
+ public void thread7()
+ throws FileLockException, IOException
+ {
+ logger.info( "thread7" );
+ Lock lock = fileLockManager.writeFileLock( this.file );
+ try
+ {
+ lock.getFile().delete();
+ FileUtils.copyFile( largeJar, lock.getFile() );
+ }
+ finally
+ {
+ fileLockManager.release( lock );
+ }
+ logger.info( "thread7 ok" );
+ }
+
+ public void thread8()
+ throws FileLockException, IOException
+ {
+ logger.info( "thread8" );
+ Lock lock = fileLockManager.readFileLock( this.file );
+ try
+ {
+ IOUtils.copy( new FileInputStream( lock.getFile() ),
+ new FileOutputStream( File.createTempFile( "foo", ".jar" ) ) );
+ }
+ finally
+ {
+ fileLockManager.release( lock );
+ }
+ logger.info( "thread8 ok" );
+ }
+
+
+
+ }
+
+ @Test
+ public void testWrite()
+ throws Throwable
+ {
+ ConcurentFileWrite concurentFileWrite = new ConcurentFileWrite( fileLockManager );
+ //concurentFileWrite.setTrace( true );
+ TestFramework.runOnce( concurentFileWrite );
+ }
+
+}
diff --git a/archiva-modules/archiva-base/archiva-filelock/src/test/resources/log4j2-test.xml b/archiva-modules/archiva-base/archiva-filelock/src/test/resources/log4j2-test.xml
new file mode 100644
index 000000000..93e519df7
--- /dev/null
+++ b/archiva-modules/archiva-base/archiva-filelock/src/test/resources/log4j2-test.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!--
+ ~ 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.
+ -->
+
+
+<configuration status="debug">
+
+
+
+ <appenders>
+ <Console name="console" target="SYSTEM_OUT">
+ <!--PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/-->
+ <PatternLayout pattern="%highlight{%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n}" />
+ </Console>
+
+ </appenders>
+ <loggers>
+
+
+ <logger name="org.apache.archiva.common.filelock" level="debug"/>
+
+ <root level="info" includeLocation="true">
+ <appender-ref ref="console"/>
+ </root>
+ </loggers>
+</configuration>
+
+
diff --git a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyConnectors.java b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyConnectors.java
index 9b78010e6..72eb22e8e 100644
--- a/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyConnectors.java
+++ b/archiva-modules/archiva-base/archiva-proxy/src/main/java/org/apache/archiva/proxy/DefaultRepositoryProxyConnectors.java
@@ -83,6 +83,7 @@ import javax.inject.Inject;
import javax.inject.Named;
import java.io.File;
import java.io.IOException;
+import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
@@ -1091,6 +1092,9 @@ public class DefaultRepositoryProxyConnectors
}
target.getParentFile().mkdirs();
+ // TODO file lock library
+ RandomAccessFile raf;
+
if ( !temp.renameTo( target ) )
{
log.warn( "Unable to rename tmp file to its final name... resorting to copy command." );
diff --git a/archiva-modules/archiva-base/pom.xml b/archiva-modules/archiva-base/pom.xml
index d8d8d7748..429ee5257 100644
--- a/archiva-modules/archiva-base/pom.xml
+++ b/archiva-modules/archiva-base/pom.xml
@@ -32,6 +32,7 @@
<modules>
<module>archiva-test-utils</module>
<module>archiva-common</module>
+ <module>archiva-filelock</module>
<module>archiva-model</module>
<module>archiva-configuration</module>
<module>archiva-checksum</module>
diff --git a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java
index e7de17e84..5b76c7cfb 100644
--- a/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java
+++ b/archiva-modules/archiva-web/archiva-webdav/src/main/java/org/apache/archiva/webdav/ArchivaDavResource.java
@@ -201,6 +201,7 @@ public class ArchivaDavResource
FileInputStream is = null;
try
{
+ // TODO file lock library
// Write content to stream
is = new FileInputStream( localResource );
IOUtils.copy( is, outputContext.getOutputStream() );
diff --git a/pom.xml b/pom.xml
index 2d1f6448a..0c28cbbfc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -262,6 +262,11 @@
</dependency>
<dependency>
<groupId>org.apache.archiva</groupId>
+ <artifactId>archiva-filelock</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.archiva</groupId>
<artifactId>archiva-configuration</artifactId>
<version>${project.version}</version>
</dependency>