CCM NG: XAFileSystemAdapter

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4644 8810af33-2d31-482b-a856-94f89814c4df
pull/2/head
jensp 2017-03-27 15:47:08 +00:00
parent dd933cfd29
commit 9a190a880d
4 changed files with 386 additions and 8 deletions

View File

@ -34,8 +34,6 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;

View File

@ -0,0 +1,52 @@
<?xml version="1.0"?>
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.libreccm</groupId>
<artifactId>libreccm-parent</artifactId>
<version>7.0.0-SNAPSHOT</version>
</parent>
<groupId>org.libreccm.files</groupId>
<artifactId>ccm-xafilesystemadapter</artifactId>
<version>1.0.0-SNAPSHOT</version>
<name>ccm-xafilesystemadapter</name>
<url>http://www.libreccm.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
</dependency>
<dependency>
<groupId>org.libreccm</groupId>
<artifactId>ccm-core</artifactId>
<version>7.0.0-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>net.java.xadisk</groupId>
<artifactId>xadisk</artifactId>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,324 @@
package org.libreccm.files;
import org.libreccm.core.UnexpectedErrorException;
import org.xadisk.additional.XAFileInputStreamWrapper;
import org.xadisk.additional.XAFileOutputStreamWrapper;
import org.xadisk.bridge.proxies.interfaces.XAFileInputStream;
import org.xadisk.bridge.proxies.interfaces.XAFileOutputStream;
import org.xadisk.connector.outbound.XADiskConnection;
import org.xadisk.connector.outbound.XADiskConnectionFactory;
import org.xadisk.filesystem.exceptions.FileNotExistsException;
import org.xadisk.filesystem.exceptions.FileUnderUseException;
import org.xadisk.filesystem.exceptions.InsufficientPermissionOnFileException;
import org.xadisk.filesystem.exceptions.LockingFailedException;
import org.xadisk.filesystem.exceptions.NoTransactionAssociatedException;
import java.io.File;
import javax.resource.ResourceException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.transaction.Transactional;
/**
* An implementation of the {@link FileSystemAdapter} which uses XADisk to provides
* a transaction safe access to the file system.
*
* This {@link FileSystemAdapter} requires that XADisk.rar is deployed into the
* application server and that a resource adapter is configured to provided
* access to the file system. Please refer the documentation of this module
* for more information.
*
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
public class XAFileSystemAdapter implements FileSystemAdapter {
private Optional<XADiskConnectionFactory> lookupConnectionFactory() {
final InitialContext context;
try {
context = new InitialContext();
} catch (NamingException ex) {
throw new UnexpectedErrorException(
"Failed to create InitialContext for JNDI lookup.", ex);
}
final Object result;
try {
result = context.lookup("java:/org/libreccm/files/xadiskcf");
} catch (NamingException ex) {
throw new UnexpectedErrorException("Failed to lookup "
+ "XAConnectionFactory at JNDI URL "
+ "java:/org/libreccm/files/xadiskcf",
ex);
}
if (result == null) {
return Optional.empty();
} else {
return Optional.of((XADiskConnectionFactory) result);
}
}
private XADiskConnection connect() {
final XADiskConnectionFactory xadiskcf = lookupConnectionFactory()
.orElseThrow(() -> new UnexpectedErrorException(
"No XADiskConnectionFactory available."));
final XADiskConnection connection;
try {
connection = xadiskcf.getConnection();
} catch (ResourceException ex) {
throw new UnexpectedErrorException(
"Failed to create XADiskConnection.", ex);
}
return connection;
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public boolean isConfigured() {
return lookupConnectionFactory().isPresent();
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public Reader createReader(final String path) throws
FileDoesNotExistException,
FileAccessException,
InsufficientPermissionsException {
return new InputStreamReader(createInputStream(path));
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public Writer createWriter(final String path) throws FileAccessException,
InsufficientPermissionsException {
return new OutputStreamWriter(createOutputStream(path));
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public InputStream createInputStream(final String path) throws
FileDoesNotExistException,
FileAccessException,
InsufficientPermissionsException {
final XADiskConnection connection = connect();
final File file = new File(path);
final XAFileInputStreamWrapper inputStream;
try {
final XAFileInputStream stream = connection
.createXAFileInputStream(file);
inputStream = new XAFileInputStreamWrapper(stream);
} catch (FileNotExistsException ex) {
throw new FileDoesNotExistException(path, ex);
} catch (InsufficientPermissionOnFileException ex) {
throw new InsufficientPermissionsException(path, ex);
} catch (InterruptedException
| LockingFailedException
| NoTransactionAssociatedException ex) {
throw new FileAccessException(path, ex);
}
return inputStream;
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public OutputStream createOutputStream(final String path) throws
FileAccessException,
InsufficientPermissionsException {
final XADiskConnection connection = connect();
final File file = new File(path);
if (!existsFile(path)) {
try {
connection.createFile(file, false);
} catch (InsufficientPermissionOnFileException ex) {
throw new InsufficientPermissionsException(path, ex);
} catch (org.xadisk.filesystem.exceptions.FileAlreadyExistsException
| FileNotExistsException
| LockingFailedException
| NoTransactionAssociatedException
| InterruptedException ex) {
throw new FileAccessException(path, ex);
}
}
final XAFileOutputStreamWrapper outputStream;
try {
final XAFileOutputStream stream = connection
.createXAFileOutputStream(file, true);
outputStream = new XAFileOutputStreamWrapper(stream);
} catch (InsufficientPermissionOnFileException ex) {
throw new InsufficientPermissionsException(path, ex);
} catch (FileNotExistsException
| FileUnderUseException
| InterruptedException
| LockingFailedException
| NoTransactionAssociatedException ex) {
throw new FileAccessException(path, ex);
}
return outputStream;
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public boolean existsFile(final String path) throws FileAccessException,
InsufficientPermissionsException {
final XADiskConnection connection = connect();
final File file = new File(path);
try {
return connection.fileExists(file);
} catch (InsufficientPermissionOnFileException ex) {
throw new InsufficientPermissionsException(path, ex);
} catch (LockingFailedException
| NoTransactionAssociatedException
| InterruptedException ex) {
throw new FileAccessException(path, ex);
}
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public boolean isDirectory(final String path) throws FileAccessException,
FileDoesNotExistException,
InsufficientPermissionsException {
final XADiskConnection connection = connect();
final File file = new File(path);
try {
return connection.fileExistsAndIsDirectory(file);
} catch (InsufficientPermissionOnFileException ex) {
throw new InsufficientPermissionsException(path, ex);
} catch (LockingFailedException
| NoTransactionAssociatedException
| InterruptedException ex) {
throw new FileAccessException(path, ex);
}
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public void createDirectory(final String path) throws FileAccessException,
FileAlreadyExistsException,
InsufficientPermissionsException {
final XADiskConnection connection = connect();
final File file = new File(path);
try {
connection.createFile(file, true);
} catch (org.xadisk.filesystem.exceptions.FileAlreadyExistsException ex) {
throw new FileAlreadyExistsException(path, ex);
} catch (InsufficientPermissionOnFileException ex) {
throw new InsufficientPermissionsException(path, ex);
} catch (FileNotExistsException
| LockingFailedException
| InterruptedException
| NoTransactionAssociatedException ex) {
throw new FileAccessException(path, ex);
}
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public List<String> listFiles(final String path) throws FileAccessException,
FileDoesNotExistException,
InsufficientPermissionsException {
final XADiskConnection connection = connect();
final File file = new File(path);
final String[] files;
try {
files = connection.listFiles(file);
} catch (FileNotExistsException ex) {
throw new FileDoesNotExistException(path, ex);
} catch (InsufficientPermissionOnFileException ex) {
throw new InsufficientPermissionsException(path, ex);
} catch (LockingFailedException
| NoTransactionAssociatedException
| InterruptedException ex) {
throw new FileAccessException(path, ex);
}
return Arrays.asList(files);
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public void deleteFile(final String path) throws FileAccessException,
FileDoesNotExistException,
DirectoryNotEmptyException,
InsufficientPermissionsException {
final XADiskConnection connection = connect();
final File file = new File(path);
if (isDirectory(path) && !listFiles(path).isEmpty()) {
throw new DirectoryNotEmptyException(path);
}
try {
connection.deleteFile(file);
} catch (org.xadisk.filesystem.exceptions.DirectoryNotEmptyException ex) {
throw new DirectoryNotEmptyException(path, ex);
} catch (FileNotExistsException ex) {
throw new FileDoesNotExistException(path, ex);
} catch (InsufficientPermissionOnFileException ex) {
throw new InsufficientPermissionsException(path, ex);
} catch (FileUnderUseException
| LockingFailedException
| NoTransactionAssociatedException
| InterruptedException ex) {
throw new FileAccessException(path, ex);
}
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public void deleteFile(final String path, boolean recursively) throws
FileAccessException,
FileDoesNotExistException,
DirectoryNotEmptyException,
InsufficientPermissionsException {
if (isDirectory(path) && recursively) {
final List<String> files = listFiles(path);
if (!files.isEmpty()) {
for (final String file : files) {
deleteFile(file, recursively);
}
}
} else {
deleteFile(path);
}
}
}

12
pom.xml
View File

@ -1,8 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<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/xsd/maven-4.0.0.xsd">
<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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
@ -66,6 +63,7 @@
<module>ccm-bundle-devel-wildfly-web</module>
<module>ccm-bundle-devel-wildfly</module>
<module>ccm-bundle-devel-wildfly-swarm</module>
<module>ccm-xafilesystemadapter</module>
</modules>
<reporting>
@ -460,6 +458,12 @@
<version>20040302</version>
</dependency>
<dependency>
<groupId>net.java.xadisk</groupId>
<artifactId>xadisk</artifactId>
<version>1.2.2</version>
</dependency>
<dependency>
<groupId>xml-resolver</groupId>
<artifactId>xml-resolver</artifactId>