CCM NG: XAFileSystemAdapter
git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4644 8810af33-2d31-482b-a856-94f89814c4df
Former-commit-id: 0b6fe39bb4
pull/2/head
parent
25d7e1ae91
commit
44dd7267d3
|
|
@ -34,8 +34,6 @@ import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.logging.Level;
|
|
||||||
import java.util.logging.Logger;
|
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
16
pom.xml
16
pom.xml
|
|
@ -1,8 +1,5 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<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">
|
||||||
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>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
|
@ -66,6 +63,7 @@
|
||||||
<module>ccm-bundle-devel-wildfly-web</module>
|
<module>ccm-bundle-devel-wildfly-web</module>
|
||||||
<module>ccm-bundle-devel-wildfly</module>
|
<module>ccm-bundle-devel-wildfly</module>
|
||||||
<module>ccm-bundle-devel-wildfly-swarm</module>
|
<module>ccm-bundle-devel-wildfly-swarm</module>
|
||||||
|
<module>ccm-xafilesystemadapter</module>
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<reporting>
|
<reporting>
|
||||||
|
|
@ -459,7 +457,13 @@
|
||||||
<artifactId>poi-2.5-final</artifactId>
|
<artifactId>poi-2.5-final</artifactId>
|
||||||
<version>20040302</version>
|
<version>20040302</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.java.xadisk</groupId>
|
||||||
|
<artifactId>xadisk</artifactId>
|
||||||
|
<version>1.2.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>xml-resolver</groupId>
|
<groupId>xml-resolver</groupId>
|
||||||
<artifactId>xml-resolver</artifactId>
|
<artifactId>xml-resolver</artifactId>
|
||||||
|
|
@ -607,4 +611,4 @@
|
||||||
</dependencies>
|
</dependencies>
|
||||||
</dependencyManagement>
|
</dependencyManagement>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
Loading…
Reference in New Issue