diff options
author | Eike Stepper | 2010-10-03 17:43:24 +0000 |
---|---|---|
committer | Eike Stepper | 2010-10-03 17:43:24 +0000 |
commit | 28970a96cbd16c2ade77c0a1d7a339cf8e7400a7 (patch) | |
tree | 5824dcbd4db52b1478c0b8e47acfaa45872a3c47 /plugins/org.eclipse.emf.cdo.common/src | |
parent | a91d414d00d86b12cea002dc06cbb75ea8f0327a (diff) | |
download | cdo-28970a96cbd16c2ade77c0a1d7a339cf8e7400a7.tar.gz cdo-28970a96cbd16c2ade77c0a1d7a339cf8e7400a7.tar.xz cdo-28970a96cbd16c2ade77c0a1d7a339cf8e7400a7.zip |
[284307] Add support for streaming of large byte arrays / BLOB
https://bugs.eclipse.org/bugs/show_bug.cgi?id=284307
Diffstat (limited to 'plugins/org.eclipse.emf.cdo.common/src')
12 files changed, 692 insertions, 8 deletions
diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java index 7022e2ac84..2be7589304 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOModelUtil.java @@ -58,6 +58,11 @@ public final class CDOModelUtil /** * @since 2.0 */ + public static final String ROOT_CLASS_NAME = "EObject"; //$NON-NLS-1$ + + /** + * @since 2.0 + */ public static final String RESOURCE_PACKAGE_URI = "http://www.eclipse.org/emf/CDO/Eresource/2.0.0"; //$NON-NLS-1$ /** @@ -76,9 +81,19 @@ public final class CDOModelUtil public static final String RESOURCE_CLASS_NAME = "CDOResource"; //$NON-NLS-1$ /** - * @since 2.0 + * @since 4.0 */ - public static final String ROOT_CLASS_NAME = "EObject"; //$NON-NLS-1$ + public static final String TYPES_PACKAGE_URI = "http://www.eclipse.org/emf/CDO/Etypes/4.0.0"; //$NON-NLS-1$ + + /** + * @since 4.0 + */ + public static final String BLOB_CLASS_NAME = "Blob"; //$NON-NLS-1$ + + /** + * @since 4.0 + */ + public static final String CLOB_CLASS_NAME = "Clob"; //$NON-NLS-1$ private static CDOType[] coreTypes; @@ -137,6 +152,14 @@ public final class CDOModelUtil /** * @since 2.0 */ + public static boolean isRoot(EClass eClass) + { + return isCorePackage(eClass.getEPackage()) && ROOT_CLASS_NAME.equals(eClass.getName()); + } + + /** + * @since 2.0 + */ public static boolean isResourcePackage(EPackage ePackage) { return RESOURCE_PACKAGE_URI.equals(ePackage.getNsURI()); @@ -177,11 +200,20 @@ public final class CDOModelUtil } /** - * @since 2.0 + * @since 4.0 */ - public static boolean isRoot(EClass eClass) + public static boolean isTypesPackage(EPackage ePackage) { - return isCorePackage(eClass.getEPackage()) && ROOT_CLASS_NAME.equals(eClass.getName()); + return TYPES_PACKAGE_URI.equals(ePackage.getNsURI()); + } + + /** + * @since 4.0 + */ + public static boolean isLob(EClassifier eClassifier) + { + return isTypesPackage(eClassifier.getEPackage()) + && (BLOB_CLASS_NAME.equals(eClassifier.getName()) || CLOB_CLASS_NAME.equals(eClassifier.getName())); } /** @@ -217,15 +249,32 @@ public final class CDOModelUtil return CDOType.ENUM_ORDINAL; } - if (isCorePackage(classifier.getEPackage())) + EDataType eDataType = (EDataType)classifier; + EPackage ePackage = eDataType.getEPackage(); + + if (isCorePackage(ePackage)) { - EDataType eDataType = (EDataType)classifier; CDOType type = getCoreType(eDataType); if (type != null) { return type; } } + else if (isTypesPackage(ePackage)) + { + String name = eDataType.getName(); + if (BLOB_CLASS_NAME.equals(name)) + { + return CDOType.BLOB; + } + + if (CLOB_CLASS_NAME.equals(name)) + { + return CDOType.CLOB; + } + + throw new IllegalArgumentException("Illegal data type: " + eDataType); + } return CDOType.CUSTOM; } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOType.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOType.java index 286067bc54..10df08d71d 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOType.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/CDOType.java @@ -90,6 +90,16 @@ public interface CDOType */ public static final CDOType ENUM_LITERAL = org.eclipse.emf.cdo.internal.common.model.CDOTypeImpl.ENUM_LITERAL; + /** + * @since 4.0 + */ + public static final CDOType BLOB = org.eclipse.emf.cdo.internal.common.model.CDOTypeImpl.BLOB; + + /** + * @since 4.0 + */ + public static final CDOType CLOB = org.eclipse.emf.cdo.internal.common.model.CDOTypeImpl.CLOB; + public static final CDOType CUSTOM = org.eclipse.emf.cdo.internal.common.model.CDOTypeImpl.CUSTOM; /** diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOBlob.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOBlob.java new file mode 100644 index 0000000000..ca424d730a --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOBlob.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.common.model.lob; + +import org.eclipse.emf.cdo.spi.common.model.CDOLobStoreImpl; + +import org.eclipse.net4j.util.io.ExtendedDataInput; + +import java.io.IOException; +import java.io.InputStream; + +/** + * @author Eike Stepper + * @since 4.0 + */ +public final class CDOBlob extends CDOLob<byte[], InputStream> +{ + public CDOBlob(InputStream contents) throws IOException + { + super(contents, CDOLobStoreImpl.INSTANCE); + } + + public CDOBlob(InputStream contents, CDOLobStore store) throws IOException + { + super(contents, store); + } + + CDOBlob(byte[] id, long size) + { + super(id, size); + } + + CDOBlob(ExtendedDataInput in) throws IOException + { + super(in); + } + + @Override + public InputStream getContents() throws IOException + { + return getStore().getBinary(this); + } + + @Override + protected CDOLobInfo put(InputStream contents) throws IOException + { + return getStore().putBinary(contents); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOClob.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOClob.java new file mode 100644 index 0000000000..18ebb65c68 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOClob.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.common.model.lob; + +import org.eclipse.emf.cdo.spi.common.model.CDOLobStoreImpl; + +import org.eclipse.net4j.util.io.ExtendedDataInput; + +import java.io.IOException; +import java.io.Reader; + +/** + * @author Eike Stepper + * @since 4.0 + */ +public final class CDOClob extends CDOLob<char[], Reader> +{ + public CDOClob(Reader contents) throws IOException + { + super(contents, CDOLobStoreImpl.INSTANCE); + } + + public CDOClob(Reader contents, CDOLobStore store) throws IOException + { + super(contents, store); + } + + CDOClob(byte[] id, long size) + { + super(id, size); + } + + CDOClob(ExtendedDataInput in) throws IOException + { + super(in); + } + + @Override + public Reader getContents() throws IOException + { + return getStore().getCharacter(this); + } + + @Override + protected CDOLobInfo put(Reader contents) throws IOException + { + return getStore().putCharacter(contents); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLob.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLob.java new file mode 100644 index 0000000000..538fa6ef9c --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLob.java @@ -0,0 +1,65 @@ +/** + * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.common.model.lob; + +import org.eclipse.net4j.util.io.ExtendedDataInput; +import org.eclipse.net4j.util.io.ExtendedDataOutput; + +import java.io.IOException; + +/** + * @author Eike Stepper + * @since 4.0 + */ +public abstract class CDOLob<ARRAY, IO> extends CDOLobInfo +{ + private CDOLobStore store; + + CDOLob(byte[] id, long size) + { + this.id = id; + this.size = size; + } + + CDOLob(IO contents, CDOLobStore store) throws IOException + { + this.store = store; + CDOLobInfo info = put(contents); + id = info.getID(); + size = info.getSize(); + } + + CDOLob(ExtendedDataInput in) throws IOException + { + id = in.readByteArray(); + size = in.readLong(); + } + + final void write(ExtendedDataOutput out) throws IOException + { + out.writeByteArray(id); + out.writeLong(size); + } + + final void setStore(CDOLobStore store) + { + this.store = store; + } + + public final CDOLobStore getStore() + { + return store; + } + + public abstract IO getContents() throws IOException; + + protected abstract CDOLobInfo put(IO contents) throws IOException; +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLobInfo.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLobInfo.java new file mode 100644 index 0000000000..e892626a47 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLobInfo.java @@ -0,0 +1,42 @@ +/** + * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.common.model.lob; + +/** + * @author Eike Stepper + * @since 4.0 + */ +public class CDOLobInfo +{ + byte[] id; + + long size; + + CDOLobInfo() + { + } + + public CDOLobInfo(byte[] id, long size) + { + this.id = id; + this.size = size; + } + + public final byte[] getID() + { + return id; + } + + public final long getSize() + { + return size; + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLobStore.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLobStore.java new file mode 100644 index 0000000000..a8c7a6b613 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLobStore.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.common.model.lob; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +/** + * @author Eike Stepper + * @since 4.0 + */ +public interface CDOLobStore +{ + public File getBinaryFile(byte[] id); + + public InputStream getBinary(CDOLobInfo info) throws IOException; + + public CDOLobInfo putBinary(InputStream contents) throws IOException; + + public File getCharacterFile(byte[] id); + + public Reader getCharacter(CDOLobInfo info) throws IOException; + + public CDOLobInfo putCharacter(Reader contents) throws IOException; + + /** + * @author Eike Stepper + */ + public static abstract class Delegating implements CDOLobStore + { + public File getBinaryFile(byte[] id) + { + return getDelegate().getBinaryFile(id); + } + + public InputStream getBinary(CDOLobInfo info) throws IOException + { + return getDelegate().getBinary(info); + } + + public CDOLobInfo putBinary(InputStream contents) throws IOException + { + return getDelegate().putBinary(contents); + } + + public File getCharacterFile(byte[] id) + { + return getDelegate().getCharacterFile(id); + } + + public Reader getCharacter(CDOLobInfo info) throws IOException + { + return getDelegate().getCharacter(info); + } + + public CDOLobInfo putCharacter(Reader contents) throws IOException + { + return getDelegate().putCharacter(contents); + } + + protected abstract CDOLobStore getDelegate(); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLobUtil.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLobUtil.java new file mode 100644 index 0000000000..774534e471 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/model/lob/CDOLobUtil.java @@ -0,0 +1,57 @@ +/** + * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.common.model.lob; + +import org.eclipse.net4j.util.io.ExtendedDataInput; +import org.eclipse.net4j.util.io.ExtendedDataOutput; + +import java.io.IOException; + +/** + * @author Eike Stepper + * @since 4.0 + */ +public final class CDOLobUtil +{ + private CDOLobUtil() + { + } + + public static CDOBlob readBlob(ExtendedDataInput in) throws IOException + { + return new CDOBlob(in); + } + + public static CDOClob readClob(ExtendedDataInput in) throws IOException + { + return new CDOClob(in); + } + + public static void write(ExtendedDataOutput out, CDOLob<?, ?> lob) throws IOException + { + lob.write(out); + } + + public static CDOBlob createBlob(byte[] id, long size) + { + return new CDOBlob(id, size); + } + + public static CDOClob createClob(byte[] id, long size) + { + return new CDOClob(id, size); + } + + public static void setStore(CDOLobStore store, CDOLob<?, ?> lob) throws IOException + { + lob.setStore(store); + } +} diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java index bf2ce437b9..89abb5bd13 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/common/protocol/CDOProtocolConstants.java @@ -194,8 +194,19 @@ public interface CDOProtocolConstants */ public static final short SIGNAL_LOAD_MERGE_DATA = 44; + /** + * @since 4.0 + */ + public static final short SIGNAL_QUERY_LOBS = 45; + + /** + * @since 4.0 + */ + public static final short SIGNAL_LOAD_LOB = 46; + // ////////////////////////////////////////////////////////////////////// // Session Refresh + /** * @since 3.0 */ diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOTypeImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOTypeImpl.java index 80fe047874..4b252a743a 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOTypeImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/model/CDOTypeImpl.java @@ -14,6 +14,9 @@ package org.eclipse.emf.cdo.internal.common.model; import org.eclipse.emf.cdo.common.id.CDOID; import org.eclipse.emf.cdo.common.model.CDOModelUtil; import org.eclipse.emf.cdo.common.model.CDOType; +import org.eclipse.emf.cdo.common.model.lob.CDOBlob; +import org.eclipse.emf.cdo.common.model.lob.CDOClob; +import org.eclipse.emf.cdo.common.model.lob.CDOLobUtil; import org.eclipse.emf.cdo.common.protocol.CDODataInput; import org.eclipse.emf.cdo.common.protocol.CDODataOutput; import org.eclipse.emf.cdo.common.revision.CDOReferenceAdjuster; @@ -568,6 +571,58 @@ public abstract class CDOTypeImpl implements CDOType } }; + public static final CDOType BLOB = new CDOTypeImpl("BLOB", 2004, true) //$NON-NLS-1$ + { + public CDOBlob readValue(CDODataInput in) throws IOException + { + if (in.readBoolean()) + { + return CDOLobUtil.readBlob(in); + } + + return null; + } + + public void writeValue(CDODataOutput out, Object value) throws IOException + { + if (value != null) + { + out.writeBoolean(true); + CDOLobUtil.write(out, (CDOBlob)value); + } + else + { + out.writeBoolean(false); + } + } + }; + + public static final CDOType CLOB = new CDOTypeImpl("CLOB", 2005, true) //$NON-NLS-1$ + { + public CDOClob readValue(CDODataInput in) throws IOException + { + if (in.readBoolean()) + { + return CDOLobUtil.readClob(in); + } + + return null; + } + + public void writeValue(CDODataOutput out, Object value) throws IOException + { + if (value != null) + { + out.writeBoolean(true); + CDOLobUtil.write(out, (CDOClob)value); + } + else + { + out.writeBoolean(false); + } + } + }; + public static final CDOType CUSTOM = new CDOTypeImpl("CUSTOM", 999, true) //$NON-NLS-1$ { @Override diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java index ee2764cc15..08b0bdd830 100644 --- a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/internal/common/protocol/CDODataInputImpl.java @@ -31,6 +31,9 @@ import org.eclipse.emf.cdo.common.model.CDOPackageInfo; import org.eclipse.emf.cdo.common.model.CDOPackageRegistry; import org.eclipse.emf.cdo.common.model.CDOPackageUnit; import org.eclipse.emf.cdo.common.model.CDOType; +import org.eclipse.emf.cdo.common.model.lob.CDOLob; +import org.eclipse.emf.cdo.common.model.lob.CDOLobStore; +import org.eclipse.emf.cdo.common.model.lob.CDOLobUtil; import org.eclipse.emf.cdo.common.protocol.CDODataInput; import org.eclipse.emf.cdo.common.revision.CDOList; import org.eclipse.emf.cdo.common.revision.CDOListFactory; @@ -439,7 +442,14 @@ public abstract class CDODataInputImpl extends ExtendedDataInput.Delegating impl public Object readCDOFeatureValue(EStructuralFeature feature) throws IOException { CDOType type = CDOModelUtil.getType(feature); - return type.readValue(this); + Object value = type.readValue(this); + if (value instanceof CDOLob<?, ?>) + { + CDOLob<?, ?> lob = (CDOLob<?, ?>)value; + CDOLobUtil.setStore(getLobStore(), lob); + } + + return value; } public CDORevisionDelta readCDORevisionDelta() throws IOException @@ -518,4 +528,6 @@ public abstract class CDODataInputImpl extends ExtendedDataInput.Delegating impl protected abstract CDORevisionFactory getRevisionFactory(); protected abstract CDOListFactory getListFactory(); + + protected abstract CDOLobStore getLobStore(); } diff --git a/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/model/CDOLobStoreImpl.java b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/model/CDOLobStoreImpl.java new file mode 100644 index 0000000000..9b24e3f670 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo.common/src/org/eclipse/emf/cdo/spi/common/model/CDOLobStoreImpl.java @@ -0,0 +1,196 @@ +/** + * Copyright (c) 2004 - 2010 Eike Stepper (Berlin, Germany) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * Contributors: + * Eike Stepper - initial API and implementation + */ +package org.eclipse.emf.cdo.spi.common.model; + +import org.eclipse.emf.cdo.common.model.lob.CDOLobInfo; +import org.eclipse.emf.cdo.common.model.lob.CDOLobStore; + +import org.eclipse.net4j.util.HexUtil; +import org.eclipse.net4j.util.WrappedException; +import org.eclipse.net4j.util.io.DigestWriter; +import org.eclipse.net4j.util.io.ExpectedFileInputStream; +import org.eclipse.net4j.util.io.IORuntimeException; +import org.eclipse.net4j.util.io.IOUtil; +import org.eclipse.net4j.util.om.OMPlatform; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.security.DigestOutputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +/** + * @author Eike Stepper + * @since 4.0 + */ +public class CDOLobStoreImpl implements CDOLobStore +{ + public static final CDOLobStoreImpl INSTANCE = new CDOLobStoreImpl(); + + private File folder; + + private int tempID; + + public CDOLobStoreImpl(File folder) + { + this.folder = folder; + if (!folder.exists()) + { + folder.mkdirs(); + if (!folder.exists()) + { + throw new IORuntimeException("Folder could not be created: " + folder); + } + + if (!folder.isDirectory()) + { + throw new IORuntimeException("Not a folder: " + folder); + } + } + } + + public CDOLobStoreImpl() + { + this(getDefaultFolder()); + } + + public File getFolder() + { + return folder; + } + + public File getBinaryFile(byte[] id) + { + return new File(folder, HexUtil.bytesToHex(id) + ".blob"); + } + + public InputStream getBinary(CDOLobInfo info) throws IOException + { + File file = getBinaryFile(info.getID()); + long expectedSize = info.getSize(); + + // if (file.length() >= expectedSize) + // { + // return new FileInputStream(file); + // } + + return new ExpectedFileInputStream(file, expectedSize); + } + + public CDOLobInfo putBinary(InputStream contents) throws IOException + { + File tempFile = getTempFile(); + MessageDigest digest = createDigest(); + digest.update("BINARY".getBytes()); + + FileOutputStream fos = null; + long size; + + try + { + fos = new FileOutputStream(tempFile); + DigestOutputStream dos = new DigestOutputStream(fos, digest); + size = IOUtil.copyBinary(contents, dos); + } + finally + { + IOUtil.close(fos); + } + + byte[] id = digest.digest(); + makePermanent(tempFile, getBinaryFile(id)); + return new CDOLobInfo(id, size); + } + + public File getCharacterFile(byte[] id) + { + return new File(folder, HexUtil.bytesToHex(id) + ".clob"); + } + + public Reader getCharacter(CDOLobInfo info) throws IOException + { + File file = getCharacterFile(info.getID()); + return new FileReader(file); + } + + public CDOLobInfo putCharacter(Reader contents) throws IOException + { + File tempFile = getTempFile(); + MessageDigest digest = createDigest(); + digest.update("CHARACTER".getBytes()); + + FileWriter fw = null; + long size; + + try + { + fw = new FileWriter(tempFile); + DigestWriter dw = new DigestWriter(fw, digest); + size = IOUtil.copyCharacter(contents, dw); + } + finally + { + IOUtil.close(fw); + } + + byte[] id = digest.digest(); + makePermanent(tempFile, getCharacterFile(id)); + return new CDOLobInfo(id, size); + } + + protected MessageDigest createDigest() + { + try + { + return MessageDigest.getInstance("SHA-1"); + } + catch (NoSuchAlgorithmException ex) + { + throw WrappedException.wrap(ex); + } + } + + protected synchronized File getTempFile() + { + for (;;) + { + ++tempID; + File file = new File(folder, "contents" + tempID + ".tmp"); + if (!file.exists()) + { + return file; + } + } + } + + private void makePermanent(File tempFile, File file) + { + if (file.exists()) + { + tempFile.delete(); + } + else + { + tempFile.renameTo(file); + } + } + + private static File getDefaultFolder() + { + String path = OMPlatform.INSTANCE.getProperty("java.io.tmpdir"); + return new File(new File(path), "cdolobs"); + } +} |