--- /dev/null
+package org.simantics.db.common.utils;\r
+\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.InputStream;\r
+import java.io.OutputStream;\r
+import java.nio.ByteBuffer;\r
+import java.nio.channels.FileChannel;\r
+import java.util.Arrays;\r
+\r
+import org.simantics.databoard.Bindings;\r
+import org.simantics.databoard.Files;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.serialization.Serializer;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.databoard.util.binary.RandomAccessBinary;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.WriteGraph;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.layer0.Layer0;\r
+\r
+/**\r
+ * Converts byte[] literals to files and back. These utilities are not usable\r
+ * for literals of any other type than byte[].\r
+ */\r
+public class LiteralFileUtil {\r
+\r
+ public static void copyByteArrayToFile(ReadGraph g, Resource source, File target) throws DatabaseException, IOException {\r
+ byte[] data = g.getValue(source, Bindings.BYTE_ARRAY);\r
+ OutputStream stream = new FileOutputStream(target);\r
+ try {\r
+ // TODO: For some peculiar reason a direct stream.write(data) OOMs with approx. 70MB array\r
+ for(int pos = 0;pos < data.length;) {\r
+ int len = Math.min(65536, data.length-pos);\r
+ stream.write(data,pos,len);\r
+ pos += len;\r
+ }\r
+ } finally {\r
+ stream.close();\r
+ }\r
+ }\r
+ \r
+ public static void copyByteArrayToFile(ReadGraph g, Resource subject, Resource predicate, File target) throws DatabaseException, IOException {\r
+ Resource source = g.getSingleObject(subject, predicate);\r
+ copyByteArrayToFile(g, source, target);\r
+ }\r
+\r
+ public static void copyRandomAccessBinaryToFile(ReadGraph g, Resource source, File target) throws DatabaseException, IOException {\r
+ OutputStream stream = new FileOutputStream(target);\r
+ try {\r
+ RandomAccessBinary rab = g.getRandomAccessBinary(source);\r
+ // Skip byte array length data according to databoard byte[] serialization rules.\r
+ rab.position(4);\r
+ ByteBuffer bb = ByteBuffer.wrap(new byte[65536]);\r
+ byte[] bbArray = bb.array();\r
+ while (rab.position() < rab.length()) {\r
+ rab.readFully(bb, (int) Math.min(bbArray.length, rab.length() - rab.position()));\r
+ stream.write(bbArray, 0, bb.position());\r
+ bb.position(0);\r
+ }\r
+ } finally {\r
+ stream.close();\r
+ }\r
+ }\r
+\r
+ public static void copyRandomAccessBinaryFromFile(File source, RandomAccessBinary rab) throws IOException {\r
+ ByteBuffer byteBuffer = ByteBuffer.wrap(new byte[65536]);\r
+\r
+ FileInputStream stream = new FileInputStream(source);\r
+ FileChannel channel = stream.getChannel();\r
+\r
+ try {\r
+ rab.position(0);\r
+ rab.writeInt((int)source.length());\r
+ while(channel.read(byteBuffer) != -1) {\r
+ byteBuffer.limit(byteBuffer.position());\r
+ byteBuffer.position(0);\r
+ rab.writeFully(byteBuffer);\r
+ byteBuffer.position(0);\r
+ }\r
+ } finally {\r
+ stream.close();\r
+ }\r
+\r
+ // Make sure the RAB file will not be longer than the\r
+ // source file due to possible previously existing data.\r
+ rab.setLength(rab.position());\r
+ rab.flush();\r
+ }\r
+\r
+\r
+ public static void copyRandomAccessBinaryToFile(ReadGraph g, Resource subject, Resource predicate, File target) throws DatabaseException, IOException {\r
+ Resource source = g.getSingleObject(subject, predicate);\r
+ copyRandomAccessBinaryToFile(g, source, target);\r
+ }\r
+\r
+ public static void copyToFileWithBinding(ReadGraph g, Resource source, File target, Binding binding) throws DatabaseException, IOException {\r
+ // Datatyyppi tieto on jo resurssissa, eik�? \r
+ // Sidonnan saisi Bindings.getBinding( type )\r
+ Object value = g.getValue(source, binding);\r
+ Serializer s = Bindings.getSerializerUnchecked(binding);\r
+ s.serialize(value, target);\r
+ }\r
+\r
+ public static void copyToFileWithBinding(ReadGraph g, Resource subject, Resource predicate, File target, Binding binding) throws DatabaseException, IOException {\r
+ Resource source = g.getSingleObject(subject, predicate);\r
+ copyToFileWithBinding(g, source, target, binding);\r
+ }\r
+\r
+ public static void copyToFileAsVariant(ReadGraph g, Resource source, File target, Binding binding) throws DatabaseException, IOException {\r
+ Object value = g.getValue(source, binding);\r
+ Files.createFile(target, binding, value);\r
+ }\r
+\r
+ public static void copyToFileAsVariant(ReadGraph g, Resource source, File target) throws DatabaseException, IOException {\r
+ Datatype type = g.getDataType(source);\r
+ Binding binding = Bindings.getBinding(type);\r
+ copyToFileAsVariant(g, source, target, binding);\r
+ }\r
+\r
+ public static void copyToFileAsVariant(ReadGraph g, Resource subject, Resource predicate, File target) throws DatabaseException, IOException {\r
+ Resource source = g.getSingleObject(subject, predicate);\r
+ copyToFileAsVariant(g, source, target);\r
+ }\r
+\r
+ public static void copyByteArrayFromFile(WriteGraph g, File source, Resource target) throws DatabaseException, IOException {\r
+ InputStream stream = new FileInputStream(source);\r
+ byte[] data = new byte[(int)source.length()];\r
+ stream.read(data);\r
+ stream.close();\r
+ g.claimValue(target, data, Bindings.BYTE_ARRAY);\r
+ }\r
+\r
+ public static void copyByteArrayFromFile(WriteGraph g, File source, Resource subject, Resource predicate) throws DatabaseException, IOException {\r
+ InputStream stream = new FileInputStream(source);\r
+ byte[] data = new byte[(int)source.length()];\r
+ stream.read(data);\r
+ stream.close();\r
+ g.claimLiteral(subject, predicate, data, Bindings.BYTE_ARRAY);\r
+ }\r
+\r
+ /**\r
+ * @param g\r
+ * @param source\r
+ * @param subject\r
+ * @param predicate\r
+ * @throws DatabaseException\r
+ * @throws IOException\r
+ */\r
+ public static void streamingCopyByteArrayFromFile(WriteGraph g, File source, Resource subject, Resource predicate) throws DatabaseException, IOException {\r
+ Resource target = g.getPossibleObject(subject, predicate);\r
+ if (target == null) {\r
+ Layer0 L0 = Layer0.getInstance(g);\r
+ target = g.newResource();\r
+ g.claim(target, L0.InstanceOf, null, L0.ByteArray);\r
+ g.claim(subject, predicate, target);\r
+ }\r
+ InputStream stream = new FileInputStream(source);\r
+ try {\r
+ copyStreamToRandomAccessBinary(g, stream, target);\r
+ } finally {\r
+ stream.close();\r
+ }\r
+ }\r
+\r
+ public static void copyByteArrayFromStream(WriteGraph g, InputStream source, Resource target) throws IOException, DatabaseException {\r
+ byte[] buffer = new byte[0x10000];\r
+ int pos = 0;\r
+ while(true) {\r
+ int count = source.read(buffer, pos, buffer.length - pos);\r
+ if(count <= 0)\r
+ break;\r
+ pos += count;\r
+ if(pos == buffer.length)\r
+ buffer = Arrays.copyOf(buffer, (pos * 3) / 2);\r
+ }\r
+ buffer = Arrays.copyOf(buffer, pos);\r
+ g.claimValue(target, buffer, Bindings.BYTE_ARRAY);\r
+ }\r
+\r
+ public static void copyStreamToRandomAccessBinary(WriteGraph g, InputStream source, Resource target) throws IOException, DatabaseException {\r
+ RandomAccessBinary rab = g.getRandomAccessBinary(target);\r
+ byte[] buffer = new byte[0x10000];\r
+ if (rab.length() < 4)\r
+ rab.setLength(4);\r
+ rab.position(4);\r
+ int length = 0;\r
+ while (true) {\r
+ int count = source.read(buffer, 0, buffer.length);\r
+ if (count <= 0)\r
+ break;\r
+ rab.write(buffer, 0, count);\r
+ length += count;\r
+ }\r
+ rab.position(0);\r
+ rab.writeInt(length);\r
+ rab.flush();\r
+ }\r
+\r
+}\r