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 FileChannel fc
= null;
33 public BinaryChannel(Node file
, Path path
) throws RepositoryException
, IOException
{
35 if (file
.isNodeType(NodeType
.NT_FILE
)) {
36 if (file
.hasNode(Property
.JCR_CONTENT
)) {
37 Node data
= file
.getNode(Property
.JCR_CONTENT
);
38 this.binary
= data
.getProperty(Property
.JCR_DATA
).getBinary();
40 Node data
= file
.addNode(Property
.JCR_CONTENT
, NodeType
.NT_RESOURCE
);
41 try (InputStream in
= new ByteArrayInputStream(new byte[0])) {
42 this.binary
= data
.getSession().getValueFactory().createBinary(in
);
44 data
.setProperty(Property
.JCR_DATA
, this.binary
);
47 String mime
= Files
.probeContentType(path
);
48 // String mime = fileTypeMap.getContentType(file.getName());
49 data
.setProperty(Property
.JCR_MIMETYPE
, mime
);
51 data
.getSession().save();
54 throw new IllegalArgumentException(
55 "Unsupported file node " + file
+ " (" + file
.getPrimaryNodeType() + ")");
60 public synchronized boolean isOpen() {
65 public synchronized void close() throws IOException
{
67 Binary newBinary
= null;
69 Session session
= file
.getSession();
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 byte[] arr
= dst
.array();
100 read
= binary
.read(arr
, position
);
103 position
= position
+ read
;
105 } catch (RepositoryException e
) {
106 throw new IOException("Cannot read into buffer", e
);
112 public int write(ByteBuffer src
) throws IOException
{
113 int written
= getFileChannel().write(src
);
118 public long position() throws IOException
{
120 return getFileChannel().position();
126 public SeekableByteChannel
position(long newPosition
) throws IOException
{
128 getFileChannel().position(position
);
130 this.position
= newPosition
;
136 public long size() throws IOException
{
138 return getFileChannel().size();
141 return binary
.getSize();
142 } catch (RepositoryException e
) {
143 throw new IOException("Cannot get size", e
);
149 public SeekableByteChannel
truncate(long size
) throws IOException
{
150 getFileChannel().truncate(size
);
154 private FileChannel
getFileChannel() throws IOException
{
157 Path tempPath
= Files
.createTempFile(getClass().getSimpleName(), null);
158 fc
= FileChannel
.open(tempPath
, StandardOpenOption
.WRITE
, StandardOpenOption
.READ
,
159 StandardOpenOption
.DELETE_ON_CLOSE
, StandardOpenOption
.SPARSE
);
160 ReadableByteChannel readChannel
= Channels
.newChannel(binary
.getStream());
161 fc
.transferFrom(readChannel
, 0, binary
.getSize());
165 } catch (RepositoryException e
) {
166 throw new IOException("Cannot get temp file channel", e
);
170 private boolean isModified() {
174 private void clearReadState() {
176 JcrUtils
.closeQuietly(binary
);