From 06df2021c8de50a308faf0f69a2461b9d604871c Mon Sep 17 00:00:00 2001 From: Britt Park Date: Thu, 10 Aug 2006 21:50:34 +0000 Subject: [PATCH] This changes the AVM service to use ContentService for storage. This gives us, in theory, AVM working underneath (more or less) NodeService and ContentService. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/BRANCHES/WCM-DEV2/root@3481 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/avm-base-context.xml | 9 +- config/alfresco/avm-services-context.xml | 22 -- config/alfresco/content-services-context.xml | 3 + config/alfresco/model/contentModel.xml | 4 + config/alfresco/node-services-context.xml | 11 + .../java/org/alfresco/model/ContentModel.java | 1 + .../org/alfresco/repo/avm/AVMContext.java | 103 ++++- .../org/alfresco/repo/avm/AVMCrawler.java | 3 +- .../org/alfresco/repo/avm/AVMInterpreter.java | 2 + .../alfresco/repo/avm/AVMNodeConverter.java | 2 +- .../org/alfresco/repo/avm/AVMNodeService.java | 52 ++- .../org/alfresco/repo/avm/AVMRepository.java | 120 +++--- .../org/alfresco/repo/avm/AVMService.java | 69 +++- .../org/alfresco/repo/avm/AVMServiceImpl.java | 152 ++++++-- .../org/alfresco/repo/avm/AVMServiceTest.java | 2 + .../java/org/alfresco/repo/avm/AVMStore.java | 50 ++- .../org/alfresco/repo/avm/AVMStoreImpl.java | 139 +++++-- .../org/alfresco/repo/avm/FileContent.java | 76 ---- .../org/alfresco/repo/avm/FileContentDAO.java | 37 -- .../repo/avm/FileContentDAOHibernate.java | 54 --- .../alfresco/repo/avm/FileContentImpl.java | 357 ------------------ .../java/org/alfresco/repo/avm/FileNode.java | 18 +- .../repo/avm/LayeredFileNodeImpl.java | 65 ++-- .../org/alfresco/repo/avm/OrphanReaper.java | 12 +- .../org/alfresco/repo/avm/PlainFileNode.java | 1 - .../alfresco/repo/avm/PlainFileNodeImpl.java | 201 +++++++--- .../alfresco/repo/avm/hibernate/AVM.hbm.xml | 20 +- .../repo/content/RoutingContentService.java | 24 +- 28 files changed, 744 insertions(+), 865 deletions(-) delete mode 100644 source/java/org/alfresco/repo/avm/FileContent.java delete mode 100644 source/java/org/alfresco/repo/avm/FileContentDAO.java delete mode 100644 source/java/org/alfresco/repo/avm/FileContentDAOHibernate.java delete mode 100644 source/java/org/alfresco/repo/avm/FileContentImpl.java diff --git a/config/alfresco/avm-base-context.xml b/config/alfresco/avm-base-context.xml index 30a504ba80..2d4b07ce91 100644 --- a/config/alfresco/avm-base-context.xml +++ b/config/alfresco/avm-base-context.xml @@ -109,12 +109,6 @@ - - - - - - @@ -194,6 +188,9 @@ + + + diff --git a/config/alfresco/avm-services-context.xml b/config/alfresco/avm-services-context.xml index fe3e5ecbad..c5db7dd4ea 100644 --- a/config/alfresco/avm-services-context.xml +++ b/config/alfresco/avm-services-context.xml @@ -16,16 +16,6 @@ - - - content - - - - - - @@ -64,12 +54,6 @@ - - - - - - @@ -125,9 +109,6 @@ - - - @@ -217,9 +198,6 @@ - - - diff --git a/config/alfresco/content-services-context.xml b/config/alfresco/content-services-context.xml index 57634868a1..9c7a9847fa 100644 --- a/config/alfresco/content-services-context.xml +++ b/config/alfresco/content-services-context.xml @@ -66,6 +66,9 @@ + + + diff --git a/config/alfresco/model/contentModel.xml b/config/alfresco/model/contentModel.xml index 06ea1289ff..f45e1b43d7 100644 --- a/config/alfresco/model/contentModel.xml +++ b/config/alfresco/model/contentModel.xml @@ -81,6 +81,10 @@ true + + d:boolean + false + diff --git a/config/alfresco/node-services-context.xml b/config/alfresco/node-services-context.xml index d1c98514ea..af5fcd6233 100644 --- a/config/alfresco/node-services-context.xml +++ b/config/alfresco/node-services-context.xml @@ -15,6 +15,7 @@ + @@ -58,6 +59,16 @@ + + + + + + + + + + diff --git a/source/java/org/alfresco/model/ContentModel.java b/source/java/org/alfresco/model/ContentModel.java index c40491691e..928898b10d 100644 --- a/source/java/org/alfresco/model/ContentModel.java +++ b/source/java/org/alfresco/model/ContentModel.java @@ -92,6 +92,7 @@ public interface ContentModel // content type and aspect constants static final QName TYPE_CONTENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "content"); static final QName PROP_CONTENT = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "content"); + static final QName PROP_READONLY = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "readonly"); // title aspect static final QName ASPECT_TITLED = QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, "titled"); diff --git a/source/java/org/alfresco/repo/avm/AVMContext.java b/source/java/org/alfresco/repo/avm/AVMContext.java index 4e088608b5..9b4f7df4f5 100644 --- a/source/java/org/alfresco/repo/avm/AVMContext.java +++ b/source/java/org/alfresco/repo/avm/AVMContext.java @@ -3,12 +3,18 @@ */ package org.alfresco.repo.avm; +import org.alfresco.repo.content.ContentStore; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.MimetypeService; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; + /** * This is the (shudder) global context for AVM. It a rendezvous * point for access to needed global instances. * @author britt */ -class AVMContext +class AVMContext implements ApplicationContextAware { /** * The single instance of an AVMContext. @@ -40,11 +46,6 @@ class AVMContext */ public VersionRootDAO fVersionRootDAO; - /** - * The FileContentDAO. - */ - public FileContentDAO fFileContentDAO; - /** * The ChildEntryDAO. */ @@ -80,6 +81,36 @@ class AVMContext */ public AVMStorePropertyDAO fAVMStorePropertyDAO; + /** + * The ContentService. + */ + private ContentService fContentService; + + /** + * The Mimetype Service. + */ + private MimetypeService fMimetypeService; + + /** + * The AVMService. + */ + private AVMService fAVMService; + + /** + * The Content Store. + */ + private ContentStore fContentStore; + + /** + * The application context. + */ + public ApplicationContext fAppContext; + + public void setApplicationContext(ApplicationContext context) + { + fAppContext = context; + } + /** * @param nodeDAO the fAVMNodeDAO to set */ @@ -104,14 +135,6 @@ class AVMContext fDeletedChildDAO = deletedChildDAO; } - /** - * @param fileContentDAO the fFileContentDAO to set - */ - public void setFileContentDAO(FileContentDAO fileContentDAO) - { - fFileContentDAO = fileContentDAO; - } - /** * @param historyLinkDAO the fHistoryLinkDAO to set */ @@ -169,4 +192,56 @@ class AVMContext { fAVMStorePropertyDAO = avmStorePropertyDAO; } + + /** + * Get the Content Service. + * @return The ContentService object. + */ + public ContentService getContentService() + { + if (fContentService == null) + { + fContentService = (ContentService)fAppContext.getBean("contentService"); + } + return fContentService; + } + + /** + * Get the mime type service. + * @return The mime type service. + */ + public MimetypeService getMimetypeService() + { + if (fMimetypeService == null) + { + fMimetypeService = (MimetypeService)fAppContext.getBean("mimetypeService"); + } + return fMimetypeService; + } + + /** + * Get the AVM Service. + * @return The AVMService instance. + */ + public AVMService getAVMService() + { + if (fAVMService == null) + { + fAVMService = (AVMService)fAppContext.getBean("AVMService"); + } + return fAVMService; + } + + /** + * Get the ContentStore. + * @return The content store. + */ + public ContentStore getContentStore() + { + if (fContentStore == null) + { + fContentStore = (ContentStore)fAppContext.getBean("fileContentStore"); + } + return fContentStore; + } } diff --git a/source/java/org/alfresco/repo/avm/AVMCrawler.java b/source/java/org/alfresco/repo/avm/AVMCrawler.java index 0883844373..a52e6f1c29 100644 --- a/source/java/org/alfresco/repo/avm/AVMCrawler.java +++ b/source/java/org/alfresco/repo/avm/AVMCrawler.java @@ -216,8 +216,7 @@ class AVMCrawler implements Runnable } catch (Exception e) { - if (e instanceof AVMNotFoundException || - e instanceof AVMExistsException) + if (e instanceof AVMException) { return; } diff --git a/source/java/org/alfresco/repo/avm/AVMInterpreter.java b/source/java/org/alfresco/repo/avm/AVMInterpreter.java index 085e9c7ed1..830861f587 100644 --- a/source/java/org/alfresco/repo/avm/AVMInterpreter.java +++ b/source/java/org/alfresco/repo/avm/AVMInterpreter.java @@ -375,6 +375,7 @@ public class AVMInterpreter out.println("Mod Time: " + new Date(desc.getModDate())); } } + /* else if (command[0].equals("catver")) { if (command.length != 4) @@ -398,6 +399,7 @@ public class AVMInterpreter } reader.close(); } + */ else if (command[0].equals("ca")) { if (command.length != 5) diff --git a/source/java/org/alfresco/repo/avm/AVMNodeConverter.java b/source/java/org/alfresco/repo/avm/AVMNodeConverter.java index b10936c45d..4a5bf9fc43 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeConverter.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeConverter.java @@ -25,7 +25,7 @@ import org.alfresco.service.cmr.repository.StoreRef; * the StoreRef, NodeRef world. * @author britt */ -class AVMNodeConverter +public class AVMNodeConverter { /** * Get a NodeRef corresponding to the given path and version. diff --git a/source/java/org/alfresco/repo/avm/AVMNodeService.java b/source/java/org/alfresco/repo/avm/AVMNodeService.java index 1f66f1b9de..b5b480436c 100644 --- a/source/java/org/alfresco/repo/avm/AVMNodeService.java +++ b/source/java/org/alfresco/repo/avm/AVMNodeService.java @@ -27,8 +27,6 @@ import java.util.Map; import java.util.Set; import java.util.SortedMap; -import javax.naming.OperationNotSupportedException; - import org.alfresco.model.ContentModel; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.service.Auditable; @@ -39,6 +37,7 @@ import org.alfresco.service.cmr.dictionary.PropertyDefinition; import org.alfresco.service.cmr.repository.AssociationExistsException; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.ContentData; import org.alfresco.service.cmr.repository.CyclicChildRelationshipException; import org.alfresco.service.cmr.repository.InvalidChildAssociationRefException; import org.alfresco.service.cmr.repository.InvalidNodeRefException; @@ -80,6 +79,15 @@ public class AVMNodeService implements NodeService fAVMService = service; } + /** + * Set the DictionaryService. For Spring. + * @param dictionaryService The DictionaryService instance. + */ + public void setDictionaryService(DictionaryService dictionaryService) + { + fDictionaryService = dictionaryService; + } + /** * Default constructor. */ @@ -281,6 +289,10 @@ public class AVMNodeService implements NodeService Map props = new HashMap(); for (QName qname : properties.keySet()) { + if (isBuiltInProperty(qname)) + { + continue; + } props.put(qname, new PropertyValue(null, properties.get(qname))); } fAVMService.setNodeProperties(newAVMPath, props); @@ -645,6 +657,19 @@ public class AVMNodeService implements NodeService result.put(ContentModel.PROP_MODIFIED, new Date(desc.getModDate())); result.put(ContentModel.PROP_MODIFIER, desc.getLastModifier()); result.put(ContentModel.PROP_OWNER, desc.getOwner()); + if (desc.isFile()) + { + try + { + ContentData contentData = fAVMService.getContentDataForRead((Integer)avmVersionPath[0], + (String)avmVersionPath[1]); + result.put(ContentModel.PROP_CONTENT, contentData); + } + catch (AVMException e) + { + // TODO For now ignore. + } + } return result; } @@ -690,6 +715,21 @@ public class AVMNodeService implements NodeService QName qName, NodeRef nodeRef) { + if (qName.equals(ContentModel.PROP_CONTENT)) + { + try + { + ContentData contentData = + fAVMService.getContentDataForRead((Integer)avmVersionPath[0], + (String)avmVersionPath[1]); + return contentData; + } + catch (AVMException e) + { + // TODO For now, ignore. + return null; + } + } AVMNodeDescriptor desc = null; try { @@ -778,7 +818,8 @@ public class AVMNodeService implements NodeService qName.equals(ContentModel.PROP_CREATOR) || qName.equals(ContentModel.PROP_MODIFIED) || qName.equals(ContentModel.PROP_MODIFIER) || - qName.equals(ContentModel.PROP_OWNER); + qName.equals(ContentModel.PROP_OWNER) || + qName.equals(ContentModel.PROP_CONTENT); } /** @@ -795,12 +836,15 @@ public class AVMNodeService implements NodeService */ public void setProperty(NodeRef nodeRef, QName qname, Serializable value) throws InvalidNodeRefException { + Object [] avmVersionPath = AVMNodeConverter.ToAVMVersionPath(nodeRef); // TODO Just until we can set built in properties on AVM Nodes. if (isBuiltInProperty(qname)) { + if (qname.equals(ContentModel.PROP_CONTENT)) + { + } return; } - Object [] avmVersionPath = AVMNodeConverter.ToAVMVersionPath(nodeRef); if ((Integer)avmVersionPath[0] >= 0) { throw new InvalidNodeRefException("Read only store.", nodeRef); diff --git a/source/java/org/alfresco/repo/avm/AVMRepository.java b/source/java/org/alfresco/repo/avm/AVMRepository.java index 066ad220b5..359f6f510e 100644 --- a/source/java/org/alfresco/repo/avm/AVMRepository.java +++ b/source/java/org/alfresco/repo/avm/AVMRepository.java @@ -20,7 +20,6 @@ package org.alfresco.repo.avm; import java.io.File; import java.io.InputStream; import java.io.OutputStream; -import java.io.RandomAccessFile; import java.util.ArrayList; import java.util.Date; import java.util.List; @@ -28,6 +27,10 @@ import java.util.Map; import java.util.SortedMap; import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentService; +import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.namespace.QName; /** @@ -52,11 +55,6 @@ class AVMRepository */ private Issuer fNodeIssuer; - /** - * The content id issuer; - */ - private Issuer fContentIssuer; - /** * The layer id issuer. */ @@ -94,15 +92,6 @@ class AVMRepository fNodeIssuer = nodeIssuer; } - /** - * Set the content issuer. For Spring. - * @param contentIssuer The issuer. - */ - public void setContentIssuer(Issuer contentIssuer) - { - fContentIssuer = contentIssuer; - } - /** * Set the layer issuer. For Spring. * @param layerIssuer The issuer. @@ -281,21 +270,6 @@ class AVMRepository return rep.getOutputStream(pathParts[1]); } - /** - * Get a random access file from a file node. - * @param version The version id (read-only if not -1) - * @param path The path to the file. - * @param access The access mode for RandomAccessFile. - * @return A RandomAccessFile. - */ - public RandomAccessFile getRandomAccess(int version, String path, String access) - { - fLookupCount.set(1); - String[] pathParts = SplitPath(path); - AVMStore rep = getAVMStoreByName(pathParts[0]); - return rep.getRandomAccess(version, pathParts[1], access); - } - /** * Rename a node. * @param srcPath Source containing directory. @@ -524,25 +498,30 @@ class AVMRepository } /** - * Get an InputStream from a given version of a file. - * @param desc The node descriptor. - * @return The InputStream. + * Get a ContentReader from a file. + * @param version The version to look under. + * @param path The path to the file. + * @return A ContentReader */ - public InputStream getInputStream(AVMNodeDescriptor desc) + public ContentReader getReader(int version, String path) { fLookupCount.set(1); - AVMNode node = AVMContext.fgInstance.fAVMNodeDAO.getByID(desc.getId()); - if (node == null) - { - throw new AVMNotFoundException("Not found."); - } - if (node.getType() != AVMNodeType.PLAIN_FILE && - node.getType() != AVMNodeType.LAYERED_FILE) - { - throw new AVMWrongTypeException("Not a file."); - } - FileNode file = (FileNode)node; - return file.getContentForRead().getInputStream(); + String [] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + return store.getReader(version, pathParts[1]); + } + + /** + * Get a ContentWriter to a file. + * @param path The path to the file. + * @return A ContentWriter. + */ + public ContentWriter getWriter(String path) + { + fLookupCount.set(1); + String [] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + return store.getWriter(pathParts[1]); } /** @@ -666,15 +645,6 @@ class AVMRepository return fNodeIssuer.issue(); } - /** - * Issue a content id. - * @return The new id. - */ - public long issueContentID() - { - return fContentIssuer.issue(); - } - /** * Issue a new layer id. * @return The new id. @@ -1112,6 +1082,46 @@ class AVMRepository return null; } + /** + * Get the ContentData for a file. + * @param version The version to look under. + * @param path The path to the file. + * @return The ContentData for the file. + */ + public ContentData getContentDataForRead(int version, String path) + { + fLookupCount.set(1); + String [] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + return store.getContentDataForRead(version, pathParts[1]); + } + + /** + * Get the ContentData for a file for writing. + * @param path The path to the file. + * @return The ContentData object. + */ + public ContentData getContentDataForWrite(String path) + { + fLookupCount.set(1); + String [] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + return store.getContentDataForWrite(pathParts[1]); + } + + /** + * Set the ContentData on a file. + * @param path The path to the file. + * @param data The content data to set. + */ + public void setContentData(String path, ContentData data) + { + fLookupCount.set(1); + String [] pathParts = SplitPath(path); + AVMStore store = getAVMStoreByName(pathParts[0]); + store.setContentData(pathParts[1], data); + } + /** * Get the single instance of AVMRepository. * @return The single instance. diff --git a/source/java/org/alfresco/repo/avm/AVMService.java b/source/java/org/alfresco/repo/avm/AVMService.java index 92be632dcc..8add9bd427 100644 --- a/source/java/org/alfresco/repo/avm/AVMService.java +++ b/source/java/org/alfresco/repo/avm/AVMService.java @@ -19,13 +19,15 @@ package org.alfresco.repo.avm; import java.io.InputStream; import java.io.OutputStream; -import java.io.RandomAccessFile; import java.util.Date; import java.util.List; import java.util.Map; import java.util.SortedMap; import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.namespace.QName; /** @@ -49,15 +51,6 @@ public interface AVMService */ public InputStream getFileInputStream(int version, String path); - /** - * Get an input stream from a particular version of a file. - * @param desc The node descriptor pointing at the node. - * @return The InputStream. - * @throws AVMNotFoundException If desc is dangling or - * otherwise invalid. - */ - public InputStream getFileInputStream(AVMNodeDescriptor desc); - /** * Get an output stream to a file node. The file must already exist. * @param path The simple absolute path to the file node. @@ -68,18 +61,23 @@ public interface AVMService public OutputStream getFileOutputStream(String path); /** - * Get a random access file to the given path. - * @param version The version to find. + * Get a ContentReader for the given file. + * @param version The version to look under. * @param path The path to the file. - * @param access The access mode for RandomAccessFile. - * @return A RandomAccessFile - * @throws AVMNotFoundException If path is not found. - * @throws AVMWrongTypeException If path contains a non-terminal - * component that is not a directory, or if path is not pointing - * at a file. - * @throws AVMException If trying to write to anything but the head version. + * @return A ContentReader. + * @throws AVMNotFoundException If path does not exist. + * @throws AVMWrongTypeException if path is not a file. */ - public RandomAccessFile getRandomAccess(int version, String path, String access); + public ContentReader getReader(int version, String path); + + /** + * Get a ContentWriter to a file. + * @param path The path to the file. + * @return A ContentWriter. + * @throws AVMNotFoundException If path does not exist. + * @throws AVMWrongTypeException if path is not a file. + */ + public ContentWriter getWriter(String path); /** * Get a listing of a Folder by name. @@ -545,4 +543,35 @@ public interface AVMService * does not exist. */ public void deleteStoreProperty(String store, QName name); + + /** + * Get the ContentData for a node. Only applies to a file. + * @param version The version to look under. + * @param path The path to the node. + * @return The ContentData object. + * @throws AVMNotFoundException If path does not exist. + * @throws AVMWrongTypeException If path does not + * point to a file. + */ + public ContentData getContentDataForRead(int version, String path); + + /** + * Get the ContentData for a node. + * @param path The path to the node. + * @return The ContentData object. + * @throws AVMNotFoundException If path does not exist. + * @throws AVMWrongTypeException If path does not point + * to a file. + */ + public ContentData getContentDataForWrite(String path); + + /** + * Set the content data on a file. + * @param path The path to the file. + * @param data The ContentData to set. + * @throws AVMNotFoundException If path does not exist. + * @throws AVMWrongTypeException If path does not point + * to a file. + */ + public void setContentData(String path, ContentData data); } diff --git a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java index d84a6d90df..cef93322c9 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceImpl.java @@ -30,6 +30,9 @@ import java.util.SortedMap; import org.alfresco.repo.avm.AVMRepository; import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.namespace.QName; import org.apache.log4j.Logger; @@ -152,30 +155,57 @@ class AVMServiceImpl implements AVMService } /** - * Get an InputStream from a particular version of a file. - * @param desc The node descriptor. - * @return The InputStream. + * Get a ContentReader for the given file. + * @param version The version to look under. + * @param path The path to the file. + * @return A ContentReader. */ - public InputStream getFileInputStream(final AVMNodeDescriptor desc) + public ContentReader getReader(final int version, final String path) { - if (desc == null) + if (path == null) { - throw new AVMBadArgumentException("Illegal null argument."); + throw new AVMBadArgumentException("Null path."); } class TxnCallback implements RetryingTransactionCallback { - public InputStream in = null; + public ContentReader reader; public void perform() { - in = fAVMRepository.getInputStream(desc); + reader = fAVMRepository.getReader(version, path); } } TxnCallback doit = new TxnCallback(); fTransaction.perform(doit, false); - return doit.in; + return doit.reader; } + /** + * Get a ContentWriter to a file. + * @param path The path to the file. + * @return A ContentWriter. + * @throws AVMNotFoundException If path does not exist. + * @throws AVMWrongTypeException if path is not a file. + */ + public ContentWriter getWriter(final String path) + { + if (path == null) + { + throw new AVMBadArgumentException("Null path."); + } + class TxnCallback implements RetryingTransactionCallback + { + public ContentWriter writer; + + public void perform() + { + writer = fAVMRepository.getWriter(path); + } + } + TxnCallback doit = new TxnCallback(); + fTransaction.perform(doit, true); + return doit.writer; + } /** * Get an output stream to a file. Triggers versioning. */ @@ -199,34 +229,6 @@ class AVMServiceImpl implements AVMService return doit.out; } - /** - * Get a random access file to the given file. - * @param version The version to look for (read-only) - * @param path The path to the file. - * @param access The access mode for RandomAccessFile - * @return A Random Access File. - */ - public RandomAccessFile getRandomAccess(final int version, final String path, final String access) - { - if (path == null || access == null) - { - throw new AVMBadArgumentException("Illegal null argument."); - } - class TxnCallback implements RetryingTransactionCallback - { - public RandomAccessFile file; - - public void perform() - { - file = fAVMRepository.getRandomAccess(version, path, access); - } - } - TxnCallback doit = new TxnCallback(); - fTransaction.perform(doit, true); - return doit.file; - } - - /** * Get a directory listing. * @param version The version id to lookup. @@ -1322,4 +1324,80 @@ class AVMServiceImpl implements AVMService TxnCallback doit = new TxnCallback(); fTransaction.perform(doit, true); } + + /** + * Get the ContentData for a node. Only applies to a file. + * @param version The version to look under. + * @param path The path to the node. + * @return The ContentData object. + */ + public ContentData getContentDataForRead(final int version, final String path) + { + if (path == null) + { + throw new AVMBadArgumentException("Null Path."); + } + class TxnCallback implements RetryingTransactionCallback + { + public ContentData content; + + public void perform() + { + content = fAVMRepository.getContentDataForRead(version, path); + } + } + TxnCallback doit = new TxnCallback(); + fTransaction.perform(doit, false); + return doit.content; + } + + /** + * Get the Content data for writing. + * @param path The path to the node. + * @return The ContentData object. + */ + public ContentData getContentDataForWrite(final String path) + { + if (path == null) + { + throw new AVMBadArgumentException("Null Path."); + } + class TxnCallback implements RetryingTransactionCallback + { + public ContentData content; + + public void perform() + { + content = fAVMRepository.getContentDataForWrite(path); + } + } + TxnCallback doit = new TxnCallback(); + fTransaction.perform(doit, true); + return doit.content; + } + + /** + * Set the content data on a file. + * @param path The path to the file. + * @param data The ContentData to set. + * @throws AVMNotFoundException If path does not exist. + * @throws AVMWrongTypeException If path does not point + * to a file. + */ + public void setContentData(final String path, final ContentData data) + { + if (path == null || data == null) + { + throw new AVMBadArgumentException("Null Path."); + } + class TxnCallback implements RetryingTransactionCallback + { + public void perform() + { + fAVMRepository.setContentData(path, data); + } + } + TxnCallback doit = new TxnCallback(); + fTransaction.perform(doit, true); + } } diff --git a/source/java/org/alfresco/repo/avm/AVMServiceTest.java b/source/java/org/alfresco/repo/avm/AVMServiceTest.java index 7692d97784..67e2bb6e6b 100644 --- a/source/java/org/alfresco/repo/avm/AVMServiceTest.java +++ b/source/java/org/alfresco/repo/avm/AVMServiceTest.java @@ -1890,6 +1890,7 @@ public class AVMServiceTest extends AVMServiceTestBase /** * The random access. */ + /* public void testRandomAccess() { try @@ -1914,6 +1915,7 @@ public class AVMServiceTest extends AVMServiceTestBase fail(); } } + */ /** * Test COW during long operations. diff --git a/source/java/org/alfresco/repo/avm/AVMStore.java b/source/java/org/alfresco/repo/avm/AVMStore.java index 3591863abb..748cad54f0 100644 --- a/source/java/org/alfresco/repo/avm/AVMStore.java +++ b/source/java/org/alfresco/repo/avm/AVMStore.java @@ -19,13 +19,15 @@ package org.alfresco.repo.avm; import java.io.File; import java.io.InputStream; import java.io.OutputStream; -import java.io.RandomAccessFile; import java.util.Date; import java.util.List; import java.util.Map; import java.util.SortedMap; import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.namespace.QName; /** @@ -102,7 +104,22 @@ interface AVMStore * @return An InputStream */ public InputStream getInputStream(int version, String path); + + /** + * Get a ContentReader from a file. + * @param version The version to look under. + * @param path The path to the file. + * @return A ContentReader. + */ + public ContentReader getReader(int version, String path); + /** + * Get a ContentWriter to a file. + * @param path The path to the file. + * @return A ContentWriter. + */ + public ContentWriter getWriter(String path); + /** * Get a listing of the designated directory. * @param version The version to look under. @@ -134,15 +151,6 @@ interface AVMStore */ public OutputStream getOutputStream(String path); - /** - * Get a random access file to the given file. - * @param version The version id (read-only if not -1) - * @param path The path to the file. - * @param access The access for RandomAccessFile. - * @return A RandomAccessFile. - */ - public RandomAccessFile getRandomAccess(int version, String path, String access); - /** * Remove a node and all of its contents. * @param path The path to the node's parent directory. @@ -336,4 +344,26 @@ interface AVMStore * @param name The name of the property to delete. */ public void deleteProperty(QName name); + + /** + * Get the ContentData on a file. + * @param version The version to look under. + * @param path The path to the file. + * @return The ContentData corresponding to the file. + */ + public ContentData getContentDataForRead(int version, String path); + + /** + * Get the ContentData for writing. + * @param path The path to the file. + * @return The ContentData object. + */ + public ContentData getContentDataForWrite(String path); + + /** + * Set the ContentData for a file. + * @param path The path to the file. + * @param data The ContentData to set. + */ + public void setContentData(String path, ContentData data); } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java index deb471f174..5a6f698875 100644 --- a/source/java/org/alfresco/repo/avm/AVMStoreImpl.java +++ b/source/java/org/alfresco/repo/avm/AVMStoreImpl.java @@ -20,7 +20,6 @@ package org.alfresco.repo.avm; import java.io.File; import java.io.InputStream; import java.io.OutputStream; -import java.io.RandomAccessFile; import java.io.Serializable; import java.util.ArrayList; import java.util.Date; @@ -33,6 +32,10 @@ import java.util.TreeMap; import org.alfresco.model.ContentModel; import org.alfresco.repo.domain.PropertyValue; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.cmr.repository.ContentWriter; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; /** @@ -231,7 +234,12 @@ class AVMStoreImpl implements AVMStore, Serializable file.setVersionID(getNextVersionID()); dir.putChild(name, file); dir.updateModTime(); - return file.getContentForWrite().getOutputStream(); + file.setContentData(new ContentData(null, + AVMContext.fgInstance.getMimetypeService().guessMimetype(name), + -1, + "UTF-8")); + ContentWriter writer = getWriter(AVMNodeConverter.ExtendAVMPath(path, name)); + return writer.getContentOutputStream(); } /** @@ -248,10 +256,17 @@ class AVMStoreImpl implements AVMStore, Serializable { throw new AVMExistsException("Child exists: " + name); } - PlainFileNodeImpl file = new PlainFileNodeImpl(this, data); + PlainFileNodeImpl file = new PlainFileNodeImpl(this); file.setVersionID(getNextVersionID()); dir.putChild(name, file); dir.updateModTime(); + file.setContentData(new ContentData(null, + AVMContext.fgInstance.getMimetypeService().guessMimetype(name), + -1, + "UTF-8")); + ContentWriter writer = getWriter(AVMNodeConverter.ExtendAVMPath(path, name)); + writer.putContent(data); + file.setContentData(writer.getContentData()); } /** @@ -284,6 +299,9 @@ class AVMStoreImpl implements AVMStore, Serializable */ public InputStream getInputStream(int version, String path) { + ContentReader reader = getReader(version, path); + return reader.getContentInputStream(); + /* Lookup lPath = lookup(version, path, false); AVMNode node = lPath.getCurrentNode(); if (node.getType() != AVMNodeType.PLAIN_FILE && @@ -294,8 +312,35 @@ class AVMStoreImpl implements AVMStore, Serializable FileNode file = (FileNode)node; FileContent content = file.getContentForRead(); return content.getInputStream(); + */ } + /** + * Get a ContentReader from a file. + * @param version The version to look under. + * @param path The path to the file. + * @return A ContentReader. + */ + public ContentReader getReader(int version, String path) + { + NodeRef nodeRef = AVMNodeConverter.ToNodeRef(version, fName + ":" + path); + return AVMContext.fgInstance.getContentService().getReader(nodeRef, ContentModel.PROP_CONTENT); + } + + /** + * Get a ContentWriter to a file. + * @param path The path to the file. + * @return A ContentWriter. + */ + public ContentWriter getWriter(String path) + { + NodeRef nodeRef = AVMNodeConverter.ToNodeRef(-1, fName + ":" + path); + ContentWriter writer = + AVMContext.fgInstance.getContentService().getWriter(nodeRef, ContentModel.PROP_CONTENT, true); + setContentData(path, writer.getContentData()); + return writer; + } + /** * Get a listing from a directory. * @param version The version to look under. @@ -368,6 +413,9 @@ class AVMStoreImpl implements AVMStore, Serializable */ public OutputStream getOutputStream(String path) { + ContentWriter writer = getWriter(path); + return writer.getContentOutputStream(); + /* Lookup lPath = lookup(-1, path, true); AVMNode node = lPath.getCurrentNode(); if (node.getType() != AVMNodeType.PLAIN_FILE && @@ -379,41 +427,7 @@ class AVMStoreImpl implements AVMStore, Serializable FileContent content = file.getContentForWrite(); file.updateModTime(); return content.getOutputStream(); - } - - /** - * Get a RandomAccessFile to a file node. - * @param version The version. - * @param path The path to the file. - * @param access The access mode for RandomAccessFile. - * @return A RandomAccessFile. - */ - public RandomAccessFile getRandomAccess(int version, String path, String access) - { - boolean write = access.indexOf("rw") == 0; - if (write && version >= 0) - { - throw new AVMException("Access denied: " + path); - } - Lookup lPath = lookup(version, path, write); - AVMNode node = lPath.getCurrentNode(); - if (node.getType() != AVMNodeType.PLAIN_FILE && - node.getType() != AVMNodeType.LAYERED_FILE) - { - throw new AVMWrongTypeException("Not a file: " + path); - } - FileNode file = (FileNode)node; - FileContent content = null; - if (write) - { - content = file.getContentForWrite(); - file.updateModTime(); - } - else - { - content = file.getContentForRead(); - } - return content.getRandomAccess(access); + */ } /** @@ -968,4 +982,53 @@ class AVMStoreImpl implements AVMStore, Serializable { AVMContext.fgInstance.fAVMStorePropertyDAO.delete(this, name); } + + /** + * Get the ContentData on a file. + * @param version The version to look under. + * @param path The path to the file. + * @return The ContentData corresponding to the file. + */ + public ContentData getContentDataForRead(int version, String path) + { + Lookup lPath = lookup(version, path, false); + AVMNode node = lPath.getCurrentNode(); + if (!(node instanceof FileNode)) + { + throw new AVMWrongTypeException("File Expected."); + } + return ((FileNode)node).getContentData(lPath); + } + + /** + * Get the ContentData on a file for writing. + * @param path The path to the file. + * @return The ContentData corresponding to the file. + */ + public ContentData getContentDataForWrite(String path) + { + Lookup lPath = lookup(-1, path, true); + AVMNode node = lPath.getCurrentNode(); + if (!(node instanceof FileNode)) + { + throw new AVMWrongTypeException("File Expected."); + } + return ((FileNode)node).getContentData(lPath); + } + + /** + * Set the ContentData for a file. + * @param path The path to the file. + * @param data The ContentData to set. + */ + public void setContentData(String path, ContentData data) + { + Lookup lPath = lookup(-1, path, true); + AVMNode node = lPath.getCurrentNode(); + if (!(node instanceof FileNode)) + { + throw new AVMWrongTypeException("File Expected."); + } + ((FileNode)node).setContentData(data); + } } diff --git a/source/java/org/alfresco/repo/avm/FileContent.java b/source/java/org/alfresco/repo/avm/FileContent.java deleted file mode 100644 index e4b9b357fd..0000000000 --- a/source/java/org/alfresco/repo/avm/FileContent.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (C) 2006 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. - */ -package org.alfresco.repo.avm; - -import java.io.InputStream; -import java.io.OutputStream; -import java.io.RandomAccessFile; - -/** - * Interface for file content. FileContent can be shared between files. - * @author britt - */ -interface FileContent -{ - /** - * Get the number of files that refer to this content. - * @return The reference count. - */ - public int getRefCount(); - - /** - * Set the reference count. - * @param count The count to set. - */ - public void setRefCount(int count); - - /** - * Get an input stream from the content. - * @return An InputStream. - */ - public InputStream getInputStream(); - - /** - * Get an output stream to the content. - * @return an OutputStream. - */ - public OutputStream getOutputStream(); - - /** - * Get a random access file to this content. - * @param access The mode to open the file in. - * @return A RandomAccessFile. - */ - public RandomAccessFile getRandomAccess(String access); - - /** - * Delete the contents of this from the backing store. - */ - public void delete(); - - /** - * Get the length of the file. - * @return The length of the file. - */ - public long getLength(); - - /** - * Get the object id. - * @return object id. - */ - public long getId(); -} \ No newline at end of file diff --git a/source/java/org/alfresco/repo/avm/FileContentDAO.java b/source/java/org/alfresco/repo/avm/FileContentDAO.java deleted file mode 100644 index b3d0abe189..0000000000 --- a/source/java/org/alfresco/repo/avm/FileContentDAO.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (C) 2006 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. - */ - -package org.alfresco.repo.avm; - -/** - * DAO for FileContent objects. - * @author britt - */ -interface FileContentDAO -{ - /** - * Save one. - * @param content To be saved. - */ - public void save(FileContent content); - - /** - * Delete one. - * @param content To be deleted. - */ - public void delete(FileContent content); -} diff --git a/source/java/org/alfresco/repo/avm/FileContentDAOHibernate.java b/source/java/org/alfresco/repo/avm/FileContentDAOHibernate.java deleted file mode 100644 index 4747197dc5..0000000000 --- a/source/java/org/alfresco/repo/avm/FileContentDAOHibernate.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (C) 2006 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. - */ - -package org.alfresco.repo.avm; - -import org.springframework.orm.hibernate3.support.HibernateDaoSupport; - -/** - * @author britt - * - */ -class FileContentDAOHibernate extends HibernateDaoSupport implements - FileContentDAO -{ - /** - * Do nothing constructor. - */ - public FileContentDAOHibernate() - { - super(); - } - - /** - * Save one. - * @param content The one to save. - */ - public void save(FileContent content) - { - getSession().save(content); - } - - /** - * Delete one. - * @param content To be deleted. - */ - public void delete(FileContent content) - { - getSession().delete(content); - } -} diff --git a/source/java/org/alfresco/repo/avm/FileContentImpl.java b/source/java/org/alfresco/repo/avm/FileContentImpl.java deleted file mode 100644 index 7855cfae4b..0000000000 --- a/source/java/org/alfresco/repo/avm/FileContentImpl.java +++ /dev/null @@ -1,357 +0,0 @@ -/* - * Copyright (C) 2006 Alfresco, Inc. - * - * Licensed under the Mozilla Public License version 1.1 - * with a permitted attribution clause. You may obtain a - * copy of the License at - * - * http://www.alfresco.org/legal/license.txt - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, - * either express or implied. See the License for the specific - * language governing permissions and limitations under the - * License. - */ - -package org.alfresco.repo.avm; - -import java.io.BufferedInputStream; -import java.io.BufferedOutputStream; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.io.RandomAccessFile; -import java.io.Serializable; -import java.util.Formatter; - -/** - * Content that is readable and writeable. - * @author britt - */ -class FileContentImpl implements FileContent, Serializable -{ - static final long serialVersionUID = -7450825236235397307L; - - /** - * The Object ID. - */ - private long fID; - - /** - * The reference count of this FileContent. - */ - private int fRefCount; - - /** - * The version (for concurrency control). - */ - private long fVers; - - /** - * The name of the file. - */ - private String fName; - - /** - * The directory path of the file. - */ - private String fPath; - - /** - * Default constructor. - */ - public FileContentImpl() - { - fName = null; - fPath = null; - } - - /** - * Make a brand new one. - * @param id The id for this content. - */ - public FileContentImpl(long id) - { - fID = id; - fRefCount = 1; - // Initialize the contents. - try - { - OutputStream out = getOutputStream(); - out.close(); - } - catch (IOException ie) - { - throw new AVMException("File data error.", ie); - } - AVMContext.fgInstance.fFileContentDAO.save(this); - } - - /** - * Initialize with the given content. - * @param id - * @param content - */ - public FileContentImpl(long id, File content) - { - fID = id; - fRefCount = 1; - // Initialize the contents. - try - { - OutputStream out = getOutputStream(); - InputStream in = new FileInputStream(content); - byte [] buff = new byte[8192]; - int count; - while ((count = in.read(buff)) != -1) - { - out.write(buff, 0, count); - } - out.close(); - in.close(); - } - catch (IOException ie) - { - throw new AVMException("I/O Error.", ie); - } - AVMContext.fgInstance.fFileContentDAO.save(this); - } - - /** - * Copy constructor, sort of. - * @param other The content to copy from. - * @param id The id for this content. - */ - public FileContentImpl(FileContent other, long id) - { - fID = id; - fRefCount = 1; - // Copy the contents from other to this. - BufferedInputStream in = new BufferedInputStream(other.getInputStream()); - BufferedOutputStream out = new BufferedOutputStream(getOutputStream()); - try - { - byte [] buff = new byte[4096]; // Nyah, nyah. - int bytesRead; - while ((bytesRead = in.read(buff)) != -1) - { - out.write(buff, 0, bytesRead); - } - out.flush(); - out.close(); - in.close(); - } - catch (IOException ie) - { - throw new AVMException("I/O failure in Copy on Write.", ie); - } - AVMContext.fgInstance.fFileContentDAO.save(this); - } - - /** - * Get this FileContent's reference count. - * @return The reference count. - */ - public int getRefCount() - { - return fRefCount; - } - - /** - * Set the reference count on this. - * @param count The reference count to set. - */ - public void setRefCount(int count) - { - fRefCount = count; - } - - /** - * Get an InputStream from this FileContent. - * @return An InputStream. - */ - public InputStream getInputStream() - { - try - { - return new FileInputStream(getContentPath()); - } - catch (IOException ie) - { - throw new AVMException("Could not open for reading: " + getContentPath(), ie); - } - } - - /** - * Gets an ouptut stream to this node. - * @return An OutputStream. - */ - public OutputStream getOutputStream() - { - try - { - File dir = new File(getDirectoryPath()); - if (!dir.exists()) - { - dir.mkdirs(); - } - return new FileOutputStream(getContentPath()); - } - catch (IOException ie) - { - throw new AVMException("Could not open for writing: " + getContentPath(), ie); - } - } - - /** - * Get a random access file from this content. It's the responsibility of - * the caller of this to insure that this object has been copied if the - * access argument is a write mode. - * @param access The access more for RandomAccessFile. - * @return A RandomAccessFile. - */ - public RandomAccessFile getRandomAccess(String access) - { - try - { - return new RandomAccessFile(getContentPath(), access); - } - catch (IOException ie) - { - throw new AVMException("Could not open for random access: " + getContentPath(), ie); - } - } - - /** - * Delete the contents of this file from the backing store. - */ - public void delete() - { - File file = new File(getContentPath()); - file.delete(); - } - - /** - * Get the length of this content. - * @return The length of the content. - */ - public long getLength() - { - File file = new File(getContentPath()); - return file.length(); - } - - /** - * Retrieve the full path for this content. - * @return The full path for this content. - */ - private synchronized String getContentPath() - { - if (fName == null) - { - calcPathData(); - } - return fName; - } - - /** - * Get the directory path for this content. - * @return The directory path. - */ - private synchronized String getDirectoryPath() - { - if (fPath == null) - { - calcPathData(); - } - return fPath; - } - - /** - * Calculate the path data. - */ - private void calcPathData() - { - Formatter form = new Formatter(new StringBuilder()); - form.format("%016x", fID); - String name = form.toString(); - form = new Formatter(new StringBuilder()); - form.format("/%02x/%02x/%02x", - (fID & 0xff000000) >> 24, - (fID & 0xff0000) >> 16, - (fID & 0xff00) >> 8); - String dir = form.toString(); - fPath = AVMRepository.GetInstance().getStorageRoot() + dir; - fName = fPath + "/" + name; - } - - /** - * Set the version for concurrency control. - * @param vers The value to set. - */ - protected void setVers(long vers) - { - fVers = vers; - } - - /** - * Get the version for concurrency control. - * @return The version. - */ - protected long getVers() - { - return fVers; - } - - /** - * Set the object id. For Hibernate. - * @param id - */ - protected void setId(long id) - { - fID = id; - } - - /** - * Get the object id. - * @return The object id. - */ - public long getId() - { - return fID; - } - - /** - * Equals predicate. Based on object ID. - * @param obj The obect to compare against. - * @return Equality. - */ - @Override - public boolean equals(Object obj) - { - if (this == obj) - { - return true; - } - if (!(obj instanceof FileContent)) - { - return false; - } - return fID == ((FileContent)obj).getId(); - } - - /** - * Generate a hashCode. - * @return The hashCode. - */ - @Override - public int hashCode() - { - return (int)fID; - } -} diff --git a/source/java/org/alfresco/repo/avm/FileNode.java b/source/java/org/alfresco/repo/avm/FileNode.java index 7d9ca08885..f993c83b05 100644 --- a/source/java/org/alfresco/repo/avm/FileNode.java +++ b/source/java/org/alfresco/repo/avm/FileNode.java @@ -16,6 +16,8 @@ */ package org.alfresco.repo.avm; +import org.alfresco.service.cmr.repository.ContentData; + /** * Interface for the generic idea of a file. * @author britt @@ -23,15 +25,15 @@ package org.alfresco.repo.avm; interface FileNode extends AVMNode { /** - * Get the content object associated with this node, for reading. - * @return A FileContent object. + * Set the ContentData for this file. + * @param contentData The value to set. */ - public FileContent getContentForRead(); - + public void setContentData(ContentData contentData); + /** - * Get the content object for writing. This will do COW - * as needed. - * @return A FileContent object. + * Get the ContentData for this file. + * @param lPath The Lookup used to get here. + * @return The ContentData object for this file. */ - public FileContent getContentForWrite(); + public ContentData getContentData(Lookup lPath); } \ No newline at end of file diff --git a/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java b/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java index ff91e06ad9..bd4e0e7173 100644 --- a/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/LayeredFileNodeImpl.java @@ -17,6 +17,8 @@ package org.alfresco.repo.avm; +import org.alfresco.service.cmr.repository.ContentData; + /** * A LayeredFileNode behaves like a copy on write symlink. * @author britt @@ -81,13 +83,10 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode { throw new AVMException("Unbacked layered file node."); } - // This is a mildly dirty trick. We use getContentForRead so as not to startle - // the ultimate destination content into copying itself prematurely. - FileContent content = ((FileNode)indirect).getContentForRead(); - PlainFileNodeImpl newMe = new PlainFileNodeImpl(this, - content, - lPath.getAVMStore(), - getBasicAttributes()); + PlainFileNodeImpl newMe = new PlainFileNodeImpl(lPath.getAVMStore(), + getBasicAttributes(), + getContentData(lPath), + getProperties()); newMe.setAncestor(this); return newMe; } @@ -101,33 +100,6 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode return AVMNodeType.LAYERED_FILE; } - /** - * Get the content of the specified version. - * @return A FileContent object. - */ - public FileContent getContentForRead() - { - Lookup lookup = AVMRepository.GetInstance().lookup(-1, fIndirection); - AVMNode node = lookup.getCurrentNode(); - if (node.getType() != AVMNodeType.LAYERED_FILE && - node.getType() != AVMNodeType.PLAIN_FILE) - { - throw new AVMException("Missing Link."); - } - FileNode file = (FileNode)node; - return file.getContentForRead(); - } - - /** - * Get File Content for writing. Should never be called. - * @return Always null. - */ - public FileContent getContentForWrite() - { - assert false : "Never happens"; - return null; - } - /** * Get the underlying path. * @param lookup The Lookup. (Unused here.) @@ -256,4 +228,29 @@ class LayeredFileNodeImpl extends FileNodeImpl implements LayeredFileNode { fIndirection = indirection; } + + /** + * Set the ContentData for this file. + * @param contentData The value to set. + */ + public void setContentData(ContentData contentData) + { + throw new AVMException("Should not be called."); + } + + /** + * Get the ContentData for this file. + * @return The ContentData object for this file. + */ + public ContentData getContentData(Lookup lPath) + { + Lookup lookup = lPath.getAVMStore().getAVMRepository().lookup(-1, getIndirection()); + AVMNode node = lookup.getCurrentNode(); + if (!(node instanceof FileNode)) + { + throw new AVMException("Invalid target."); + } + FileNode file = (FileNode)node; + return file.getContentData(lookup); + } } diff --git a/source/java/org/alfresco/repo/avm/OrphanReaper.java b/source/java/org/alfresco/repo/avm/OrphanReaper.java index 92649bc4da..f727c62ec8 100644 --- a/source/java/org/alfresco/repo/avm/OrphanReaper.java +++ b/source/java/org/alfresco/repo/avm/OrphanReaper.java @@ -295,17 +295,7 @@ class OrphanReaper implements Runnable } AVMContext.fgInstance.fAVMNodeDAO.delete(node); } - else if (node.getType() == AVMNodeType.PLAIN_FILE) - { - AVMContext.fgInstance.fAVMNodeDAO.delete(node); - // FileContent should be purged if nobody else references it. - FileContent content = ((PlainFileNode)node).getContent(); - if (content.getRefCount() == 1) - { - content.delete(); - AVMContext.fgInstance.fFileContentDAO.delete(content); - } - } + // TODO Need to properly clean up deleted files. else { AVMContext.fgInstance.fAVMNodeDAO.delete(node); diff --git a/source/java/org/alfresco/repo/avm/PlainFileNode.java b/source/java/org/alfresco/repo/avm/PlainFileNode.java index 80b603cbc3..00a1cf878f 100644 --- a/source/java/org/alfresco/repo/avm/PlainFileNode.java +++ b/source/java/org/alfresco/repo/avm/PlainFileNode.java @@ -6,5 +6,4 @@ package org.alfresco.repo.avm; */ interface PlainFileNode extends FileNode { - public FileContent getContent(); } diff --git a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java index 742fb4bba6..a9a0ee0c27 100644 --- a/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java +++ b/source/java/org/alfresco/repo/avm/PlainFileNodeImpl.java @@ -17,7 +17,12 @@ package org.alfresco.repo.avm; -import java.io.File; +import java.util.Map; + +import org.alfresco.repo.domain.PropertyValue; +import org.alfresco.service.cmr.repository.ContentData; +import org.alfresco.service.cmr.repository.ContentReader; +import org.alfresco.service.namespace.QName; /** @@ -29,9 +34,24 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode static final long serialVersionUID = 8720376837929735294L; /** - * The file content. + * The Content URL. */ - private FileContent fContent; + private String fContentURL; + + /** + * The Mime type. + */ + private String fMimeType; + + /** + * The character encoding. + */ + private String fEncoding; + + /** + * The length of the file. + */ + private long fLength; /** * Default constructor. @@ -48,27 +68,12 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode public PlainFileNodeImpl(AVMStore store) { super(store.getAVMRepository().issueID(), store); - fContent = new FileContentImpl(AVMRepository.GetInstance().issueContentID()); // AVMContext.fgInstance.fAVMNodeDAO.flush(); AVMContext.fgInstance.fAVMNodeDAO.save(this); AVMContext.fgInstance.fAVMNodeDAO.flush(); AVMContext.fgInstance.fNewInAVMStoreDAO.save(new NewInAVMStoreImpl(store, this)); } - /** - * Create a new plain file with given content. - * @param store The store. - * @param content The content to set. - */ - public PlainFileNodeImpl(AVMStore store, File content) - { - super(store.getAVMRepository().issueID(), store); - fContent = new FileContentImpl(AVMRepository.GetInstance().issueContentID(), content); - AVMContext.fgInstance.fAVMNodeDAO.save(this); - AVMContext.fgInstance.fAVMNodeDAO.flush(); - AVMContext.fgInstance.fNewInAVMStoreDAO.save(new NewInAVMStoreImpl(store, this)); - } - /** * Copy on write constructor. * @param other The node we are being copied from. @@ -78,8 +83,9 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode AVMStore store) { super(store.getAVMRepository().issueID(), store); - fContent = other.getContent(); - fContent.setRefCount(fContent.getRefCount() + 1); + // The null is OK because the Lookup argument is only use by + // layered files. + setContentData(other.getContentData(null)); AVMContext.fgInstance.fAVMNodeDAO.save(this); AVMContext.fgInstance.fAVMNodeDAO.flush(); AVMContext.fgInstance.fNewInAVMStoreDAO.save(new NewInAVMStoreImpl(store, this)); @@ -87,24 +93,26 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode } /** - * Constructor that takes a FileContent to share. Called by LayeredFileNodeImpl.copy(). - * @param content The FileContent to share. - * @param store The AVMStore. + * Construct a new one. This is called when a LayeredFileNode + * is copied. + * @param store + * @param attrs + * @param content */ - public PlainFileNodeImpl(LayeredFileNode other, - FileContent content, - AVMStore store, - BasicAttributes oAttrs) + public PlainFileNodeImpl(AVMStore store, + BasicAttributes attrs, + ContentData content, + Map props) { super(store.getAVMRepository().issueID(), store); - fContent = content; - fContent.setRefCount(fContent.getRefCount() + 1); + setContentData(content); + setBasicAttributes(attrs); AVMContext.fgInstance.fAVMNodeDAO.save(this); AVMContext.fgInstance.fAVMNodeDAO.flush(); + this.setProperties(props); AVMContext.fgInstance.fNewInAVMStoreDAO.save(new NewInAVMStoreImpl(store, this)); - copyProperties(other); } - + /** * Copy on write logic. * @param lPath The lookup path. @@ -125,25 +133,6 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode return AVMNodeType.PLAIN_FILE; } - /** - * Get content for reading. - */ - public FileContent getContentForRead() - { - return fContent; - } - /** - * Get content for writing. - */ - public FileContent getContentForWrite() - { - if (fContent.getRefCount() > 1) - { - fContent = new FileContentImpl(fContent, AVMRepository.GetInstance().issueContentID()); - } - return fContent; - } - /** * Get a diagnostic string representation. * @param lPath The Lookup. @@ -187,7 +176,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode false, -1, false, - getContentForRead().getLength()); + getLength()); } /** @@ -214,7 +203,7 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode false, -1, false, - getContentForRead().getLength()); + getFileLength()); } /** @@ -243,25 +232,115 @@ class PlainFileNodeImpl extends FileNodeImpl implements PlainFileNode false, -1, false, - getContentForRead().getLength()); + getFileLength()); } /** - * Get the file content of this node. - * @return The file content object. + * Get the Content URL. + * @return The content URL. */ - public FileContent getContent() + public String getContentURL() { - return fContent; + return fContentURL; + } + + /** + * Set the Content URL. + * @param contentURL + */ + protected void setContentURL(String contentURL) + { + fContentURL = contentURL; + } + + /** + * Get the character encoding. + * @return The encoding. + */ + public String getEncoding() + { + return fEncoding; + } + + /** + * Set the character encoding. + * @param encoding The encoding to set. + */ + protected void setEncoding(String encoding) + { + fEncoding = encoding; + } + + /** + * Get the file length. + * @return The file length or null if unknown. + */ + public long getLength() + { + return fLength; } /** - * Set the FileContent for this file. - * @param content + * Get the actual file length. + * @return The actual file length; */ - protected void setContent(FileContent content) + private long getFileLength() { - fContent = content; + ContentReader reader = AVMContext.fgInstance.getContentStore().getReader(fContentURL); + return reader.getSize(); + } + + /** + * Set the file length. + * @param length The length of the file. + */ + protected void setLength(long length) + { + fLength = length; + } + + /** + * Get the mime type of the content. + * @return The Mime Type of the content. + */ + public String getMimeType() + { + return fMimeType; + } + + /** + * Set the Mime Type of the content. + * @param mimeType The Mime Type to set. + */ + protected void setMimeType(String mimeType) + { + fMimeType = mimeType; + } + + /** + * Set the ContentData for this file. + * @param contentData The value to set. + */ + public void setContentData(ContentData contentData) + { + fContentURL = contentData.getContentUrl(); + fMimeType = contentData.getMimetype(); + if (fMimeType == null) + { + throw new AVMException("Null mime type."); + } + fEncoding = contentData.getEncoding(); + fLength = contentData.getSize(); + } + + /** + * Get the ContentData for this file. + * @param lPath The lookup path used to get here. Unused here. + * @return The ContentData object for this file. + */ + public ContentData getContentData(Lookup lPath) + { + return new ContentData(fContentURL, fMimeType, fLength, fEncoding); } } diff --git a/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml b/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml index b7597cb21a..a6a87e914e 100644 --- a/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml +++ b/source/java/org/alfresco/repo/avm/hibernate/AVM.hbm.xml @@ -77,9 +77,10 @@ - - + + + + - - - - - - - -