mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
Moving to root below branch label
git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@2005 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.Enumeration;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.alfresco.service.cmr.view.ImportPackageHandler;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
|
||||
|
||||
/**
|
||||
* Handler for importing Repository content from zip package file
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class ACPImportPackageHandler
|
||||
implements ImportPackageHandler
|
||||
{
|
||||
|
||||
protected File file;
|
||||
protected ZipFile zipFile;
|
||||
protected String dataFileEncoding;
|
||||
|
||||
|
||||
/**
|
||||
* Constuct Handler
|
||||
*
|
||||
* @param sourceDir source directory
|
||||
* @param packageDir relative directory within source to place exported content
|
||||
*/
|
||||
public ACPImportPackageHandler(File zipFile, String dataFileEncoding)
|
||||
{
|
||||
this.file = zipFile;
|
||||
this.dataFileEncoding = dataFileEncoding;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.view.ImportPackageHandler#startImport()
|
||||
*/
|
||||
public void startImport()
|
||||
{
|
||||
log("Importing from zip file " + file.getAbsolutePath());
|
||||
try
|
||||
{
|
||||
zipFile = new ZipFile(file);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new ImporterException("Failed to read zip file due to " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.view.ImportPackageHandler#getDataStream()
|
||||
*/
|
||||
public Reader getDataStream()
|
||||
{
|
||||
try
|
||||
{
|
||||
// find data file
|
||||
InputStream dataStream = null;
|
||||
Enumeration entries = zipFile.entries();
|
||||
while(entries.hasMoreElements())
|
||||
{
|
||||
ZipEntry entry = (ZipEntry)entries.nextElement();
|
||||
if (!entry.isDirectory())
|
||||
{
|
||||
if (entry.getName().endsWith(".xml"))
|
||||
{
|
||||
dataStream = zipFile.getInputStream(entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// oh dear, there's no data file
|
||||
if (dataStream == null)
|
||||
{
|
||||
throw new ImporterException("Failed to find data file within zip package");
|
||||
}
|
||||
|
||||
Reader inputReader = (dataFileEncoding == null) ? new InputStreamReader(dataStream) : new InputStreamReader(dataStream, dataFileEncoding);
|
||||
return new BufferedReader(inputReader);
|
||||
}
|
||||
catch(UnsupportedEncodingException e)
|
||||
{
|
||||
throw new ImporterException("Encoding " + dataFileEncoding + " is not supported");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new ImporterException("Failed to open data file within zip package due to " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.view.ImportStreamHandler#importStream(java.lang.String)
|
||||
*/
|
||||
public InputStream importStream(String content)
|
||||
{
|
||||
ZipEntry zipEntry = zipFile.getEntry(content);
|
||||
if (zipEntry == null)
|
||||
{
|
||||
throw new ImporterException("Failed to find content " + content + " within zip package");
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return zipFile.getInputStream(zipEntry);
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
throw new ImporterException("Failed to open content " + content + " within zip package due to " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.view.ImportPackageHandler#endImport()
|
||||
*/
|
||||
public void endImport()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Import Message
|
||||
*
|
||||
* @param message message to log
|
||||
*/
|
||||
protected void log(String message)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.alfresco.util.ParameterCheck;
|
||||
import org.xml.sax.Attributes;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
import org.xml.sax.Locator;
|
||||
import org.xml.sax.SAXException;
|
||||
import org.xml.sax.SAXParseException;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Base Import Content Handler
|
||||
*/
|
||||
public class DefaultContentHandler
|
||||
implements ImportContentHandler, ErrorHandler
|
||||
{
|
||||
private ImportContentHandler targetHandler = null;
|
||||
private Importer importer = null;
|
||||
|
||||
|
||||
public DefaultContentHandler(ImportContentHandler targetHandler)
|
||||
{
|
||||
ParameterCheck.mandatory("targetHandler", targetHandler);
|
||||
this.targetHandler = targetHandler;
|
||||
}
|
||||
|
||||
public void setImporter(Importer importer)
|
||||
{
|
||||
this.importer = importer;
|
||||
this.targetHandler.setImporter(importer);
|
||||
}
|
||||
|
||||
public InputStream importStream(String content)
|
||||
{
|
||||
return targetHandler.importStream(content);
|
||||
}
|
||||
|
||||
public void setDocumentLocator(Locator locator)
|
||||
{
|
||||
targetHandler.setDocumentLocator(locator);
|
||||
}
|
||||
|
||||
public void startDocument() throws SAXException
|
||||
{
|
||||
importer.start();
|
||||
targetHandler.startDocument();
|
||||
}
|
||||
|
||||
public void endDocument() throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
targetHandler.endDocument();
|
||||
}
|
||||
finally
|
||||
{
|
||||
importer.end();
|
||||
}
|
||||
}
|
||||
|
||||
public void startPrefixMapping(String prefix, String uri) throws SAXException
|
||||
{
|
||||
targetHandler.startPrefixMapping(prefix, uri);
|
||||
}
|
||||
|
||||
public void endPrefixMapping(String prefix) throws SAXException
|
||||
{
|
||||
targetHandler.endPrefixMapping(prefix);
|
||||
}
|
||||
|
||||
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException
|
||||
{
|
||||
targetHandler.startElement(uri, localName, qName, atts);
|
||||
}
|
||||
|
||||
public void endElement(String uri, String localName, String qName) throws SAXException
|
||||
{
|
||||
targetHandler.endElement(uri, localName, qName);
|
||||
}
|
||||
|
||||
public void characters(char[] ch, int start, int length) throws SAXException
|
||||
{
|
||||
targetHandler.characters(ch, start, length);
|
||||
}
|
||||
|
||||
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
|
||||
{
|
||||
targetHandler.ignorableWhitespace(ch, start, length);
|
||||
}
|
||||
|
||||
public void processingInstruction(String target, String data) throws SAXException
|
||||
{
|
||||
targetHandler.processingInstruction(target, data);
|
||||
}
|
||||
|
||||
public void skippedEntity(String name) throws SAXException
|
||||
{
|
||||
targetHandler.skippedEntity(name);
|
||||
}
|
||||
|
||||
|
||||
public void error(SAXParseException exception) throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
targetHandler.error(exception);
|
||||
}
|
||||
finally
|
||||
{
|
||||
importer.error(exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void fatalError(SAXParseException exception) throws SAXException
|
||||
{
|
||||
try
|
||||
{
|
||||
targetHandler.error(exception);
|
||||
}
|
||||
finally
|
||||
{
|
||||
importer.error(exception);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void warning(SAXParseException exception) throws SAXException
|
||||
{
|
||||
targetHandler.warning(exception);
|
||||
}
|
||||
|
||||
|
||||
}
|
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.alfresco.service.cmr.view.ImportPackageHandler;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
|
||||
|
||||
/**
|
||||
* Handler for importing Repository content streams from file system
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class FileImportPackageHandler
|
||||
implements ImportPackageHandler
|
||||
{
|
||||
protected File sourceDir;
|
||||
protected File dataFile;
|
||||
protected String dataFileEncoding;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param sourceDir
|
||||
* @param dataFile
|
||||
* @param dataFileEncoding
|
||||
*/
|
||||
public FileImportPackageHandler(File sourceDir, File dataFile, String dataFileEncoding)
|
||||
{
|
||||
this.sourceDir = sourceDir;
|
||||
this.dataFile = new File(sourceDir, dataFile.getPath());
|
||||
this.dataFileEncoding = dataFileEncoding;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.view.ImportPackageHandler#startImport()
|
||||
*/
|
||||
public void startImport()
|
||||
{
|
||||
log("Importing from package " + dataFile.getAbsolutePath());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.view.ImportPackageHandler#getDataStream()
|
||||
*/
|
||||
public Reader getDataStream()
|
||||
{
|
||||
try
|
||||
{
|
||||
InputStream inputStream = new FileInputStream(dataFile);
|
||||
Reader inputReader = (dataFileEncoding == null) ? new InputStreamReader(inputStream) : new InputStreamReader(inputStream, dataFileEncoding);
|
||||
return new BufferedReader(inputReader);
|
||||
}
|
||||
catch(UnsupportedEncodingException e)
|
||||
{
|
||||
throw new ImporterException("Encoding " + dataFileEncoding + " is not supported");
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new ImporterException("Failed to read package " + dataFile.getAbsolutePath() + " due to " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.view.ImportStreamHandler#importStream(java.lang.String)
|
||||
*/
|
||||
public InputStream importStream(String content)
|
||||
{
|
||||
File fileURL = new File(content);
|
||||
if (fileURL.isAbsolute() == false)
|
||||
{
|
||||
fileURL = new File(sourceDir, content);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
return new FileInputStream(fileURL);
|
||||
}
|
||||
catch(IOException e)
|
||||
{
|
||||
throw new ImporterException("Failed to read content url " + content + " from file " + fileURL.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.view.ImportPackageHandler#endImport()
|
||||
*/
|
||||
public void endImport()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Log Import Message
|
||||
*
|
||||
* @param message message to log
|
||||
*/
|
||||
protected void log(String message)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
67
source/java/org/alfresco/repo/importer/FileImporter.java
Normal file
67
source/java/org/alfresco/repo/importer/FileImporter.java
Normal file
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
|
||||
/**
|
||||
* Interface to load files and directories into the hub.
|
||||
* All will be created as new - there is no detection if a file exists or has changed etc..
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public interface FileImporter
|
||||
{
|
||||
/**
|
||||
* Load a file or directory into the repository
|
||||
*
|
||||
* @param container - the node into which to insert the file or directory
|
||||
* @param file - the start point for the import
|
||||
* @param recurse - if the start point is a directoty then recurse
|
||||
* @return Returns the number of successfully imported files and directories
|
||||
* @throws FileImporterException
|
||||
*/
|
||||
public int loadFile(NodeRef container, File file, boolean recurse) throws FileImporterException;
|
||||
|
||||
/**
|
||||
* Load all files or directories that match the file filter in the given directory
|
||||
*
|
||||
* @param container
|
||||
* @param file
|
||||
* @param filter
|
||||
* @param recurse
|
||||
* @return Returns the number of successfully imported files and directories
|
||||
* @throws FileImporterException
|
||||
*/
|
||||
public int loadFile(NodeRef container, File file, FileFilter filter, boolean recurse) throws FileImporterException;
|
||||
|
||||
|
||||
/**
|
||||
* Load a single file or directory without any recursion
|
||||
*
|
||||
* @param container
|
||||
* @param file
|
||||
* @return Returns the number of successfully imported files and directories
|
||||
* @throws FileImporterException
|
||||
*/
|
||||
public int loadFile(NodeRef container, File file) throws FileImporterException;
|
||||
|
||||
public int loadNamedFile(NodeRef container, File file, boolean recurse, String name) throws FileImporterException;
|
||||
}
|
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
|
||||
public class FileImporterException extends AlfrescoRuntimeException
|
||||
{
|
||||
|
||||
/**
|
||||
* Comment for <code>serialVersionUID</code>
|
||||
*/
|
||||
private static final long serialVersionUID = 3544669594364490545L;
|
||||
|
||||
public FileImporterException(String msg)
|
||||
{
|
||||
super(msg);
|
||||
}
|
||||
|
||||
public FileImporterException(String msg, Throwable cause)
|
||||
{
|
||||
super(msg, cause);
|
||||
}
|
||||
|
||||
}
|
294
source/java/org/alfresco/repo/importer/FileImporterImpl.java
Normal file
294
source/java/org/alfresco/repo/importer/FileImporterImpl.java
Normal file
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.ChildAssociationRef;
|
||||
import org.alfresco.service.cmr.repository.ContentData;
|
||||
import org.alfresco.service.cmr.repository.ContentIOException;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
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.security.AuthenticationService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Simple import of content into the repository
|
||||
*
|
||||
* @author andyh
|
||||
*/
|
||||
public class FileImporterImpl implements FileImporter
|
||||
{
|
||||
private static Log logger = LogFactory.getLog(FileImporterImpl.class);
|
||||
|
||||
private AuthenticationService authenticationService;
|
||||
private NodeService nodeService;
|
||||
private DictionaryService dictionaryService;
|
||||
private ContentService contentService;
|
||||
private MimetypeService mimetypeService;
|
||||
|
||||
public FileImporterImpl()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public int loadFile(NodeRef container, File file, boolean recurse) throws FileImporterException
|
||||
{
|
||||
Counter counter = new Counter();
|
||||
create(counter, container, file, null, recurse, null);
|
||||
return counter.getCount();
|
||||
}
|
||||
|
||||
public int loadNamedFile(NodeRef container, File file, boolean recurse, String name) throws FileImporterException
|
||||
{
|
||||
Counter counter = new Counter();
|
||||
create(counter, container, file, null, recurse, name);
|
||||
return counter.getCount();
|
||||
}
|
||||
|
||||
public int loadFile(NodeRef container, File file, FileFilter filter, boolean recurse) throws FileImporterException
|
||||
{
|
||||
Counter counter = new Counter();
|
||||
create(counter, container, file, filter, recurse, null);
|
||||
return counter.getCount();
|
||||
}
|
||||
|
||||
public int loadFile(NodeRef container, File file) throws FileImporterException
|
||||
{
|
||||
Counter counter = new Counter();
|
||||
create(counter, container, file, null, false, null);
|
||||
return counter.getCount();
|
||||
}
|
||||
|
||||
/** Helper class for mutable int */
|
||||
private static class Counter
|
||||
{
|
||||
private int count = 0;
|
||||
public void increment()
|
||||
{
|
||||
count++;
|
||||
}
|
||||
public int getCount()
|
||||
{
|
||||
return count;
|
||||
}
|
||||
}
|
||||
|
||||
private NodeRef create(Counter counter, NodeRef container, File file, FileFilter filter, boolean recurse, String containerName)
|
||||
{
|
||||
if(containerName != null)
|
||||
{
|
||||
NodeRef newContainer = createDirectory(container, containerName, containerName);
|
||||
return create(counter, newContainer, file, filter, recurse, null);
|
||||
|
||||
}
|
||||
if (file.isDirectory())
|
||||
{
|
||||
NodeRef directoryNodeRef = createDirectory(container, file);
|
||||
counter.increment();
|
||||
|
||||
if(recurse)
|
||||
{
|
||||
File[] files = ((filter == null) ? file.listFiles() : file.listFiles(filter));
|
||||
for(int i = 0; i < files.length; i++)
|
||||
{
|
||||
create(counter, directoryNodeRef, files[i], filter, recurse, null);
|
||||
}
|
||||
}
|
||||
|
||||
return directoryNodeRef;
|
||||
}
|
||||
else
|
||||
{
|
||||
counter.increment();
|
||||
return createFile(container, file);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the type of child association that should be created.
|
||||
*
|
||||
* @param parentNodeRef the parent
|
||||
* @return Returns the appropriate child association type qualified name for the type of the
|
||||
* parent. Null will be returned if it can't be determined.
|
||||
*/
|
||||
private QName getAssocTypeQName(NodeRef parentNodeRef)
|
||||
{
|
||||
// check the parent node's type to determine which association to use
|
||||
QName parentNodeTypeQName = nodeService.getType(parentNodeRef);
|
||||
QName assocTypeQName = null;
|
||||
if (dictionaryService.isSubClass(parentNodeTypeQName, ContentModel.TYPE_CONTAINER))
|
||||
{
|
||||
// it may be a root node or something similar
|
||||
assocTypeQName = ContentModel.ASSOC_CHILDREN;
|
||||
}
|
||||
else if (dictionaryService.isSubClass(parentNodeTypeQName, ContentModel.TYPE_FOLDER))
|
||||
{
|
||||
// more like a directory
|
||||
assocTypeQName = ContentModel.ASSOC_CONTAINS;
|
||||
}
|
||||
return assocTypeQName;
|
||||
}
|
||||
|
||||
private NodeRef createFile(NodeRef parentNodeRef, File file)
|
||||
{
|
||||
// check the parent node's type to determine which association to use
|
||||
QName assocTypeQName = getAssocTypeQName(parentNodeRef);
|
||||
if (assocTypeQName == null)
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"Unable to create file. " +
|
||||
"Parent type is inappropriate: " + nodeService.getType(parentNodeRef));
|
||||
}
|
||||
|
||||
// create properties for content type
|
||||
Map<QName, Serializable> contentProps = new HashMap<QName, Serializable>(3, 1.0f);
|
||||
contentProps.put(ContentModel.PROP_NAME, file.getName());
|
||||
contentProps.put(
|
||||
ContentModel.PROP_CONTENT,
|
||||
new ContentData(null, mimetypeService.guessMimetype(file.getName()), 0L, "UTF-8"));
|
||||
String currentUser = authenticationService.getCurrentUserName();
|
||||
contentProps.put(ContentModel.PROP_CREATOR, currentUser == null ? "unknown" : currentUser);
|
||||
|
||||
// create the node to represent the node
|
||||
String assocName = QName.createValidLocalName(file.getName());
|
||||
ChildAssociationRef assocRef = this.nodeService.createNode(
|
||||
parentNodeRef,
|
||||
assocTypeQName,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, assocName),
|
||||
ContentModel.TYPE_CONTENT, contentProps);
|
||||
|
||||
NodeRef fileNodeRef = assocRef.getChildRef();
|
||||
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Created file node for file: " + file.getName());
|
||||
|
||||
// apply the titled aspect - title and description
|
||||
Map<QName, Serializable> titledProps = new HashMap<QName, Serializable>(5);
|
||||
titledProps.put(ContentModel.PROP_TITLE, file.getName());
|
||||
|
||||
titledProps.put(ContentModel.PROP_DESCRIPTION, file.getPath());
|
||||
|
||||
this.nodeService.addAspect(fileNodeRef, ContentModel.ASPECT_TITLED, titledProps);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Added titled aspect with properties: " + titledProps);
|
||||
|
||||
// get a writer for the content and put the file
|
||||
ContentWriter writer = contentService.getWriter(fileNodeRef, ContentModel.PROP_CONTENT, true);
|
||||
try
|
||||
{
|
||||
writer.putContent(new BufferedInputStream(new FileInputStream(file)));
|
||||
}
|
||||
catch (ContentIOException e)
|
||||
{
|
||||
throw new FileImporterException("Failed to load content from "+file.getPath(), e);
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new FileImporterException("Failed to load content (file not found) "+file.getPath(), e);
|
||||
}
|
||||
|
||||
return fileNodeRef;
|
||||
}
|
||||
|
||||
private NodeRef createDirectory(NodeRef parentNodeRef, File file)
|
||||
{
|
||||
return createDirectory(parentNodeRef, file.getName(), file.getPath());
|
||||
|
||||
}
|
||||
|
||||
private NodeRef createDirectory(NodeRef parentNodeRef, String name, String path)
|
||||
{
|
||||
// check the parent node's type to determine which association to use
|
||||
QName assocTypeQName = getAssocTypeQName(parentNodeRef);
|
||||
if (assocTypeQName == null)
|
||||
{
|
||||
throw new IllegalArgumentException(
|
||||
"Unable to create directory. " +
|
||||
"Parent type is inappropriate: " + nodeService.getType(parentNodeRef));
|
||||
}
|
||||
|
||||
String qname = QName.createValidLocalName(name);
|
||||
ChildAssociationRef assocRef = this.nodeService.createNode(
|
||||
parentNodeRef,
|
||||
assocTypeQName,
|
||||
QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, qname),
|
||||
ContentModel.TYPE_FOLDER);
|
||||
|
||||
NodeRef nodeRef = assocRef.getChildRef();
|
||||
|
||||
// set the name property on the node
|
||||
this.nodeService.setProperty(nodeRef, ContentModel.PROP_NAME, name);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Created folder node with name: " + name);
|
||||
|
||||
// apply the uifacets aspect - icon, title and description props
|
||||
Map<QName, Serializable> uiFacetsProps = new HashMap<QName, Serializable>(5);
|
||||
uiFacetsProps.put(ContentModel.PROP_ICON, "space-icon-default");
|
||||
uiFacetsProps.put(ContentModel.PROP_TITLE, name);
|
||||
uiFacetsProps.put(ContentModel.PROP_DESCRIPTION, path);
|
||||
this.nodeService.addAspect(nodeRef, ContentModel.ASPECT_UIFACETS, uiFacetsProps);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Added uifacets aspect with properties: " + uiFacetsProps);
|
||||
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
protected void setAuthenticationService(AuthenticationService authenticationService)
|
||||
{
|
||||
this.authenticationService = authenticationService;
|
||||
}
|
||||
|
||||
protected void setContentService(ContentService contentService)
|
||||
{
|
||||
this.contentService = contentService;
|
||||
}
|
||||
|
||||
protected void setMimetypeService(MimetypeService mimetypeService)
|
||||
{
|
||||
this.mimetypeService = mimetypeService;
|
||||
}
|
||||
|
||||
protected void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
}
|
313
source/java/org/alfresco/repo/importer/FileImporterTest.java
Normal file
313
source/java/org/alfresco/repo/importer/FileImporterTest.java
Normal file
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileFilter;
|
||||
import java.net.URL;
|
||||
import java.util.List;
|
||||
|
||||
import javax.transaction.HeuristicMixedException;
|
||||
import javax.transaction.HeuristicRollbackException;
|
||||
import javax.transaction.NotSupportedException;
|
||||
import javax.transaction.RollbackException;
|
||||
import javax.transaction.SystemException;
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.content.transform.AbstractContentTransformerTest;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.repository.ContentService;
|
||||
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.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchParameters;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.cmr.security.AuthenticationService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.alfresco.util.ApplicationContextHelper;
|
||||
import org.alfresco.util.TempFileProvider;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
||||
public class FileImporterTest extends TestCase
|
||||
{
|
||||
static ApplicationContext ctx = ApplicationContextHelper.getApplicationContext();
|
||||
private NodeService nodeService;
|
||||
private SearchService searchService;
|
||||
private DictionaryService dictionaryService;
|
||||
private ContentService contentService;
|
||||
private AuthenticationService authenticationService;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
private MimetypeService mimetypeService;
|
||||
private NamespaceService namespaceService;
|
||||
|
||||
private ServiceRegistry serviceRegistry;
|
||||
private NodeRef rootNodeRef;
|
||||
|
||||
private SearchService searcher;
|
||||
|
||||
public FileImporterTest()
|
||||
{
|
||||
super();
|
||||
}
|
||||
|
||||
public FileImporterTest(String arg0)
|
||||
{
|
||||
super(arg0);
|
||||
}
|
||||
|
||||
public void setUp()
|
||||
{
|
||||
serviceRegistry = (ServiceRegistry) ctx.getBean(ServiceRegistry.SERVICE_REGISTRY);
|
||||
|
||||
searcher = serviceRegistry.getSearchService();
|
||||
nodeService = serviceRegistry.getNodeService();
|
||||
searchService = serviceRegistry.getSearchService();
|
||||
dictionaryService = serviceRegistry.getDictionaryService();
|
||||
contentService = serviceRegistry.getContentService();
|
||||
authenticationService = (AuthenticationService) ctx.getBean("authenticationService");
|
||||
authenticationComponent = (AuthenticationComponent) ctx.getBean("authenticationComponent");
|
||||
mimetypeService = serviceRegistry.getMimetypeService();
|
||||
namespaceService = serviceRegistry.getNamespaceService();
|
||||
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||
rootNodeRef = nodeService.getRootNode(storeRef);
|
||||
}
|
||||
|
||||
private FileImporter createFileImporter()
|
||||
{
|
||||
FileImporterImpl fileImporter = new FileImporterImpl();
|
||||
fileImporter.setAuthenticationService(authenticationService);
|
||||
fileImporter.setContentService(contentService);
|
||||
fileImporter.setMimetypeService(mimetypeService);
|
||||
fileImporter.setNodeService(nodeService);
|
||||
fileImporter.setDictionaryService(dictionaryService);
|
||||
return fileImporter;
|
||||
}
|
||||
|
||||
public void testCreateFile() throws Exception
|
||||
{
|
||||
FileImporter fileImporter = createFileImporter();
|
||||
File file = AbstractContentTransformerTest.loadQuickTestFile("xml");
|
||||
fileImporter.loadFile(rootNodeRef, file);
|
||||
}
|
||||
|
||||
public void testLoadRootNonRecursive1()
|
||||
{
|
||||
FileImporter fileImporter = createFileImporter();
|
||||
URL url = this.getClass().getClassLoader().getResource("");
|
||||
File root = new File(url.getFile());
|
||||
int count = fileImporter.loadFile(rootNodeRef, new File(url.getFile()));
|
||||
assertEquals("Expected to load a single file", 1, count);
|
||||
}
|
||||
|
||||
public void testLoadRootNonRecursive2()
|
||||
{
|
||||
FileImporter fileImporter = createFileImporter();
|
||||
URL url = this.getClass().getClassLoader().getResource("");
|
||||
File root = new File(url.getFile());
|
||||
int count = fileImporter.loadFile(rootNodeRef, root, null, false);
|
||||
assertEquals("Expected to load a single file", 1, count);
|
||||
}
|
||||
|
||||
public void testLoadXMLFiles()
|
||||
{
|
||||
FileImporter fileImporter = createFileImporter();
|
||||
URL url = this.getClass().getClassLoader().getResource("");
|
||||
FileFilter filter = new XMLFileFilter();
|
||||
fileImporter.loadFile(rootNodeRef, new File(url.getFile()), filter, true);
|
||||
}
|
||||
|
||||
public void testLoadSourceTestResources()
|
||||
{
|
||||
FileImporter fileImporter = createFileImporter();
|
||||
URL url = this.getClass().getClassLoader().getResource("quick");
|
||||
FileFilter filter = new QuickFileFilter();
|
||||
fileImporter.loadFile(rootNodeRef, new File(url.getFile()), filter, true);
|
||||
}
|
||||
|
||||
private static class XMLFileFilter implements FileFilter
|
||||
{
|
||||
public boolean accept(File file)
|
||||
{
|
||||
return file.getName().endsWith(".xml");
|
||||
}
|
||||
}
|
||||
|
||||
private static class QuickFileFilter implements FileFilter
|
||||
{
|
||||
public boolean accept(File file)
|
||||
{
|
||||
return file.getName().startsWith("quick");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param args
|
||||
* <ol>
|
||||
* <li>StoreRef
|
||||
* <li>Store Path
|
||||
* <li>Directory
|
||||
* <li>Optional maximum time in seconds for node loading
|
||||
* </ol>
|
||||
* @throws SystemException
|
||||
* @throws NotSupportedException
|
||||
* @throws HeuristicRollbackException
|
||||
* @throws HeuristicMixedException
|
||||
* @throws RollbackException
|
||||
* @throws IllegalStateException
|
||||
* @throws SecurityException
|
||||
*/
|
||||
public static final void main(String[] args) throws Exception
|
||||
{
|
||||
|
||||
int exitCode = 0;
|
||||
|
||||
int grandTotal = 0;
|
||||
int count = 0;
|
||||
int target = Integer.parseInt(args[4]);
|
||||
while (count < target)
|
||||
{
|
||||
File directory = TempFileProvider.getTempDir();
|
||||
File[] files = directory.listFiles();
|
||||
System.out.println("Start temp file count = " + files.length);
|
||||
|
||||
count++;
|
||||
FileImporterTest test = new FileImporterTest();
|
||||
test.setUp();
|
||||
|
||||
test.authenticationComponent.setSystemUserAsCurrentUser();
|
||||
TransactionService transactionService = test.serviceRegistry.getTransactionService();
|
||||
UserTransaction tx = transactionService.getUserTransaction();
|
||||
tx.begin();
|
||||
|
||||
try
|
||||
{
|
||||
StoreRef spacesStore = new StoreRef(args[0]);
|
||||
if (!test.nodeService.exists(spacesStore))
|
||||
{
|
||||
test.nodeService.createStore(spacesStore.getProtocol(), spacesStore.getIdentifier());
|
||||
}
|
||||
|
||||
NodeRef storeRoot = test.nodeService.getRootNode(spacesStore);
|
||||
List<NodeRef> location = test.searchService.selectNodes(
|
||||
storeRoot,
|
||||
args[1],
|
||||
null,
|
||||
test.namespaceService,
|
||||
false);
|
||||
if (location.size() == 0)
|
||||
{
|
||||
throw new AlfrescoRuntimeException(
|
||||
"Root node not found, " +
|
||||
args[1] +
|
||||
" not found in store, " +
|
||||
storeRoot);
|
||||
}
|
||||
|
||||
long start = System.nanoTime();
|
||||
int importCount = test.createFileImporter().loadNamedFile(location.get(0), new File(args[2]), true, args[3]+count);
|
||||
grandTotal += importCount;
|
||||
long end = System.nanoTime();
|
||||
long first = end-start;
|
||||
System.out.println("Created in: " + ((end - start) / 1000000.0) + "ms");
|
||||
start = System.nanoTime();
|
||||
|
||||
tx.commit();
|
||||
end = System.nanoTime();
|
||||
long second = end-start;
|
||||
System.out.println("Committed in: " + ((end - start) / 1000000.0) + "ms");
|
||||
double total = ((first+second)/1000000.0);
|
||||
System.out.println("Grand Total: "+ grandTotal);
|
||||
System.out.println("Count: "+ count + "ms");
|
||||
System.out.println("Imported: " + importCount + " files or directories");
|
||||
System.out.println("Average: " + (importCount / (total / 1000.0)) + " files per second");
|
||||
|
||||
directory = TempFileProvider.getTempDir();
|
||||
files = directory.listFiles();
|
||||
System.out.println("End temp file count = " + files.length);
|
||||
|
||||
|
||||
tx = transactionService.getUserTransaction();
|
||||
tx.begin();
|
||||
SearchParameters sp = new SearchParameters();
|
||||
sp.setLanguage("lucene");
|
||||
sp.setQuery("ISNODE:T");
|
||||
sp.addStore(spacesStore);
|
||||
start = System.nanoTime();
|
||||
ResultSet rs = test.searchService.query(sp);
|
||||
end = System.nanoTime();
|
||||
System.out.println("Find all in: " + ((end - start) / 1000000.0) + "ms");
|
||||
System.out.println(" = "+rs.length() +"\n\n");
|
||||
rs.close();
|
||||
|
||||
sp = new SearchParameters();
|
||||
sp.setLanguage("lucene");
|
||||
sp.setQuery("TEXT:\"andy\"");
|
||||
sp.addStore(spacesStore);
|
||||
start = System.nanoTime();
|
||||
rs = test.searchService.query(sp);
|
||||
end = System.nanoTime();
|
||||
System.out.println("Find andy in: " + ((end - start) / 1000000.0) + "ms");
|
||||
System.out.println(" = "+rs.length() +"\n\n");
|
||||
rs.close();
|
||||
|
||||
sp = new SearchParameters();
|
||||
sp.setLanguage("lucene");
|
||||
sp.setQuery("TYPE:\"" + ContentModel.TYPE_CONTENT.toString() + "\"");
|
||||
sp.addStore(spacesStore);
|
||||
start = System.nanoTime();
|
||||
rs = test.searchService.query(sp);
|
||||
end = System.nanoTime();
|
||||
System.out.println("Find content in: " + ((end - start) / 1000000.0) + "ms");
|
||||
System.out.println(" = "+rs.length() +"\n\n");
|
||||
rs.close();
|
||||
|
||||
sp = new SearchParameters();
|
||||
sp.setLanguage("lucene");
|
||||
sp.setQuery("PATH:\"/*/*/*\"");
|
||||
sp.addStore(spacesStore);
|
||||
start = System.nanoTime();
|
||||
rs = test.searchService.query(sp);
|
||||
end = System.nanoTime();
|
||||
System.out.println("Find /*/*/* in: " + ((end - start) / 1000000.0) + "ms");
|
||||
System.out.println(" = "+rs.length() +"\n\n");
|
||||
rs.close();
|
||||
|
||||
tx.commit();
|
||||
|
||||
}
|
||||
catch (Throwable e)
|
||||
{
|
||||
tx.rollback();
|
||||
e.printStackTrace();
|
||||
exitCode = 1;
|
||||
}
|
||||
//System.exit(exitCode);
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
@@ -0,0 +1,15 @@
|
||||
package org.alfresco.repo.importer;
|
||||
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.xml.sax.ContentHandler;
|
||||
import org.xml.sax.ErrorHandler;
|
||||
|
||||
|
||||
public interface ImportContentHandler extends ContentHandler, ErrorHandler
|
||||
{
|
||||
public void setImporter(Importer importer);
|
||||
|
||||
public InputStream importStream(String content);
|
||||
|
||||
}
|
76
source/java/org/alfresco/repo/importer/ImportNode.java
Normal file
76
source/java/org/alfresco/repo/importer/ImportNode.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
|
||||
/**
|
||||
* Description of node to import.
|
||||
*
|
||||
* @author David Caruana
|
||||
*
|
||||
*/
|
||||
public interface ImportNode
|
||||
{
|
||||
/**
|
||||
* @return the parent context
|
||||
*/
|
||||
public ImportParent getParentContext();
|
||||
|
||||
/**
|
||||
* @return the type definition
|
||||
*/
|
||||
public TypeDefinition getTypeDefinition();
|
||||
|
||||
/**
|
||||
* @return the node ref
|
||||
*/
|
||||
public NodeRef getNodeRef();
|
||||
|
||||
/**
|
||||
* @return the child name
|
||||
*/
|
||||
public String getChildName();
|
||||
|
||||
/**
|
||||
* Gets all properties for the node
|
||||
*
|
||||
* @return the properties
|
||||
*/
|
||||
public Map<QName,Serializable> getProperties();
|
||||
|
||||
/**
|
||||
* Gets all property datatypes for the node
|
||||
*
|
||||
* @return the property datatypes
|
||||
*/
|
||||
public Map<QName,DataTypeDefinition> getPropertyDatatypes();
|
||||
|
||||
/**
|
||||
* @return the aspects of this node
|
||||
*/
|
||||
public Set<QName> getNodeAspects();
|
||||
|
||||
}
|
41
source/java/org/alfresco/repo/importer/ImportParent.java
Normal file
41
source/java/org/alfresco/repo/importer/ImportParent.java
Normal file
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
|
||||
/**
|
||||
* Description of parent for node to import.
|
||||
*
|
||||
* @author David Caruana
|
||||
*
|
||||
*/
|
||||
public interface ImportParent
|
||||
{
|
||||
/**
|
||||
* @return the parent ref
|
||||
*/
|
||||
/*package*/ NodeRef getParentRef();
|
||||
|
||||
/**
|
||||
* @return the child association type
|
||||
*/
|
||||
/*package*/ QName getAssocType();
|
||||
|
||||
}
|
76
source/java/org/alfresco/repo/importer/Importer.java
Normal file
76
source/java/org/alfresco/repo/importer/Importer.java
Normal file
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
/**
|
||||
* The Importer interface encapusulates the strategy for importing
|
||||
* a node into the Repository.
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public interface Importer
|
||||
{
|
||||
/**
|
||||
* @return the root node to import into
|
||||
*/
|
||||
public NodeRef getRootRef();
|
||||
|
||||
/**
|
||||
* @return the root child association type to import under
|
||||
*/
|
||||
public QName getRootAssocType();
|
||||
|
||||
/**
|
||||
* Signal start of import
|
||||
*/
|
||||
public void start();
|
||||
|
||||
/**
|
||||
* Signal end of import
|
||||
*/
|
||||
public void end();
|
||||
|
||||
/**
|
||||
* Signal import error
|
||||
*/
|
||||
public void error(Throwable e);
|
||||
|
||||
/**
|
||||
* Import meta-data
|
||||
*/
|
||||
public void importMetaData(Map<QName, String> properties);
|
||||
|
||||
/**
|
||||
* Import a node
|
||||
*
|
||||
* @param node the node description
|
||||
* @return the node ref of the imported node
|
||||
*/
|
||||
public NodeRef importNode(ImportNode node);
|
||||
|
||||
/**
|
||||
* Signal completion of node import
|
||||
*
|
||||
* @param nodeRef the node ref of the imported node
|
||||
*/
|
||||
public void childrenImported(NodeRef nodeRef);
|
||||
}
|
507
source/java/org/alfresco/repo/importer/ImporterBootstrap.java
Normal file
507
source/java/org/alfresco/repo/importer/ImporterBootstrap.java
Normal file
@@ -0,0 +1,507 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.io.Serializable;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
import java.util.ResourceBundle;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.transaction.UserTransaction;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
import org.alfresco.i18n.I18NUtil;
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
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.ImporterBinding;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
import org.alfresco.service.cmr.view.ImporterProgress;
|
||||
import org.alfresco.service.cmr.view.ImporterService;
|
||||
import org.alfresco.service.cmr.view.Location;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.transaction.TransactionService;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Bootstrap Repository store.
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class ImporterBootstrap
|
||||
{
|
||||
// View Properties (used in setBootstrapViews)
|
||||
public static final String VIEW_PATH_PROPERTY = "path";
|
||||
public static final String VIEW_CHILDASSOCTYPE_PROPERTY = "childAssocType";
|
||||
public static final String VIEW_MESSAGES_PROPERTY = "messages";
|
||||
public static final String VIEW_LOCATION_VIEW = "location";
|
||||
public static final String VIEW_ENCODING = "encoding";
|
||||
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(ImporterBootstrap.class);
|
||||
|
||||
// Dependencies
|
||||
private boolean allowWrite = true;
|
||||
private TransactionService transactionService;
|
||||
private NamespaceService namespaceService;
|
||||
private NodeService nodeService;
|
||||
private ImporterService importerService;
|
||||
private List<Properties> bootstrapViews;
|
||||
private StoreRef storeRef = null;
|
||||
private List<String> mustNotExistStoreUrls = null;
|
||||
private Properties configuration = null;
|
||||
private String strLocale = null;
|
||||
private Locale locale = null;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
|
||||
/**
|
||||
* Set whether we write or not
|
||||
*
|
||||
* @param write true (default) if the import must go ahead, otherwise no import will occur
|
||||
*/
|
||||
public void setAllowWrite(boolean write)
|
||||
{
|
||||
this.allowWrite = write;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Transaction Service
|
||||
*
|
||||
* @param userTransaction the transaction service
|
||||
*/
|
||||
public void setTransactionService(TransactionService transactionService)
|
||||
{
|
||||
this.transactionService = transactionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the namespace service
|
||||
*
|
||||
* @param namespaceService the namespace service
|
||||
*/
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the node service
|
||||
*
|
||||
* @param nodeService the node service
|
||||
*/
|
||||
public void setNodeService(NodeService nodeService)
|
||||
{
|
||||
this.nodeService = nodeService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the importer service
|
||||
*
|
||||
* @param importerService the importer service
|
||||
*/
|
||||
public void setImporterService(ImporterService importerService)
|
||||
{
|
||||
this.importerService = importerService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the authentication component
|
||||
*
|
||||
* @param authenticationComponent
|
||||
*/
|
||||
public void setAuthenticationComponent(AuthenticationComponent authenticationComponent)
|
||||
{
|
||||
this.authenticationComponent = authenticationComponent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the bootstrap views
|
||||
*
|
||||
* @param bootstrapViews
|
||||
*/
|
||||
public void setBootstrapViews(List<Properties> bootstrapViews)
|
||||
{
|
||||
this.bootstrapViews = bootstrapViews;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Store Ref to bootstrap into
|
||||
*
|
||||
* @param storeUrl
|
||||
*/
|
||||
public void setStoreUrl(String storeUrl)
|
||||
{
|
||||
this.storeRef = new StoreRef(storeUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* If any of the store urls exist, the bootstrap does not take place
|
||||
*
|
||||
* @param storeUrls the list of store urls to check
|
||||
*/
|
||||
public void setMustNotExistStoreUrls(List<String> storeUrls)
|
||||
{
|
||||
this.mustNotExistStoreUrls = storeUrls;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Store Reference
|
||||
*
|
||||
* @return store reference
|
||||
*/
|
||||
public StoreRef getStoreRef()
|
||||
{
|
||||
return this.storeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Configuration values for binding place holders
|
||||
*
|
||||
* @param configuration
|
||||
*/
|
||||
public void setConfiguration(Properties configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Configuration values for binding place holders
|
||||
*
|
||||
* @return configuration
|
||||
*/
|
||||
public Properties getConfiguration()
|
||||
{
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Locale
|
||||
*
|
||||
* @param locale (language_country_variant)
|
||||
*/
|
||||
public void setLocale(String locale)
|
||||
{
|
||||
// construct locale
|
||||
StringTokenizer t = new StringTokenizer(locale, "_");
|
||||
int tokens = t.countTokens();
|
||||
if (tokens == 1)
|
||||
{
|
||||
this.locale = new Locale(locale);
|
||||
}
|
||||
else if (tokens == 2)
|
||||
{
|
||||
this.locale = new Locale(t.nextToken(), t.nextToken());
|
||||
}
|
||||
else if (tokens == 3)
|
||||
{
|
||||
this.locale = new Locale(t.nextToken(), t.nextToken(), t.nextToken());
|
||||
}
|
||||
|
||||
// store original
|
||||
strLocale = locale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Locale
|
||||
*
|
||||
* @return locale
|
||||
*/
|
||||
public String getLocale()
|
||||
{
|
||||
return strLocale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boostrap the Repository
|
||||
*/
|
||||
public void bootstrap()
|
||||
{
|
||||
if (transactionService == null)
|
||||
{
|
||||
throw new ImporterException("Transaction Service must be provided");
|
||||
}
|
||||
if (namespaceService == null)
|
||||
{
|
||||
throw new ImporterException("Namespace Service must be provided");
|
||||
}
|
||||
if (nodeService == null)
|
||||
{
|
||||
throw new ImporterException("Node Service must be provided");
|
||||
}
|
||||
if (importerService == null)
|
||||
{
|
||||
throw new ImporterException("Importer Service must be provided");
|
||||
}
|
||||
if (storeRef == null)
|
||||
{
|
||||
throw new ImporterException("Store URL must be provided");
|
||||
}
|
||||
|
||||
UserTransaction userTransaction = transactionService.getUserTransaction();
|
||||
authenticationComponent.setCurrentUser(authenticationComponent.getSystemUserName());
|
||||
|
||||
try
|
||||
{
|
||||
userTransaction.begin();
|
||||
|
||||
// check the repository exists, create if it doesn't
|
||||
if (!performBootstrap())
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Store exists - bootstrap ignored: " + storeRef);
|
||||
|
||||
userTransaction.rollback();
|
||||
}
|
||||
else if (!allowWrite)
|
||||
{
|
||||
// we're in read-only node
|
||||
logger.warn("Store does not exist, but mode is read-only: " + storeRef);
|
||||
userTransaction.rollback();
|
||||
}
|
||||
else
|
||||
{
|
||||
// create the store
|
||||
storeRef = nodeService.createStore(storeRef.getProtocol(), storeRef.getIdentifier());
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Created store: " + storeRef);
|
||||
|
||||
// bootstrap the store contents
|
||||
if (bootstrapViews != null)
|
||||
{
|
||||
for (Properties bootstrapView : bootstrapViews)
|
||||
{
|
||||
// Create input stream reader onto view file
|
||||
String view = bootstrapView.getProperty(VIEW_LOCATION_VIEW);
|
||||
if (view == null || view.length() == 0)
|
||||
{
|
||||
throw new ImporterException("View file location must be provided");
|
||||
}
|
||||
String encoding = bootstrapView.getProperty(VIEW_ENCODING);
|
||||
Reader viewReader = getReader(view, encoding);
|
||||
|
||||
// Create import location
|
||||
Location importLocation = new Location(storeRef);
|
||||
String path = bootstrapView.getProperty(VIEW_PATH_PROPERTY);
|
||||
if (path != null && path.length() > 0)
|
||||
{
|
||||
importLocation.setPath(path);
|
||||
}
|
||||
String childAssocType = bootstrapView.getProperty(VIEW_CHILDASSOCTYPE_PROPERTY);
|
||||
if (childAssocType != null && childAssocType.length() > 0)
|
||||
{
|
||||
importLocation.setChildAssocType(QName.createQName(childAssocType, namespaceService));
|
||||
}
|
||||
|
||||
// Create import binding
|
||||
BootstrapBinding binding = new BootstrapBinding();
|
||||
binding.setConfiguration(configuration);
|
||||
String messages = bootstrapView.getProperty(VIEW_MESSAGES_PROPERTY);
|
||||
if (messages != null && messages.length() > 0)
|
||||
{
|
||||
Locale bindingLocale = (locale == null) ? I18NUtil.getLocale() : locale;
|
||||
ResourceBundle bundle = ResourceBundle.getBundle(messages, bindingLocale);
|
||||
binding.setResourceBundle(bundle);
|
||||
}
|
||||
|
||||
// Now import...
|
||||
importerService.importView(viewReader, importLocation, binding, new BootstrapProgress());
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a Reader onto an XML view
|
||||
*
|
||||
* @param view the view location
|
||||
* @param encoding the encoding of the view
|
||||
* @return the reader
|
||||
*/
|
||||
private Reader getReader(String view, String encoding)
|
||||
{
|
||||
// Get Input Stream
|
||||
InputStream viewStream = getClass().getClassLoader().getResourceAsStream(view);
|
||||
if (viewStream == null)
|
||||
{
|
||||
throw new ImporterException("Could not find view file " + view);
|
||||
}
|
||||
|
||||
// Wrap in buffered reader
|
||||
try
|
||||
{
|
||||
InputStreamReader inputReader = (encoding == null) ? new InputStreamReader(viewStream) : new InputStreamReader(viewStream, encoding);
|
||||
BufferedReader reader = new BufferedReader(inputReader);
|
||||
return reader;
|
||||
}
|
||||
catch (UnsupportedEncodingException e)
|
||||
{
|
||||
throw new ImporterException("Could not create reader for view " + view + " as encoding " + encoding + " is not supported");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap Binding
|
||||
*/
|
||||
private class BootstrapBinding implements ImporterBinding
|
||||
{
|
||||
private Properties configuration = null;
|
||||
private ResourceBundle resourceBundle = null;
|
||||
|
||||
/**
|
||||
* Set Import Configuration
|
||||
*
|
||||
* @param configuration
|
||||
*/
|
||||
public void setConfiguration(Properties configuration)
|
||||
{
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Import Configuration
|
||||
*
|
||||
* @return configuration
|
||||
*/
|
||||
public Properties getConfiguration()
|
||||
{
|
||||
return this.configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Resource Bundle
|
||||
*
|
||||
* @param resourceBundle
|
||||
*/
|
||||
public void setResourceBundle(ResourceBundle resourceBundle)
|
||||
{
|
||||
this.resourceBundle = resourceBundle;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.service.cmr.view.ImporterBinding#getValue(java.lang.String)
|
||||
*/
|
||||
public String getValue(String key)
|
||||
{
|
||||
String value = null;
|
||||
if (configuration != null)
|
||||
{
|
||||
value = configuration.getProperty(key);
|
||||
}
|
||||
if (value == null && resourceBundle != null)
|
||||
{
|
||||
value = resourceBundle.getString(key);
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bootstrap Progress (debug logging)
|
||||
*/
|
||||
private class BootstrapProgress implements ImporterProgress
|
||||
{
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.Progress#nodeCreated(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, org.alfresco.service.namespace.QName)
|
||||
*/
|
||||
public void nodeCreated(NodeRef nodeRef, NodeRef parentRef, QName assocName, QName childName)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Created node " + nodeRef + " (child name: " + childName + ") within parent " + parentRef + " (association type: " + assocName + ")");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.Progress#contentCreated(org.alfresco.service.cmr.repository.NodeRef, java.lang.String)
|
||||
*/
|
||||
public void contentCreated(NodeRef nodeRef, String sourceUrl)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Imported content from " + sourceUrl + " into node " + nodeRef);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.Progress#propertySet(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName, java.io.Serializable)
|
||||
*/
|
||||
public void propertySet(NodeRef nodeRef, QName property, Serializable value)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Property " + property + " set to value " + value + " on node " + nodeRef);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.Progress#aspectAdded(org.alfresco.service.cmr.repository.NodeRef, org.alfresco.service.namespace.QName)
|
||||
*/
|
||||
public void aspectAdded(NodeRef nodeRef, QName aspect)
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Added aspect " + aspect + " to node " + nodeRef);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if bootstrap should take place
|
||||
*
|
||||
* @return true => yes, it should
|
||||
*/
|
||||
private boolean performBootstrap()
|
||||
{
|
||||
if (nodeService.exists(storeRef))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mustNotExistStoreUrls != null)
|
||||
{
|
||||
for (String storeUrl : mustNotExistStoreUrls)
|
||||
{
|
||||
StoreRef storeRef = new StoreRef(storeUrl);
|
||||
if (nodeService.exists(storeRef))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
1008
source/java/org/alfresco/repo/importer/ImporterComponent.java
Normal file
1008
source/java/org/alfresco/repo/importer/ImporterComponent.java
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.alfresco.repo.security.authentication.AuthenticationComponent;
|
||||
import org.alfresco.service.ServiceRegistry;
|
||||
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.ImporterProgress;
|
||||
import org.alfresco.service.cmr.view.ImporterService;
|
||||
import org.alfresco.service.cmr.view.Location;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.util.BaseSpringTest;
|
||||
import org.alfresco.util.debug.NodeStoreInspector;
|
||||
|
||||
|
||||
public class ImporterComponentTest extends BaseSpringTest
|
||||
{
|
||||
private ImporterService importerService;
|
||||
private ImporterBootstrap importerBootstrap;
|
||||
private NodeService nodeService;
|
||||
private StoreRef storeRef;
|
||||
private AuthenticationComponent authenticationComponent;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onSetUpInTransaction() throws Exception
|
||||
{
|
||||
nodeService = (NodeService)applicationContext.getBean(ServiceRegistry.NODE_SERVICE.getLocalName());
|
||||
importerService = (ImporterService)applicationContext.getBean(ServiceRegistry.IMPORTER_SERVICE.getLocalName());
|
||||
|
||||
importerBootstrap = (ImporterBootstrap)applicationContext.getBean("importerBootstrap");
|
||||
|
||||
this.authenticationComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent");
|
||||
|
||||
this.authenticationComponent.setSystemUserAsCurrentUser();
|
||||
|
||||
// Create the store
|
||||
this.storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onTearDownInTransaction()
|
||||
{
|
||||
authenticationComponent.clearCurrentSecurityContext();
|
||||
super.onTearDownInTransaction();
|
||||
}
|
||||
|
||||
public void testImport()
|
||||
throws Exception
|
||||
{
|
||||
InputStream test = getClass().getClassLoader().getResourceAsStream("org/alfresco/repo/importer/importercomponent_test.xml");
|
||||
InputStreamReader testReader = new InputStreamReader(test, "UTF-8");
|
||||
TestProgress testProgress = new TestProgress();
|
||||
Location location = new Location(storeRef);
|
||||
importerService.importView(testReader, location, null, testProgress);
|
||||
System.out.println(NodeStoreInspector.dumpNodeStore(nodeService, storeRef));
|
||||
}
|
||||
|
||||
|
||||
public void testBootstrap()
|
||||
{
|
||||
StoreRef bootstrapStoreRef = new StoreRef(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
|
||||
importerBootstrap.setStoreUrl(bootstrapStoreRef.toString());
|
||||
importerBootstrap.bootstrap();
|
||||
authenticationComponent.setSystemUserAsCurrentUser();
|
||||
System.out.println(NodeStoreInspector.dumpNodeStore(nodeService, bootstrapStoreRef));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static class TestProgress implements ImporterProgress
|
||||
{
|
||||
public void nodeCreated(NodeRef nodeRef, NodeRef parentRef, QName assocName, QName childName)
|
||||
{
|
||||
System.out.println("TestProgress: created node " + nodeRef + " within parent " + parentRef + " named " + childName +
|
||||
" (association " + assocName + ")");
|
||||
}
|
||||
|
||||
public void contentCreated(NodeRef nodeRef, String sourceUrl)
|
||||
{
|
||||
System.out.println("TestProgress: created content " + nodeRef + " from url " + sourceUrl);
|
||||
}
|
||||
|
||||
public void propertySet(NodeRef nodeRef, QName property, Serializable value)
|
||||
{
|
||||
System.out.println("TestProgress: set property " + property + " on node " + nodeRef + " to value " + value);
|
||||
}
|
||||
|
||||
public void aspectAdded(NodeRef nodeRef, QName aspect)
|
||||
{
|
||||
System.out.println("TestProgress: added aspect " + aspect + " to node ");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
42
source/java/org/alfresco/repo/importer/Parser.java
Normal file
42
source/java/org/alfresco/repo/importer/Parser.java
Normal file
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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.importer;
|
||||
|
||||
import java.io.Reader;
|
||||
|
||||
|
||||
/**
|
||||
* This interface represents the contract between the importer service and a
|
||||
* parser (which is responsible for parsing the input stream and extracting
|
||||
* node descriptions).
|
||||
*
|
||||
* The parser interacts with the passed importer to import nodes into the
|
||||
* Repository.
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public interface Parser
|
||||
{
|
||||
/**
|
||||
* Parse nodes from specified input stream and import via the provided importer
|
||||
*
|
||||
* @param viewReader
|
||||
* @param importer
|
||||
*/
|
||||
public void parse(Reader viewReader, Importer importer);
|
||||
|
||||
}
|
@@ -0,0 +1,74 @@
|
||||
|
||||
<!-- Note: The import will be performed relative to a specific path specified at import
|
||||
time -->
|
||||
|
||||
<view:view xmlns:view="http://www.alfresco.org/view/repository/1.0"
|
||||
xmlns:cm="http://www.alfresco.org/model/content/1.0"
|
||||
xmlns="">
|
||||
|
||||
<view:metadata>
|
||||
<view:exportBy>unknown</view:exportBy>
|
||||
<view:exportDate>2005-10-19T19:18:01.387+01:00</view:exportDate>
|
||||
<view:exporterVersion>1.0.0 (rc1b)</view:exporterVersion>
|
||||
<view:exportOf>/system</view:exportOf>
|
||||
</view:metadata>
|
||||
|
||||
<cm:systemfolder view:childName="system">
|
||||
<cm:name>System</cm:name>
|
||||
<cm:orderedchildren>true</cm:orderedchildren>
|
||||
<cm:contains>
|
||||
|
||||
<cm:systemfolder view:childName="cm:people folder">
|
||||
<view:aspects>
|
||||
<cm:auditable/>
|
||||
</view:aspects>
|
||||
<view:properties>
|
||||
<cm:name>`¬¦!£$%^&()-_=+tnu0000[]{};'#@~,</cm:name>
|
||||
<cm:creator>testuser</cm:creator>
|
||||
<cm:modifier>testuser</cm:modifier>
|
||||
<cm:notinmodel>
|
||||
<view:value view:datatype="d:text">dfsdfsdf</view:value>
|
||||
</cm:notinmodel>
|
||||
</view:properties>
|
||||
<view:associations>
|
||||
<cm:contains>
|
||||
<cm:person view:childName="cm:fredb">
|
||||
<view:aspects/>
|
||||
<view:properties>
|
||||
<cm:userName>${username}</cm:userName>
|
||||
<cm:firstName>Fred</cm:firstName>
|
||||
<cm:lastName>Bloggs</cm:lastName>
|
||||
<cm:homeFolder>../../cm:people_x0020_folder</cm:homeFolder>
|
||||
</view:properties>
|
||||
</cm:person>
|
||||
</cm:contains>
|
||||
</view:associations>
|
||||
</cm:systemfolder>
|
||||
|
||||
<!-- note: if no explicit view:childName, take from name if one exists -->
|
||||
<cm:cmobject>
|
||||
<cm:translatable/>
|
||||
<cm:generalclassifiable/>
|
||||
<cm:name>Some Content</cm:name>
|
||||
<cm:categories>
|
||||
<view:value>../cm:people_x0020_folder</view:value>
|
||||
<view:value>../cm:people_x0020_folder</view:value>
|
||||
</cm:categories>
|
||||
<cm:translations view:idref="xyz"/>
|
||||
</cm:cmobject>
|
||||
|
||||
<cm:cmobject view:id="xyz">
|
||||
<cm:name>Translation of Some Content</cm:name>
|
||||
<cm:creator></cm:creator>
|
||||
</cm:cmobject>
|
||||
|
||||
<cm:content>
|
||||
<cm:name>Real content</cm:name>
|
||||
<cm:content>contentUrl=classpath:org/alfresco/repo/importer/importercomponent_testfile.txt|mimetype=text|size=|encoding=</cm:content>
|
||||
</cm:content>
|
||||
|
||||
</cm:contains>
|
||||
|
||||
</cm:systemfolder>
|
||||
|
||||
</view:view>
|
@@ -0,0 +1 @@
|
||||
A test import file
|
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.importer.view;
|
||||
|
||||
import org.alfresco.repo.importer.Importer;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
|
||||
/**
|
||||
* Maintains state about the currently imported element.
|
||||
*
|
||||
* @author David Caruana
|
||||
*
|
||||
*/
|
||||
public class ElementContext
|
||||
{
|
||||
// Dictionary Service
|
||||
private DictionaryService dictionary;
|
||||
|
||||
// Element Name
|
||||
private QName elementName;
|
||||
|
||||
// Importer
|
||||
private Importer importer;
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param dictionary
|
||||
* @param elementName
|
||||
* @param progress
|
||||
*/
|
||||
public ElementContext(QName elementName, DictionaryService dictionary, Importer importer)
|
||||
{
|
||||
this.elementName = elementName;
|
||||
this.dictionary = dictionary;
|
||||
this.importer = importer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the element name
|
||||
*/
|
||||
public QName getElementName()
|
||||
{
|
||||
return elementName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the dictionary service
|
||||
*/
|
||||
public DictionaryService getDictionaryService()
|
||||
{
|
||||
return dictionary;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the importer
|
||||
*/
|
||||
public Importer getImporter()
|
||||
{
|
||||
return importer;
|
||||
}
|
||||
}
|
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* 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.importer.view;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
|
||||
/**
|
||||
* Represents View Meta Data
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class MetaDataContext extends ElementContext
|
||||
{
|
||||
|
||||
private Map<QName, String> properties = new HashMap<QName, String>();
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param elementName
|
||||
* @param dictionary
|
||||
* @param importer
|
||||
*/
|
||||
public MetaDataContext(QName elementName, ElementContext context)
|
||||
{
|
||||
super(elementName, context.getDictionaryService(), context.getImporter());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set meta-data property
|
||||
*
|
||||
* @param property property name
|
||||
* @param value property value
|
||||
*/
|
||||
public void setProperty(QName property, String value)
|
||||
{
|
||||
properties.put(property, value);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get meta-data property
|
||||
*
|
||||
* @param property property name
|
||||
* @return property value
|
||||
*/
|
||||
public String getProperty(QName property)
|
||||
{
|
||||
return properties.get(property);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all meta-data properties
|
||||
*
|
||||
* @return all meta-data properties
|
||||
*/
|
||||
public Map<QName, String> getProperties()
|
||||
{
|
||||
return properties;
|
||||
}
|
||||
|
||||
}
|
341
source/java/org/alfresco/repo/importer/view/NodeContext.java
Normal file
341
source/java/org/alfresco/repo/importer/view/NodeContext.java
Normal file
@@ -0,0 +1,341 @@
|
||||
/*
|
||||
* 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.importer.view;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.repo.importer.ImportNode;
|
||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.AssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ClassDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DataTypeDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
|
||||
/**
|
||||
* Maintains state about the currently imported node.
|
||||
*
|
||||
* @author David Caruana
|
||||
*
|
||||
*/
|
||||
public class NodeContext extends ElementContext
|
||||
implements ImportNode
|
||||
{
|
||||
private ParentContext parentContext;
|
||||
private NodeRef nodeRef;
|
||||
private TypeDefinition typeDef;
|
||||
private String childName;
|
||||
private Map<QName, AspectDefinition> nodeAspects = new HashMap<QName, AspectDefinition>();
|
||||
private Map<QName, ChildAssociationDefinition> nodeChildAssocs = new HashMap<QName, ChildAssociationDefinition>();
|
||||
private Map<QName, Serializable> nodeProperties = new HashMap<QName, Serializable>();
|
||||
private Map<QName, DataTypeDefinition> propertyDatatypes = new HashMap<QName, DataTypeDefinition>();
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param elementName
|
||||
* @param parentContext
|
||||
* @param typeDef
|
||||
*/
|
||||
public NodeContext(QName elementName, ParentContext parentContext, TypeDefinition typeDef)
|
||||
{
|
||||
super(elementName, parentContext.getDictionaryService(), parentContext.getImporter());
|
||||
this.parentContext = parentContext;
|
||||
this.typeDef = typeDef;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportNode#getParentContext()
|
||||
*/
|
||||
public ParentContext getParentContext()
|
||||
{
|
||||
return parentContext;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportNode#getTypeDefinition()
|
||||
*/
|
||||
public TypeDefinition getTypeDefinition()
|
||||
{
|
||||
return typeDef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set Type Definition
|
||||
*
|
||||
* @param typeDef
|
||||
*/
|
||||
public void setTypeDefinition(TypeDefinition typeDef)
|
||||
{
|
||||
this.typeDef = typeDef;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportNode#getNodeRef()
|
||||
*/
|
||||
public NodeRef getNodeRef()
|
||||
{
|
||||
return nodeRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param nodeRef the node ref
|
||||
*/
|
||||
public void setNodeRef(NodeRef nodeRef)
|
||||
{
|
||||
this.nodeRef = nodeRef;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportNode#getChildName()
|
||||
*/
|
||||
public String getChildName()
|
||||
{
|
||||
return childName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param childName the child name
|
||||
*/
|
||||
public void setChildName(String childName)
|
||||
{
|
||||
this.childName = childName;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a collection property to the node
|
||||
*
|
||||
* @param property
|
||||
*/
|
||||
public void addPropertyCollection(QName property)
|
||||
{
|
||||
// Do not import properties of sys:referenceable or cm:versionable
|
||||
// TODO: Make this configurable...
|
||||
PropertyDefinition propDef = getDictionaryService().getProperty(property);
|
||||
ClassDefinition classDef = (propDef == null) ? null : propDef.getContainerClass();
|
||||
if (classDef != null)
|
||||
{
|
||||
if (classDef.getName().equals(ContentModel.ASPECT_REFERENCEABLE) ||
|
||||
classDef.getName().equals(ContentModel.ASPECT_VERSIONABLE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// create collection and assign to property
|
||||
List<Serializable>values = new ArrayList<Serializable>();
|
||||
nodeProperties.put(property, (Serializable)values);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a property to the node
|
||||
*
|
||||
* @param property the property name
|
||||
* @param value the property value
|
||||
*/
|
||||
public void addProperty(QName property, String value)
|
||||
{
|
||||
// Do not import properties of sys:referenceable or cm:versionable
|
||||
// TODO: Make this configurable...
|
||||
PropertyDefinition propDef = getDictionaryService().getProperty(property);
|
||||
ClassDefinition classDef = (propDef == null) ? null : propDef.getContainerClass();
|
||||
if (classDef != null)
|
||||
{
|
||||
if (classDef.getName().equals(ContentModel.ASPECT_REFERENCEABLE) ||
|
||||
classDef.getName().equals(ContentModel.ASPECT_VERSIONABLE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Handle single / multi-valued cases
|
||||
Serializable newValue = value;
|
||||
Serializable existingValue = nodeProperties.get(property);
|
||||
if (existingValue != null)
|
||||
{
|
||||
if (existingValue instanceof Collection)
|
||||
{
|
||||
// add to existing collection of values
|
||||
((Collection<Serializable>)existingValue).add(value);
|
||||
newValue = existingValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
// convert single to multi-valued
|
||||
List<Serializable>values = new ArrayList<Serializable>();
|
||||
values.add((String)existingValue);
|
||||
values.add(value);
|
||||
newValue = (Serializable)values;
|
||||
}
|
||||
}
|
||||
nodeProperties.put(property, newValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a property datatype to the node
|
||||
*
|
||||
* @param property property name
|
||||
* @param datatype property datatype
|
||||
*/
|
||||
public void addDatatype(QName property, DataTypeDefinition datatype)
|
||||
{
|
||||
propertyDatatypes.put(property, datatype);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportNode#getPropertyDatatypes()
|
||||
*/
|
||||
public Map<QName, DataTypeDefinition> getPropertyDatatypes()
|
||||
{
|
||||
return propertyDatatypes;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportNode#getProperties()
|
||||
*/
|
||||
public Map<QName, Serializable> getProperties()
|
||||
{
|
||||
return nodeProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an aspect to the node
|
||||
*
|
||||
* @param aspect the aspect
|
||||
*/
|
||||
public void addAspect(AspectDefinition aspect)
|
||||
{
|
||||
nodeAspects.put(aspect.getName(), aspect);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportNode#getNodeAspects()
|
||||
*/
|
||||
public Set<QName> getNodeAspects()
|
||||
{
|
||||
return nodeAspects.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the type of definition (aspect, property, association) from the
|
||||
* specified name
|
||||
*
|
||||
* @param defName
|
||||
* @return the dictionary definition
|
||||
*/
|
||||
public Object determineDefinition(QName defName)
|
||||
{
|
||||
Object def = determineAspect(defName);
|
||||
if (def == null)
|
||||
{
|
||||
def = determineProperty(defName);
|
||||
if (def == null)
|
||||
{
|
||||
def = determineAssociation(defName);
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if name referes to an aspect
|
||||
*
|
||||
* @param defName
|
||||
* @return
|
||||
*/
|
||||
public AspectDefinition determineAspect(QName defName)
|
||||
{
|
||||
AspectDefinition def = null;
|
||||
if (nodeAspects.containsKey(defName) == false)
|
||||
{
|
||||
def = getDictionaryService().getAspect(defName);
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if name refers to a property
|
||||
*
|
||||
* @param defName
|
||||
* @return
|
||||
*/
|
||||
public PropertyDefinition determineProperty(QName defName)
|
||||
{
|
||||
PropertyDefinition def = null;
|
||||
if (nodeProperties.containsKey(defName) == false)
|
||||
{
|
||||
def = getDictionaryService().getProperty(typeDef.getName(), defName);
|
||||
if (def == null)
|
||||
{
|
||||
Set<AspectDefinition> allAspects = new HashSet<AspectDefinition>();
|
||||
allAspects.addAll(typeDef.getDefaultAspects());
|
||||
allAspects.addAll(nodeAspects.values());
|
||||
for (AspectDefinition aspectDef : allAspects)
|
||||
{
|
||||
def = getDictionaryService().getProperty(aspectDef.getName(), defName);
|
||||
if (def != null)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if name referes to an association
|
||||
*
|
||||
* @param defName
|
||||
* @return
|
||||
*/
|
||||
public AssociationDefinition determineAssociation(QName defName)
|
||||
{
|
||||
AssociationDefinition def = null;
|
||||
if (nodeChildAssocs.containsKey(defName) == false)
|
||||
{
|
||||
def = getDictionaryService().getAssociation(defName);
|
||||
}
|
||||
return def;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "NodeContext[childName=" + getChildName() + ",type=" + (typeDef == null ? "null" : typeDef.getName()) + ",nodeRef=" + nodeRef +
|
||||
",aspects=" + nodeAspects.values() + ",parentContext=" + parentContext.toString() + "]";
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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.importer.view;
|
||||
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
|
||||
/**
|
||||
* Represents Property Context
|
||||
*
|
||||
* @author David Caruana
|
||||
*
|
||||
*/
|
||||
public class NodeItemContext extends ElementContext
|
||||
{
|
||||
private NodeContext nodeContext;
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param elementName
|
||||
* @param dictionary
|
||||
* @param importer
|
||||
*/
|
||||
public NodeItemContext(QName elementName, NodeContext nodeContext)
|
||||
{
|
||||
super(elementName, nodeContext.getDictionaryService(), nodeContext.getImporter());
|
||||
this.nodeContext = nodeContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Node Context
|
||||
*/
|
||||
public NodeContext getNodeContext()
|
||||
{
|
||||
return nodeContext;
|
||||
}
|
||||
}
|
131
source/java/org/alfresco/repo/importer/view/ParentContext.java
Normal file
131
source/java/org/alfresco/repo/importer/view/ParentContext.java
Normal file
@@ -0,0 +1,131 @@
|
||||
/*
|
||||
* 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.importer.view;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.alfresco.repo.importer.ImportParent;
|
||||
import org.alfresco.repo.importer.Importer;
|
||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
|
||||
|
||||
/**
|
||||
* Maintains state about the parent context of the node being imported.
|
||||
*
|
||||
* @author David Caruana
|
||||
*
|
||||
*/
|
||||
public class ParentContext extends ElementContext
|
||||
implements ImportParent
|
||||
{
|
||||
private NodeRef parentRef;
|
||||
private QName assocType;
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param dictionary
|
||||
* @param configuration
|
||||
* @param progress
|
||||
* @param elementName
|
||||
* @param parentRef
|
||||
* @param assocType
|
||||
*/
|
||||
public ParentContext(QName elementName, DictionaryService dictionary, Importer importer)
|
||||
{
|
||||
super(elementName, dictionary, importer);
|
||||
parentRef = importer.getRootRef();
|
||||
assocType = importer.getRootAssocType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct (with unknown child association)
|
||||
*
|
||||
* @param elementName
|
||||
* @param parent
|
||||
*/
|
||||
public ParentContext(QName elementName, NodeContext parent)
|
||||
{
|
||||
super(elementName, parent.getDictionaryService(), parent.getImporter());
|
||||
parentRef = parent.getNodeRef();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*
|
||||
* @param elementName
|
||||
* @param parent
|
||||
* @param childDef
|
||||
*/
|
||||
public ParentContext(QName elementName, NodeContext parent, ChildAssociationDefinition childDef)
|
||||
{
|
||||
this(elementName, parent);
|
||||
|
||||
// Ensure association is valid for node
|
||||
Set<QName> allAspects = new HashSet<QName>();
|
||||
for (AspectDefinition typeAspect : parent.getTypeDefinition().getDefaultAspects())
|
||||
{
|
||||
allAspects.add(typeAspect.getName());
|
||||
}
|
||||
allAspects.addAll(parent.getNodeAspects());
|
||||
TypeDefinition anonymousType = getDictionaryService().getAnonymousType(parent.getTypeDefinition().getName(), allAspects);
|
||||
Map<QName, ChildAssociationDefinition> nodeAssociations = anonymousType.getChildAssociations();
|
||||
if (nodeAssociations.containsKey(childDef.getName()) == false)
|
||||
{
|
||||
throw new ImporterException("Association " + childDef.getName() + " is not valid for node " + parent.getTypeDefinition().getName());
|
||||
}
|
||||
|
||||
parentRef = parent.getNodeRef();
|
||||
assocType = childDef.getName();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportParent#getParentRef()
|
||||
*/
|
||||
public NodeRef getParentRef()
|
||||
{
|
||||
return parentRef;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.ImportParent#getAssocType()
|
||||
*/
|
||||
public QName getAssocType()
|
||||
{
|
||||
return assocType;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return "ParentContext[parent=" + parentRef + ",assocType=" + getAssocType() + "]";
|
||||
}
|
||||
|
||||
}
|
634
source/java/org/alfresco/repo/importer/view/ViewParser.java
Normal file
634
source/java/org/alfresco/repo/importer/view/ViewParser.java
Normal file
@@ -0,0 +1,634 @@
|
||||
/*
|
||||
* 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.importer.view;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.alfresco.repo.importer.Importer;
|
||||
import org.alfresco.repo.importer.Parser;
|
||||
import org.alfresco.service.cmr.dictionary.AspectDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.ChildAssociationDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.DictionaryService;
|
||||
import org.alfresco.service.cmr.dictionary.PropertyDefinition;
|
||||
import org.alfresco.service.cmr.dictionary.TypeDefinition;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.view.ImporterException;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.xmlpull.v1.XmlPullParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
import org.xmlpull.v1.XmlPullParserFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Importer for parsing and importing nodes given the Repository View schema.
|
||||
*
|
||||
* @author David Caruana
|
||||
*/
|
||||
public class ViewParser implements Parser
|
||||
{
|
||||
// Logger
|
||||
private static final Log logger = LogFactory.getLog(ViewParser.class);
|
||||
|
||||
// View schema elements and attributes
|
||||
private static final String VIEW_CHILD_NAME_ATTR = "childName";
|
||||
private static final String VIEW_DATATYPE_ATTR = "datatype";
|
||||
private static final String VIEW_ISNULL_ATTR = "isNull";
|
||||
private static final QName VIEW_METADATA = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "metadata");
|
||||
private static final QName VIEW_VALUE_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "value");
|
||||
private static final QName VIEW_VALUES_QNAME = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "values");
|
||||
private static final QName VIEW_ASPECTS = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "aspects");
|
||||
private static final QName VIEW_PROPERTIES = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "properties");
|
||||
private static final QName VIEW_ASSOCIATIONS = QName.createQName(NamespaceService.REPOSITORY_VIEW_1_0_URI, "associations");
|
||||
|
||||
// XML Pull Parser Factory
|
||||
private XmlPullParserFactory factory;
|
||||
|
||||
// Supporting services
|
||||
private NamespaceService namespaceService;
|
||||
private DictionaryService dictionaryService;
|
||||
|
||||
|
||||
/**
|
||||
* Construct
|
||||
*/
|
||||
public ViewParser()
|
||||
{
|
||||
try
|
||||
{
|
||||
// Construct Xml Pull Parser Factory
|
||||
factory = XmlPullParserFactory.newInstance(System.getProperty(XmlPullParserFactory.PROPERTY_NAME), this.getClass());
|
||||
factory.setNamespaceAware(true);
|
||||
}
|
||||
catch (XmlPullParserException e)
|
||||
{
|
||||
throw new ImporterException("Failed to initialise view importer", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param namespaceService the namespace service
|
||||
*/
|
||||
public void setNamespaceService(NamespaceService namespaceService)
|
||||
{
|
||||
this.namespaceService = namespaceService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param dictionaryService the dictionary service
|
||||
*/
|
||||
public void setDictionaryService(DictionaryService dictionaryService)
|
||||
{
|
||||
this.dictionaryService = dictionaryService;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.alfresco.repo.importer.Parser#parse(java.io.Reader, org.alfresco.repo.importer.Importer)
|
||||
*/
|
||||
public void parse(Reader viewReader, Importer importer)
|
||||
{
|
||||
try
|
||||
{
|
||||
XmlPullParser xpp = factory.newPullParser();
|
||||
xpp.setInput(viewReader);
|
||||
Stack<ElementContext> contextStack = new Stack<ElementContext>();
|
||||
|
||||
try
|
||||
{
|
||||
for (int eventType = xpp.getEventType(); eventType != XmlPullParser.END_DOCUMENT; eventType = xpp.next())
|
||||
{
|
||||
switch (eventType)
|
||||
{
|
||||
case XmlPullParser.START_TAG:
|
||||
{
|
||||
if (xpp.getDepth() == 1)
|
||||
{
|
||||
processRoot(xpp, importer, contextStack);
|
||||
}
|
||||
else
|
||||
{
|
||||
processStartElement(xpp, contextStack);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case XmlPullParser.END_TAG:
|
||||
{
|
||||
processEndElement(xpp, contextStack);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
throw new ImporterException("Failed to import package at line " + xpp.getLineNumber() + "; column " + xpp.getColumnNumber() + " due to error: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
catch(XmlPullParserException e)
|
||||
{
|
||||
throw new ImporterException("Failed to parse view", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process start of xml element
|
||||
*
|
||||
* @param xpp
|
||||
* @param contextStack
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void processStartElement(XmlPullParser xpp, Stack<ElementContext> contextStack)
|
||||
throws XmlPullParserException, IOException
|
||||
{
|
||||
// Extract qualified name
|
||||
QName defName = getName(xpp);
|
||||
|
||||
// Process the element
|
||||
Object context = contextStack.peek();
|
||||
|
||||
// Handle special view directives
|
||||
if (defName.equals(VIEW_METADATA))
|
||||
{
|
||||
contextStack.push(new MetaDataContext(defName, (ElementContext)context));
|
||||
}
|
||||
else if (defName.equals(VIEW_ASPECTS) || defName.equals(VIEW_PROPERTIES) || defName.equals(VIEW_ASSOCIATIONS))
|
||||
{
|
||||
if (context instanceof NodeItemContext)
|
||||
{
|
||||
throw new ImporterException("Cannot nest element " + defName + " within " + ((NodeItemContext)context).getElementName());
|
||||
}
|
||||
if (!(context instanceof NodeContext))
|
||||
{
|
||||
throw new ImporterException("Element " + defName + " can only be declared within a node");
|
||||
}
|
||||
NodeContext nodeContext = (NodeContext)context;
|
||||
contextStack.push(new NodeItemContext(defName, nodeContext));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (context instanceof MetaDataContext)
|
||||
{
|
||||
processMetaData(xpp, defName, contextStack);
|
||||
}
|
||||
else if (context instanceof ParentContext)
|
||||
{
|
||||
// Process type definition
|
||||
TypeDefinition typeDef = dictionaryService.getType(defName);
|
||||
if (typeDef == null)
|
||||
{
|
||||
throw new ImporterException("Type " + defName + " has not been defined in the Repository dictionary");
|
||||
}
|
||||
processStartType(xpp, typeDef, contextStack);
|
||||
return;
|
||||
}
|
||||
else if (context instanceof NodeContext)
|
||||
{
|
||||
// Process children of node
|
||||
// Note: Process in the following order: aspects, properties and associations
|
||||
Object def = ((NodeContext)context).determineDefinition(defName);
|
||||
if (def == null)
|
||||
{
|
||||
throw new ImporterException("Definition " + defName + " is not valid; cannot find in Repository dictionary");
|
||||
}
|
||||
|
||||
if (def instanceof AspectDefinition)
|
||||
{
|
||||
processAspect(xpp, (AspectDefinition)def, contextStack);
|
||||
return;
|
||||
}
|
||||
else if (def instanceof PropertyDefinition)
|
||||
{
|
||||
processProperty(xpp, ((PropertyDefinition)def).getName(), contextStack);
|
||||
return;
|
||||
}
|
||||
else if (def instanceof ChildAssociationDefinition)
|
||||
{
|
||||
processStartChildAssoc(xpp, (ChildAssociationDefinition)def, contextStack);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: general association
|
||||
}
|
||||
}
|
||||
else if (context instanceof NodeItemContext)
|
||||
{
|
||||
NodeItemContext nodeItemContext = (NodeItemContext)context;
|
||||
NodeContext nodeContext = nodeItemContext.getNodeContext();
|
||||
QName itemName = nodeItemContext.getElementName();
|
||||
if (itemName.equals(VIEW_ASPECTS))
|
||||
{
|
||||
AspectDefinition def = nodeContext.determineAspect(defName);
|
||||
if (def == null)
|
||||
{
|
||||
throw new ImporterException("Aspect name " + defName + " is not valid; cannot find in Repository dictionary");
|
||||
}
|
||||
processAspect(xpp, def, contextStack);
|
||||
}
|
||||
else if (itemName.equals(VIEW_PROPERTIES))
|
||||
{
|
||||
// Note: Allow properties which do not have a data dictionary definition
|
||||
processProperty(xpp, defName, contextStack);
|
||||
}
|
||||
else if (itemName.equals(VIEW_ASSOCIATIONS))
|
||||
{
|
||||
// TODO: Handle general associations...
|
||||
ChildAssociationDefinition def = (ChildAssociationDefinition)nodeContext.determineAssociation(defName);
|
||||
if (def == null)
|
||||
{
|
||||
throw new ImporterException("Association name " + defName + " is not valid; cannot find in Repository dictionary");
|
||||
}
|
||||
processStartChildAssoc(xpp, def, contextStack);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process Root
|
||||
*
|
||||
* @param xpp
|
||||
* @param parentRef
|
||||
* @param childAssocType
|
||||
* @param configuration
|
||||
* @param progress
|
||||
* @param contextStack
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void processRoot(XmlPullParser xpp, Importer importer, Stack<ElementContext> contextStack)
|
||||
throws XmlPullParserException, IOException
|
||||
{
|
||||
ParentContext parentContext = new ParentContext(getName(xpp), dictionaryService, importer);
|
||||
contextStack.push(parentContext);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug(indentLog("Pushed " + parentContext, contextStack.size() -1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process meta-data
|
||||
*
|
||||
* @param xpp
|
||||
* @param metaDataName
|
||||
* @param contextStack
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void processMetaData(XmlPullParser xpp, QName metaDataName, Stack<ElementContext> contextStack)
|
||||
throws XmlPullParserException, IOException
|
||||
{
|
||||
MetaDataContext context = (MetaDataContext)contextStack.peek();
|
||||
|
||||
String value = null;
|
||||
|
||||
int eventType = xpp.next();
|
||||
if (eventType == XmlPullParser.TEXT)
|
||||
{
|
||||
// Extract value
|
||||
value = xpp.getText();
|
||||
eventType = xpp.next();
|
||||
}
|
||||
if (eventType != XmlPullParser.END_TAG)
|
||||
{
|
||||
throw new ImporterException("Meta data element " + metaDataName + " is missing end tag");
|
||||
}
|
||||
|
||||
context.setProperty(metaDataName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process start of a node definition
|
||||
*
|
||||
* @param xpp
|
||||
* @param typeDef
|
||||
* @param contextStack
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void processStartType(XmlPullParser xpp, TypeDefinition typeDef, Stack<ElementContext> contextStack)
|
||||
throws XmlPullParserException, IOException
|
||||
{
|
||||
ParentContext parentContext = (ParentContext)contextStack.peek();
|
||||
NodeContext context = new NodeContext(typeDef.getName(), parentContext, typeDef);
|
||||
|
||||
// Extract child name if explicitly defined
|
||||
String childName = xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_CHILD_NAME_ATTR);
|
||||
if (childName != null && childName.length() > 0)
|
||||
{
|
||||
context.setChildName(childName);
|
||||
}
|
||||
|
||||
contextStack.push(context);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug(indentLog("Pushed " + context, contextStack.size() -1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process aspect definition
|
||||
*
|
||||
* @param xpp
|
||||
* @param aspectDef
|
||||
* @param contextStack
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void processAspect(XmlPullParser xpp, AspectDefinition aspectDef, Stack<ElementContext> contextStack)
|
||||
throws XmlPullParserException, IOException
|
||||
{
|
||||
NodeContext context = peekNodeContext(contextStack);
|
||||
context.addAspect(aspectDef);
|
||||
|
||||
int eventType = xpp.next();
|
||||
if (eventType != XmlPullParser.END_TAG)
|
||||
{
|
||||
throw new ImporterException("Aspect " + aspectDef.getName() + " definition is not valid - it cannot contain any elements");
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug(indentLog("Processed aspect " + aspectDef.getName(), contextStack.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process property definition
|
||||
*
|
||||
* @param xpp
|
||||
* @param propDef
|
||||
* @param contextStack
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void processProperty(XmlPullParser xpp, QName propertyName, Stack<ElementContext> contextStack)
|
||||
throws XmlPullParserException, IOException
|
||||
{
|
||||
NodeContext context = peekNodeContext(contextStack);
|
||||
|
||||
// Extract single value
|
||||
String value = "";
|
||||
int eventType = xpp.next();
|
||||
if (eventType == XmlPullParser.TEXT)
|
||||
{
|
||||
value = xpp.getText();
|
||||
eventType = xpp.next();
|
||||
}
|
||||
if (eventType == XmlPullParser.END_TAG)
|
||||
{
|
||||
context.addProperty(propertyName, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
// Extract collection, if specified
|
||||
boolean isCollection = false;
|
||||
if (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
QName name = getName(xpp);
|
||||
if (name.equals(VIEW_VALUES_QNAME))
|
||||
{
|
||||
context.addPropertyCollection(propertyName);
|
||||
isCollection = true;
|
||||
eventType = xpp.next();
|
||||
if (eventType == XmlPullParser.TEXT)
|
||||
{
|
||||
eventType = xpp.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Extract decorated value
|
||||
while (eventType == XmlPullParser.START_TAG)
|
||||
{
|
||||
QName name = getName(xpp);
|
||||
if (!name.equals(VIEW_VALUE_QNAME))
|
||||
{
|
||||
throw new ImporterException("Invalid view structure - expected element " + VIEW_VALUE_QNAME + " for property " + propertyName);
|
||||
}
|
||||
QName datatype = QName.createQName(xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_DATATYPE_ATTR), namespaceService);
|
||||
Boolean isNull = Boolean.valueOf(xpp.getAttributeValue(NamespaceService.REPOSITORY_VIEW_1_0_URI, VIEW_ISNULL_ATTR));
|
||||
String decoratedValue = isNull ? null : "";
|
||||
eventType = xpp.next();
|
||||
if (eventType == XmlPullParser.TEXT)
|
||||
{
|
||||
decoratedValue = xpp.getText();
|
||||
eventType = xpp.next();
|
||||
}
|
||||
if (eventType == XmlPullParser.END_TAG)
|
||||
{
|
||||
context.addProperty(propertyName, decoratedValue);
|
||||
if (datatype != null)
|
||||
{
|
||||
context.addDatatype(propertyName, dictionaryService.getDataType(datatype));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ImporterException("Value for property " + propertyName + " has not been defined correctly - missing end tag");
|
||||
}
|
||||
eventType = xpp.next();
|
||||
if (eventType == XmlPullParser.TEXT)
|
||||
{
|
||||
eventType = xpp.next();
|
||||
}
|
||||
}
|
||||
|
||||
// End of value
|
||||
if (eventType != XmlPullParser.END_TAG)
|
||||
{
|
||||
throw new ImporterException("Invalid view structure - property " + propertyName + " definition is invalid");
|
||||
}
|
||||
|
||||
// End of collection
|
||||
if (isCollection)
|
||||
{
|
||||
eventType = xpp.next();
|
||||
if (eventType == XmlPullParser.TEXT)
|
||||
{
|
||||
eventType = xpp.next();
|
||||
}
|
||||
if (eventType != XmlPullParser.END_TAG)
|
||||
{
|
||||
throw new ImporterException("Invalid view structure - property " + propertyName + " definition is invalid");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug(indentLog("Processed property " + propertyName, contextStack.size()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process start of child association definition
|
||||
*
|
||||
* @param xpp
|
||||
* @param childAssocDef
|
||||
* @param contextStack
|
||||
* @throws XmlPullParserException
|
||||
* @throws IOException
|
||||
*/
|
||||
private void processStartChildAssoc(XmlPullParser xpp, ChildAssociationDefinition childAssocDef, Stack<ElementContext> contextStack)
|
||||
throws XmlPullParserException, IOException
|
||||
{
|
||||
NodeContext context = peekNodeContext(contextStack);
|
||||
|
||||
if (context.getNodeRef() == null)
|
||||
{
|
||||
// Create Node
|
||||
NodeRef nodeRef = context.getImporter().importNode(context);
|
||||
context.setNodeRef(nodeRef);
|
||||
}
|
||||
|
||||
// Construct Child Association Context
|
||||
ParentContext parentContext = new ParentContext(childAssocDef.getName(), context, childAssocDef);
|
||||
contextStack.push(parentContext);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug(indentLog("Pushed " + parentContext, contextStack.size() -1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Process end of xml element
|
||||
*
|
||||
* @param xpp
|
||||
* @param contextStack
|
||||
*/
|
||||
private void processEndElement(XmlPullParser xpp, Stack<ElementContext> contextStack)
|
||||
{
|
||||
ElementContext context = contextStack.peek();
|
||||
if (context.getElementName().getLocalName().equals(xpp.getName()) &&
|
||||
context.getElementName().getNamespaceURI().equals(xpp.getNamespace()))
|
||||
{
|
||||
context = contextStack.pop();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug(indentLog("Popped " + context, contextStack.size()));
|
||||
|
||||
if (context instanceof NodeContext)
|
||||
{
|
||||
processEndType((NodeContext)context);
|
||||
}
|
||||
else if (context instanceof ParentContext)
|
||||
{
|
||||
processEndChildAssoc((ParentContext)context);
|
||||
}
|
||||
else if (context instanceof MetaDataContext)
|
||||
{
|
||||
processEndMetaData((MetaDataContext)context);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Process end of the type definition
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
private void processEndType(NodeContext context)
|
||||
{
|
||||
NodeRef nodeRef = context.getNodeRef();
|
||||
if (nodeRef == null)
|
||||
{
|
||||
nodeRef = context.getImporter().importNode(context);
|
||||
context.setNodeRef(nodeRef);
|
||||
}
|
||||
context.getImporter().childrenImported(nodeRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process end of the child association
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
private void processEndChildAssoc(ParentContext context)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Process end of meta data
|
||||
*
|
||||
* @param context
|
||||
*/
|
||||
private void processEndMetaData(MetaDataContext context)
|
||||
{
|
||||
context.getImporter().importMetaData(context.getProperties());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get parent Node Context
|
||||
*
|
||||
* @param contextStack context stack
|
||||
* @return node context
|
||||
*/
|
||||
private NodeContext peekNodeContext(Stack<ElementContext> contextStack)
|
||||
{
|
||||
ElementContext context = contextStack.peek();
|
||||
if (context instanceof NodeContext)
|
||||
{
|
||||
return (NodeContext)context;
|
||||
}
|
||||
else if (context instanceof NodeItemContext)
|
||||
{
|
||||
return ((NodeItemContext)context).getNodeContext();
|
||||
}
|
||||
throw new ImporterException("Internal error: Failed to retrieve node context");
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to create Qualified name from current xml element
|
||||
*
|
||||
* @param xpp
|
||||
* @return
|
||||
*/
|
||||
private QName getName(XmlPullParser xpp)
|
||||
{
|
||||
// Ensure namespace is valid
|
||||
String uri = xpp.getNamespace();
|
||||
if (namespaceService.getURIs().contains(uri) == false)
|
||||
{
|
||||
throw new ImporterException("Namespace URI " + uri + " has not been defined in the Repository dictionary");
|
||||
}
|
||||
|
||||
// Construct name
|
||||
String name = xpp.getName();
|
||||
return QName.createQName(uri, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper to indent debug output
|
||||
*
|
||||
* @param msg
|
||||
* @param depth
|
||||
* @return
|
||||
*/
|
||||
private String indentLog(String msg, int depth)
|
||||
{
|
||||
StringBuffer buf = new StringBuffer(1024);
|
||||
for (int i = 0; i < depth; i++)
|
||||
{
|
||||
buf.append(' ');
|
||||
}
|
||||
buf.append(msg);
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user