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
.activation
.FileTypeMap
;
16 import javax
.activation
.MimetypesFileTypeMap
;
17 import javax
.jcr
.Binary
;
18 import javax
.jcr
.Node
;
19 import javax
.jcr
.Property
;
20 import javax
.jcr
.RepositoryException
;
21 import javax
.jcr
.Session
;
22 import javax
.jcr
.nodetype
.NodeType
;
24 import org
.argeo
.jcr
.JcrUtils
;
26 public class BinaryChannel
implements SeekableByteChannel
{
27 private final Node file
;
28 private Binary binary
;
29 private boolean open
= true;
31 private long position
= 0;
33 // private ByteBuffer toWrite;
34 private FileChannel fc
= null;
36 private static FileTypeMap fileTypeMap
;
40 fileTypeMap
= new MimetypesFileTypeMap("/etc/mime.types");
41 } catch (IOException e
) {
42 fileTypeMap
= FileTypeMap
.getDefaultFileTypeMap();
46 public BinaryChannel(Node file
) throws RepositoryException
, IOException
{
48 // int capacity = 1024 * 1024;
49 // this.toWrite = ByteBuffer.allocate(capacity);
50 if (file
.isNodeType(NodeType
.NT_FILE
)) {
51 if (file
.hasNode(Property
.JCR_CONTENT
)) {
52 Node data
= file
.getNode(Property
.JCR_CONTENT
);
53 this.binary
= data
.getProperty(Property
.JCR_DATA
).getBinary();
55 Node data
= file
.addNode(Property
.JCR_CONTENT
, NodeType
.NT_RESOURCE
);
56 try (InputStream in
= new ByteArrayInputStream(new byte[0])) {
57 this.binary
= data
.getSession().getValueFactory().createBinary(in
);
59 data
.setProperty(Property
.JCR_DATA
, this.binary
);
62 String mime
= fileTypeMap
.getContentType(file
.getName());
63 data
.setProperty(Property
.JCR_MIMETYPE
, mime
);
65 data
.getSession().save();
68 throw new IllegalArgumentException(
69 "Unsupported file node " + file
+ " (" + file
.getPrimaryNodeType() + ")");
74 public synchronized boolean isOpen() {
79 public synchronized void close() throws IOException
{
81 Binary newBinary
= null;
83 Session session
= file
.getSession();
84 // byte[] arr = new byte[(int) position];
88 InputStream in
= Channels
.newInputStream(fc
);
89 newBinary
= session
.getValueFactory().createBinary(in
);
90 file
.getNode(Property
.JCR_CONTENT
).setProperty(Property
.JCR_DATA
, newBinary
);
93 } catch (RepositoryException e
) {
94 throw new IOException("Cannot close " + file
, e
);
96 JcrUtils
.closeQuietly(newBinary
);
97 // IOUtils.closeQuietly(fc);
109 public int read(ByteBuffer dst
) throws IOException
{
116 // int capacity = dst.capacity();
117 byte[] arr
= dst
.array();
118 read
= binary
.read(arr
, position
);
119 // dst.put(arr, 0, read);
122 // byte[] arr = dst.array();
123 // read = binary.read(arr, position);
124 // } catch (UnsupportedOperationException e) {
125 // int capacity = dst.capacity();
126 // byte[] arr = new byte[capacity];
127 // read = binary.read(arr, position);
131 position
= position
+ read
;
133 } catch (RepositoryException e
) {
134 throw new IOException("Cannot read into buffer", e
);
140 public int write(ByteBuffer src
) throws IOException
{
141 int written
= getFileChannel().write(src
);
143 // int byteCount = src.remaining();
144 // if (toWrite.remaining() < byteCount)
145 // throw new JcrFsException("Write buffer is full");
147 // if (position < binarySize)
148 // position = binarySize + byteCount;
150 // position = position + byteCount;
155 public long position() throws IOException
{
157 return getFileChannel().position();
163 public SeekableByteChannel
position(long newPosition
) throws IOException
{
165 getFileChannel().position(position
);
167 this.position
= newPosition
;
173 public long size() throws IOException
{
175 return getFileChannel().size();
178 return binary
.getSize();
179 } catch (RepositoryException e
) {
180 throw new IOException("Cannot get size", e
);
186 public SeekableByteChannel
truncate(long size
) throws IOException
{
187 getFileChannel().truncate(size
);
188 // if (size != size())
189 // throw new UnsupportedOperationException("Cannot truncate JCR
194 private FileChannel
getFileChannel() throws IOException
{
197 Path tempPath
= Files
.createTempFile(getClass().getSimpleName(), null);
198 fc
= FileChannel
.open(tempPath
, StandardOpenOption
.WRITE
, StandardOpenOption
.READ
,
199 StandardOpenOption
.DELETE_ON_CLOSE
, StandardOpenOption
.SPARSE
);
200 ReadableByteChannel readChannel
= Channels
.newChannel(binary
.getStream());
201 fc
.transferFrom(readChannel
, 0, binary
.getSize());
205 } catch (RepositoryException e
) {
206 throw new IOException("Cannot get temp file channel", e
);
210 private boolean isModified() {
214 private void clearReadState() {
216 JcrUtils
.closeQuietly(binary
);