From 44dd7267d3b09d96dfeed6d1bea69d6107fe1dcd Mon Sep 17 00:00:00 2001 From: jensp Date: Mon, 27 Mar 2017 15:47:08 +0000 Subject: [PATCH] CCM NG: XAFileSystemAdapter git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4644 8810af33-2d31-482b-a856-94f89814c4df Former-commit-id: 0b6fe39bb4ab943804e276fd953bac876c2cbc5d --- .../libreccm/files/NIOFileSystemAdapter.java | 2 - ccm-xafilesystemadapter/pom.xml | 52 +++ .../libreccm/files/XAFileSystemAdapter.java | 324 ++++++++++++++++++ pom.xml | 16 +- 4 files changed, 386 insertions(+), 8 deletions(-) create mode 100644 ccm-xafilesystemadapter/pom.xml create mode 100644 ccm-xafilesystemadapter/src/main/java/org/libreccm/files/XAFileSystemAdapter.java diff --git a/ccm-core/src/main/java/org/libreccm/files/NIOFileSystemAdapter.java b/ccm-core/src/main/java/org/libreccm/files/NIOFileSystemAdapter.java index 6fad272fe..11013a61e 100644 --- a/ccm-core/src/main/java/org/libreccm/files/NIOFileSystemAdapter.java +++ b/ccm-core/src/main/java/org/libreccm/files/NIOFileSystemAdapter.java @@ -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; diff --git a/ccm-xafilesystemadapter/pom.xml b/ccm-xafilesystemadapter/pom.xml new file mode 100644 index 000000000..49e4bacf0 --- /dev/null +++ b/ccm-xafilesystemadapter/pom.xml @@ -0,0 +1,52 @@ + + + + 4.0.0 + + + org.libreccm + libreccm-parent + 7.0.0-SNAPSHOT + + + org.libreccm.files + ccm-xafilesystemadapter + 1.0.0-SNAPSHOT + + ccm-xafilesystemadapter + http://www.libreccm.org + + + UTF-8 + + + + + + javax + javaee-api + + + + + org.libreccm + ccm-core + 7.0.0-SNAPSHOT + provided + + + + net.java.xadisk + xadisk + provided + + + + junit + junit + test + + + + diff --git a/ccm-xafilesystemadapter/src/main/java/org/libreccm/files/XAFileSystemAdapter.java b/ccm-xafilesystemadapter/src/main/java/org/libreccm/files/XAFileSystemAdapter.java new file mode 100644 index 000000000..cf5f8b77b --- /dev/null +++ b/ccm-xafilesystemadapter/src/main/java/org/libreccm/files/XAFileSystemAdapter.java @@ -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 Jens Pelzetter + */ +@RequestScoped +public class XAFileSystemAdapter implements FileSystemAdapter { + + private Optional 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 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 files = listFiles(path); + if (!files.isEmpty()) { + for (final String file : files) { + deleteFile(file, recursively); + } + } + } else { + deleteFile(path); + } + } + +} diff --git a/pom.xml b/pom.xml index ac6bec3e0..5a8fb748e 100644 --- a/pom.xml +++ b/pom.xml @@ -1,8 +1,5 @@ - + 4.0.0 @@ -66,6 +63,7 @@ ccm-bundle-devel-wildfly-web ccm-bundle-devel-wildfly ccm-bundle-devel-wildfly-swarm + ccm-xafilesystemadapter @@ -459,7 +457,13 @@ poi-2.5-final 20040302 - + + + net.java.xadisk + xadisk + 1.2.2 + + xml-resolver xml-resolver @@ -607,4 +611,4 @@ - + \ No newline at end of file