Full Repository Export / Import Support - first checkpoint

git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2591 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
David Caruana
2006-03-30 18:38:03 +00:00
parent 69039bc6c9
commit 701657f2f1
28 changed files with 1179 additions and 443 deletions

View File

@@ -0,0 +1,75 @@
/*
* Copyright (C) 2005 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.action.executer;
import java.util.List;
import org.alfresco.repo.action.ParameterDefinitionImpl;
import org.alfresco.service.cmr.action.Action;
import org.alfresco.service.cmr.action.ParameterDefinition;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.view.RepositoryExporterService;
/**
* Repository Exporter action executor
*
* @author davidc
*/
public class RepositoryExporterActionExecuter extends ActionExecuterAbstractBase
{
public static final String NAME = "repository-export";
public static final String PARAM_PACKAGE_NAME = "package-name";
public static final String PARAM_DESTINATION_FOLDER = "destination";
/**
* The exporter service
*/
private RepositoryExporterService exporterService;
/**
* Sets the ExporterService to use
*
* @param exporterService The ExporterService
*/
public void setRepositoryExporterService(RepositoryExporterService exporterService)
{
this.exporterService = exporterService;
}
/**
* @see org.alfresco.repo.action.executer.ActionExecuter#execute(org.alfresco.repo.ref.NodeRef, org.alfresco.repo.ref.NodeRef)
*/
public void executeImpl(Action ruleAction, NodeRef actionedUponNodeRef)
{
String packageName = (String)ruleAction.getParameterValue(PARAM_PACKAGE_NAME);
NodeRef repoDestination = (NodeRef)ruleAction.getParameterValue(PARAM_DESTINATION_FOLDER);
exporterService.export(repoDestination, packageName);
}
/**
* @see org.alfresco.repo.action.ParameterizedItemAbstractBase#addParameterDefintions(java.util.List)
*/
protected void addParameterDefintions(List<ParameterDefinition> paramList)
{
paramList.add(new ParameterDefinitionImpl(PARAM_PACKAGE_NAME, DataTypeDefinition.TEXT, true,
getParamDisplayLabel(PARAM_PACKAGE_NAME)));
paramList.add(new ParameterDefinitionImpl(PARAM_DESTINATION_FOLDER, DataTypeDefinition.NODE_REF, true,
getParamDisplayLabel(PARAM_DESTINATION_FOLDER)));
}
}

View File

@@ -17,6 +17,7 @@
package org.alfresco.repo.content;
import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
@@ -241,17 +242,28 @@ public class RoutingContentService implements ContentService
{
// get the property value
ContentData contentData = null;
Serializable propValue = nodeService.getProperty(nodeRef, propertyQName);
if (propValue instanceof Collection)
{
Collection colPropValue = (Collection)propValue;
if (colPropValue.size() > 0)
{
propValue = (Serializable)colPropValue.iterator().next();
}
}
if (propValue instanceof ContentData)
{
contentData = (ContentData)propValue;
}
// ensure that the node property is of type content
if (contentData == null)
{
// if no value or a value other content, and a property definition has been provided, ensure that it's CONTENT or ANY
PropertyDefinition contentPropDef = dictionaryService.getProperty(propertyQName);
if (contentPropDef == null || !(contentPropDef.getDataType().getName().equals(DataTypeDefinition.CONTENT)))
if (contentPropDef != null &&
(!(contentPropDef.getDataType().getName().equals(DataTypeDefinition.CONTENT) ||
contentPropDef.getDataType().getName().equals(DataTypeDefinition.ANY))))
{
throw new InvalidTypeException("The node property must be of type content: \n" +
" node: " + nodeRef + "\n" +

View File

@@ -258,22 +258,22 @@ import org.alfresco.service.namespace.QName;
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable)
*/
public void value(NodeRef nodeRef, QName property, Object value)
public void value(NodeRef nodeRef, QName property, Object value, int index)
{
for (Exporter exporter : exporters)
{
exporter.value(nodeRef, property, value);
exporter.value(nodeRef, property, value, index);
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream)
*/
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData)
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index)
{
for (Exporter exporter : exporters)
{
exporter.content(nodeRef, property, content, contentData);
exporter.content(nodeRef, property, content, contentData, index);
}
}

View File

@@ -215,7 +215,7 @@ public class ExporterComponent
try
{
XMLWriter writer = new XMLWriter(viewWriter, format);
return new ViewXMLExporter(namespaceService, nodeService, dictionaryService, permissionService, writer);
return new ViewXMLExporter(namespaceService, nodeService, searchService, dictionaryService, permissionService, writer);
}
catch (UnsupportedEncodingException e)
{
@@ -399,14 +399,18 @@ public class ExporterComponent
if (value instanceof Collection)
{
exporter.startValueCollection(nodeRef, property);
int index = 0;
for (Object valueInCollection : (Collection)value)
{
walkProperty(nodeRef, property, valueInCollection, parameters, exporter);
walkProperty(nodeRef, property, valueInCollection, index, parameters, exporter);
index++;
}
exporter.endValueCollection(nodeRef, property);
}
else
{
walkProperty(nodeRef, property, value, parameters, exporter);
walkProperty(nodeRef, property, value, -1, parameters, exporter);
}
// end export of property
@@ -468,10 +472,11 @@ public class ExporterComponent
* @param nodeRef
* @param property
* @param value
* @param index
* @param parameters
* @param exporter
*/
private void walkProperty(NodeRef nodeRef, QName property, Object value, ExporterCrawlerParameters parameters, Exporter exporter)
private void walkProperty(NodeRef nodeRef, QName property, Object value, int index, ExporterCrawlerParameters parameters, Exporter exporter)
{
// determine data type of value
PropertyDefinition propDef = dictionaryService.getProperty(property);
@@ -495,12 +500,12 @@ public class ExporterComponent
// Export non content data types
try
{
exporter.value(nodeRef, property, value);
exporter.value(nodeRef, property, value, index);
}
catch(TypeConversionException e)
{
exporter.warning("Value of property " + property + " could not be converted to xml string");
exporter.value(nodeRef, property, value.toString());
exporter.value(nodeRef, property, value.toString(), index);
}
}
else
@@ -512,7 +517,7 @@ public class ExporterComponent
// export an empty url for the content
ContentData contentData = (ContentData)value;
ContentData noContentURL = new ContentData("", contentData.getMimetype(), contentData.getSize(), contentData.getEncoding());
exporter.content(nodeRef, property, null, noContentURL);
exporter.content(nodeRef, property, null, noContentURL, index);
exporter.warning("Skipped content for property " + property + " on node " + nodeRef);
}
else
@@ -520,7 +525,7 @@ public class ExporterComponent
InputStream inputStream = reader.getContentInputStream();
try
{
exporter.content(nodeRef, property, inputStream, reader.getContentData());
exporter.content(nodeRef, property, inputStream, reader.getContentData(), index);
}
finally
{

View File

@@ -160,12 +160,12 @@ public class ExporterComponentTest extends BaseSpringTest
// System.out.println("TestProgress: end value collection: node " + nodeRef + " , property " + property);
}
public void value(NodeRef nodeRef, QName property, Object value)
public void value(NodeRef nodeRef, QName property, Object value, int index)
{
// System.out.println("TestProgress: single value " + value);
}
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData)
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index)
{
// System.out.println("TestProgress: content stream ");
}

View File

@@ -0,0 +1,420 @@
/*
* Copyright (C) 2005 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.exporter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.alfresco.i18n.I18NUtil;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.content.MimetypeMap;
import org.alfresco.service.cmr.model.FileExistsException;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
import org.alfresco.service.cmr.repository.ContentWriter;
import org.alfresco.service.cmr.repository.MimetypeService;
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.cmr.view.Exporter;
import org.alfresco.service.cmr.view.ExporterCrawlerParameters;
import org.alfresco.service.cmr.view.ExporterException;
import org.alfresco.service.cmr.view.ExporterService;
import org.alfresco.service.cmr.view.Location;
import org.alfresco.service.cmr.view.RepositoryExporterService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.ParameterCheck;
import org.alfresco.util.TempFileProvider;
/**
* Full Repository Export Service
*
* @author davidc
*/
public class RepositoryExporterComponent implements RepositoryExporterService
{
private static final String STOREREF_KEY = "storeRef";
private static final String PACKAGENAME_KEY = "packageName";
// component dependencies
private ExporterService exporterService;
private MimetypeService mimetypeService;
private FileFolderService fileFolderService;
private NodeService nodeService;
private List<Properties> exportStores;
public void setExporterService(ExporterService exporterService)
{
this.exporterService = exporterService;
}
public void setMimetypeService(MimetypeService mimetypeService)
{
this.mimetypeService = mimetypeService;
}
public void setFileFolderService(FileFolderService fileFolderService)
{
this.fileFolderService = fileFolderService;
}
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setStores(List<Properties> exportStores)
{
this.exportStores = exportStores;
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.RepositoryExporterService#export()
*/
public FileExportHandle[] export(String packageName)
{
List<FileExportHandle> exportHandles = exportStores(exportStores, packageName, new TempFileExporter());
return exportHandles.toArray(new FileExportHandle[exportHandles.size()]);
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.RepositoryExporterService#export(java.io.File)
*/
public FileExportHandle[] export(File directoryDestination, String packageName)
{
ParameterCheck.mandatory("directoryDestination", directoryDestination);
if (!directoryDestination.isDirectory())
{
throw new ExporterException("Export location " + directoryDestination.getAbsolutePath() + " is not a directory");
}
List<FileExportHandle> exportHandles = exportStores(exportStores, packageName, new FileExporter(directoryDestination));
return exportHandles.toArray(new FileExportHandle[exportHandles.size()]);
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.RepositoryExporterService#export(org.alfresco.service.cmr.repository.NodeRef)
*/
public RepositoryExportHandle[] export(NodeRef repositoryDestination, String packageName)
{
ParameterCheck.mandatory("repositoryDestination", repositoryDestination);
FileInfo destInfo = fileFolderService.getFileInfo(repositoryDestination);
if (destInfo == null || !destInfo.isFolder())
{
throw new ExporterException("Repository destination " + repositoryDestination + " is not a folder.");
}
List<FileExportHandle> exportHandles = exportStores(exportStores, packageName, new TempFileExporter());
List<RepositoryExportHandle> repoExportHandles = new ArrayList<RepositoryExportHandle>(exportHandles.size());
for (FileExportHandle exportHandle : exportHandles)
{
String description = I18NUtil.getMessage("export.store.package.description", new Object[] { exportHandle.storeRef.getIdentifier() });
NodeRef repoExportFile = addExportFile(repositoryDestination, exportHandle.packageName, description, exportHandle.exportFile);
RepositoryExportHandle handle = new RepositoryExportHandle();
handle.storeRef = exportHandle.storeRef;
handle.packageName = exportHandle.packageName;
handle.exportFile = repoExportFile;
repoExportHandles.add(handle);
}
return repoExportHandles.toArray(new RepositoryExportHandle[repoExportHandles.size()]);
}
/**
* Add a file system based .acp file into the repository
*
* @param repoDestination location within repository to place .acp file
* @param packageName acp package name
* @param packageDescription acp package description
* @param exportFile the .acp file
* @return node reference to import .acp file
*/
private NodeRef addExportFile(NodeRef repoDestination, String packageName, String packageDescription, File exportFile)
{
//
// import temp file into repository
//
// determine if file already exists
String fileName = packageName + "." + ACPExportPackageHandler.ACP_EXTENSION;
List<String> paths = new ArrayList<String>();
paths.add(fileName);
try
{
FileInfo fileInfo = fileFolderService.resolveNamePath(repoDestination, paths);
// Note: file already exists - delete
fileFolderService.delete(fileInfo.getNodeRef());
}
catch (org.alfresco.service.cmr.model.FileNotFoundException e)
{
// Note: file does not exist - no need to delete
}
// create acp file in repository
NodeRef exportFileNodeRef = null;
try
{
FileInfo fileInfo = fileFolderService.create(repoDestination, fileName, ContentModel.TYPE_CONTENT);
ContentWriter writer = fileFolderService.getWriter(fileInfo.getNodeRef());
writer.setMimetype(MimetypeMap.MIMETYPE_ACP);
writer.putContent(exportFile);
exportFileNodeRef = fileInfo.getNodeRef();
// add a title for Web Client viewing
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(3, 1.0f);
titledProps.put(ContentModel.PROP_TITLE, packageName);
titledProps.put(ContentModel.PROP_DESCRIPTION, packageDescription);
nodeService.addAspect(exportFileNodeRef, ContentModel.ASPECT_TITLED, titledProps);
}
catch (FileExistsException e)
{
// Note: shouldn't get here
}
return exportFileNodeRef;
}
/**
* Contract for exporting a store
*
* @author davidc
*
* @param <ExportHandleType>
*/
private interface ExportStore<ExportHandleType extends ExportHandle>
{
public ExportHandleType exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress);
}
/**
* Enumerate list of pre-configured Stores and export one by one
*
* @param <ExportHandle> type of export file handle
* @param stores the list of stores to export
* @param exportStore the exporter call-back for handling the actual export
* @return the list export file handles
*/
private <ExportHandleType extends ExportHandle> List<ExportHandleType> exportStores(List<Properties> stores, String packageName, ExportStore<ExportHandleType> exportStore)
{
List<ExportHandleType> exportHandles = new ArrayList<ExportHandleType>(stores.size());
for (Properties store : stores)
{
// retrieve store reference to export
String storeRefStr = (String)store.get(STOREREF_KEY);
if (storeRefStr == null || storeRefStr.length() == 0)
{
throw new ExporterException("Store Reference has not been provided.");
}
StoreRef storeRef = new StoreRef(storeRefStr);
// retrieve package name to export into
String storePackageName = (String)store.get(PACKAGENAME_KEY);
if (storePackageName == null || storePackageName.length() == 0)
{
storePackageName = storeRef.getIdentifier();
}
String completePackageName = (packageName == null) ? storePackageName : packageName + "_" + storePackageName;
// now export
// NOTE: For now, do not provide exporter progress
ExporterCrawlerParameters exportParameters = getExportParameters(storeRef);
ExportHandleType exportHandle = exportStore.exportStore(exportParameters, completePackageName, null);
exportHandles.add(exportHandle);
}
return exportHandles;
}
/**
* Get export parameters for exporting a complete store
*
* @param storeRef store reference to export
* @return the parameters for exporting the complete store
*/
private ExporterCrawlerParameters getExportParameters(StoreRef storeRef)
{
ExporterCrawlerParameters parameters = new ExporterCrawlerParameters();
parameters.setExportFrom(new Location(storeRef));
parameters.setCrawlSelf(true);
parameters.setCrawlChildNodes(true);
parameters.setCrawlContent(true);
parameters.setCrawlAssociations(true);
parameters.setCrawlNullProperties(true);
parameters.setExcludeNamespaceURIs(new String[] {});
return parameters;
}
/**
* Export a Store to a temporary file
*
* @author davidc
*/
private class TempFileExporter implements ExportStore<FileExportHandle>
{
/*
* (non-Javadoc)
* @see org.alfresco.repo.exporter.RepositoryExporterComponent.ExportStore#exportStore(org.alfresco.service.cmr.view.ExporterCrawlerParameters, java.lang.String, org.alfresco.service.cmr.view.Exporter)
*/
public FileExportHandle exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress)
{
// create a temporary file to hold the acp export
File tempFile = TempFileProvider.createTempFile("repoExp", "." + ACPExportPackageHandler.ACP_EXTENSION);
// create acp export handler around the temp file
File dataFile = new File(packageName);
File contentDir = new File(packageName);
try
{
OutputStream outputStream = new FileOutputStream(tempFile);
ACPExportPackageHandler acpHandler = new ACPExportPackageHandler(outputStream, dataFile, contentDir, mimetypeService);
// export the store
exporterService.exportView(acpHandler, exportParameters, progress);
}
catch(FileNotFoundException e)
{
tempFile.delete();
throw new ExporterException("Failed to create temporary file for holding export of store " + exportParameters.getExportFrom().getStoreRef());
}
// return handle onto temp file
FileExportHandle handle = new FileExportHandle();
handle.storeRef = exportParameters.getExportFrom().getStoreRef();
handle.packageName = packageName;
handle.exportFile = tempFile;
return handle;
};
};
/**
* Export a Store to a file in a specified folder
*
* @author davidc
*/
private class FileExporter implements ExportStore<FileExportHandle>
{
private File directoryDestination;
/**
* Construct
*
* @param directoryDestination destination file system folder to create export file
*/
public FileExporter(File directoryDestination)
{
this.directoryDestination = directoryDestination;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.exporter.RepositoryExporterComponent.ExportStore#exportStore(org.alfresco.service.cmr.view.ExporterCrawlerParameters, java.lang.String, org.alfresco.service.cmr.view.Exporter)
*/
public FileExportHandle exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress)
{
// create a file to hold the acp export
File file = new File(directoryDestination, packageName + "." + ACPExportPackageHandler.ACP_EXTENSION);
// create acp export handler around the temp file
File dataFile = new File(packageName);
File contentDir = new File(packageName);
try
{
OutputStream outputStream = new FileOutputStream(file);
ACPExportPackageHandler acpHandler = new ACPExportPackageHandler(outputStream, dataFile, contentDir, mimetypeService);
// export the store
exporterService.exportView(acpHandler, exportParameters, progress);
}
catch(FileNotFoundException e)
{
file.delete();
throw new ExporterException("Failed to create file " + file.getAbsolutePath() + " for holding the export of store " + exportParameters.getExportFrom().getStoreRef());
}
// return handle onto temp file
FileExportHandle handle = new FileExportHandle();
handle.storeRef = exportParameters.getExportFrom().getStoreRef();
handle.packageName = packageName;
handle.exportFile = file;
return handle;
};
};
/**
* Export a store to Repository File
*
* @author davidc
*/
private class RepositoryFileExporter implements ExportStore<RepositoryExportHandle>
{
private TempFileExporter tempFileExporter = new TempFileExporter();
private NodeRef repoDestination;
/**
* Construct
*
* @param repoDestination destination within repository to create export file
*/
public RepositoryFileExporter(NodeRef repoDestination)
{
this.repoDestination = repoDestination;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.exporter.RepositoryExporterComponent.ExportStore#exportStore(org.alfresco.service.cmr.view.ExporterCrawlerParameters, java.lang.String, org.alfresco.service.cmr.view.Exporter)
*/
public RepositoryExportHandle exportStore(ExporterCrawlerParameters exportParameters, String packageName, Exporter progress)
{
// export acp to temporary file
FileExportHandle tempFile = tempFileExporter.exportStore(exportParameters, packageName, progress);
String description = I18NUtil.getMessage("export.store.package.description", new Object[] { tempFile.storeRef.getIdentifier() });
NodeRef repoExportFile = addExportFile(repoDestination, packageName, description, tempFile.exportFile);
RepositoryExportHandle handle = new RepositoryExportHandle();
handle.storeRef = exportParameters.getExportFrom().getStoreRef();
handle.packageName = packageName;
handle.exportFile = repoExportFile;
return handle;
}
};
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright (C) 2005 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.exporter;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.ServiceRegistry;
import org.alfresco.service.cmr.model.FileFolderService;
import org.alfresco.service.cmr.model.FileInfo;
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.cmr.view.RepositoryExporterService;
import org.alfresco.service.cmr.view.RepositoryExporterService.FileExportHandle;
import org.alfresco.service.cmr.view.RepositoryExporterService.RepositoryExportHandle;
import org.alfresco.util.BaseSpringTest;
public class RepositoryExporterComponentTest extends BaseSpringTest
{
private RepositoryExporterService repositoryService;
private AuthenticationComponent authenticationComponent;
private NodeService nodeService;
private FileFolderService fileFolderService;
@Override
protected void onSetUpInTransaction() throws Exception
{
this.nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName());
this.fileFolderService = (FileFolderService)applicationContext.getBean(ServiceRegistry.FILE_FOLDER_SERVICE.getLocalName());
this.repositoryService = (RepositoryExporterService)applicationContext.getBean("repositoryExporterComponent");
this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent");
this.authenticationComponent.setSystemUserAsCurrentUser();
}
@Override
protected void onTearDownInTransaction() throws Exception
{
authenticationComponent.clearCurrentSecurityContext();
super.onTearDownInTransaction();
}
public void testDummy()
{
}
public void xtestTempFileExport()
throws Exception
{
FileExportHandle[] handles = repositoryService.export("test");
assertNotNull(handles);
assertEquals(4, handles.length);
for (FileExportHandle tempFile : handles)
{
assertTrue(tempFile.exportFile.exists());
}
}
public void xtestRepositoryExport()
throws Exception
{
// Create a temp store to hold exports
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
NodeRef rootNode = nodeService.getRootNode(storeRef);
FileInfo container = fileFolderService.create(rootNode, "export", ContentModel.TYPE_FOLDER);
// Export stores
RepositoryExportHandle[] handles = repositoryService.export(container.getNodeRef(), "test");
assertNotNull(handles);
assertEquals(4, handles.length);
for (RepositoryExportHandle handle : handles)
{
assertTrue(nodeService.exists(handle.exportFile));
}
setComplete();
}
}

View File

@@ -204,19 +204,19 @@ import org.alfresco.util.ParameterCheck;
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable)
*/
public void value(NodeRef nodeRef, QName property, Object value)
public void value(NodeRef nodeRef, QName property, Object value, int index)
{
exporter.value(nodeRef, property, value);
exporter.value(nodeRef, property, value, index);
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream)
*/
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData)
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index)
{
// Handle the stream by converting it to a URL and export the URL
ContentData exportedContentData = streamHandler.exportContent(content, contentData);
value(nodeRef, property, exportedContentData);
value(nodeRef, property, exportedContentData, index);
}
/* (non-Javadoc)

View File

@@ -17,7 +17,7 @@
package org.alfresco.repo.exporter;
import java.io.InputStream;
import java.util.Collection;
import java.util.List;
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
@@ -28,6 +28,7 @@ import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.Path;
import org.alfresco.service.cmr.repository.datatype.DefaultTypeConverter;
import org.alfresco.service.cmr.search.SearchService;
import org.alfresco.service.cmr.security.AccessPermission;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.view.Exporter;
@@ -98,6 +99,7 @@ import org.xml.sax.helpers.AttributesImpl;
// Service dependencies
private NamespaceService namespaceService;
private NodeService nodeService;
private SearchService searchService;
private DictionaryService dictionaryService;
private PermissionService permissionService;
@@ -113,11 +115,12 @@ import org.xml.sax.helpers.AttributesImpl;
* @param nodeService node service
* @param contentHandler content handler
*/
ViewXMLExporter(NamespaceService namespaceService, NodeService nodeService,
ViewXMLExporter(NamespaceService namespaceService, NodeService nodeService, SearchService searchService,
DictionaryService dictionaryService, PermissionService permissionService, ContentHandler contentHandler)
{
this.namespaceService = namespaceService;
this.nodeService = nodeService;
this.searchService = searchService;
this.dictionaryService = dictionaryService;
this.permissionService = permissionService;
this.contentHandler = contentHandler;
@@ -492,7 +495,7 @@ import org.xml.sax.helpers.AttributesImpl;
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable)
*/
public void value(NodeRef nodeRef, QName property, Object value)
public void value(NodeRef nodeRef, QName property, Object value, int index)
{
try
{
@@ -512,12 +515,16 @@ import org.xml.sax.helpers.AttributesImpl;
// convert node references to paths
if (value instanceof NodeRef)
{
Path nodeRefPath = createRelativePath(context.getExportOf(), nodeRef, (NodeRef)value);
value = (nodeRefPath == null) ? null : nodeRefPath.toPrefixString(namespaceService);
NodeRef valueNodeRef = (NodeRef)value;
if (nodeRef.getStoreRef().equals(valueNodeRef.getStoreRef()))
{
Path nodeRefPath = createRelativePath(context.getExportOf(), nodeRef, valueNodeRef);
value = (nodeRefPath == null) ? null : nodeRefPath.toPrefixString(namespaceService);
}
}
// output value wrapper if value is null or property data type is ANY
if (value == null || valueDataType != null)
// output value wrapper if value is null or property data type is ANY or value is part of collection
if (value == null || valueDataType != null || index != -1)
{
AttributesImpl attrs = new AttributesImpl();
if (value == null)
@@ -539,7 +546,7 @@ import org.xml.sax.helpers.AttributesImpl;
}
// output value wrapper if property data type is any
if (value == null || valueDataType != null)
if (value == null || valueDataType != null || index != -1)
{
contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUE_LOCALNAME, toPrefixString(VALUE_QNAME));
}
@@ -550,74 +557,10 @@ import org.xml.sax.helpers.AttributesImpl;
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.util.Collection)
*/
public void value(NodeRef nodeRef, QName property, Collection values)
{
try
{
PropertyDefinition propDef = dictionaryService.getProperty(property);
DataTypeDefinition dataTypeDef = (propDef == null) ? null : propDef.getDataType();
// start collection
contentHandler.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUES_LOCALNAME, toPrefixString(VALUES_QNAME), EMPTY_ATTRIBUTES);
for (Object value : values)
{
// determine data type of value
QName valueDataType = null;
if (dataTypeDef == null || dataTypeDef.getName().equals(DataTypeDefinition.ANY))
{
dataTypeDef = (value == null) ? null : dictionaryService.getDataType(value.getClass());
if (dataTypeDef != null)
{
valueDataType = dataTypeDef.getName();
}
}
// output value wrapper with datatype
AttributesImpl attrs = new AttributesImpl();
if (value == null)
{
attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_PREFIX, ISNULL_LOCALNAME, ISNULL_QNAME.toPrefixString(), null, "true");
}
if (valueDataType != null)
{
attrs.addAttribute(NamespaceService.REPOSITORY_VIEW_PREFIX, DATATYPE_LOCALNAME, DATATYPE_QNAME.toPrefixString(), null, toPrefixString(valueDataType));
}
contentHandler.startElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUE_LOCALNAME, toPrefixString(VALUE_QNAME), attrs);
// convert node references to paths
if (value instanceof NodeRef)
{
value = createRelativePath(context.getExportOf(), nodeRef, (NodeRef)value).toPrefixString(namespaceService);
}
// output value
String strValue = (String)DefaultTypeConverter.INSTANCE.convert(String.class, value);
if (strValue != null)
{
contentHandler.characters(strValue.toCharArray(), 0, strValue.length());
}
// output value wrapper if property data type is any
contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUE_LOCALNAME, toPrefixString(VALUE_QNAME));
}
// end collection
contentHandler.endElement(NamespaceService.REPOSITORY_VIEW_PREFIX, VALUES_LOCALNAME, toPrefixString(VALUES_QNAME));
}
catch (SAXException e)
{
throw new ExporterException("Failed to process multi-value event - nodeRef " + nodeRef + "; property " + toPrefixString(property), e);
}
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream)
*/
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData)
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index)
{
// TODO: Base64 encode content and send out via Content Handler
}
@@ -770,9 +713,9 @@ import org.xml.sax.helpers.AttributesImpl;
return null;
}
Path rootPath = nodeService.getPath(rootRef);
Path fromPath = nodeService.getPath(fromRef);
Path toPath = nodeService.getPath(toRef);
Path rootPath = createIndexedPath(rootRef, nodeService.getPath(rootRef));
Path fromPath = createIndexedPath(fromRef, nodeService.getPath(fromRef));
Path toPath = createIndexedPath(toRef, nodeService.getPath(toRef));
Path relativePath = null;
try
@@ -840,4 +783,43 @@ import org.xml.sax.helpers.AttributesImpl;
return relativePath;
}
/**
* Helper to convert a path into an indexed path which uniquely identifies a node
*
* @param nodeRef
* @param path
* @return
*/
private Path createIndexedPath(NodeRef nodeRef, Path path)
{
// Add indexes for same name siblings
// TODO: Look at more efficient approach
for (int i = path.size() - 1; i >= 0; i--)
{
Path.Element pathElement = path.get(i);
if (i > 0 && pathElement instanceof Path.ChildAssocElement)
{
int index = 1; // for xpath index compatibility
String searchPath = path.subPath(i).toPrefixString(namespaceService);
List<NodeRef> siblings = searchService.selectNodes(nodeRef, searchPath, null, namespaceService, false);
if (siblings.size() > 1)
{
ChildAssociationRef childAssoc = ((Path.ChildAssocElement)pathElement).getRef();
NodeRef childRef = childAssoc.getChildRef();
for (NodeRef sibling : siblings)
{
if (sibling.equals(childRef))
{
childAssoc.setNthSibling(index);
break;
}
index++;
}
}
}
}
return path;
}
}

View File

@@ -39,6 +39,7 @@ import org.alfresco.service.cmr.view.ImporterBinding;
import org.alfresco.service.cmr.view.ImporterService;
import org.alfresco.service.cmr.view.Location;
import org.alfresco.service.namespace.NamespacePrefixResolver;
import org.alfresco.service.namespace.QName;
import org.alfresco.service.transaction.TransactionService;
import org.alfresco.util.TempFileProvider;
import org.dom4j.io.OutputFormat;
@@ -202,6 +203,11 @@ public class ExportSourceImporter implements ImporterJobSPI
return false;
}
public QName[] getExcludedClasses()
{
return null;
}
};
}

View File

@@ -75,6 +75,14 @@ public interface Importer
*/
public NodeRef resolvePath(String path);
/**
* Is excluded Content Model Class?
*
* @param QName the class name to test
* @return true => the provided class is excluded from import
*/
public boolean isExcludedClass(QName className);
/**
* Signal completion of node import
*

View File

@@ -313,7 +313,7 @@ public class ImporterBootstrap implements ApplicationListener
}
UserTransaction userTransaction = transactionService.getUserTransaction();
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
authenticationComponent.setSystemUserAsCurrentUser();
try
{
@@ -550,7 +550,7 @@ public class ImporterBootstrap implements ApplicationListener
public UUID_BINDING getUUIDBinding()
{
// always use create new strategy for bootstrap import
return UUID_BINDING.CREATE_NEW;
return UUID_BINDING.CREATE_NEW_WITH_UUID;
}
/*
@@ -561,6 +561,16 @@ public class ImporterBootstrap implements ApplicationListener
{
return true;
}
/*
* (non-Javadoc)
* @see org.alfresco.service.cmr.view.ImporterBinding#getExcludedClasses()
*/
public QName[] getExcludedClasses()
{
// Note: Do not exclude any classes, we want to import all
return new QName[] {};
}
}
/**

View File

@@ -401,6 +401,7 @@ public class ImporterComponent
private ImportPackageHandler streamHandler;
private NodeImporterStrategy importStrategy;
private UpdateExistingNodeImporterStrategy updateStrategy;
private QName[] excludedClasses;
// Import tracking
private List<ImportedNodeRef> nodeRefs = new ArrayList<ImportedNodeRef>();
@@ -422,6 +423,16 @@ public class ImporterComponent
this.streamHandler = streamHandler;
this.importStrategy = createNodeImporterStrategy(binding == null ? null : binding.getUUIDBinding());
this.updateStrategy = new UpdateExistingNodeImporterStrategy();
// initialise list of content models to exclude from import
if (binding == null || binding.getExcludedClasses() == null)
{
this.excludedClasses = new QName[] { ContentModel.ASPECT_REFERENCEABLE, ContentModel.ASPECT_VERSIONABLE };
}
else
{
this.excludedClasses = binding.getExcludedClasses();
}
}
/**
@@ -440,6 +451,10 @@ public class ImporterComponent
{
return new CreateNewNodeImporterStrategy(true);
}
else if (uuidBinding.equals(UUID_BINDING.CREATE_NEW_WITH_UUID))
{
return new CreateNewNodeImporterStrategy(false);
}
else if (uuidBinding.equals(UUID_BINDING.REMOVE_EXISTING))
{
return new RemoveExistingNodeImporterStrategy();
@@ -652,6 +667,22 @@ public class ImporterComponent
}
return referencedRef;
}
/*
* (non-Javadoc)
* @see org.alfresco.repo.importer.Importer#isExcludedClass(org.alfresco.service.namespace.QName)
*/
public boolean isExcludedClass(QName className)
{
for (QName excludedClass : excludedClasses)
{
if (excludedClass.equals(className))
{
return true;
}
}
return false;
}
/* (non-Javadoc)
* @see org.alfresco.repo.importer.Importer#end()
@@ -670,13 +701,16 @@ public class ImporterComponent
List<NodeRef> resolvedRefs = new ArrayList<NodeRef>(unresolvedRefs.size());
for (String unresolvedRef : unresolvedRefs)
{
NodeRef nodeRef = resolveImportedNodeRef(importedRef.context.getNodeRef(), unresolvedRef);
if (nodeRef == null)
if (unresolvedRef != null)
{
// TODO: Probably need an alternative mechanism here e.g. report warning
throw new ImporterException("Failed to find item referenced (in property " + importedRef.property + ") as " + importedRef.value);
NodeRef nodeRef = resolveImportedNodeRef(importedRef.context.getNodeRef(), unresolvedRef);
if (nodeRef == null)
{
// TODO: Probably need an alternative mechanism here e.g. report warning
throw new ImporterException("Failed to find item referenced (in property " + importedRef.property + ") as " + importedRef.value);
}
resolvedRefs.add(nodeRef);
}
resolvedRefs.add(nodeRef);
}
refProperty = (Serializable)resolvedRefs;
}
@@ -998,19 +1032,11 @@ public class ImporterComponent
}
catch(XPathException e)
{
// attempt to resolve as a node reference
try
{
NodeRef directRef = new NodeRef(importedRef);
if (nodeService.exists(directRef))
{
nodeRef = directRef;
}
}
catch(AlfrescoRuntimeException e1)
{
// Note: Invalid reference format
}
nodeRef = new NodeRef(importedRef);
}
catch(AlfrescoRuntimeException e1)
{
// Note: Invalid reference format - try path search instead
}
}

View File

@@ -459,8 +459,7 @@ public class NodeContext extends ElementContext
*/
private boolean isImportableClass(QName className)
{
return !(className.equals(ContentModel.ASPECT_REFERENCEABLE) ||
className.equals(ContentModel.ASPECT_VERSIONABLE));
return !getImporter().isExcludedClass(className);
}
/* (non-Javadoc)

View File

@@ -178,7 +178,7 @@ public class StoreRedirectorProxyFactory<I> implements FactoryBean, Initializing
// Otherwise, determine the apropriate implementation to invoke for
// the service interface method
Object binding = null;
StoreRef storeRef = getStoreRef(args);
StoreRef storeRef = getStoreRef(method.getParameterTypes(), args);
if (storeRef == null)
{
binding = StoreRedirectorProxyFactory.this.defaultBinding;
@@ -224,7 +224,7 @@ public class StoreRedirectorProxyFactory<I> implements FactoryBean, Initializing
* @param args the method arguments
* @return the store type (or null, if one is not specified)
*/
private StoreRef getStoreRef(Object[] args)
private StoreRef getStoreRef(Class[] argTypes, Object[] args)
{
StoreRef storeRef = null;
@@ -233,17 +233,17 @@ public class StoreRedirectorProxyFactory<I> implements FactoryBean, Initializing
return null;
}
for (Object arg : args)
for (int i = 0; i < argTypes.length; i++)
{
// Extract store type from argument, if store type provided
StoreRef argStoreRef = null;
if (arg instanceof NodeRef)
if (argTypes[i].equals(NodeRef.class))
{
argStoreRef = ((NodeRef) arg).getStoreRef();
argStoreRef = ((NodeRef) args[i]).getStoreRef();
}
else if (arg instanceof StoreRef)
else if (argTypes[i].equals(StoreRef.class))
{
argStoreRef = ((StoreRef) arg);
argStoreRef = ((StoreRef) args[i]);
}
// Only allow one store type

View File

@@ -1,111 +0,0 @@
/*
* Copyright (C) 2005 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.version;
import javax.transaction.UserTransaction;
import org.alfresco.error.AlfrescoRuntimeException;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.transaction.TransactionService;
/**
* Bootstrap Version Store
*
* @author David Caruana
*/
public class VersionBootstrap
{
private TransactionService transactionService;
private NodeService nodeService;
private AuthenticationComponent authenticationComponent;
private PermissionService permissionService;
/**
* Sets the Transaction Service
*
* @param userTransaction the user transaction
*/
public void setTransactionService(TransactionService transactionService)
{
this.transactionService = transactionService;
}
/**
* Sets the Node Service
*
* @param nodeService the node service
*/
public void setNodeService(NodeService nodeService)
{
this.nodeService = nodeService;
}
public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
{
this.authenticationComponent = authenticationComponent;
}
public void setPermissionService(PermissionService permissionService)
{
this.permissionService = permissionService;
}
/**
* Bootstrap the Version Store
*/
public void bootstrap()
{
UserTransaction userTransaction = transactionService.getUserTransaction();
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
try
{
userTransaction.begin();
// Ensure that the version store has been created
if (this.nodeService.exists(new StoreRef(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID)) == true)
{
userTransaction.rollback();
}
else
{
StoreRef vStore = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, VersionModel.STORE_ID);
// TODO: For now there are no permissions on version access
permissionService.setPermission(nodeService.getRootNode(vStore), permissionService.getAllAuthorities(), permissionService.getAllPermission(), true);
userTransaction.commit();
}
}
catch(Throwable e)
{
// rollback the transaction
try { if (userTransaction != null) {userTransaction.rollback();} } catch (Exception ex) {}
try {authenticationComponent.clearCurrentSecurityContext(); } catch (Exception ex) {}
throw new AlfrescoRuntimeException("Bootstrap failed", e);
}
finally
{
authenticationComponent.clearCurrentSecurityContext();
}
}
}

View File

@@ -171,14 +171,26 @@ public interface Exporter
public void startValueCollection(NodeRef nodeRef, QName property);
/**
* Export single valued property
* Export property value
*
* @param nodeRef the node reference
* @param property the property name
* @param value the value
* @param index value index (or -1, if not part of multi-valued collection)
*/
public void value(NodeRef nodeRef, QName property, Object value);
public void value(NodeRef nodeRef, QName property, Object value, int index);
/**
* Export content stream property value
*
* @param nodeRef the node reference
* @param property the property name
* @param content the content stream
* @param contentData content descriptor
* @param index value index (or -1, if not part of multi-valued collection)
*/
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index);
/**
* Export end of value collection
*
@@ -187,16 +199,6 @@ public interface Exporter
*/
public void endValueCollection(NodeRef nodeRef, QName property);
/**
* Export content stream property
*
* @param nodeRef the node reference
* @param property the property name
* @param content the content stream
* @param contentData content descriptor
*/
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData);
/**
* Start export of associations
*

View File

@@ -16,6 +16,8 @@
*/
package org.alfresco.service.cmr.view;
import org.alfresco.service.namespace.QName;
/**
* Encapsulation of Import binding parameters
@@ -30,7 +32,7 @@ public interface ImporterBinding
*/
public enum UUID_BINDING
{
CREATE_NEW, REMOVE_EXISTING, REPLACE_EXISTING, UPDATE_EXISTING, THROW_ON_COLLISION
CREATE_NEW, CREATE_NEW_WITH_UUID, REMOVE_EXISTING, REPLACE_EXISTING, UPDATE_EXISTING, THROW_ON_COLLISION
}
/**
@@ -56,4 +58,11 @@ public interface ImporterBinding
*/
public String getValue(String key);
/**
* Gets the list of content model classes to exclude from import
*
* @return list of model class qnames to exclude (return null to indicate use of default list)
*/
public QName[] getExcludedClasses();
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright (C) 2005 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.service.cmr.view;
import java.io.File;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.StoreRef;
/**
* Repository Export Service
*
* @author davidc
*/
public interface RepositoryExporterService
{
/**
* Export complete Repository.
*
* Each store is exported to its own temporary .acp file
*
* @param packageName package name prefix for export .acp files
* @return list of temporary export files
*/
public FileExportHandle[] export(String packageName);
/**
* Export complete Repository.
*
* Each store is exported to a file held in the Repository.
*
* @param repositoryDestination location within Repository to hold .acp files
* @param packageName package name prefix for export .acp files
* @return list of repository held export files
*/
public RepositoryExportHandle[] export(NodeRef repositoryDestination, String packageName);
/**
* Export complete Repository.
*
* @param directoryDestination location within File System to hold .acp files
* @param packageName package name prefix for export .acp files
* @return list of export files
*/
public FileExportHandle[] export(File directoryDestination, String packageName);
/**
* General Export Handle
*
* @author davidc
*/
public class ExportHandle
{
public StoreRef storeRef;
public String packageName;
}
/**
* File Exort Handle
*
* @author davidc
*/
public class FileExportHandle extends ExportHandle
{
public File exportFile;
}
/**
* Repository File Export Handle
*
* @author davidc
*/
public class RepositoryExportHandle extends ExportHandle
{
public NodeRef exportFile;
}
}

View File

@@ -568,14 +568,14 @@ public final class Export extends Tool
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#value(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable)
*/
public void value(NodeRef nodeRef, QName property, Object value)
public void value(NodeRef nodeRef, QName property, Object value, int index)
{
}
/* (non-Javadoc)
* @see org.alfresco.service.cmr.view.Exporter#content(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.InputStream)
*/
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData)
public void content(NodeRef nodeRef, QName property, InputStream content, ContentData contentData, int index)
{
}