org.exoplatform.wcm.connector.fckeditor.DriverConnector.java Source code

Java tutorial

Introduction

Here is the source code for org.exoplatform.wcm.connector.fckeditor.DriverConnector.java

Source

/*
 * Copyright (C) 2003-2007 eXo Platform SEA.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Affero General Public License
 * as published by the Free Software Foundation; either version 3
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see<http://www.gnu.org/licenses/>.
 */
package org.exoplatform.wcm.connector.fckeditor;

import java.net.URLDecoder;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;

import javax.annotation.security.RolesAllowed;
import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.CacheControl;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.transform.dom.DOMSource;

import org.exoplatform.container.xml.InitParams;
import org.exoplatform.ecm.connector.fckeditor.FCKUtils;
import org.exoplatform.ecm.utils.text.Text;
import org.exoplatform.services.cms.BasePath;
import org.exoplatform.services.cms.drives.DriveData;
import org.exoplatform.services.cms.drives.ManageDriveService;
import org.exoplatform.services.cms.impl.Utils;
import org.exoplatform.services.cms.link.LinkManager;
import org.exoplatform.services.cms.link.NodeFinder;
import org.exoplatform.services.cms.templates.TemplateService;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.ext.common.SessionProvider;
import org.exoplatform.services.jcr.ext.hierarchy.NodeHierarchyCreator;
import org.exoplatform.services.log.ExoLogger;
import org.exoplatform.services.log.Log;
import org.exoplatform.services.resources.ResourceBundleService;
import org.exoplatform.services.rest.resource.ResourceContainer;
import org.exoplatform.services.security.ConversationState;
import org.exoplatform.services.security.Identity;
import org.exoplatform.services.security.IdentityRegistry;
import org.exoplatform.services.security.MembershipEntry;
import org.exoplatform.services.wcm.core.NodeLocation;
import org.exoplatform.services.wcm.core.NodetypeConstant;
import org.exoplatform.services.wcm.portal.PortalFolderSchemaHandler;
import org.exoplatform.services.wcm.utils.WCMCoreUtils;
import org.exoplatform.services.wcm.webcontent.WebContentSchemaHandler;
import org.exoplatform.wcm.connector.BaseConnector;
import org.exoplatform.wcm.connector.FileUploadHandler;
import org.exoplatform.wcm.connector.handler.FCKFileHandler;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.apache.commons.lang.StringUtils;

/**
 * Returns a list of drives/folders/documents in a specified location for a given user. Also, it processes the file uploading action.
 *
 * {{{{portalname}}}}: The name of portal.
 * {{{{restcontextname}}}}: The context name of REST web application which is deployed to the "{{{{portalname}}}}" portal.
 *
 * @LevelAPI Provisional
 * @anchor DriverConnector
 */
@Path("/wcmDriver/")
public class DriverConnector extends BaseConnector implements ResourceContainer {

    /** The Constant FILE_TYPE_WEBCONTENT. */
    public static final String FILE_TYPE_WEBCONTENT = "Web Contents";

    /** The Constant FILE_TYPE_DMSDOC. */
    public static final String FILE_TYPE_DMSDOC = "DMS Documents";

    /** The Constant FILE_TYPE_MEDIAS. */
    public static final String FILE_TYPE_MEDIAS = "Medias";

    /** The Constant FILE_TYPE_MEDIAS. */
    public static final String FILE_TYPE_ALL = "All";

    /** The Constant FILE_TYPE_IMAGE. */
    public static final String FILE_TYPE_IMAGE = "Image";

    /** The Constant MEDIA_MIMETYPE. */
    public static final String[] MEDIA_MIMETYPE = new String[] { "application", "image", "audio", "video" };

    /** The Constant MEDIA_MIMETYPE. */
    public static final String[] IMAGE_MIMETYPE = new String[] { "image" };

    public static final String TYPE_FOLDER = "folder";

    public static final String TYPE_EDITOR = "editor";

    public static final String TYPE_CONTENT = "multi";

    public static final String ILLUSTRATED_WEBCONTENT = "exo:pictureOnHeadWebcontent";
    /** The log. */
    private static final Log LOG = ExoLogger.getLogger(DriverConnector.class.getName());

    /** The limit. */
    private int limit;

    /** The file number limit on client side. */
    private int limitCountClient_ = 3;

    /** The file number limit on server side. */
    private int limitCountServer_ = 30;

    private ResourceBundleService resourceBundleService = null;
    private NodeFinder nodeFinder_ = null;
    private LinkManager linkManager_ = null;

    private String resourceBundleNames[];
    private ResourceBundle sharedResourceBundle = null;

    private Locale lang = Locale.ENGLISH;

    /**
     * Instantiates a new driver connector.
     *
     * @param params The init parameters.
     */
    public DriverConnector(InitParams params) {
        limit = Integer.parseInt(params.getValueParam("upload.limit.size").getValue());
        if (params.getValueParam("upload.limit.count.client") != null) {
            limitCountClient_ = Integer.parseInt(params.getValueParam("upload.limit.count.client").getValue());
        }
        if (params.getValueParam("upload.limit.count.server") != null) {
            limitCountServer_ = Integer.parseInt(params.getValueParam("upload.limit.count.server").getValue());
        }
    }

    /**
     * Gets the maximum size of the uploaded file.
     * @return The file size limit.
     */
    public int getLimitSize() {
        return limit;
    }

    /**
     * Gets the maximum number of files uploaded from the client side.
     * @return The maximum number of files uploaded on the client side.
     */
    public int getMaxUploadCount() {
        return limitCountClient_;
    }

    /**
     * Returns a list of drives for the current user.
     *
     * @param lang The language of the drive name.
     * @return The drives.
     * @throws Exception The exception
     *
     * @anchor DriverConnector.getDrivers
     */
    @GET
    @Path("/getDrivers/")
    @RolesAllowed("users")
    public Response getDrivers(@QueryParam("lang") String lang) throws Exception {
        ConversationState conversationState = ConversationState.getCurrent();
        String userId = conversationState.getIdentity().getUserId();
        List<DriveData> listDriver = getDriversByUserId(userId);
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document document = builder.newDocument();

        Element rootElement = document.createElement("Connector");
        document.appendChild(rootElement);

        rootElement.setAttribute("isUpload", "false");
        rootElement.appendChild(appendDrivers(document, generalDrivers(listDriver), "General Drives", lang));
        rootElement.appendChild(appendDrivers(document, groupDrivers(listDriver), "Group Drives", lang));
        rootElement
                .appendChild(appendDrivers(document, personalDrivers(listDriver, userId), "Personal Drives", lang));

        CacheControl cacheControl = new CacheControl();
        cacheControl.setNoCache(true);
        cacheControl.setNoStore(true);

        DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
        return Response.ok(new DOMSource(document), MediaType.TEXT_XML).cacheControl(cacheControl)
                .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
    }

    /**
     * Returns all folders and files in a given location.
     *
     * @param driverName The drive name.
     * @param currentFolder The current folder.
     * @param currentPortal The current portal.
     * @param repositoryName The repository name.
     * @param workspaceName The workspace name.
     * @param filterBy The type of filter.
     * @return The folders and files.
     * @throws Exception The exception
     *
     * @anchor DriverConnector.getFoldersAndFiles
     */
    @GET
    @Path("/getFoldersAndFiles/")
    @RolesAllowed("users")
    public Response getFoldersAndFiles(@QueryParam("driverName") String driverName,
            @QueryParam("currentFolder") String currentFolder, @QueryParam("currentPortal") String currentPortal,
            @QueryParam("repositoryName") String repositoryName, @QueryParam("workspaceName") String workspaceName,
            @QueryParam("filterBy") String filterBy, @QueryParam("type") String type) throws Exception {
        try {
            RepositoryService repositoryService = WCMCoreUtils.getService(RepositoryService.class);
            ManageDriveService manageDriveService = WCMCoreUtils.getService(ManageDriveService.class);

            SessionProvider sessionProvider = WCMCoreUtils.getUserSessionProvider();
            ManageableRepository manageableRepository = repositoryService.getCurrentRepository();
            DriveData drive = manageDriveService.getDriveByName(Text.escapeIllegalJcrChars(driverName));
            workspaceName = drive.getWorkspace();
            Session session = sessionProvider.getSession(workspaceName, manageableRepository);

            String driverHomePath = drive.getHomePath();
            String itemPath = driverHomePath
                    + ((currentFolder != null && !"".equals(currentFolder) && !driverHomePath.endsWith("/")) ? "/"
                            : "")
                    + currentFolder;
            ConversationState conversationState = ConversationState.getCurrent();
            String userId = conversationState.getIdentity().getUserId();
            itemPath = Utils.getPersonalDrivePath(itemPath, userId);
            Node node = (Node) session.getItem(Text.escapeIllegalJcrChars(itemPath));
            return buildXMLResponseForChildren(node, null, filterBy, session, currentPortal,
                    Text.escapeIllegalJcrChars(driverName), type);

        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Error when perform getFoldersAndFiles: ", e);
            }
        }

        DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
        return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
    }

    /**
     * Checks if the drive can upload a new file.
     *
     * @return Response containing the status indicating if upload is available.
     * @throws Exception
     * @anchor DriverConnector.checkUploadAvailable
     */
    @GET
    @Path("/uploadFile/checkUploadAvailable/")
    @RolesAllowed("users")
    public Response checkUploadAvailable() throws Exception {
        CacheControl cacheControl = new CacheControl();
        cacheControl.setNoCache(true);
        DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
        String msg = fileUploadHandler.getUploadingFileCount() < limitCountServer_ ? "uploadAvailable"
                : "uploadNotAvailable";
        return Response.ok(createDOMResponse(msg), MediaType.TEXT_XML).cacheControl(cacheControl)
                .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
    }

    /**
     * Uploads a file.
     *
     * @param uploadId The Id of the uploaded file.
     * @return The response.
     * @throws Exception The exception
     *
     * @anchor DriverConnector.uploadFile
     */
    @POST
    @Path("/uploadFile/upload/")
    @RolesAllowed("users")
    public Response uploadFile(@Context HttpServletRequest servletRequest, @QueryParam("uploadId") String uploadId)
            throws Exception {
        //check if number of file uploading is greater than the limit
        //    if (fileUploadHandler.getUploadingFileCount() >= limitCountServer_) {
        //      CacheControl cacheControl = new CacheControl();
        //      cacheControl.setNoCache(true);
        //      DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
        //      return Response.ok(createDOMResponse("uploadNotAvailable"), MediaType.TEXT_XML)
        //                      .cacheControl(cacheControl)
        //                      .header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date()))
        //                      .build();
        //    }
        return fileUploadHandler.upload(servletRequest, uploadId, limit);
    }

    /**
     * Check the status of uploading a file, such as aborting, deleting or progressing the file.
     *
     * @param repositoryName The repository name.
     * @param workspaceName The workspace name.
     * @param driverName The drive name.
     * @param currentFolder The current folder.
     * @param currentPortal The portal name.
     * @param language The language file.
     * @param fileName The file name.
     * @return The response
     * @throws Exception The exception
     *
     * @anchor DriverConnector.checkExistence
     */
    @GET
    @Path("/uploadFile/checkExistence/")
    @RolesAllowed("users")
    public Response checkExistence(@QueryParam("repositoryName") String repositoryName,
            @QueryParam("workspaceName") String workspaceName, @QueryParam("driverName") String driverName,
            @QueryParam("currentFolder") String currentFolder, @QueryParam("currentPortal") String currentPortal,
            @QueryParam("language") String language, @QueryParam("fileName") String fileName) throws Exception {
        try {
            // Check file existence
            Node currentFolderNode = getParentFolderNode(workspaceName, Text.escapeIllegalJcrChars(driverName),
                    Text.escapeIllegalJcrChars(currentFolder));

            if (StringUtils.isNotEmpty(fileName))
                fileName = URLDecoder.decode(fileName, "UTF-8");
            return fileUploadHandler.checkExistence(currentFolderNode, fileName);
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Error when perform processUpload: ", e);
            }
        }

        DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
        return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
    }

    /**
     * Clean file name
     * 
     * @param fileName original file name
     * @return the response
     */

    @GET
    @Path("/uploadFile/cleanName")
    @RolesAllowed("users")
    public Response cleanName(@QueryParam("fileName") String fileName) throws Exception {
        return fileUploadHandler.cleanName(fileName);
    }

    /**
     * Controls the process of uploading a file, such as aborting, deleting or progressing the file.
     *
     * @param repositoryName The repository name.
     * @param workspaceName The workspace name.
     * @param driverName The drive name.
     * @param currentFolder The current folder.
     * @param currentPortal The current portal.
     * @param userId The user identity.
     * @param jcrPath The path of the file.
     * @param action The action.
     * @param language The language.
     * @param fileName The file name.
     * @param uploadId The Id of upload.
     * @param existenceAction Checks if an action exists or not.
     * @return The response.
     * @throws Exception The exception
     *
     * @anchor DriverConnector.processUpload
     */
    @GET
    @Path("/uploadFile/control/")
    @RolesAllowed("users")
    public Response processUpload(@QueryParam("repositoryName") String repositoryName,
            @QueryParam("workspaceName") String workspaceName, @QueryParam("driverName") String driverName,
            @QueryParam("currentFolder") String currentFolder, @QueryParam("currentPortal") String currentPortal,
            @QueryParam("userId") String userId, @QueryParam("jcrPath") String jcrPath,
            @QueryParam("action") String action, @QueryParam("language") String language,
            @QueryParam("fileName") String fileName, @QueryParam("uploadId") String uploadId,
            @QueryParam("existenceAction") String existenceAction, @QueryParam("srcAction") String srcAction)
            throws Exception {
        try {
            // Check upload status
            if (StringUtils.isNotEmpty(fileName))
                fileName = URLDecoder.decode(fileName, "UTF-8");
            Response msgResponse = fileUploadHandler.checkStatus(uploadId, language);
            if (msgResponse != null)
                return msgResponse;

            if ((repositoryName != null) && (workspaceName != null) && (driverName != null)
                    && (currentFolder != null)) {
                ManageDriveService manageDriveService = WCMCoreUtils.getService(ManageDriveService.class);
                workspaceName = workspaceName != null ? workspaceName
                        : manageDriveService.getDriveByName(Text.escapeIllegalJcrChars(driverName)).getWorkspace();

                Node currentFolderNode = getParentFolderNode(workspaceName, Text.escapeIllegalJcrChars(driverName),
                        Text.escapeIllegalJcrChars(currentFolder));
                fileName = Text.escapeIllegalJcrChars(fileName);
                return createProcessUploadResponse(workspaceName, currentFolderNode, currentPortal, userId,
                        Text.escapeIllegalJcrChars(jcrPath), action, language, fileName, uploadId, existenceAction);
            }
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Error when perform processUpload: ", e);
            }
        }

        DateFormat dateFormat = new SimpleDateFormat(IF_MODIFIED_SINCE_DATE_FORMAT);
        return Response.ok().header(LAST_MODIFIED_PROPERTY, dateFormat.format(new Date())).build();
    }

    /**
     * Gets the drives by user Id.
     *
     * @param userId the user Id
     *
     * @return the drives by user Id
     *
     * @throws Exception the exception
     */
    private List<DriveData> getDriversByUserId(String userId) throws Exception {
        ManageDriveService driveService = WCMCoreUtils.getService(ManageDriveService.class);
        List<String> userRoles = getMemberships(userId);
        return driveService.getDriveByUserRoles(userId, userRoles);
    }

    /**
     * Appends drives.
     *
     * @param document The document.
     * @param driversList The drivers list.
     * @param groupName The group name.
     *
     * @return The element.
     */
    private Element appendDrivers(Document document, List<DriveData> driversList, String groupName, String lang)
            throws Exception {
        Element folders = document.createElement("Folders");
        folders.setAttribute("name", resolveDriveLabel(groupName, lang));
        folders.setAttribute("isUpload", "false");
        for (DriveData driver : driversList) {
            String repository = WCMCoreUtils.getRepository().getConfiguration().getName();
            String workspace = driver.getWorkspace();
            String path = driver.getHomePath();
            String name = driver.getName();
            Element folder = document.createElement("Folder");
            NodeLocation nodeLocation = new NodeLocation(repository, workspace, path);
            Node driveNode = NodeLocation.getNodeByLocation(nodeLocation);
            if (driveNode == null)
                continue;
            folder.setAttribute("name", name);
            folder.setAttribute("label", resolveDriveLabel(name, lang));
            folder.setAttribute("url", FCKUtils.createWebdavURL(driveNode));
            folder.setAttribute("folderType", "exo:drive");
            folder.setAttribute("path", path);
            folder.setAttribute("repository", repository);
            folder.setAttribute("workspace", workspace);
            folder.setAttribute("isUpload", "true");
            folder.setAttribute("hasFolderChild", String.valueOf(this.hasFolderChild(driveNode)));
            folder.setAttribute("nodeTypeCssClass", Utils.getNodeTypeIcon(driveNode, "uiIcon16x16"));

            folders.appendChild(folder);
        }
        return folders;
    }

    private String resolveDriveLabel(String name, String lang) {
        if (resourceBundleService == null) {
            resourceBundleService = WCMCoreUtils.getService(ResourceBundleService.class);
            resourceBundleNames = resourceBundleService.getSharedResourceBundleNames();
            sharedResourceBundle = resourceBundleService.getResourceBundle(resourceBundleNames, this.lang);
        }
        try {
            if (!this.lang.getLanguage().equals(lang)) {
                this.lang = new Locale(lang);
                sharedResourceBundle = resourceBundleService.getResourceBundle(resourceBundleNames, this.lang);
            }
            return sharedResourceBundle.getString("ContentSelector.title." + name.replaceAll(" ", ""));
        } catch (MissingResourceException e) {
            if (LOG.isDebugEnabled()) {
                LOG.debug(e.getMessage());
            }
        }
        return name;
    }

    /**
     * Personal drivers.
     *
     * @param driveList the drive list
     *
     * @return the list< drive data>
     * @throws Exception
     */
    private List<DriveData> personalDrivers(List<DriveData> driveList, String userId) throws Exception {
        List<DriveData> personalDrivers = new ArrayList<DriveData>();
        NodeHierarchyCreator nodeHierarchyCreator = WCMCoreUtils.getService(NodeHierarchyCreator.class);
        SessionProvider sessionProvider = WCMCoreUtils.getSystemSessionProvider();
        Node userNode = nodeHierarchyCreator.getUserNode(sessionProvider, userId);
        for (DriveData drive : driveList) {
            String driveHomePath = Utils.getPersonalDrivePath(drive.getHomePath(), userId);
            if (driveHomePath.startsWith(userNode.getPath())) {
                drive.setHomePath(driveHomePath);
                personalDrivers.add(drive);
            }
        }
        Collections.sort(personalDrivers);
        return personalDrivers;
    }

    /**
     * Group drivers.
     *
     * @param driverList the driver list
     * @return the list< drive data>
     * @throws Exception the exception
     */
    private List<DriveData> groupDrivers(List<DriveData> driverList) throws Exception {
        ManageDriveService driveService = WCMCoreUtils.getService(ManageDriveService.class);
        String currentUserId = ConversationState.getCurrent().getIdentity().getUserId();
        List<String> userRoles = this.getMemberships(currentUserId);
        return driveService.getGroupDrives(currentUserId, userRoles);
    }

    /**
     * General drivers.
     *
     * @param driverList the driver list
     *
     * @return the list< drive data>
     *
     * @throws Exception the exception
     */
    private List<DriveData> generalDrivers(List<DriveData> driverList) throws Exception {
        List<DriveData> generalDrivers = new ArrayList<DriveData>();
        NodeHierarchyCreator nodeHierarchyCreator = WCMCoreUtils.getService(NodeHierarchyCreator.class);
        String userPath = nodeHierarchyCreator.getJcrPath(BasePath.CMS_USERS_PATH);
        String groupPath = nodeHierarchyCreator.getJcrPath(BasePath.CMS_GROUPS_PATH);
        for (DriveData drive : driverList) {
            if ((!drive.getHomePath().startsWith(userPath) && !drive.getHomePath().startsWith(groupPath))
                    || drive.getHomePath().equals(userPath)) {
                generalDrivers.add(drive);
            }
        }
        return generalDrivers;
    }

    /**
     * Gets the memberships.
     *
     * @param userId the user id
     *
     * @return the memberships
     *
     * @throws Exception the exception
     */
    private List<String> getMemberships(String userId) throws Exception {
        List<String> userMemberships = new ArrayList<String>();
        userMemberships.add(userId);
        // here we must retrieve memberships of the user using the
        // IdentityRegistry Service instead of Organization Service to
        // allow JAAS based authorization
        Collection<MembershipEntry> memberships = getUserMembershipsFromIdentityRegistry(userId);
        if (memberships != null) {
            for (MembershipEntry membership : memberships) {
                String role = membership.getMembershipType() + ":" + membership.getGroup();
                userMemberships.add(role);
            }
        }

        return userMemberships;
    }

    /**
     * this method retrieves memberships of the user having the given id using the
     * IdentityRegistry service instead of the Organization service to allow JAAS
     * based authorization
     *
     * @param authenticatedUser the authenticated user id
     * @return a collection of MembershipEntry
     */
    private static Collection<MembershipEntry> getUserMembershipsFromIdentityRegistry(String authenticatedUser) {
        IdentityRegistry identityRegistry = WCMCoreUtils.getService(IdentityRegistry.class);
        Identity currentUserIdentity = identityRegistry.getIdentity(authenticatedUser);
        return currentUserIdentity.getMemberships();
    }

    private Response buildXMLResponseForChildren(Node node, String command, String filterBy, Session session,
            String currentPortal, String nodeDriveName, String type) throws Exception {
        TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
        Element rootElement = FCKUtils.createRootElement(command, node, folderHandler.getFolderType(node));
        NodeList nodeList = rootElement.getElementsByTagName("CurrentFolder");
        Element currentFolder = (Element) nodeList.item(0);
        currentFolder.setAttribute("isUpload", "true");
        Document document = rootElement.getOwnerDocument();
        Element folders = document.createElement("Folders");
        folders.setAttribute("isUpload", "true");
        Element files = document.createElement("Files");
        files.setAttribute("isUpload", "true");
        Node sourceNode = null;
        Node checkNode = null;
        List<Node> childList = new ArrayList<Node>();
        for (NodeIterator iterator = node.getNodes(); iterator.hasNext();) {
            childList.add(iterator.nextNode());
        }
        Collections.sort(childList, new NodeTitleComparator());
        for (Node child : childList) {
            String fileType = null;
            if (child.isNodeType(FCKUtils.EXO_HIDDENABLE))
                continue;
            if (TYPE_FOLDER.equals(type) && templateService.isManagedNodeType(child.getPrimaryNodeType().getName()))
                continue;

            if (child.isNodeType("exo:symlink") && child.hasProperty("exo:uuid")) {
                LinkManager linkManager = WCMCoreUtils.getService(LinkManager.class);
                sourceNode = linkManager.getTarget(child);
            } else {
                sourceNode = child;
            }

            checkNode = sourceNode != null ? sourceNode : child;

            if (isFolder(checkNode, type)) {
                // Get node name from node path to fix same name problem (ECMS-3586)
                String nodePath = child.getPath();
                Element folder = createFolderElement(document, checkNode, checkNode.getPrimaryNodeType().getName(),
                        nodePath.substring(nodePath.lastIndexOf("/") + 1, nodePath.length()), nodeDriveName, type);
                folders.appendChild(folder);
            }

            if (FILE_TYPE_ALL.equals(filterBy)
                    && (checkNode.isNodeType(NodetypeConstant.EXO_WEBCONTENT) || !isFolder(checkNode, type))) {
                fileType = FILE_TYPE_ALL;
            }

            if (FILE_TYPE_WEBCONTENT.equals(filterBy)) {
                if (checkNode.isNodeType(NodetypeConstant.EXO_WEBCONTENT)) {
                    fileType = FILE_TYPE_WEBCONTENT;
                }
            }

            if (FILE_TYPE_MEDIAS.equals(filterBy) && isMediaType(checkNode)) {
                fileType = FILE_TYPE_MEDIAS;
            }

            if (FILE_TYPE_DMSDOC.equals(filterBy) && isDMSDocument(checkNode)) {
                fileType = FILE_TYPE_DMSDOC;
            }

            if (FILE_TYPE_IMAGE.equals(filterBy) && isImageType(checkNode)) {
                fileType = FILE_TYPE_IMAGE;
            }

            if (fileType != null) {
                Element file = FCKFileHandler.createFileElement(document, fileType, checkNode, child, currentPortal,
                        linkManager);
                files.appendChild(file);
            }
        }

        rootElement.appendChild(folders);
        rootElement.appendChild(files);
        return getResponse(document);
    }

    /**
     * Checks if is folder and is not web content.
     *
     * @param checkNode the check node
     *
     * @return true, if is folder and is not web content
     *
     * @throws RepositoryException the repository exception
     */
    private boolean isFolder(Node checkNode, String type) throws RepositoryException {
        try {
            if (isDocument(checkNode, type))
                return false;
        } catch (Exception e) {
            if (LOG.isWarnEnabled()) {
                LOG.warn(e.getMessage());
            }
        }
        return checkNode.isNodeType(NodetypeConstant.NT_UNSTRUCTURED)
                || checkNode.isNodeType(NodetypeConstant.NT_FOLDER)
                || checkNode.isNodeType(NodetypeConstant.EXO_TAXONOMY);
    }

    /**
     * Check if specific node has child which is type of nt:folder or nt:unstructured.
     *
     * @param checkNode The node to be checked
     * @return True if the folder has some child.
     * @throws Exception
     */
    private boolean hasFolderChild(Node checkNode) throws Exception {
        return (Utils.hasChild(checkNode, NodetypeConstant.NT_UNSTRUCTURED)
                || Utils.hasChild(checkNode, NodetypeConstant.NT_FOLDER));
    }

    /**
     * Checks if is dMS document.(not including free layout webcontent & media & article)
     *
     * @param node the node
     *
     * @return true, if is dMS document
     *
     * @throws Exception the exception
     */
    private boolean isDMSDocument(Node node) throws Exception {
        TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
        List<String> dmsDocumentListTmp = templateService.getDocumentTemplates();
        List<String> dmsDocumentList = new ArrayList<String>();
        dmsDocumentList.addAll(dmsDocumentListTmp);
        dmsDocumentList.remove(NodetypeConstant.EXO_WEBCONTENT);
        for (String documentType : dmsDocumentList) {
            if (node.getPrimaryNodeType().isNodeType(documentType) && !isMediaType(node)
                    && !node.isNodeType(NodetypeConstant.EXO_WEBCONTENT)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Checks if specific node is document
     *
     * @param node specific Node
     * @return true: is document, false: not document
     * @throws RepositoryException
     */
    private boolean isDocument(Node node, String type) throws RepositoryException {
        TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
        List<String> documentTypeList = templateService.getDocumentTemplates();
        if (TYPE_EDITOR.equals(type)) {
            documentTypeList.remove(NodetypeConstant.EXO_WEBCONTENT);
            documentTypeList.remove(ILLUSTRATED_WEBCONTENT);
        }
        for (String documentType : documentTypeList) {
            if (node.getPrimaryNodeType().isNodeType(documentType)) {
                return true;
            }
        }
        return false;
    }

    /**
     * Checks if is media type.
     *
     * @param node the node
     *
     * @return true, if is media type
     */
    private boolean isMediaType(Node node) {
        String mimeType = "";

        try {
            mimeType = node.getNode("jcr:content").getProperty("jcr:mimeType").getString();
        } catch (Exception e) {
            return false;
        }

        for (String type : MEDIA_MIMETYPE) {
            if (mimeType.contains(type)) {
                return true;
            }
        }

        return false;
    }

    /**
     * Checks if is image type.
     *
     * @param node the node
     *
     * @return true, if is image type
     */
    private boolean isImageType(Node node) {
        String mimeType = "";

        try {
            mimeType = node.getNode("jcr:content").getProperty("jcr:mimeType").getString();
        } catch (Exception e) {
            return false;
        }

        for (String type : IMAGE_MIMETYPE) {
            if (mimeType.contains(type)) {
                return true;
            }
        }

        return false;
    }

    /* (non-Javadoc)
     * @see org.exoplatform.wcm.connector.BaseConnector#getContentStorageType()
     */
    @Override
    protected String getContentStorageType() throws Exception {
        return null;
    }

    /* (non-Javadoc)
     * @see org.exoplatform.wcm.connector.BaseConnector#getRootContentStorage(javax.jcr.Node)
     */
    @Override
    protected Node getRootContentStorage(Node node) throws Exception {
        try {
            PortalFolderSchemaHandler folderSchemaHandler = webSchemaConfigService
                    .getWebSchemaHandlerByType(PortalFolderSchemaHandler.class);
            return folderSchemaHandler.getImagesFolder(node);
        } catch (Exception e) {
            WebContentSchemaHandler webContentSchemaHandler = webSchemaConfigService
                    .getWebSchemaHandlerByType(WebContentSchemaHandler.class);
            return webContentSchemaHandler.getImagesFolders(node);
        }
    }

    /**
     *
     * @param workspaceName The workspace name.
     * @param currentFolderNode The current folder.
     * @param siteName The portal name.
     * @param userId  The user Id.
     * @param jcrPath The path of the file.
     * @param action The action.
     * @param language The language.
     * @param fileName The file name.
     * @param uploadId The Id of upload.
     * @param existenceAction Checks if an action exists.
     * @return the response
     * @throws Exception the exception
     */
    protected Response createProcessUploadResponse(String workspaceName, Node currentFolderNode, String siteName,
            String userId, String jcrPath, String action, String language, String fileName, String uploadId,
            String existenceAction) throws Exception {
        if (FileUploadHandler.SAVE_ACTION.equals(action)) {
            CacheControl cacheControl = new CacheControl();
            cacheControl.setNoCache(true);
            return fileUploadHandler.saveAsNTFile(currentFolderNode, uploadId, fileName, language, siteName, userId,
                    existenceAction);
        } else if (FileUploadHandler.SAVE_NEW_VERSION_ACTION.equals(action)) {
            CacheControl cacheControl = new CacheControl();
            cacheControl.setNoCache(true);
            return fileUploadHandler.saveAsNTFile(currentFolderNode, uploadId, fileName, language, siteName, userId,
                    existenceAction, true);
        }
        return fileUploadHandler.control(uploadId, action);
    }

    /**
     * Gets the parent folder node.
     *
     * @param workspaceName the workspace name
     * @param driverName the driver name
     * @param currentFolder the current folder
     *
     * @return the parent folder node
     *
     * @throws Exception the exception
     */
    private Node getParentFolderNode(String workspaceName, String driverName, String currentFolder)
            throws Exception {
        SessionProvider sessionProvider = WCMCoreUtils.getUserSessionProvider();
        ManageableRepository manageableRepository = WCMCoreUtils.getRepository();
        Session session = sessionProvider.getSession(workspaceName, manageableRepository);
        ManageDriveService manageDriveService = WCMCoreUtils.getService(ManageDriveService.class);
        DriveData driveData = manageDriveService.getDriveByName(driverName);
        String parentPath = (driveData != null ? driveData.getHomePath() : "");
        NodeHierarchyCreator nodeHierarchyCreator = WCMCoreUtils.getService(NodeHierarchyCreator.class);
        if (driveData != null && driveData.getHomePath()
                .startsWith(nodeHierarchyCreator.getJcrPath(BasePath.CMS_USERS_PATH) + "/${userId}")) {
            parentPath = Utils.getPersonalDrivePath(driveData.getHomePath(),
                    ConversationState.getCurrent().getIdentity().getUserId());
        }
        ;
        parentPath += ((currentFolder != null && currentFolder.length() != 0) ? "/" : "") + currentFolder;
        parentPath = parentPath.replace("//", "/");
        //return result;
        return getTargetNode(session, parentPath);
    }

    private Node getTargetNode(Session session, String path) throws Exception {
        Node node = null;
        if (linkManager_ == null) {
            linkManager_ = WCMCoreUtils.getService(LinkManager.class);
        }
        if (nodeFinder_ == null) {
            nodeFinder_ = WCMCoreUtils.getService(NodeFinder.class);
        }
        node = (Node) nodeFinder_.getItem(session, path, true);
        return node;
    }

    private Element createFolderElement(Document document, Node child, String folderType, String childName,
            String nodeDriveName, String type) throws Exception {
        Element folder = document.createElement("Folder");

        folder.setAttribute("name", childName.replaceAll("%", "%25"));
        folder.setAttribute("title", Utils.getTitle(child).replaceAll("%", "%25"));
        folder.setAttribute("url", FCKUtils.createWebdavURL(child));
        folder.setAttribute("folderType", folderType);

        if (TYPE_FOLDER.equals(type) || TYPE_CONTENT.equals(type)) {
            boolean hasFolderChild = (getChildOfType(child, NodetypeConstant.NT_UNSTRUCTURED, type) != null)
                    || (getChildOfType(child, NodetypeConstant.NT_FOLDER, type) != null);
            folder.setAttribute("hasFolderChild", String.valueOf(hasFolderChild));
        } else {
            folder.setAttribute("hasFolderChild", String.valueOf(this.hasFolderChild(child)));
        }
        folder.setAttribute("path", child.getPath());
        folder.setAttribute("isUpload", "true");
        folder.setAttribute("nodeTypeCssClass", Utils.getNodeTypeIcon(child, "uiIcon16x16"));

        if (nodeDriveName != null && nodeDriveName.length() > 0)
            folder.setAttribute("nodeDriveName", nodeDriveName);
        return folder;
    }

    /**
     * Check isFolder (skip all templateNodetype)
     * @param node
     * @param childType
     * @return
     * @throws Exception
     */
    private Node getChildOfType(Node node, String childType, String type) throws Exception {
        TemplateService templateService = WCMCoreUtils.getService(TemplateService.class);
        if (node == null) {
            return null;
        }
        NodeIterator iter = node.getNodes();
        while (iter.hasNext()) {
            Node child = iter.nextNode();
            if (!isDocument(child, type) && child.isNodeType(childType)
                    && !templateService.isManagedNodeType(child.getPrimaryNodeType().getName())
                    && !"exo:thumbnails".equals(child.getPrimaryNodeType().getName())) {
                return child;
            }
        }
        return null;
    }

    /**
     * returns a DOMSource object containing given message
     * @param message the message
     * @return DOMSource object
     * @throws Exception
     */
    private DOMSource createDOMResponse(String message) throws Exception {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        DocumentBuilder builder = factory.newDocumentBuilder();
        Document doc = builder.newDocument();
        Element rootElement = doc.createElement(message);
        doc.appendChild(rootElement);
        return new DOMSource(doc);
    }

    private static class NodeTitleComparator implements Comparator<Node> {
        @Override
        public int compare(Node node1, Node node2) {
            try {
                String titleNode1 = Utils.getTitle(node1);
                String titleNode2 = Utils.getTitle(node2);
                return titleNode1.compareToIgnoreCase(titleNode2);
            } catch (Exception e) {
                return 0;
            }
        }
    }
}