1 package org
.argeo
.jcr
.fs
;
3 import java
.io
.ByteArrayInputStream
;
4 import java
.io
.IOException
;
5 import java
.io
.InputStream
;
6 import java
.nio
.ByteBuffer
;
7 import java
.nio
.channels
.Channels
;
8 import java
.nio
.channels
.FileChannel
;
9 import java
.nio
.channels
.ReadableByteChannel
;
10 import java
.nio
.channels
.SeekableByteChannel
;
11 import java
.nio
.file
.Files
;
12 import java
.nio
.file
.Path
;
13 import java
.nio
.file
.StandardOpenOption
;
15 import javax
.jcr
.Binary
;
16 import javax
.jcr
.Node
;
17 import javax
.jcr
.Property
;
18 import javax
.jcr
.RepositoryException
;
19 import javax
.jcr
.Session
;
20 import javax
.jcr
.nodetype
.NodeType
;
22 import org
.argeo
.jcr
.JcrUtils
;
24 public class BinaryChannel
implements SeekableByteChannel
{
25 private final Node file
;
26 private Binary binary
;
27 private boolean open
= true;
29 private long position
= 0;
31 // private ByteBuffer toWrite;
32 private FileChannel fc
= null;
34 public BinaryChannel(Node file
) throws RepositoryException
, IOException
{
36 // int capacity = 1024 * 1024;
37 // this.toWrite = ByteBuffer.allocate(capacity);
38 if (file
.isNodeType(NodeType
.NT_FILE
)) {
39 if (file
.hasNode(Property
.JCR_CONTENT
)) {
40 Node data
= file
.getNode(Property
.JCR_CONTENT
);
41 this.binary
= data
.getProperty(Property
.JCR_DATA
).getBinary();
43 Node data
= file
.addNode(Property
.JCR_CONTENT
, NodeType
.NT_RESOURCE
);
44 try (InputStream in
= new ByteArrayInputStream(new byte[0])) {
45 this.binary
= data
.getSession().getValueFactory().createBinary(in
);
47 data
.setProperty(Property
.JCR_DATA
, this.binary
);
48 data
.getSession().save();
51 throw new IllegalArgumentException(
52 "Unsupported file node " + file
+ " (" + file
.getPrimaryNodeType() + ")");
57 public synchronized boolean isOpen() {
62 public synchronized void close() throws IOException
{
64 Binary newBinary
= null;
66 Session session
= file
.getSession();
67 // byte[] arr = new byte[(int) position];
71 InputStream in
= Channels
.newInputStream(fc
);
72 newBinary
= session
.getValueFactory().createBinary(in
);
73 file
.getNode(Property
.JCR_CONTENT
).setProperty(Property
.JCR_DATA
, newBinary
);
76 } catch (RepositoryException e
) {
77 throw new IOException("Cannot close " + file
, e
);
79 JcrUtils
.closeQuietly(newBinary
);
80 // IOUtils.closeQuietly(fc);
92 public int read(ByteBuffer dst
) throws IOException
{
99 // int capacity = dst.capacity();
100 byte[] arr
= dst
.array();
101 read
= binary
.read(arr
, position
);
102 // dst.put(arr, 0, read);
105 // byte[] arr = dst.array();
106 // read = binary.read(arr, position);
107 // } catch (UnsupportedOperationException e) {
108 // int capacity = dst.capacity();
109 // byte[] arr = new byte[capacity];
110 // read = binary.read(arr, position);
114 position
= position
+ read
;
116 } catch (RepositoryException e
) {
117 throw new IOException("Cannot read into buffer", e
);
123 public int write(ByteBuffer src
) throws IOException
{
124 int written
= getFileChannel().write(src
);
126 // int byteCount = src.remaining();
127 // if (toWrite.remaining() < byteCount)
128 // throw new JcrFsException("Write buffer is full");
130 // if (position < binarySize)
131 // position = binarySize + byteCount;
133 // position = position + byteCount;
138 public long position() throws IOException
{
140 return getFileChannel().position();
146 public SeekableByteChannel
position(long newPosition
) throws IOException
{
148 getFileChannel().position(position
);
150 this.position
= newPosition
;
156 public long size() throws IOException
{
158 return getFileChannel().size();
161 return binary
.getSize();
162 } catch (RepositoryException e
) {
163 throw new IOException("Cannot get size", e
);
169 public SeekableByteChannel
truncate(long size
) throws IOException
{
170 getFileChannel().truncate(size
);
171 // if (size != size())
172 // throw new UnsupportedOperationException("Cannot truncate JCR
177 private FileChannel
getFileChannel() throws IOException
{
180 Path tempPath
= Files
.createTempFile(getClass().getSimpleName(), null);
181 fc
= FileChannel
.open(tempPath
, StandardOpenOption
.WRITE
, StandardOpenOption
.READ
,
182 StandardOpenOption
.DELETE_ON_CLOSE
, StandardOpenOption
.SPARSE
);
183 ReadableByteChannel readChannel
= Channels
.newChannel(binary
.getStream());
184 fc
.transferFrom(readChannel
, 0, binary
.getSize());
188 } catch (RepositoryException e
) {
189 throw new IOException("Cannot get temp file channel", e
);
193 private boolean isModified() {
197 private void clearReadState() {
199 JcrUtils
.closeQuietly(binary
);