mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Added the notion of a ContentContext to select the content store to write to.
Added AbstractRoutingContentStore as a start base implementation. Added warnings to drive config away from disused setTransactionService towards setRetryingTransactionHelper. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5734 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -74,9 +74,6 @@
|
|||||||
<value>false</value>
|
<value>false</value>
|
||||||
</property>
|
</property>
|
||||||
<!-- this is required if outbound replication is active, otherwise not -->
|
<!-- this is required if outbound replication is active, otherwise not -->
|
||||||
<property name="transactionService">
|
|
||||||
<ref bean="transactionComponent" />
|
|
||||||
</property>
|
|
||||||
<property name="retryingTransactionHelper">
|
<property name="retryingTransactionHelper">
|
||||||
<ref bean="retryingTransactionHelper"/>
|
<ref bean="retryingTransactionHelper"/>
|
||||||
</property>
|
</property>
|
||||||
|
@@ -55,7 +55,8 @@ import org.springframework.util.FileCopyUtils;
|
|||||||
* Implements all the convenience methods of the interface. The only methods
|
* Implements all the convenience methods of the interface. The only methods
|
||||||
* that need to be implemented, i.e. provide low-level content access are:
|
* that need to be implemented, i.e. provide low-level content access are:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>{@link #getDirectReadableChannel()} to read content from the repository</li>
|
* <li>{@link #createReader()} to read content from the repository</li>
|
||||||
|
* <li>{@link #getDirectReadableChannel()} to provide direct storage access</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author Derek Hulley
|
* @author Derek Hulley
|
||||||
|
@@ -31,6 +31,7 @@ import java.util.Set;
|
|||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.util.GUID;
|
import org.alfresco.util.GUID;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -45,16 +46,6 @@ import org.alfresco.util.GUID;
|
|||||||
*/
|
*/
|
||||||
public abstract class AbstractContentStore implements ContentStore
|
public abstract class AbstractContentStore implements ContentStore
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Simple implementation that uses the
|
|
||||||
* {@link ContentReader#exists() reader's exists} method as its implementation.
|
|
||||||
*/
|
|
||||||
public boolean exists(String contentUrl) throws ContentIOException
|
|
||||||
{
|
|
||||||
ContentReader reader = getReader(contentUrl);
|
|
||||||
return reader.exists();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new content URL. This must be supported by all
|
* Creates a new content URL. This must be supported by all
|
||||||
* stores that are compatible with Alfresco.
|
* stores that are compatible with Alfresco.
|
||||||
@@ -126,8 +117,33 @@ public abstract class AbstractContentStore implements ContentStore
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simple implementation that uses the
|
||||||
|
* {@link ContentReader#exists() reader's exists} method as its implementation.
|
||||||
|
*/
|
||||||
|
public boolean exists(String contentUrl) throws ContentIOException
|
||||||
|
{
|
||||||
|
ContentReader reader = getReader(contentUrl);
|
||||||
|
return reader.exists();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Searches for URLs using null dates.
|
||||||
|
*
|
||||||
|
* @see ContentStore#getUrls(java.util.Date, java.util.Date)
|
||||||
|
*/
|
||||||
public final Set<String> getUrls() throws ContentIOException
|
public final Set<String> getUrls() throws ContentIOException
|
||||||
{
|
{
|
||||||
return getUrls(null, null);
|
return getUrls(null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see ContentContext
|
||||||
|
* @see ContentStore#getWriter(ContentContext)
|
||||||
|
*/
|
||||||
|
public final ContentWriter getWriter(ContentReader existingContentReader, String newContentUrl) throws ContentIOException
|
||||||
|
{
|
||||||
|
ContentContext ctx = new ContentContext(existingContentReader, newContentUrl);
|
||||||
|
return getWriter(ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -55,6 +55,7 @@ import org.springframework.util.FileCopyUtils;
|
|||||||
* Implements all the convenience methods of the interface. The only methods
|
* Implements all the convenience methods of the interface. The only methods
|
||||||
* that need to be implemented, i.e. provide low-level content access are:
|
* that need to be implemented, i.e. provide low-level content access are:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
* <li>{@link #getReader()} to create a reader to the underlying content</li>
|
||||||
* <li>{@link #getDirectWritableChannel()} to write content to the repository</li>
|
* <li>{@link #getDirectWritableChannel()} to write content to the repository</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
@@ -0,0 +1,298 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.content;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock.ReadLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock.WriteLock;
|
||||||
|
|
||||||
|
import org.alfresco.repo.cache.SimpleCache;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A store providing support for content store implementations that provide
|
||||||
|
* routing of content read and write requests based on context.
|
||||||
|
*
|
||||||
|
* @see ContentContext
|
||||||
|
*
|
||||||
|
* @since 2.1
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public abstract class AbstractRoutingContentStore implements ContentStore
|
||||||
|
{
|
||||||
|
private static Log logger = LogFactory.getLog(AbstractRoutingContentStore.class);
|
||||||
|
|
||||||
|
private SimpleCache<String, ContentStore> storesByContentUrl;
|
||||||
|
private ReadLock storesCacheReadLock;
|
||||||
|
private WriteLock storesCacheWriteLock;
|
||||||
|
|
||||||
|
protected AbstractRoutingContentStore()
|
||||||
|
{
|
||||||
|
ReentrantReadWriteLock lock = new ReentrantReadWriteLock();
|
||||||
|
storesCacheReadLock = lock.readLock();
|
||||||
|
storesCacheWriteLock = lock.writeLock();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param storesCache cache of stores used to access URLs
|
||||||
|
*/
|
||||||
|
public void setStoresCache(SimpleCache<String, ContentStore> storesCache)
|
||||||
|
{
|
||||||
|
this.storesByContentUrl = storesCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns a list of all possible stores available for reading or writing
|
||||||
|
*/
|
||||||
|
protected abstract List<ContentStore> getAllStores();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a content store based on the context provided. The applicability of the
|
||||||
|
* context and even the types of context allowed are up to the implementation, but
|
||||||
|
* normally there should be a fallback case for when the parameters are not adequate
|
||||||
|
* to make a decision.
|
||||||
|
*
|
||||||
|
* @param ctx the context to use to make the choice
|
||||||
|
* @return Returns the store most appropriate for the given context
|
||||||
|
*/
|
||||||
|
protected abstract ContentStore selectWriteStore(ContentContext ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks the cache for the store and ensures that the URL is in the store.
|
||||||
|
*
|
||||||
|
* @param contentUrl the content URL to search for
|
||||||
|
* @return Returns the store matching the content URL
|
||||||
|
*/
|
||||||
|
private ContentStore selectReadStore(String contentUrl)
|
||||||
|
{
|
||||||
|
storesCacheReadLock.lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Check if the store is in the cache
|
||||||
|
ContentStore store = storesByContentUrl.get(contentUrl);
|
||||||
|
if (store != null && store.exists(contentUrl))
|
||||||
|
{
|
||||||
|
// We found a store and can use it
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
storesCacheReadLock.unlock();
|
||||||
|
}
|
||||||
|
// Get the write lock and double check
|
||||||
|
storesCacheWriteLock.lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Double check
|
||||||
|
ContentStore store = storesByContentUrl.get(contentUrl);
|
||||||
|
if (store != null && store.exists(contentUrl))
|
||||||
|
{
|
||||||
|
// We found a store and can use it
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug(
|
||||||
|
"Found mapped store for content URL: \n" +
|
||||||
|
" Content URL: " + contentUrl + "\n" +
|
||||||
|
" Store: " + store);
|
||||||
|
}
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
// It isn't, so search all the stores
|
||||||
|
List<ContentStore> stores = getAllStores();
|
||||||
|
for (ContentStore storeInList : stores)
|
||||||
|
{
|
||||||
|
if (!store.exists(contentUrl))
|
||||||
|
{
|
||||||
|
// It is not in the store
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// We found one
|
||||||
|
store = storeInList;
|
||||||
|
// Put the value in the cache
|
||||||
|
storesByContentUrl.put(contentUrl, store);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug(
|
||||||
|
"Mapped content URL to store for reading: \n" +
|
||||||
|
" Content URL: " + contentUrl + "\n" +
|
||||||
|
" Store: " + store);
|
||||||
|
}
|
||||||
|
return store;
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
storesCacheWriteLock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This operation has to be performed on all the stores in order to maintain the
|
||||||
|
* {@link ContentStore#exists(String)} contract.
|
||||||
|
*/
|
||||||
|
public boolean delete(String contentUrl) throws ContentIOException
|
||||||
|
{
|
||||||
|
boolean deleted = true;
|
||||||
|
List<ContentStore> stores = getAllStores();
|
||||||
|
for (ContentStore store : stores)
|
||||||
|
{
|
||||||
|
deleted &= store.delete(contentUrl);
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Deleted content URL from stores: \n" +
|
||||||
|
" Stores: " + stores.size() + "\n" +
|
||||||
|
" Deleted: " + deleted);
|
||||||
|
}
|
||||||
|
return deleted;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see #selectReadStore(String)
|
||||||
|
*/
|
||||||
|
public boolean exists(String contentUrl) throws ContentIOException
|
||||||
|
{
|
||||||
|
ContentStore store = selectReadStore(contentUrl);
|
||||||
|
return (store != null);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns a valid reader from one of the stores otherwise
|
||||||
|
* a {@link EmptyContentReader} is returned.
|
||||||
|
*/
|
||||||
|
public ContentReader getReader(String contentUrl) throws ContentIOException
|
||||||
|
{
|
||||||
|
ContentStore store = selectReadStore(contentUrl);
|
||||||
|
if (store != null)
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Getting reader from store: \n" +
|
||||||
|
" Content URL: " + contentUrl + "\n" +
|
||||||
|
" Store: " + store);
|
||||||
|
}
|
||||||
|
return store.getReader(contentUrl);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Getting empty reader for content URL: " + contentUrl);
|
||||||
|
}
|
||||||
|
return new EmptyContentReader(contentUrl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile a set of URLs from all stores.
|
||||||
|
*/
|
||||||
|
public Set<String> getUrls() throws ContentIOException
|
||||||
|
{
|
||||||
|
Set<String> urls = new HashSet<String>(1139);
|
||||||
|
List<ContentStore> stores = getAllStores();
|
||||||
|
for (ContentStore store : stores)
|
||||||
|
{
|
||||||
|
Set<String> storeUrls = store.getUrls();
|
||||||
|
urls.addAll(storeUrls);
|
||||||
|
}
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Found " + urls.size() + " URLs from " + stores.size() + " stores");
|
||||||
|
}
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Compile a set of URLs from all stores given the date range.
|
||||||
|
*/
|
||||||
|
public Set<String> getUrls(Date createdAfter, Date createdBefore) throws ContentIOException
|
||||||
|
{
|
||||||
|
Set<String> urls = new HashSet<String>(1139);
|
||||||
|
List<ContentStore> stores = getAllStores();
|
||||||
|
for (ContentStore store : stores)
|
||||||
|
{
|
||||||
|
Set<String> storeUrls = store.getUrls(createdAfter, createdBefore);
|
||||||
|
urls.addAll(storeUrls);
|
||||||
|
}
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug("Found " + urls.size() + " URLs from " + stores.size() + " stores");
|
||||||
|
}
|
||||||
|
return urls;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Selects a store for the given context and caches store that was used.
|
||||||
|
*
|
||||||
|
* @see #selectWriteStore(ContentContext)
|
||||||
|
*/
|
||||||
|
public ContentWriter getWriter(ContentContext context) throws ContentIOException
|
||||||
|
{
|
||||||
|
// Select the store for writing
|
||||||
|
ContentStore store = selectWriteStore(context);
|
||||||
|
ContentWriter writer = store.getWriter(context);
|
||||||
|
// Cache the store against the URL
|
||||||
|
storesCacheWriteLock.lock();
|
||||||
|
try
|
||||||
|
{
|
||||||
|
String contentUrl = writer.getContentUrl();
|
||||||
|
storesByContentUrl.put(contentUrl, store);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
storesCacheWriteLock.unlock();
|
||||||
|
}
|
||||||
|
// Done
|
||||||
|
if (logger.isDebugEnabled())
|
||||||
|
{
|
||||||
|
logger.debug(
|
||||||
|
"Got writer and cache URL from store: \n" +
|
||||||
|
" Context: " + context + "\n" +
|
||||||
|
" Writer: " + writer + "\n" +
|
||||||
|
" Store: " + store);
|
||||||
|
}
|
||||||
|
return writer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @see
|
||||||
|
*/
|
||||||
|
public ContentWriter getWriter(ContentReader existingContentReader, String newContentUrl) throws ContentIOException
|
||||||
|
{
|
||||||
|
return getWriter(new ContentContext(existingContentReader, newContentUrl));
|
||||||
|
}
|
||||||
|
}
|
91
source/java/org/alfresco/repo/content/ContentContext.java
Normal file
91
source/java/org/alfresco/repo/content/ContentContext.java
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.content;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The location and lookup data for content. The very least data required to
|
||||||
|
* find content or assign a content writer is the content URL and any previous
|
||||||
|
* content that may have logically existed.
|
||||||
|
* <p>
|
||||||
|
* Although this class is doesn't enforce any conditions on the context,
|
||||||
|
* derived instances may have relationships that need to be maintained between
|
||||||
|
* various context values.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class ContentContext implements Serializable
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = 6476617391229895125L;
|
||||||
|
|
||||||
|
/** An empty context. */
|
||||||
|
public static final ContentContext NULL_CONTEXT = new ContentContext(null, null);
|
||||||
|
|
||||||
|
private ContentReader existingContentReader;
|
||||||
|
private String contentUrl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the instance with the content URL.
|
||||||
|
*
|
||||||
|
* @param existingContentReader content with which to seed the new writer - may be <tt>null</tt>
|
||||||
|
* @param contentUrl the content URL - may be <tt>null</tt>
|
||||||
|
*/
|
||||||
|
public ContentContext(ContentReader existingContentReader, String contentUrl)
|
||||||
|
{
|
||||||
|
this.existingContentReader = existingContentReader;
|
||||||
|
this.contentUrl = contentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
StringBuilder sb = new StringBuilder(128);
|
||||||
|
sb.append("ContentContext")
|
||||||
|
.append("[ contentUrl=").append(getContentUrl())
|
||||||
|
.append(", existing=").append((getExistingContentReader() == null ? false : true))
|
||||||
|
.append("]");
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the content to seed the writer with - may be <tt>null</tt>
|
||||||
|
*/
|
||||||
|
public ContentReader getExistingContentReader()
|
||||||
|
{
|
||||||
|
return existingContentReader;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the content URL for the content's context - may be <tt>null</tt>
|
||||||
|
*/
|
||||||
|
public String getContentUrl()
|
||||||
|
{
|
||||||
|
return contentUrl;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@@ -27,6 +27,7 @@ package org.alfresco.repo.content;
|
|||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.ContentAccessor;
|
||||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
import org.alfresco.service.cmr.repository.ContentStreamListener;
|
import org.alfresco.service.cmr.repository.ContentStreamListener;
|
||||||
@@ -48,6 +49,8 @@ import org.alfresco.service.cmr.repository.ContentWriter;
|
|||||||
* <li> <b>year</b>: year </li>
|
* <li> <b>year</b>: year </li>
|
||||||
* <li> <b>month</b>: 1-based month of the year </li>
|
* <li> <b>month</b>: 1-based month of the year </li>
|
||||||
* <li> <b>day</b>: 1-based day of the month </li>
|
* <li> <b>day</b>: 1-based day of the month </li>
|
||||||
|
* <li> <b>hour</b>: 0-based hour of the day </li>
|
||||||
|
* <li> <b>minute</b>: 0-based minute of the hour </li>
|
||||||
* <li> <b>GUID</b>: A unique identifier </li>
|
* <li> <b>GUID</b>: A unique identifier </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* The old <b>file://</b> prefix must still be supported - and functionality
|
* The old <b>file://</b> prefix must still be supported - and functionality
|
||||||
@@ -77,14 +80,12 @@ public interface ContentStore
|
|||||||
public boolean exists(String contentUrl) throws ContentIOException;
|
public boolean exists(String contentUrl) throws ContentIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the accessor with which to read from the content
|
* Get the accessor with which to read from the content at the given URL.
|
||||||
* at the given URL. The reader is <b>stateful</b> and
|
* The reader is <b>stateful</b> and can <b>only be used once</b>.
|
||||||
* can <b>only be used once</b>.
|
|
||||||
*
|
*
|
||||||
* @param contentUrl the path to where the content is located
|
* @param contentUrl the path to where the content is located
|
||||||
* @return Returns a read-only content accessor for the given URL. There may
|
* @return Returns a read-only content accessor for the given URL. There may
|
||||||
* be no content at the given URL, but the reader must still be returned.
|
* be no content at the given URL, but the reader must still be returned.
|
||||||
* The reader may implement the {@link RandomAccessContent random access interface}.
|
|
||||||
* @throws ContentIOException
|
* @throws ContentIOException
|
||||||
*
|
*
|
||||||
* @see #exists(String)
|
* @see #exists(String)
|
||||||
@@ -98,22 +99,31 @@ public interface ContentStore
|
|||||||
* <b>only be used once</b>. The location may be specified but must, in that case,
|
* <b>only be used once</b>. The location may be specified but must, in that case,
|
||||||
* be a valid and unused URL.
|
* be a valid and unused URL.
|
||||||
* <p>
|
* <p>
|
||||||
|
* The store will ensure that the {@link ContentAccessor#getContentUrl() new content URL} will
|
||||||
|
* be valid for all subsequent read attempts.
|
||||||
|
* <p>
|
||||||
* By supplying a reader to existing content, the store implementation may
|
* By supplying a reader to existing content, the store implementation may
|
||||||
* enable {@link RandomAccessContent random access}. The store implementation
|
* enable {@link RandomAccessContent random access}. The store implementation
|
||||||
* can enable this by copying the existing content into the new location
|
* can enable this by copying the existing content into the new location
|
||||||
* before supplying a writer onto the new content.
|
* before supplying a writer onto the new content.
|
||||||
*
|
*
|
||||||
* @param existingContentReader a reader onto any existing content for which
|
* @param context the context of content.
|
||||||
* a writer is required - may be null
|
* @return Returns a write-only content accessor
|
||||||
* @param newContentUrl an unused, valid URL to use - may be null.
|
* @throws ContentIOException if completely new content storage could not be created
|
||||||
* @return Returns a write-only content accessor, possibly implementing
|
|
||||||
* the {@link RandomAccessContent random access interface}
|
|
||||||
* @throws ContentIOException if completely new content storage could not be
|
|
||||||
* created
|
|
||||||
*
|
*
|
||||||
|
* @see #getWriter(ContentReader, String)
|
||||||
* @see ContentWriter#addListener(ContentStreamListener)
|
* @see ContentWriter#addListener(ContentStreamListener)
|
||||||
* @see ContentWriter#getContentUrl()
|
* @see ContentWriter#getContentUrl()
|
||||||
*/
|
*/
|
||||||
|
public ContentWriter getWriter(ContentContext context) throws ContentIOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shortcut method to {@link #getWriter(ContentContext)}.
|
||||||
|
*
|
||||||
|
* @see #getWriter(ContentContext)
|
||||||
|
*
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
public ContentWriter getWriter(ContentReader existingContentReader, String newContentUrl) throws ContentIOException;
|
public ContentWriter getWriter(ContentReader existingContentReader, String newContentUrl) throws ContentIOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -140,13 +150,11 @@ public interface ContentStore
|
|||||||
* <p>
|
* <p>
|
||||||
* A delete cannot be forced since it is much better to have the
|
* A delete cannot be forced since it is much better to have the
|
||||||
* file remain longer than desired rather than deleted prematurely.
|
* file remain longer than desired rather than deleted prematurely.
|
||||||
* The store implementation should safeguard files for certain
|
|
||||||
* minimum period, in which case all files younger than a certain
|
|
||||||
* age will not be deleted.
|
|
||||||
*
|
*
|
||||||
* @param contentUrl the URL of the content to delete
|
* @param contentUrl the URL of the content to delete
|
||||||
* @return Return true if the content was deleted (either by this or
|
* @return Return true if the content was deleted (either by this or
|
||||||
* another operation), otherwise false
|
* another operation), otherwise false. If the content no longer
|
||||||
|
* exists, then <tt>true</tt> is returned.
|
||||||
* @throws ContentIOException
|
* @throws ContentIOException
|
||||||
*/
|
*/
|
||||||
public boolean delete(String contentUrl) throws ContentIOException;
|
public boolean delete(String contentUrl) throws ContentIOException;
|
||||||
|
@@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.content;
|
||||||
|
|
||||||
|
import java.nio.channels.ReadableByteChannel;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A blank reader for which <code>exists()</code> always returns false.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class EmptyContentReader extends AbstractContentReader
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @param contentUrl the content URL
|
||||||
|
*/
|
||||||
|
public EmptyContentReader(String contentUrl)
|
||||||
|
{
|
||||||
|
super(contentUrl);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns an instance of the this class
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
protected ContentReader createReader() throws ContentIOException
|
||||||
|
{
|
||||||
|
return new EmptyContentReader(this.getContentUrl());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ReadableByteChannel getDirectReadableChannel() throws ContentIOException
|
||||||
|
{
|
||||||
|
throw new UnsupportedOperationException("The content never exists");
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean exists()
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getLastModified()
|
||||||
|
{
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSize()
|
||||||
|
{
|
||||||
|
return 0L;
|
||||||
|
}
|
||||||
|
}
|
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2007 Alfresco Software Limited.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU General Public License
|
||||||
|
* as published by the Free Software Foundation; either version 2
|
||||||
|
* of the License, or (at your option) any later version.
|
||||||
|
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
|
|
||||||
|
* As a special exception to the terms and conditions of version 2.0 of
|
||||||
|
* the GPL, you may redistribute this Program in connection with Free/Libre
|
||||||
|
* and Open Source Software ("FLOSS") applications as described in Alfresco's
|
||||||
|
* FLOSS exception. You should have recieved a copy of the text describing
|
||||||
|
* the FLOSS exception, and it is also available here:
|
||||||
|
* http://www.alfresco.com/legal/licensing"
|
||||||
|
*/
|
||||||
|
package org.alfresco.repo.content;
|
||||||
|
|
||||||
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
|
import org.alfresco.service.namespace.QName;
|
||||||
|
import org.alfresco.util.ParameterCheck;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Context information for node-related content.
|
||||||
|
*
|
||||||
|
* @author Derek Hulley
|
||||||
|
*/
|
||||||
|
public class NodeContentContext extends ContentContext
|
||||||
|
{
|
||||||
|
private static final long serialVersionUID = -1836714367516857907L;
|
||||||
|
|
||||||
|
private NodeRef nodeRef;
|
||||||
|
private QName propertyQName;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct the instance with the content URL.
|
||||||
|
*
|
||||||
|
* @param existingContentReader content with which to seed the new writer - may be <tt>null</tt>
|
||||||
|
* @param contentUrl the content URL - may be <tt>null</tt>
|
||||||
|
* @param nodeRef the node holding the content metadata - may not be <tt>null</tt>
|
||||||
|
* @param propertyQName the property holding the content metadata - may not be <tt>null</tt>
|
||||||
|
*/
|
||||||
|
public NodeContentContext(
|
||||||
|
ContentReader existingContentReader,
|
||||||
|
String contentUrl,
|
||||||
|
NodeRef nodeRef,
|
||||||
|
QName propertyQName)
|
||||||
|
{
|
||||||
|
super(existingContentReader, contentUrl);
|
||||||
|
ParameterCheck.mandatory("nodeRef", nodeRef);
|
||||||
|
ParameterCheck.mandatory("propertyQName", propertyQName);
|
||||||
|
this.nodeRef = nodeRef;
|
||||||
|
this.propertyQName = propertyQName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns the node holding the content metadata
|
||||||
|
*/
|
||||||
|
public NodeRef getNodeRef()
|
||||||
|
{
|
||||||
|
return nodeRef;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @return Returns the property holding the content metadata
|
||||||
|
*/
|
||||||
|
public QName getPropertyQName()
|
||||||
|
{
|
||||||
|
return propertyQName;
|
||||||
|
}
|
||||||
|
}
|
@@ -77,7 +77,6 @@ public class RoutingContentService implements ContentService
|
|||||||
{
|
{
|
||||||
private static Log logger = LogFactory.getLog(RoutingContentService.class);
|
private static Log logger = LogFactory.getLog(RoutingContentService.class);
|
||||||
|
|
||||||
private TransactionService transactionService;
|
|
||||||
private DictionaryService dictionaryService;
|
private DictionaryService dictionaryService;
|
||||||
private NodeService nodeService;
|
private NodeService nodeService;
|
||||||
private AVMService avmService;
|
private AVMService avmService;
|
||||||
@@ -110,9 +109,12 @@ public class RoutingContentService implements ContentService
|
|||||||
this.tempStore = new FileContentStore(TempFileProvider.getTempDir().getAbsolutePath());
|
this.tempStore = new FileContentStore(TempFileProvider.getTempDir().getAbsolutePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @deprecated Replaced by {@link #setRetryingTransactionHelper(RetryingTransactionHelper)}
|
||||||
|
*/
|
||||||
public void setTransactionService(TransactionService transactionService)
|
public void setTransactionService(TransactionService transactionService)
|
||||||
{
|
{
|
||||||
this.transactionService = transactionService;
|
logger.warn("Property 'transactionService' has been replaced by 'retryingTransactionHelper'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setRetryingTransactionHelper(RetryingTransactionHelper helper)
|
public void setRetryingTransactionHelper(RetryingTransactionHelper helper)
|
||||||
@@ -313,7 +315,7 @@ public class RoutingContentService implements ContentService
|
|||||||
}
|
}
|
||||||
String contentUrl = contentData.getContentUrl();
|
String contentUrl = contentData.getContentUrl();
|
||||||
|
|
||||||
// TODO: Choose the store to read from at runtime
|
// The context of the read is entirely described by the URL
|
||||||
ContentReader reader = store.getReader(contentUrl);
|
ContentReader reader = store.getReader(contentUrl);
|
||||||
|
|
||||||
// set extra data on the reader
|
// set extra data on the reader
|
||||||
@@ -338,12 +340,11 @@ public class RoutingContentService implements ContentService
|
|||||||
|
|
||||||
public ContentWriter getWriter(NodeRef nodeRef, QName propertyQName, boolean update)
|
public ContentWriter getWriter(NodeRef nodeRef, QName propertyQName, boolean update)
|
||||||
{
|
{
|
||||||
// TODO: Choose the store to write to at runtime
|
|
||||||
|
|
||||||
if (nodeRef == null)
|
if (nodeRef == null)
|
||||||
{
|
{
|
||||||
|
ContentContext ctx = new ContentContext(null, null);
|
||||||
// for this case, we just give back a valid URL into the content store
|
// for this case, we just give back a valid URL into the content store
|
||||||
ContentWriter writer = store.getWriter(null, null);
|
ContentWriter writer = store.getWriter(ctx);
|
||||||
// done
|
// done
|
||||||
return writer;
|
return writer;
|
||||||
}
|
}
|
||||||
@@ -353,7 +354,8 @@ public class RoutingContentService implements ContentService
|
|||||||
|
|
||||||
// get the content using the (potentially) existing content - the new content
|
// get the content using the (potentially) existing content - the new content
|
||||||
// can be wherever the store decides.
|
// can be wherever the store decides.
|
||||||
ContentWriter writer = store.getWriter(existingContentReader, null);
|
ContentContext ctx = new NodeContentContext(existingContentReader, null, nodeRef, propertyQName);
|
||||||
|
ContentWriter writer = store.getWriter(ctx);
|
||||||
|
|
||||||
// Special case for AVM repository.
|
// Special case for AVM repository.
|
||||||
Serializable contentValue = null;
|
Serializable contentValue = null;
|
||||||
@@ -395,7 +397,7 @@ public class RoutingContentService implements ContentService
|
|||||||
public ContentWriter getTempWriter()
|
public ContentWriter getTempWriter()
|
||||||
{
|
{
|
||||||
// there is no existing content and we don't specify the location of the new content
|
// there is no existing content and we don't specify the location of the new content
|
||||||
return tempStore.getWriter(null, null);
|
return tempStore.getWriter(ContentContext.NULL_CONTEXT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@@ -32,6 +32,7 @@ import java.util.Set;
|
|||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.repo.content.AbstractContentStore;
|
import org.alfresco.repo.content.AbstractContentStore;
|
||||||
|
import org.alfresco.repo.content.ContentContext;
|
||||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
@@ -39,10 +40,11 @@ import org.apache.commons.logging.Log;
|
|||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a store of node content directly to the file system.
|
* Provides a store of node content directly to the file system. The writers
|
||||||
|
* are generated using information from the {@link ContentContext simple content context}.
|
||||||
* <p>
|
* <p>
|
||||||
* The file names obey, as they must, the URL naming convention
|
* The file names obey, as they must, the URL naming convention
|
||||||
* as specified in the {@link org.alfresco.repo.content.ContentStore}.
|
* as specified in the {@link org.alfresco.repo.content.ContentStore ContentStore interface}.
|
||||||
*
|
*
|
||||||
* @author Derek Hulley
|
* @author Derek Hulley
|
||||||
*/
|
*/
|
||||||
@@ -241,8 +243,10 @@ public class FileContentStore extends AbstractContentStore
|
|||||||
/**
|
/**
|
||||||
* @return Returns a writer onto a location based on the date
|
* @return Returns a writer onto a location based on the date
|
||||||
*/
|
*/
|
||||||
public ContentWriter getWriter(ContentReader existingContentReader, String newContentUrl)
|
public ContentWriter getWriter(ContentContext ctx)
|
||||||
{
|
{
|
||||||
|
ContentReader existingContentReader = ctx.getExistingContentReader();
|
||||||
|
String newContentUrl = ctx.getContentUrl();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
File file = null;
|
File file = null;
|
||||||
|
@@ -35,6 +35,7 @@ import java.util.concurrent.locks.ReentrantReadWriteLock;
|
|||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.repo.content.AbstractContentStore;
|
import org.alfresco.repo.content.AbstractContentStore;
|
||||||
|
import org.alfresco.repo.content.ContentContext;
|
||||||
import org.alfresco.repo.content.ContentStore;
|
import org.alfresco.repo.content.ContentStore;
|
||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
||||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||||
@@ -106,7 +107,6 @@ public class ReplicatingContentStore extends AbstractContentStore
|
|||||||
|
|
||||||
private static Log logger = LogFactory.getLog(ReplicatingContentStore.class);
|
private static Log logger = LogFactory.getLog(ReplicatingContentStore.class);
|
||||||
|
|
||||||
private TransactionService transactionService;
|
|
||||||
private RetryingTransactionHelper transactionHelper;
|
private RetryingTransactionHelper transactionHelper;
|
||||||
private ContentStore primaryStore;
|
private ContentStore primaryStore;
|
||||||
private List<ContentStore> secondaryStores;
|
private List<ContentStore> secondaryStores;
|
||||||
@@ -131,17 +131,17 @@ public class ReplicatingContentStore extends AbstractContentStore
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Required to ensure that content listeners are executed in a transaction
|
* @deprecated Replaced with {@link #setRetryingTransactionHelper(RetryingTransactionHelper)}
|
||||||
*
|
|
||||||
* @param transactionService
|
|
||||||
*/
|
*/
|
||||||
public void setTransactionService(TransactionService transactionService)
|
public void setTransactionService(TransactionService transactionService)
|
||||||
{
|
{
|
||||||
this.transactionService = transactionService;
|
logger.warn("Property 'transactionService' has been replaced with 'retryingTransactionHelper'.");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the retrying transaction helper.
|
* Set the retrying transaction helper.
|
||||||
|
*
|
||||||
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public void setRetryingTransactionHelper(RetryingTransactionHelper helper)
|
public void setRetryingTransactionHelper(RetryingTransactionHelper helper)
|
||||||
{
|
{
|
||||||
@@ -273,7 +273,8 @@ public class ReplicatingContentStore extends AbstractContentStore
|
|||||||
return primaryContentReader;
|
return primaryContentReader;
|
||||||
}
|
}
|
||||||
// get a writer
|
// get a writer
|
||||||
ContentWriter primaryContentWriter = primaryStore.getWriter(existingContentReader, contentUrl);
|
ContentContext ctx = new ContentContext(existingContentReader, contentUrl);
|
||||||
|
ContentWriter primaryContentWriter = primaryStore.getWriter(ctx);
|
||||||
// copy it over
|
// copy it over
|
||||||
primaryContentWriter.putContent(existingContentReader);
|
primaryContentWriter.putContent(existingContentReader);
|
||||||
// get a writer to the new content
|
// get a writer to the new content
|
||||||
@@ -287,13 +288,10 @@ public class ReplicatingContentStore extends AbstractContentStore
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public ContentWriter getWriter(ContentContext ctx)
|
||||||
*
|
|
||||||
*/
|
|
||||||
public ContentWriter getWriter(ContentReader existingContentReader, String newContentUrl) throws ContentIOException
|
|
||||||
{
|
{
|
||||||
// get the writer
|
// get the writer
|
||||||
ContentWriter writer = primaryStore.getWriter(existingContentReader, newContentUrl);
|
ContentWriter writer = primaryStore.getWriter(ctx);
|
||||||
|
|
||||||
// attach a replicating listener if outbound replication is on
|
// attach a replicating listener if outbound replication is on
|
||||||
if (outbound)
|
if (outbound)
|
||||||
@@ -434,7 +432,8 @@ public class ReplicatingContentStore extends AbstractContentStore
|
|||||||
ContentReader reader = writer.getReader();
|
ContentReader reader = writer.getReader();
|
||||||
String contentUrl = reader.getContentUrl();
|
String contentUrl = reader.getContentUrl();
|
||||||
// in order to replicate, we have to specify the URL that we are going to write to
|
// in order to replicate, we have to specify the URL that we are going to write to
|
||||||
ContentWriter replicatedWriter = store.getWriter(null, contentUrl);
|
ContentContext ctx = new ContentContext(null, contentUrl);
|
||||||
|
ContentWriter replicatedWriter = store.getWriter(ctx);
|
||||||
// write it
|
// write it
|
||||||
replicatedWriter.putContent(reader);
|
replicatedWriter.putContent(reader);
|
||||||
|
|
||||||
|
@@ -33,9 +33,9 @@ import java.util.concurrent.ThreadPoolExecutor;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.alfresco.repo.content.AbstractContentReadWriteTest;
|
import org.alfresco.repo.content.AbstractContentReadWriteTest;
|
||||||
|
import org.alfresco.repo.content.ContentContext;
|
||||||
import org.alfresco.repo.content.ContentStore;
|
import org.alfresco.repo.content.ContentStore;
|
||||||
import org.alfresco.repo.content.filestore.FileContentStore;
|
import org.alfresco.repo.content.filestore.FileContentStore;
|
||||||
import org.alfresco.repo.transaction.DummyTransactionService;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentReader;
|
import org.alfresco.service.cmr.repository.ContentReader;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.util.GUID;
|
import org.alfresco.util.GUID;
|
||||||
@@ -77,7 +77,6 @@ public class ReplicatingContentStoreTest extends AbstractContentReadWriteTest
|
|||||||
secondaryStores.add(store);
|
secondaryStores.add(store);
|
||||||
}
|
}
|
||||||
replicatingStore = new ReplicatingContentStore();
|
replicatingStore = new ReplicatingContentStore();
|
||||||
replicatingStore.setTransactionService(new DummyTransactionService());
|
|
||||||
replicatingStore.setPrimaryStore(primaryStore);
|
replicatingStore.setPrimaryStore(primaryStore);
|
||||||
replicatingStore.setSecondaryStores(secondaryStores);
|
replicatingStore.setSecondaryStores(secondaryStores);
|
||||||
replicatingStore.setOutbound(false);
|
replicatingStore.setOutbound(false);
|
||||||
@@ -184,7 +183,7 @@ public class ReplicatingContentStoreTest extends AbstractContentReadWriteTest
|
|||||||
|
|
||||||
// pick a secondary store and write some content to it
|
// pick a secondary store and write some content to it
|
||||||
ContentStore secondaryStore = secondaryStores.get(2);
|
ContentStore secondaryStore = secondaryStores.get(2);
|
||||||
ContentWriter writer = secondaryStore.getWriter(null, null);
|
ContentWriter writer = secondaryStore.getWriter(ContentContext.NULL_CONTEXT);
|
||||||
writer.putContent(SOME_CONTENT);
|
writer.putContent(SOME_CONTENT);
|
||||||
String contentUrl = writer.getContentUrl();
|
String contentUrl = writer.getContentUrl();
|
||||||
|
|
||||||
|
@@ -28,6 +28,7 @@ import junit.framework.TestCase;
|
|||||||
|
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.content.AbstractContentStore;
|
import org.alfresco.repo.content.AbstractContentStore;
|
||||||
|
import org.alfresco.repo.content.ContentContext;
|
||||||
import org.alfresco.repo.content.ContentStore;
|
import org.alfresco.repo.content.ContentStore;
|
||||||
import org.alfresco.repo.node.db.NodeDaoService;
|
import org.alfresco.repo.node.db.NodeDaoService;
|
||||||
import org.alfresco.repo.search.Indexer;
|
import org.alfresco.repo.search.Indexer;
|
||||||
@@ -148,7 +149,8 @@ public class MissingContentReindexComponentTest extends TestCase
|
|||||||
}
|
}
|
||||||
|
|
||||||
// now put some content in the store
|
// now put some content in the store
|
||||||
ContentWriter writer = contentStore.getWriter(null, contentUrl);
|
ContentContext ctx = new ContentContext(null, contentUrl);
|
||||||
|
ContentWriter writer = contentStore.getWriter(ctx);
|
||||||
writer.setMimetype("text/plain");
|
writer.setMimetype("text/plain");
|
||||||
writer.setEncoding("UTF8");
|
writer.setEncoding("UTF8");
|
||||||
writer.putContent("123abc456def");
|
writer.putContent("123abc456def");
|
||||||
|
Reference in New Issue
Block a user