}
if (!xmlReader.getLocalName().equals(DumpConstants.RESOURCE)) {
String msg = "Invalid dump to restore at " + path;
log.error(msg);
throw new RegistryException(msg);
}
// keeping the path to support backward compatibility
String incomingParentPath = xmlReader.getAttributeValue(null, DumpConstants.RESOURCE_PATH);
// the name of the resource is used instead of the path
String resourceName = xmlReader.getAttributeValue(null, DumpConstants.RESOURCE_NAME);
String ignoreConflictsStrValue = xmlReader.getAttributeValue(null,
DumpConstants.IGNORE_CONFLICTS);
boolean ignoreConflicts = true;
if (ignoreConflictsStrValue != null &&
Boolean.toString(false).equals(ignoreConflictsStrValue)) {
ignoreConflicts = false;
}
String isCollectionString = xmlReader.getAttributeValue(null,
DumpConstants.RESOURCE_IS_COLLECTION);
boolean isCollection = isCollectionString.equals(DumpConstants.RESOURCE_IS_COLLECTION_TRUE);
if (path.equals(RegistryConstants.ROOT_PATH) && !isCollection) {
// you can not put non collection to the root path
String msg = "Illegal to restore a non-collection in place of root collection.";
log.error(msg);
throw new RegistryException(msg);
}
ResourceImpl resourceImpl;
byte[] contentBytes = new byte[0];
if (isCollection) {
resourceImpl = new CollectionImpl();
} else {
resourceImpl = new ResourceImpl();
}
List<CommentDO> commentDOList = new ArrayList<CommentDO>();
List<TaggingDO> taggingDOList = new ArrayList<TaggingDO>();
List<RatingDO> ratingDOList = new ArrayList<RatingDO>();
List<Association> associationList = new ArrayList<Association>();
boolean isCreatorExisting = false;
boolean isCreatedTimeExisting = false;
boolean isUpdaterExisting = false;
boolean isUpdatedTimeExisting = false;
long dumpingResourceVersion = -1;
// traversing to the next element
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
while (xmlReader.hasNext()) {
String localName = xmlReader.getLocalName();
// setMediaType
if (localName.equals(DumpConstants.MEDIA_TYPE)) {
String text = xmlReader.getElementText();
if (text.indexOf("/") < 0) {
text = MediaTypesUtils.getMediaType("dummy." + text);
}
if (text != null) {
resourceImpl.setMediaType(text);
}
// now go to the next element
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
}
// creator
else if (localName.equals(DumpConstants.CREATOR)) {
String text = xmlReader.getElementText();
if (text != null) {
resourceImpl.setAuthorUserName(text);
isCreatorExisting = true;
}
// now go to the next element
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
}
// version: just to keep track of the server changes
else if (localName.equals(DumpConstants.VERSION)) {
String text = xmlReader.getElementText();
if (text != null) {
dumpingResourceVersion = Long.parseLong(text);
}
// now go to the next element
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
}
// createdTime
else if (localName.equals(DumpConstants.CREATED_TIME)) {
String text = xmlReader.getElementText();
if (text != null) {
long date = Long.parseLong(text);
resourceImpl.setCreatedTime(new Date(date));
isCreatedTimeExisting = true;
}
// now go to the next element
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
}
// setLastUpdater
else if (localName.equals(DumpConstants.LAST_UPDATER)) {
String text = xmlReader.getElementText();
if (text != null) {
resourceImpl.setLastUpdaterUserName(text);
isUpdaterExisting = true;
}
// now go to the next element
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
}
// LastModified
else if (localName.equals(DumpConstants.LAST_MODIFIED)) {
String text = xmlReader.getElementText();
if (text != null) {
long date = Long.parseLong(text);
resourceImpl.setLastModified(new Date(date));
isUpdatedTimeExisting = true;
}
// now go to the next element
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
}
// get description
else if (localName.equals(DumpConstants.DESCRIPTION)) {
String text = xmlReader.getElementText();
if (text != null) {
resourceImpl.setDescription(text);
}
// now go to the next element
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
}
// get properties
else if (localName.equals(DumpConstants.PROPERTIES)) {
// iterating trying to find the children..
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
while (xmlReader.hasNext() &&
xmlReader.getLocalName().equals(DumpConstants.PROPERTY_ENTRY)) {
String key = xmlReader.getAttributeValue(null, DumpConstants.PROPERTY_ENTRY_KEY);
String text = xmlReader.getElementText();
if (text.equals("")) {
text = null;
}
if (text != null) {
resourceImpl.addPropertyWithNoUpdate(key, text);
}
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
}
}
// get content
else if (localName.equals(DumpConstants.CONTENT)) {
String text = xmlReader.getElementText();
// we keep content as base64 encoded
if (text != null) {
contentBytes = Base64.decode(text);
}
do {
xmlReader.next();
} while ((!xmlReader.isStartElement() && xmlReader.hasNext()) &&
!(xmlReader.isEndElement() &&
xmlReader.getLocalName().equals(DumpConstants.RESOURCE)));
}
// getting comment information
else if (localName.equals(DumpConstants.COMMENTS)) {
// iterating trying to find the children..
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
while (xmlReader.hasNext() &&
xmlReader.getLocalName().equals(DumpConstants.COMMENT_ENTRY)) {
CommentDO commentDO = new CommentDO();
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
localName = xmlReader.getLocalName();
while (xmlReader.hasNext() &&
(localName.equals(DumpConstants.COMMENT_ENTRY_USER) ||
localName.equals(DumpConstants.COMMENT_ENTRY_TEXT))) {
if (localName.equals(DumpConstants.COMMENT_ENTRY_USER)) {
String text = xmlReader.getElementText();
if (text != null) {
commentDO.setCommentedUser(text);
}
} else if (localName.equals(DumpConstants.COMMENT_ENTRY_TEXT)) {
String text = xmlReader.getElementText();
if (text != null) {
commentDO.setCommentText(text);
}
}
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
if (xmlReader.hasNext()) {
localName = xmlReader.getLocalName();
}
}
commentDOList.add(commentDO);
}
}
// getting tagging information
else if (localName.equals(DumpConstants.TAGGINGS)) {
// iterating trying to find the children..
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
while (xmlReader.hasNext() &&
xmlReader.getLocalName().equals(DumpConstants.TAGGING_ENTRY)) {
TaggingDO taggingDO = new TaggingDO();
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
localName = xmlReader.getLocalName();
while (xmlReader.hasNext() &&
(localName.equals(DumpConstants.TAGGING_ENTRY_USER) ||
localName.equals(DumpConstants.TAGGING_ENTRY_DATE) ||
localName.equals(DumpConstants.TAGGING_ENTRY_TAG_NAME))) {
if (localName.equals(DumpConstants.TAGGING_ENTRY_USER)) {
String text = xmlReader.getElementText();
if (text != null) {
taggingDO.setTaggedUserName(text);
}
} else if (localName.equals(DumpConstants.TAGGING_ENTRY_DATE)) {
String text = xmlReader.getElementText();
if (text != null) {
long date = Long.parseLong(text);
taggingDO.setTaggedTime(new Date(date));
}
} else if (localName.equals(DumpConstants.TAGGING_ENTRY_TAG_NAME)) {
String text = xmlReader.getElementText();
if (text != null) {
taggingDO.setTagName(text);
}
}
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
if (xmlReader.hasNext()) {
localName = xmlReader.getLocalName();
}
}
taggingDOList.add(taggingDO);
}
}
// getting rating information
else if (localName.equals(DumpConstants.RATINGS)) {
// iterating trying to find the children..
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
while (xmlReader.hasNext() &&
xmlReader.getLocalName().equals(DumpConstants.RATING_ENTRY)) {
RatingDO ratingDO = new RatingDO();
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
localName = xmlReader.getLocalName();
while (xmlReader.hasNext() &&
(localName.equals(DumpConstants.RATING_ENTRY_USER) ||
localName.equals(DumpConstants.RATING_ENTRY_DATE) ||
localName.equals(DumpConstants.RATING_ENTRY_RATE))) {
if (localName.equals(DumpConstants.RATING_ENTRY_USER)) {
String text = xmlReader.getElementText();
if (text != null) {
ratingDO.setRatedUserName(text);
}
} else if (localName.equals(DumpConstants.RATING_ENTRY_DATE)) {
String text = xmlReader.getElementText();
if (text != null) {
long date = Long.parseLong(text);
ratingDO.setRatedTime(new Date(date));
}
} else if (localName.equals(DumpConstants.RATING_ENTRY_RATE)) {
String text = xmlReader.getElementText();
if (text != null) {
int ratingValue = Integer.parseInt(text);
ratingDO.setRating(ratingValue);
}
}
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
if (xmlReader.hasNext()) {
localName = xmlReader.getLocalName();
}
}
ratingDOList.add(ratingDO);
}
}
// getting rating information
else if (localName.equals(DumpConstants.ASSOCIATIONS)) {
// iterating trying to find the children..
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
while (xmlReader.hasNext() &&
xmlReader.getLocalName().equals(DumpConstants.ASSOCIATION_ENTRY)) {
String source = null;
String destination = null;
String type = null;
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
localName = xmlReader.getLocalName();
while (xmlReader.hasNext() &&
(localName.equals(DumpConstants.ASSOCIATION_ENTRY_SOURCE) ||
localName.equals(DumpConstants.ASSOCIATION_ENTRY_DESTINATION) ||
localName.equals(DumpConstants.ASSOCIATION_ENTRY_TYPE))) {
if (localName.equals(DumpConstants.ASSOCIATION_ENTRY_SOURCE)) {
String text = xmlReader.getElementText();
if (text != null) {
source = text;
}
} else if (localName.equals(DumpConstants.ASSOCIATION_ENTRY_DESTINATION)) {
String text = xmlReader.getElementText();
if (text != null) {
destination = text;
}
} else if (localName.equals(DumpConstants.ASSOCIATION_ENTRY_TYPE)) {
String text = xmlReader.getElementText();
if (text != null) {
type = text;
}
}
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
if (xmlReader.hasNext()) {
localName = xmlReader.getLocalName();
}
}
// get the source and destination as absolute paths
source = RegistryUtils.getAbsoluteAssociationPath(source, path);
if (destination.startsWith(
DumpConstants.EXTERNAL_ASSOCIATION_DESTINATION_PREFIX)) {
destination =
destination.substring(
DumpConstants.EXTERNAL_ASSOCIATION_DESTINATION_PREFIX.
length());
} else {
destination =
RegistryUtils.getAbsoluteAssociationPath(destination, path);
}
associationList.add(new Association(source, destination, type));
}
}
// getting children, just storing in array list now, will used at the end
// we are keeping old name to keep backward compatibility.
else if (localName.equals(DumpConstants.CHILDREN) ||
localName.equals(DumpConstants.CHILDS)) {
// we keep the stream to call this function recursively
break;
} else if (localName.equals(DumpConstants.RESOURCE)) {
// we keep the stream to call this function recursively
break;
} else {
// we don't mind having unwanted elements, now go to the next element
do {
xmlReader.next();
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
}
}
if (!ignoreConflicts) {
// so we handling the conflicts.
if (dumpingResourceVersion > 0) {
if (currentVersion == -1) {
// the current version == -1 means the resource is deleted in the server
// but since the client is sending a version number, it has a previously checkout
// resource
String msg = "Resource is deleted in the server, resource path: " + path + ".";
log.error(msg);
throw new RegistryException(msg);
}
// we should check whether our dump is up-to-date
if (currentVersion > dumpingResourceVersion) {
// that mean the current resource is updated before the current version
// so we have to notify user to get an update
String msg = "Resource is in a newer version than the restoring version. " +
"resource path: " + path + ".";
log.error(msg);
throw new RegistryException(msg);
}
}
}
// completing the empty fields
if (!isCreatorExisting) {
String creator = CurrentSession.getUser();
resourceImpl.setAuthorUserName(creator);
}
if (!isCreatedTimeExisting) {
long now = System.currentTimeMillis();
resourceImpl.setCreatedTime(new Date(now));
}
if (!isUpdaterExisting) {
String updater = CurrentSession.getUser();
resourceImpl.setLastUpdaterUserName(updater);
}
if (!isUpdatedTimeExisting) {
long now = System.currentTimeMillis();
resourceImpl.setLastModified(new Date(now));
}
// create sym links
String linkRestoration = resourceImpl.getProperty(
RegistryConstants.REGISTRY_LINK_RESTORATION);
if (linkRestoration != null) {
String[] parts = linkRestoration.split(RegistryConstants.URL_SEPARATOR);
if (parts.length == 4) {
if (parts[2] != null && parts[2].length() == 0) {
parts[2] = null;
}
if (parts[0] != null && parts[1] != null && parts[3] != null) {
RegistryUtils.registerHandlerForRemoteLinks(RegistryContext.getBaseInstance(),
parts[0], parts[1], parts[2], parts[3]);
}
} else if (parts.length == 3) {
// here parts[0] the current path, path[1] is the target path.
if (parts[0] != null && parts[1] != null) {
// first we are calculating the relative path of path[1] to path[0]
String relativeTargetPath = RegistryUtils.getRelativeAssociationPath(parts[1],
parts[0]);
// then we derive the absolute path with reference to the current path.
String absoluteTargetPath = RegistryUtils.getAbsoluteAssociationPath(
relativeTargetPath, path);
RegistryUtils.registerHandlerForSymbolicLinks(RegistryContext.getBaseInstance(),
path, absoluteTargetPath, parts[2]);
}
}
}
// creating the resourceID
ResourceIDImpl resourceID = resourceDAO.getResourceID(path, isCollection);
if (resourceID == null) {
// need to create a resourceID
String parentPath = RegistryUtils.getParentPath(path);
ResourceIDImpl parentResourceID = resourceDAO.getResourceID(parentPath, true);
if (parentResourceID == null || !resourceDAO.resourceExists(parentResourceID)) {
addEmptyCollection(parentPath);
if (parentResourceID == null) {
parentResourceID = resourceDAO.getResourceID(parentPath, true);
}
}
resourceDAO.createAndApplyResourceID(path, parentResourceID, resourceImpl);
} else {
resourceImpl.setPathID(resourceID.getPathID());
resourceImpl.setPath(path);
resourceImpl.setName(resourceID.getName());
}
// adding resource followed by content (for nonCollection
if (!isCollection) {
int contentId = 0;
if (contentBytes.length > 0) {
contentId = resourceDAO.addContentBytes(new ByteArrayInputStream(contentBytes));
}
resourceImpl.setDbBasedContentID(contentId);
}
ResourceDO resourceDO = resourceImpl.getResourceDO();
resourceDAO.addResourceDO(resourceDO);
resourceImpl.setVersionNumber(resourceDO.getVersion());
// adding the properties.
resourceDAO.addProperties(resourceImpl);
// adding comments
commentsDAO.addComments(resourceImpl,
commentDOList.toArray(new CommentDO[commentDOList.size()]));
// adding tags
tagsDAO.addTaggings(resourceImpl,
taggingDOList.toArray(new TaggingDO[taggingDOList.size()]));
// adding ratings
ratingsDAO.addRatings(resourceImpl,
ratingDOList.toArray(new RatingDO[ratingDOList.size()]));
for (Association association : associationList) {
associationDAO.addAssociation(association.getSourcePath(),
association.getDestinationPath(), association.getAssociationType());
}
if (!xmlReader.hasNext() || !(xmlReader.getLocalName().equals(DumpConstants.CHILDREN) ||
xmlReader.getLocalName().equals(DumpConstants.CHILDS))) {
// before returning we will remove all the children
if (resourceImpl instanceof CollectionImpl) {
String[] allChildPaths = resourceDAO.getChildren((CollectionImpl) resourceImpl,
0, -1);
for (String childPath: allChildPaths) {
delete(childPath);
}
}
// finished the recursion
return;
}
do {
xmlReader.next();
if (xmlReader.isEndElement() &&
(xmlReader.getLocalName().equals(DumpConstants.CHILDREN) ||
xmlReader.getLocalName().equals(DumpConstants.CHILDS))) {
// this means empty children, just quit from here
// before that we have to set the cursor to the start of the next element
if (xmlReader.hasNext()) {
do {
xmlReader.next();
} while ((!xmlReader.isStartElement() && xmlReader.hasNext()) &&
!(xmlReader.isEndElement() &&
xmlReader.getLocalName().equals(DumpConstants.RESOURCE)));
}
// before returning we will remove all the children
if (resourceImpl instanceof CollectionImpl) {
String[] allChildPaths = resourceDAO.getChildren((CollectionImpl) resourceImpl,
0, -1);
for (String childPath: allChildPaths) {
delete(childPath);
}
}
return;
}
} while (!xmlReader.isStartElement() && xmlReader.hasNext());
// we are tracking what children are restored, in order to clear the non-restored children
Set<String> restoredChildPaths = new HashSet<String>();
int i = 0;
if (xmlReader.hasNext() && xmlReader.getLocalName().equals(DumpConstants.RESOURCE)) {
while (true) {
if (i != 0) {
dumpReader.setReadingChildResourceIndex(i);
// otherwise we will set the stuff for the next resource
// get an xlm reader in the checking child by parent mode.
xmlReader = XMLInputFactory.newInstance().createXMLStreamReader(dumpReader);
while (!xmlReader.isStartElement() && xmlReader.hasNext()) {
xmlReader.next();
}
}
String absoluteChildPath;
if (incomingParentPath != null) {
// the code to support backward compatibility.
// prepare the children absolute path
String incomingChildPath = xmlReader.getAttributeValue(null,
DumpConstants.RESOURCE_PATH);
if (!incomingChildPath.startsWith(incomingParentPath)) {
//break;
}
String relativeChildPath;
if (incomingParentPath.equals(RegistryConstants.ROOT_PATH)) {
relativeChildPath = incomingChildPath;
} else {
if (incomingParentPath.contains(incomingChildPath)) {
relativeChildPath =
incomingChildPath.substring(incomingParentPath.length());
} else {
// this happens only at some custom editing of dump.xml
relativeChildPath = null;
}
}
if (relativeChildPath != null) {
if (path.equals(RegistryConstants.ROOT_PATH)) {
absoluteChildPath = relativeChildPath;
} else {
absoluteChildPath = path + relativeChildPath;
}
} else {
String checkoutRoot =
path.substring(0, path.length() - incomingParentPath.length());
absoluteChildPath = checkoutRoot + incomingChildPath;
}
} else if (resourceName != null) {
String childName = xmlReader.getAttributeValue(null,
DumpConstants.RESOURCE_NAME);
absoluteChildPath = path +
(path.equals(RegistryConstants.ROOT_PATH) ? "" :
RegistryConstants.PATH_SEPARATOR) +
childName;
} else {
String msg =
"Error in deriving the child paths for collection. path: " + path + ".";
log.error(msg);
throw new RegistryException(msg);
}
// we give the control back to the child.
dumpReader.setCheckingChildByParent(false);
dumpReader.setReadingChildResourceIndex(i);
// call the check in method recursively
recursionRepository.restoreRecursively(absoluteChildPath, dumpReader);
restoredChildPaths.add(absoluteChildPath);
dumpReader.setCheckingChildByParent(true);
try {
if (dumpReader.isLastResource(i)) {
dumpReader.setCheckingChildByParent(false);
break;
}
} catch (IOException e) {
String msg = "Error in checking the last resource exists.";
log.error(msg, e);
throw new RegistryException(msg + e.getMessage(), e);
}
// by this time i ++ child resource should exist
i++;
}
}