mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-06-09 17:45:10 +00:00
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
This commit is contained in:
parent
9a2a67605c
commit
06df2021c8
@ -109,12 +109,6 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="fileContentDAO" class="org.alfresco.repo.avm.FileContentDAOHibernate">
|
||||
<property name="sessionFactory">
|
||||
<ref bean="sessionFactory"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="childEntryDAO" class="org.alfresco.repo.avm.ChildEntryDAOHibernate">
|
||||
<property name="sessionFactory">
|
||||
<ref bean="sessionFactory"/>
|
||||
@ -194,6 +188,9 @@
|
||||
<property name="avmStorePropertyDAO">
|
||||
<ref bean="avmStorePropertyDAO"/>
|
||||
</property>
|
||||
<property name="contentService">
|
||||
<ref bean="ContentService"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- The HibernateTransactionManager -->
|
||||
|
@ -16,16 +16,6 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="contentIssuer" class="org.alfresco.repo.avm.Issuer"
|
||||
depends-on="retryingTransaction,avmContext" init-method="init">
|
||||
<property name="name">
|
||||
<value>content</value>
|
||||
</property>
|
||||
<property name="retryingTransaction">
|
||||
<ref bean="retryingTransaction"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="layerIssuer" class="org.alfresco.repo.avm.Issuer"
|
||||
depends-on="retryingTransaction,avmContext" init-method="init">
|
||||
<property name="name">
|
||||
@ -64,12 +54,6 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="fileContentDAO" class="org.alfresco.repo.avm.FileContentDAOHibernate">
|
||||
<property name="sessionFactory">
|
||||
<ref bean="sessionFactory"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="childEntryDAO" class="org.alfresco.repo.avm.ChildEntryDAOHibernate">
|
||||
<property name="sessionFactory">
|
||||
<ref bean="sessionFactory"/>
|
||||
@ -125,9 +109,6 @@
|
||||
<property name="versionRootDAO">
|
||||
<ref bean="versionRootDAO"/>
|
||||
</property>
|
||||
<property name="fileContentDAO">
|
||||
<ref bean="fileContentDAO"/>
|
||||
</property>
|
||||
<property name="childEntryDAO">
|
||||
<ref bean="childEntryDAO"/>
|
||||
</property>
|
||||
@ -217,9 +198,6 @@
|
||||
<property name="nodeIssuer">
|
||||
<ref bean="nodeIssuer"/>
|
||||
</property>
|
||||
<property name="contentIssuer">
|
||||
<ref bean="contentIssuer"/>
|
||||
</property>
|
||||
<property name="layerIssuer">
|
||||
<ref bean="layerIssuer"/>
|
||||
</property>
|
||||
|
@ -66,6 +66,9 @@
|
||||
<property name="policyComponent">
|
||||
<ref bean="policyComponent" />
|
||||
</property>
|
||||
<property name="avmService">
|
||||
<ref bean="AVMService"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="mimetypeConfigService" class="org.alfresco.config.xml.XMLConfigService" init-method="init">
|
||||
|
@ -81,6 +81,10 @@
|
||||
<tokenised>true</tokenised>
|
||||
</index>
|
||||
</property>
|
||||
<property name="cm:readonly">
|
||||
<type>d:boolean</type>
|
||||
<mandatory>false</mandatory>
|
||||
</property>
|
||||
</properties>
|
||||
</type>
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
<map>
|
||||
<entry key="workspace"><ref bean="dbNodeService"></ref></entry>
|
||||
<entry key="versionStore"><ref bean="versionNodeService"></ref></entry>
|
||||
<entry key="avm"><ref bean="avmNodeService"/></entry>
|
||||
</map>
|
||||
</property>
|
||||
</bean>
|
||||
@ -58,6 +59,16 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- AVMNodeService -->
|
||||
<bean id="avmNodeService" class="org.alfresco.repo.avm.AVMNodeService">
|
||||
<property name="dictionaryService">
|
||||
<ref bean="dictionaryService"/>
|
||||
</property>
|
||||
<property name="avmService">
|
||||
<ref bean="AVMService"/>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<!-- Handles policy callbacks to ensure that node hierarchy gets indexed -->
|
||||
<bean id="nodeIndexer" class="org.alfresco.repo.node.index.NodeIndexer" init-method="init">
|
||||
<property name="policyComponent">
|
||||
|
@ -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");
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -216,8 +216,7 @@ class AVMCrawler implements Runnable
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (e instanceof AVMNotFoundException ||
|
||||
e instanceof AVMExistsException)
|
||||
if (e instanceof AVMException)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -25,7 +25,7 @@ import org.alfresco.service.cmr.repository.StoreRef;
|
||||
* the <code>StoreRef</code>, <code>NodeRef</code> world.
|
||||
* @author britt
|
||||
*/
|
||||
class AVMNodeConverter
|
||||
public class AVMNodeConverter
|
||||
{
|
||||
/**
|
||||
* Get a NodeRef corresponding to the given path and version.
|
||||
|
@ -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<QName, PropertyValue> props = new HashMap<QName, PropertyValue>();
|
||||
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);
|
||||
|
@ -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.
|
||||
|
@ -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 <code>desc</code> 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 <code>path</code> is not found.
|
||||
* @throws AVMWrongTypeException If <code>path</code> contains a non-terminal
|
||||
* component that is not a directory, or if <code>path</code> is not pointing
|
||||
* at a file.
|
||||
* @throws AVMException If trying to write to anything but the head version.
|
||||
* @return A ContentReader.
|
||||
* @throws AVMNotFoundException If <code>path</code> does not exist.
|
||||
* @throws AVMWrongTypeException if <code>path</code> 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 <code>path</code> does not exist.
|
||||
* @throws AVMWrongTypeException if <code>path</code> 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 <code>path</code> does not exist.
|
||||
* @throws AVMWrongTypeException If <code>path</code> 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 <code>path</code> does not exist.
|
||||
* @throws AVMWrongTypeException If <code>path</code> 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 <code>path</code> does not exist.
|
||||
* @throws AVMWrongTypeException If <code>path</code> does not point
|
||||
* to a file.
|
||||
*/
|
||||
public void setContentData(String path, ContentData data);
|
||||
}
|
||||
|
@ -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 <code>path</code> does not exist.
|
||||
* @throws AVMWrongTypeException if <code>path</code> 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 <code>path</code> does not exist.
|
||||
* @throws AVMWrongTypeException If <code>path</code> 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);
|
||||
}
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -6,5 +6,4 @@ package org.alfresco.repo.avm;
|
||||
*/
|
||||
interface PlainFileNode extends FileNode
|
||||
{
|
||||
public FileContent getContent();
|
||||
}
|
||||
|
@ -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<QName, PropertyValue> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -77,9 +77,10 @@
|
||||
<!-- Plain files just have a reference to a Content object. -->
|
||||
<subclass discriminator-value="plainfile"
|
||||
name="PlainFileNodeImpl" proxy="PlainFileNode" lazy="true">
|
||||
<many-to-one name="content" column="content_id"
|
||||
class="FileContentImpl" fetch="join" cascade="save-update">
|
||||
</many-to-one>
|
||||
<property name="contentURL" column="content_url" type="string" length="128"/>
|
||||
<property name="mimeType" column="mime_type" type="string" length="32"/>
|
||||
<property name="encoding" column="encoding" type="string" length="16"/>
|
||||
<property name="length" column="length" type="long"/>
|
||||
</subclass>
|
||||
<!-- Layered files are almost exactly copy on write symlinks. -->
|
||||
<subclass name="LayeredFileNodeImpl"
|
||||
@ -89,19 +90,6 @@
|
||||
</subclass>
|
||||
</subclass>
|
||||
</class>
|
||||
<!-- Contents are objects to hang actual bytestreams off. They are explicitly reference
|
||||
counted. -->
|
||||
<class table="avm_contents" name="FileContentImpl" proxy="FileContent"
|
||||
optimistic-lock="version">
|
||||
<cache usage="read-write" />
|
||||
<id name="id" column="id" type="long"/>
|
||||
<version name="vers" column="vers" type="long"/>
|
||||
<!-- The reference count. Contents are explicitly reference counted for now,
|
||||
however it make sense to fold this into a generalized garbage collection
|
||||
scheme. -->
|
||||
<property name="refCount" column="ref_count" type="int"
|
||||
not-null="true"/>
|
||||
</class>
|
||||
<!-- A store is the what we used to call a virtual repository.
|
||||
Each store has it's own branch ids and layer ids but shares node ids
|
||||
with other repositories. The physical repository is structured this way
|
||||
|
@ -23,6 +23,9 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.avm.AVMNodeConverter;
|
||||
import org.alfresco.repo.avm.AVMService;
|
||||
import org.alfresco.repo.content.ContentServicePolicies.OnContentReadPolicy;
|
||||
import org.alfresco.repo.content.ContentServicePolicies.OnContentUpdatePolicy;
|
||||
import org.alfresco.repo.content.filestore.FileContentStore;
|
||||
@ -44,6 +47,7 @@ import org.alfresco.service.cmr.repository.ContentWriter;
|
||||
import org.alfresco.service.cmr.repository.NoTransformerException;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.repository.StoreRef;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
@ -66,6 +70,8 @@ public class RoutingContentService implements ContentService
|
||||
private TransactionService transactionService;
|
||||
private DictionaryService dictionaryService;
|
||||
private NodeService nodeService;
|
||||
private AVMService avmService;
|
||||
|
||||
/** a registry of all available content transformers */
|
||||
private ContentTransformerRegistry transformerRegistry;
|
||||
/** TEMPORARY until we have a map to choose from at runtime */
|
||||
@ -122,6 +128,11 @@ public class RoutingContentService implements ContentService
|
||||
this.policyComponent = policyComponent;
|
||||
}
|
||||
|
||||
public void setAvmService(AVMService service)
|
||||
{
|
||||
this.avmService = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Service initialise
|
||||
*/
|
||||
@ -304,6 +315,7 @@ public class RoutingContentService implements ContentService
|
||||
|
||||
public ContentWriter getWriter(NodeRef nodeRef, QName propertyQName, boolean update)
|
||||
{
|
||||
|
||||
// check for an existing URL - the get of the reader will perform type checking
|
||||
ContentReader existingContentReader = getReader(nodeRef, propertyQName, false);
|
||||
|
||||
@ -313,8 +325,18 @@ public class RoutingContentService implements ContentService
|
||||
// can be wherever the store decides.
|
||||
ContentWriter writer = store.getWriter(existingContentReader, null);
|
||||
|
||||
// Special case for AVM repository.
|
||||
Serializable contentValue = null;
|
||||
if (nodeRef.getStoreRef().getProtocol().equals(StoreRef.PROTOCOL_AVM))
|
||||
{
|
||||
Object [] avmVersionPath = AVMNodeConverter.ToAVMVersionPath(nodeRef);
|
||||
contentValue = avmService.getContentDataForWrite((String)avmVersionPath[1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
contentValue = nodeService.getProperty(nodeRef, propertyQName);
|
||||
}
|
||||
// set extra data on the reader if the property is pre-existing
|
||||
Serializable contentValue = nodeService.getProperty(nodeRef, propertyQName);
|
||||
if (contentValue != null && contentValue instanceof ContentData)
|
||||
{
|
||||
ContentData contentData = (ContentData)contentValue;
|
||||
|
Loading…
x
Reference in New Issue
Block a user