Java tutorial
/* * Copyright 2011-2012 Alfresco Software Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * 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. * * This file is part of an unsupported extension to Alfresco. */ package org.alfresco.dropbox.webscripts; import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import java.util.regex.Matcher; import org.alfresco.dropbox.DropboxConstants; import org.springframework.social.dropbox.api.Metadata; import org.springframework.web.client.HttpClientErrorException; import org.alfresco.model.ContentModel; import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.version.Version2Model; import org.alfresco.service.cmr.model.FileExistsException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.version.VersionService; import org.alfresco.service.cmr.version.VersionType; import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.extensions.webscripts.Cache; import org.springframework.extensions.webscripts.Status; import org.springframework.extensions.webscripts.WebScriptException; import org.springframework.extensions.webscripts.WebScriptRequest; /** * @author Jared Ottley */ public class GetNode extends Node { private static Log logger = LogFactory.getLog(GetNode.class); private BehaviourFilter behaviourFilter; private VersionService versionService; public void setBehaviourFilter(BehaviourFilter behaviourFilter) { this.behaviourFilter = behaviourFilter; } public void setVersionService(VersionService versionService) { this.versionService = versionService; } @Override protected Map<String, Object> executeImpl(WebScriptRequest req, Status status, Cache cache) { // our return map Map<String, Object> model = new HashMap<String, Object>(); // Get the list of nodeRefs passed from Share List<NodeRef> nodeRefs = parseNodeRefs(req); // We don't want to cache the returned response cache.setNeverCache(true); // Turn off Dropbox policies for this node. behaviourFilter.disableBehaviour(DropboxConstants.Model.ASPECT_DROPBOX); // Loop through the list of nodeRefs passed from Share for (NodeRef nodeRef : nodeRefs) { logger.debug("Retrieving Node: " + nodeRef); // Need to match the children in both paths (dropbox and alfresco) if (nodeService.getType(nodeRef).equals(ContentModel.TYPE_FOLDER)) { updateChildren(nodeRef); } else if (nodeService.getType(nodeRef).equals(ContentModel.TYPE_CONTENT)) { update(nodeRef); } } return model; } /* * Override parseNodeRefs. When a GET is passing a JSON object, the JSON object is changed to and passed as URL parameters * (non-Javadoc) * * @see org.alfresco.dropbox.webscripts.Node#parseNodeRefs(org.springframework .extensions.webscripts.WebScriptRequest) */ @Override protected final List<NodeRef> parseNodeRefs(final WebScriptRequest req) { final List<NodeRef> result = new ArrayList<NodeRef>(); String nodeRefs = req.getParameter("nodeRefs"); try { if (nodeRefs == null || nodeRefs.length() == 0) { throw new WebScriptException(Status.STATUS_BAD_REQUEST, "No content sent with request."); } NodeRef nodeRef = new NodeRef(nodeRefs); result.add(nodeRef); } catch (final WebScriptException wse) { throw wse; // Ensure WebScriptExceptions get re-thrown verbatim } catch (final Exception e) { throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Unable to retrieve nodeRefs from Parameter '" + req.getURL() + "'.", e); } return result; } private void update(NodeRef nodeRef) { Metadata metadata = dropboxService.getMetadata(nodeRef); Map<QName, Serializable> persistedMetadata = dropboxService.getPersistedMetadata(nodeRef); if (nodeService.getType(nodeRef).equals(ContentModel.TYPE_CONTENT)) { if (!metadata.getRev().equals(persistedMetadata.get(DropboxConstants.Model.PROP_REV).toString())) { // We need to make the node Versionable if it isn't already makeVersionable(nodeRef); // TODO Add modified date test? metadata = dropboxService.getFile(nodeRef); dropboxService.persistMetadata(metadata, nodeRef); syncUpdate(nodeRef, false); } } } private void updateChildren(NodeRef nodeRef) { Metadata parentMetadata = dropboxService.getMetadata(nodeRef); // Get the list of the content returned. List<Metadata> list = parentMetadata.getContents(); for (Metadata child : list) { String name = child.getPath().replaceAll(Matcher.quoteReplacement(parentMetadata.getPath() + "/"), ""); NodeRef childNodeRef = fileFolderService.searchSimple(nodeRef, name); if (childNodeRef == null) { NodeRef newChildNodeRef = null; try { if (child.isDir()) { newChildNodeRef = fileFolderService.create(nodeRef, name, ContentModel.TYPE_FOLDER) .getNodeRef(); updateChildren(newChildNodeRef); dropboxService.persistMetadata(child, newChildNodeRef); } else { newChildNodeRef = fileFolderService.create(nodeRef, name, ContentModel.TYPE_CONTENT) .getNodeRef(); Metadata metadata = dropboxService.getFile(newChildNodeRef); dropboxService.persistMetadata(metadata, newChildNodeRef); } syncUpdate(newChildNodeRef, true); } catch (FileExistsException fee) { // TODO What to do here? fee.printStackTrace(); } } else { if (nodeService.getType(childNodeRef).equals(ContentModel.TYPE_CONTENT)) { update(childNodeRef); } else if (nodeService.getType(childNodeRef).equals(ContentModel.TYPE_FOLDER)) { updateChildren(childNodeRef); } } } update(nodeRef); } private void syncUpdate(final NodeRef nodeRef, boolean useParent) { String currentUser = AuthenticationUtil.getRunAsUser(); Map<String, NodeRef> syncedUsers = dropboxService.getSyncedUsers(nodeRef); if (useParent) { syncedUsers = filterMap(nodeRef); } else { syncedUsers = dropboxService.getSyncedUsers(nodeRef); } syncedUsers.remove(currentUser); for (String key : syncedUsers.keySet()) { AuthenticationUtil.runAs(new AuthenticationUtil.RunAsWork<Object>() { public Object doWork() throws Exception { Metadata metadata = null; if (nodeService.getType(nodeRef).equals(ContentModel.TYPE_CONTENT)) { metadata = dropboxService.putFile(nodeRef, true); dropboxService.persistMetadata(metadata, nodeRef); } else if (nodeService.getType(nodeRef).equals(ContentModel.TYPE_FOLDER)) { // If this is a folder, we need to try and create the // folder in Dropbox for the user. If the folder already // exists a 403 status error is returned, at which // point, we get the metadata for the folder and then // update the node with the metadata. try { metadata = dropboxService.createFolder(nodeRef); logger.debug("Dropbox: Add: createFolder: " + nodeRef.toString()); } catch (HttpClientErrorException hcee) { if (hcee.getStatusCode().ordinal() == Status.STATUS_FORBIDDEN) { metadata = dropboxService.getMetadata(nodeRef); } else { throw new WebScriptException(hcee.getMessage()); } } } if (metadata != null) { dropboxService.persistMetadata(metadata, nodeRef); } else { throw new WebScriptException(Status.STATUS_BAD_REQUEST, "Dropbox metadata maybe out of sync for " + nodeRef); } return null; } }, key); } } /** * Filter out users on the node being passed that are on the parent that don't need to be updated. * * @param nodeRef Node being added to the folder * @return synced users that need to be updated */ private Map<String, NodeRef> filterMap(NodeRef nodeRef) { Map<String, NodeRef> filteredMap = new HashMap<String, NodeRef>(); Map<String, NodeRef> parentMap = dropboxService .getSyncedUsers(nodeService.getPrimaryParent(nodeRef).getParentRef()); Map<String, NodeRef> childMap = dropboxService.getSyncedUsers(nodeRef); if (parentMap.size() > 0) { if (childMap.size() > 0) { Set<Map.Entry<String, NodeRef>> parentMapSet = parentMap.entrySet(); Iterator<Map.Entry<String, NodeRef>> i = parentMapSet.iterator(); while (i.hasNext()) { Map.Entry<String, NodeRef> entry = i.next(); if (!childMap.containsKey(entry.getKey())) { filteredMap.put(entry.getKey(), entry.getValue()); } } } else { filteredMap = parentMap; } } return filteredMap; } private void makeVersionable(NodeRef nodeRef) { if (!nodeService.hasAspect(nodeRef, ContentModel.ASPECT_VERSIONABLE)) { Map<String, Serializable> versionProperties = new HashMap<String, Serializable>(); versionProperties.put(Version2Model.PROP_VERSION_TYPE, VersionType.MAJOR); nodeService.setProperty(nodeRef, ContentModel.PROP_AUTO_VERSION, true); nodeService.setProperty(nodeRef, ContentModel.PROP_AUTO_VERSION_PROPS, true); versionService.createVersion(nodeRef, versionProperties); } } }