diff options
author | Olivier Lamy <olamy@apache.org> | 2013-12-12 11:26:40 +0000 |
---|---|---|
committer | Olivier Lamy <olamy@apache.org> | 2013-12-12 11:26:40 +0000 |
commit | 6b23332e9def8fc0e75be883f8a18807f0fccbbd (patch) | |
tree | 96de94a165343d5f8a69abe6f2bdd3f580e2931a | |
parent | 074386d154d4134fbfae4bc7642cd72d58422313 (diff) | |
download | archiva-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
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 Binary files differnew file mode 100644 index 000000000..0a4b1c542 --- /dev/null +++ b/archiva-modules/archiva-base/archiva-filelock/src/test/cassandra-all-2.0.3.jar 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() ); @@ -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> |