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
.apache
.commons
.io
.IOUtils
;
23 import org
.argeo
.jcr
.JcrUtils
;
25 public class BinaryChannel
implements SeekableByteChannel
{
26 private final Node file
;
27 private Binary binary
;
28 private boolean open
= true;
30 private long position
= 0;
32 // private ByteBuffer toWrite;
33 private FileChannel fc
= null;
35 public BinaryChannel(Node file
) throws RepositoryException
, IOException
{
37 // int capacity = 1024 * 1024;
38 // this.toWrite = ByteBuffer.allocate(capacity);
39 if (file
.isNodeType(NodeType
.NT_FILE
)) {
40 if (file
.hasNode(Property
.JCR_CONTENT
)) {
41 Node data
= file
.getNode(Property
.JCR_CONTENT
);
42 this.binary
= data
.getProperty(Property
.JCR_DATA
).getBinary();
44 Node data
= file
.addNode(Property
.JCR_CONTENT
, NodeType
.NT_RESOURCE
);
45 try (InputStream in
= new ByteArrayInputStream(new byte[0])) {
46 this.binary
= data
.getSession().getValueFactory().createBinary(in
);
48 data
.setProperty(Property
.JCR_DATA
, this.binary
);
49 data
.getSession().save();
52 throw new IllegalArgumentException(
53 "Unsupported file node " + file
+ " (" + file
.getPrimaryNodeType() + ")");
58 public synchronized boolean isOpen() {
63 public synchronized void close() throws IOException
{
65 Binary newBinary
= null;
67 Session session
= file
.getSession();
68 // byte[] arr = new byte[(int) position];
72 InputStream in
= Channels
.newInputStream(fc
);
73 newBinary
= session
.getValueFactory().createBinary(in
);
74 file
.getNode(Property
.JCR_CONTENT
).setProperty(Property
.JCR_DATA
, newBinary
);
77 } catch (RepositoryException e
) {
78 throw new JcrFsException("Cannot close " + file
, e
);
80 JcrUtils
.closeQuietly(newBinary
);
81 IOUtils
.closeQuietly(fc
);
90 public int read(ByteBuffer dst
) throws IOException
{
97 // int capacity = dst.capacity();
98 byte[] arr
= dst
.array();
99 read
= binary
.read(arr
, position
);
100 // dst.put(arr, 0, read);
103 // byte[] arr = dst.array();
104 // read = binary.read(arr, position);
105 // } catch (UnsupportedOperationException e) {
106 // int capacity = dst.capacity();
107 // byte[] arr = new byte[capacity];
108 // read = binary.read(arr, position);
112 position
= position
+ read
;
114 } catch (RepositoryException e
) {
115 throw new JcrFsException("Cannot read into buffer", e
);
121 public int write(ByteBuffer src
) throws IOException
{
122 int written
= getFileChannel().write(src
);
124 // int byteCount = src.remaining();
125 // if (toWrite.remaining() < byteCount)
126 // throw new JcrFsException("Write buffer is full");
128 // if (position < binarySize)
129 // position = binarySize + byteCount;
131 // position = position + byteCount;
136 public long position() throws IOException
{
138 return getFileChannel().position();
144 public SeekableByteChannel
position(long newPosition
) throws IOException
{
146 getFileChannel().position(position
);
148 this.position
= newPosition
;
154 public long size() throws IOException
{
156 return getFileChannel().size();
159 return binary
.getSize();
160 } catch (RepositoryException e
) {
161 throw new JcrFsException("Cannot get size", e
);
167 public SeekableByteChannel
truncate(long size
) throws IOException
{
168 getFileChannel().truncate(size
);
169 // if (size != size())
170 // throw new UnsupportedOperationException("Cannot truncate JCR
175 private FileChannel
getFileChannel() throws IOException
{
178 Path tempPath
= Files
.createTempFile(getClass().getSimpleName(), null);
179 fc
= FileChannel
.open(tempPath
, StandardOpenOption
.WRITE
, StandardOpenOption
.READ
,
180 StandardOpenOption
.DELETE_ON_CLOSE
, StandardOpenOption
.SPARSE
);
181 ReadableByteChannel readChannel
= Channels
.newChannel(binary
.getStream());
182 fc
.transferFrom(readChannel
, 0, binary
.getSize());
186 } catch (RepositoryException e
) {
187 throw new JcrFsException("Cannot get temp file channel", e
);
191 private boolean isModified() {
195 private void clearReadState() {
197 JcrUtils
.closeQuietly(binary
);