001/*
002 * This library is part of OpenCms -
003 * the Open Source Content Management System
004 *
005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com)
006 *
007 * This library is free software; you can redistribute it and/or
008 * modify it under the terms of the GNU Lesser General Public
009 * License as published by the Free Software Foundation; either
010 * version 2.1 of the License, or (at your option) any later version.
011 *
012 * This library is distributed in the hope that it will be useful,
013 * but WITHOUT ANY WARRANTY; without even the implied warranty of
014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015 * Lesser General Public License for more details.
016 *
017 * For further information about Alkacon Software, please see the
018 * company website: http://www.alkacon.com
019 *
020 * For further information about OpenCms, please see the
021 * project website: http://www.opencms.org
022 *
023 * You should have received a copy of the GNU Lesser General Public
024 * License along with this library; if not, write to the Free Software
025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
026 */
027
028package org.opencms.gwt;
029
030import org.opencms.ade.configuration.CmsADEConfigData;
031import org.opencms.ade.configuration.CmsGalleryDisabledTypesMode;
032import org.opencms.db.CmsResourceState;
033import org.opencms.file.CmsObject;
034import org.opencms.file.CmsProject;
035import org.opencms.file.CmsPropertyDefinition;
036import org.opencms.file.CmsResource;
037import org.opencms.file.CmsResourceFilter;
038import org.opencms.file.CmsUser;
039import org.opencms.file.CmsVfsResourceNotFoundException;
040import org.opencms.flex.CmsFlexController;
041import org.opencms.gwt.shared.CmsBroadcastMessage;
042import org.opencms.gwt.shared.CmsCategoryTreeEntry;
043import org.opencms.gwt.shared.CmsContextMenuEntryBean;
044import org.opencms.gwt.shared.CmsCoreData;
045import org.opencms.gwt.shared.CmsCoreData.AdeContext;
046import org.opencms.gwt.shared.CmsCoreData.UserInfo;
047import org.opencms.gwt.shared.CmsLockInfo;
048import org.opencms.gwt.shared.CmsResourceCategoryInfo;
049import org.opencms.gwt.shared.CmsReturnLinkInfo;
050import org.opencms.gwt.shared.CmsTinyMCEData;
051import org.opencms.gwt.shared.CmsUploadRestrictionInfo;
052import org.opencms.gwt.shared.CmsUserSettingsBean;
053import org.opencms.gwt.shared.CmsValidationQuery;
054import org.opencms.gwt.shared.CmsValidationResult;
055import org.opencms.gwt.shared.rpc.I_CmsCoreService;
056import org.opencms.i18n.CmsMessages;
057import org.opencms.lock.CmsLock;
058import org.opencms.main.CmsBroadcast;
059import org.opencms.main.CmsException;
060import org.opencms.main.CmsIllegalArgumentException;
061import org.opencms.main.CmsLog;
062import org.opencms.main.CmsSessionInfo;
063import org.opencms.main.OpenCms;
064import org.opencms.module.CmsModule;
065import org.opencms.relations.CmsCategory;
066import org.opencms.relations.CmsCategoryService;
067import org.opencms.security.CmsPasswordInfo;
068import org.opencms.security.CmsRole;
069import org.opencms.security.CmsRoleManager;
070import org.opencms.security.CmsSecurityException;
071import org.opencms.site.CmsSite;
072import org.opencms.ui.CmsUserIconHelper;
073import org.opencms.ui.CmsVaadinUtils;
074import org.opencms.ui.I_CmsDialogContext;
075import org.opencms.ui.I_CmsDialogContextWithAdeContext;
076import org.opencms.ui.actions.I_CmsADEAction;
077import org.opencms.ui.apps.A_CmsWorkplaceApp;
078import org.opencms.ui.apps.CmsFileExplorerConfiguration;
079import org.opencms.ui.components.CmsBasicDialog.DialogWidth;
080import org.opencms.ui.contextmenu.CmsContextMenuTreeBuilder;
081import org.opencms.ui.contextmenu.CmsMenuItemVisibilityMode;
082import org.opencms.ui.contextmenu.I_CmsContextMenuItem;
083import org.opencms.ui.dialogs.CmsEmbeddedDialogsUI;
084import org.opencms.util.CmsFileUtil;
085import org.opencms.util.CmsStringUtil;
086import org.opencms.util.CmsTreeNode;
087import org.opencms.util.CmsUUID;
088import org.opencms.workplace.CmsWorkplace;
089import org.opencms.workplace.CmsWorkplaceLoginHandler;
090import org.opencms.xml.containerpage.CmsADESessionCache;
091
092import java.util.ArrayList;
093import java.util.Collection;
094import java.util.Collections;
095import java.util.HashMap;
096import java.util.HashSet;
097import java.util.LinkedHashMap;
098import java.util.List;
099import java.util.Locale;
100import java.util.Map;
101import java.util.Map.Entry;
102import java.util.Set;
103
104import javax.servlet.http.HttpServletRequest;
105
106import org.apache.commons.collections.Buffer;
107import org.apache.commons.logging.Log;
108
109import com.vaadin.ui.Component;
110import com.vaadin.ui.Window;
111
112/**
113 * Provides general core services.<p>
114 *
115 * @since 8.0.0
116 *
117 * @see org.opencms.gwt.CmsCoreService
118 * @see org.opencms.gwt.shared.rpc.I_CmsCoreService
119 * @see org.opencms.gwt.shared.rpc.I_CmsCoreServiceAsync
120 */
121public class CmsCoreService extends CmsGwtService implements I_CmsCoreService {
122
123    /** The editor back-link URI. */
124    private static final String EDITOR_BACKLINK_URI = "/system/workplace/commons/editor-backlink.html";
125
126    /** The xml-content editor URI. */
127    private static final String EDITOR_URI = "/system/workplace/editors/editor.jsp";
128
129    /** The log instance for this class. */
130    private static final Log LOG = CmsLog.getLog(CmsCoreService.class);
131
132    /** Serialization uid. */
133    private static final long serialVersionUID = 5915848952948986278L;
134
135    /**
136     * Builds the tree structure for the given categories.<p>
137     *
138     * @param cms the current cms context
139     * @param categories the categories
140     *
141     * @return the tree root element
142     */
143    public static List<CmsCategoryTreeEntry> buildCategoryTree(CmsObject cms, List<CmsCategory> categories) {
144
145        List<CmsCategoryTreeEntry> result = new ArrayList<CmsCategoryTreeEntry>();
146        for (CmsCategory category : categories) {
147            CmsCategoryTreeEntry current = new CmsCategoryTreeEntry(category);
148            current.setSitePath(cms.getRequestContext().removeSiteRoot(category.getRootPath()));
149            String parentPath = CmsResource.getParentFolder(current.getPath());
150            CmsCategoryTreeEntry parent = null;
151            parent = findCategory(result, parentPath);
152            if (parent != null) {
153                parent.addChild(current);
154            } else {
155                result.add(current);
156            }
157        }
158        return result;
159    }
160
161    /**
162     * Helper method for getting the category beans for the given site path.<p>
163     *
164     * @param cms the CMS context to use
165     * @param sitePath the site path
166     * @return the list of category beans
167     *
168     * @throws CmsException if something goes wrong
169     */
170    public static List<CmsCategoryTreeEntry> getCategoriesForSitePathStatic(CmsObject cms, String sitePath)
171    throws CmsException {
172
173        return getCategoriesForSitePathStatic(cms, sitePath, null);
174    }
175
176    /**
177     * Helper method for getting the category beans for the given site path.<p>
178     *
179     * @param cms the CMS context to use
180     * @param sitePath the site path
181     * @param localCategoryRepositoryPath the categories for this repository are added separately
182     * @return the list of category beans
183     *
184     * @throws CmsException if something goes wrong
185     */
186    public static List<CmsCategoryTreeEntry> getCategoriesForSitePathStatic(
187        CmsObject cms,
188        String sitePath,
189        String localCategoryRepositoryPath)
190    throws CmsException {
191
192        List<CmsCategoryTreeEntry> result;
193        CmsCategoryService catService = CmsCategoryService.getInstance();
194        List<CmsCategory> categories;
195        Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
196        // get the categories
197        if (null == localCategoryRepositoryPath) {
198            categories = catService.readCategories(cms, "", true, sitePath);
199            categories = catService.localizeCategories(cms, categories, wpLocale);
200            result = buildCategoryTree(cms, categories);
201        } else {
202            List<String> repositories = catService.getCategoryRepositories(cms, sitePath);
203            repositories.remove(localCategoryRepositoryPath);
204            categories = catService.readCategoriesForRepositories(cms, "", true, repositories);
205            categories = catService.localizeCategories(cms, categories, wpLocale);
206            result = buildCategoryTree(cms, categories);
207            categories = catService.readCategoriesForRepositories(
208                cms,
209                "",
210                true,
211                Collections.singletonList(localCategoryRepositoryPath));
212            categories = catService.localizeCategories(cms, categories, wpLocale);
213            List<CmsCategoryTreeEntry> localCategories = buildCategoryTree(cms, categories);
214            result.addAll(localCategories);
215        }
216
217        return result;
218    }
219
220    /**
221     * Returns the context menu entries for the given URI.<p>
222     *
223     * @param cms the cms context
224     * @param structureId the currently requested structure id
225     * @param context the ade context (sitemap or containerpage)
226     *
227     * @return the context menu entries
228     */
229    public static List<CmsContextMenuEntryBean> getContextMenuEntries(
230        final CmsObject cms,
231        CmsUUID structureId,
232        final AdeContext context) {
233
234        Map<String, CmsContextMenuEntryBean> entries = new LinkedHashMap<String, CmsContextMenuEntryBean>();
235        try {
236            final List<CmsResource> resources;
237            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.ALL.addRequireVisible());
238            // in case of sitemap editor check visibility with empty list
239            if (context.equals(AdeContext.sitemapeditor)) {
240                resources = Collections.emptyList();
241                cms.getRequestContext().setAttribute(I_CmsDialogContext.ATTR_SITEMAP_CONFIG_RESOURCE, resource);
242            } else {
243                resources = Collections.singletonList(resource);
244            }
245            Locale locale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
246            // context to check item visibility
247            I_CmsDialogContext dcontext = new I_CmsDialogContextWithAdeContext() {
248
249                public void error(Throwable error) {
250
251                    // not supported
252                }
253
254                public void finish(CmsProject project, String siteRoot) {
255
256                    // not supported
257                }
258
259                public void finish(Collection<CmsUUID> result) {
260
261                    // not supported
262                }
263
264                public void focus(CmsUUID id) {
265
266                    // not supported
267                }
268
269                public AdeContext getAdeContext() {
270
271                    return context;
272                }
273
274                public List<CmsUUID> getAllStructureIdsInView() {
275
276                    return null;
277                }
278
279                public String getAppId() {
280
281                    return context.name();
282                }
283
284                public CmsObject getCms() {
285
286                    return cms;
287                }
288
289                public ContextType getContextType() {
290
291                    ContextType type;
292                    switch (context) {
293                        case pageeditor:
294                        case editprovider:
295                            type = ContextType.containerpageToolbar;
296                            break;
297                        case sitemapeditor:
298                            type = ContextType.sitemapToolbar;
299                            break;
300                        default:
301                            type = ContextType.fileTable;
302                    }
303                    return type;
304                }
305
306                public List<CmsResource> getResources() {
307
308                    return resources;
309                }
310
311                public void navigateTo(String appId) {
312
313                    // not supported
314                }
315
316                public void onViewChange() {
317
318                    // not supported
319                }
320
321                public void reload() {
322
323                    // not supported
324                }
325
326                public void setWindow(Window window) {
327
328                    // not supported
329                }
330
331                public void start(String title, Component dialog) {
332
333                    // not supported
334                }
335
336                public void start(String title, Component dialog, DialogWidth width) {
337
338                    // not supported
339                }
340
341                public void updateUserInfo() {
342
343                    // not supported
344                }
345            };
346            CmsContextMenuTreeBuilder builder = new CmsContextMenuTreeBuilder(dcontext);
347            List<I_CmsContextMenuItem> items = new ArrayList<I_CmsContextMenuItem>();
348            CmsTreeNode<I_CmsContextMenuItem> root = builder.buildAll(
349                OpenCms.getWorkplaceAppManager().getMenuItemProvider().getMenuItems());
350            for (CmsTreeNode<I_CmsContextMenuItem> child : root.getChildren()) {
351                child.addDataInPreOrder(items);
352            }
353            Map<String, List<CmsContextMenuEntryBean>> submenus = new HashMap<String, List<CmsContextMenuEntryBean>>();
354            for (I_CmsContextMenuItem item : items) {
355                if (!item.isLeafItem()) {
356                    CmsMenuItemVisibilityMode visibility = item.getVisibility(dcontext);
357                    entries.put(
358                        item.getId(),
359                        new CmsContextMenuEntryBean(
360                            visibility.isActive(),
361                            true,
362                            null,
363                            item.getTitle(locale),
364                            null,
365                            CmsStringUtil.isEmptyOrWhitespaceOnly(visibility.getMessageKey())
366                            ? null
367                            : OpenCms.getWorkplaceManager().getMessages(locale).getString(visibility.getMessageKey()),
368                            false,
369                            new ArrayList<CmsContextMenuEntryBean>()));
370
371                } else if ((item instanceof I_CmsADEAction) && ((I_CmsADEAction)item).isAdeSupported()) {
372                    CmsMenuItemVisibilityMode visibility = item.getVisibility(dcontext);
373
374                    String jspPath = ((I_CmsADEAction)item).getJspPath();
375                    if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(jspPath)) {
376                        jspPath = OpenCms.getLinkManager().substituteLink(cms, jspPath);
377                    }
378                    CmsContextMenuEntryBean itemBean = new CmsContextMenuEntryBean(
379                        visibility.isActive(),
380                        true,
381                        jspPath,
382                        item.getTitle(locale),
383                        ((I_CmsADEAction)item).getCommandClassName(),
384                        CmsStringUtil.isEmptyOrWhitespaceOnly(visibility.getMessageKey())
385                        ? null
386                        : OpenCms.getWorkplaceManager().getMessages(locale).getString(visibility.getMessageKey()),
387                        false,
388                        null);
389                    Map<String, String> params = ((I_CmsADEAction)item).getParams();
390                    if (params != null) {
391                        params = new HashMap<String, String>(params);
392                        for (Entry<String, String> param : params.entrySet()) {
393                            String value = CmsVfsService.prepareFileNameForEditor(cms, resource, param.getValue());
394                            param.setValue(value);
395                        }
396                        itemBean.setParams(params);
397                    }
398                    entries.put(item.getId(), itemBean);
399                    if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(item.getParentId())) {
400                        List<CmsContextMenuEntryBean> submenu;
401                        if (submenus.containsKey(item.getParentId())) {
402                            submenu = submenus.get(item.getParentId());
403                        } else {
404                            submenu = new ArrayList<CmsContextMenuEntryBean>();
405                            submenus.put(item.getParentId(), submenu);
406                        }
407                        submenu.add(itemBean);
408                    }
409                }
410            }
411            List<CmsContextMenuEntryBean> result = new ArrayList<CmsContextMenuEntryBean>();
412            for (I_CmsContextMenuItem item : items) {
413                if (entries.containsKey(item.getId())) {
414                    if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(item.getParentId())) {
415                        if (entries.containsKey(item.getParentId())) {
416                            CmsContextMenuEntryBean parent = entries.get(item.getParentId());
417                            if (parent.getSubMenu() != null) {
418                                parent.getSubMenu().add(entries.get(item.getId()));
419                            }
420                        }
421                    } else {
422                        result.add(entries.get(item.getId()));
423                    }
424                }
425            }
426            return result;
427        } catch (CmsException e) {
428            // ignore, the user probably has not enough permissions to read the resource
429            LOG.debug(e.getLocalizedMessage(), e);
430        }
431        return Collections.emptyList();
432    }
433
434    /**
435     * Returns the file explorer link prefix. Append resource site path for complete link.<p>
436     *
437     * @param cms the cms context
438     * @param siteRoot the site root
439     *
440     * @return the file explorer link prefix
441     */
442    public static String getFileExplorerLink(CmsObject cms, String siteRoot) {
443
444        return CmsVaadinUtils.getWorkplaceLink(
445            CmsFileExplorerConfiguration.APP_ID,
446            cms.getRequestContext().getCurrentProject().getUuid()
447                + A_CmsWorkplaceApp.PARAM_SEPARATOR
448                + siteRoot
449                + A_CmsWorkplaceApp.PARAM_SEPARATOR);
450    }
451
452    /**
453     * Returns the workplace link.<p>
454     *
455     * @param cms the cms context
456     * @param structureId the structure id of the current resource
457     *
458     * @return the workplace link
459     */
460    public static String getVaadinWorkplaceLink(CmsObject cms, CmsUUID structureId) {
461
462        String resourceRootFolder = null;
463
464        if (structureId != null) {
465            try {
466                resourceRootFolder = CmsResource.getFolderPath(
467                    cms.readResource(structureId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED).getRootPath());
468            } catch (CmsException e) {
469                LOG.debug("Error reading resource for workplace link.", e);
470            }
471        }
472        if (resourceRootFolder == null) {
473            resourceRootFolder = cms.getRequestContext().getSiteRoot();
474        }
475        return getVaadinWorkplaceLink(cms, resourceRootFolder);
476
477    }
478
479    /**
480     * Returns the workplace link.<p>
481     *
482     * @param cms the cms context
483     * @param resourceRootFolder the resource folder root path
484     *
485     * @return the workplace link
486     */
487    public static String getVaadinWorkplaceLink(CmsObject cms, String resourceRootFolder) {
488
489        CmsSite site = OpenCms.getSiteManager().getSiteForRootPath(resourceRootFolder);
490        String siteRoot = site != null
491        ? site.getSiteRoot()
492        : OpenCms.getSiteManager().startsWithShared(resourceRootFolder)
493        ? OpenCms.getSiteManager().getSharedFolder()
494        : "";
495        String sitePath = resourceRootFolder.substring(siteRoot.length());
496        String link = getFileExplorerLink(cms, siteRoot) + sitePath;
497        return link;
498    }
499
500    /**
501     * Internal helper method for getting a validation service.<p>
502     *
503     * @param name the class name of the validation service
504     *
505     * @return the validation service
506     *
507     * @throws CmsException if something goes wrong
508     */
509    public static I_CmsValidationService getValidationService(String name) throws CmsException {
510
511        try {
512            Class<?> cls = Class.forName(name, false, I_CmsValidationService.class.getClassLoader());
513            if (!I_CmsValidationService.class.isAssignableFrom(cls)) {
514                throw new CmsIllegalArgumentException(
515                    Messages.get().container(Messages.ERR_VALIDATOR_INCORRECT_TYPE_1, name));
516            }
517            return (I_CmsValidationService)cls.newInstance();
518        } catch (ClassNotFoundException e) {
519            throw new CmsException(Messages.get().container(Messages.ERR_VALIDATOR_INSTANTIATION_FAILED_1, name), e);
520        } catch (InstantiationException e) {
521            throw new CmsException(Messages.get().container(Messages.ERR_VALIDATOR_INSTANTIATION_FAILED_1, name), e);
522        } catch (IllegalAccessException e) {
523            throw new CmsException(Messages.get().container(Messages.ERR_VALIDATOR_INSTANTIATION_FAILED_1, name), e);
524        }
525    }
526
527    /**
528     * Instantiates a class given its name using its default constructor.<p>
529     *
530     * Also checks whether the class with the given name is the subclass of another class/interface.<p>
531     *
532     *
533     * @param <T> the type of the interface/class passed as a parameter
534     *
535     * @param anInterface the interface or class against which the class should be checked
536     * @param className the name of the class
537     * @return a new instance of the class
538     *
539     * @throws CmsException if the instantiation fails
540     */
541    public static <T> T instantiate(Class<T> anInterface, String className) throws CmsException {
542
543        try {
544            Class<?> cls = Class.forName(className, false, anInterface.getClassLoader());
545            if (!anInterface.isAssignableFrom(cls)) {
546                // class was found, but does not implement the interface
547                throw new CmsIllegalArgumentException(
548                    Messages.get().container(
549                        Messages.ERR_INSTANTIATION_INCORRECT_TYPE_2,
550                        className,
551                        anInterface.getName()));
552            }
553
554            // we use another variable so we don't have to put the @SuppressWarnings on the method itself
555            @SuppressWarnings("unchecked")
556            Class<T> typedClass = (Class<T>)cls;
557            return typedClass.newInstance();
558        } catch (ClassNotFoundException e) {
559            throw new CmsException(Messages.get().container(Messages.ERR_INSTANTIATION_FAILED_1, className), e);
560        } catch (InstantiationException e) {
561            throw new CmsException(Messages.get().container(Messages.ERR_INSTANTIATION_FAILED_1, className), e);
562        } catch (IllegalAccessException e) {
563            throw new CmsException(Messages.get().container(Messages.ERR_INSTANTIATION_FAILED_1, className), e);
564        }
565    }
566
567    /**
568     * Implementation method for getting the link for a given return code.<p>
569     *
570     * @param cms the CMS context
571     * @param returnCode the return code
572     * @return the link for the return code
573     *
574     * @throws CmsException if something goes wrong
575     */
576    public static CmsReturnLinkInfo internalGetLinkForReturnCode(CmsObject cms, String returnCode) throws CmsException {
577
578        if (CmsUUID.isValidUUID(returnCode)) {
579            try {
580                CmsResource pageRes = cms.readResource(new CmsUUID(returnCode), CmsResourceFilter.IGNORE_EXPIRATION);
581                return new CmsReturnLinkInfo(
582                    OpenCms.getLinkManager().substituteLink(cms, pageRes),
583                    CmsReturnLinkInfo.Status.ok);
584            } catch (CmsVfsResourceNotFoundException e) {
585                LOG.debug(e.getLocalizedMessage(), e);
586                return new CmsReturnLinkInfo(null, CmsReturnLinkInfo.Status.notfound);
587            }
588        } else {
589            int colonIndex = returnCode.indexOf(':');
590            if (colonIndex >= 0) {
591                String before = returnCode.substring(0, colonIndex);
592                String after = returnCode.substring(colonIndex + 1);
593
594                if (CmsUUID.isValidUUID(before) && CmsUUID.isValidUUID(after)) {
595                    try {
596                        CmsUUID pageId = new CmsUUID(before);
597                        CmsUUID detailId = new CmsUUID(after);
598                        CmsResource pageRes = cms.readResource(pageId);
599                        CmsResource folder = pageRes.isFolder()
600                        ? pageRes
601                        : cms.readParentFolder(pageRes.getStructureId());
602                        String pageLink = OpenCms.getLinkManager().substituteLink(cms, folder);
603                        CmsResource detailRes = cms.readResource(detailId);
604                        String detailName = cms.getDetailName(
605                            detailRes,
606                            cms.getRequestContext().getLocale(),
607                            OpenCms.getLocaleManager().getDefaultLocales());
608                        String link = CmsFileUtil.removeTrailingSeparator(pageLink) + "/" + detailName;
609                        return new CmsReturnLinkInfo(link, CmsReturnLinkInfo.Status.ok);
610                    } catch (CmsVfsResourceNotFoundException e) {
611                        LOG.debug(e.getLocalizedMessage(), e);
612                        return new CmsReturnLinkInfo(null, CmsReturnLinkInfo.Status.notfound);
613
614                    }
615                }
616            }
617            throw new IllegalArgumentException("return code has wrong format");
618        }
619    }
620
621    /**
622     * Fetches the core data.<p>
623     *
624     * @param request the current request
625     *
626     * @return the core data
627     */
628    public static CmsCoreData prefetch(HttpServletRequest request) {
629
630        CmsCoreService srv = new CmsCoreService();
631        srv.setCms(CmsFlexController.getCmsObject(request));
632        srv.setRequest(request);
633        CmsCoreData result = null;
634        try {
635            result = srv.prefetch();
636        } finally {
637            srv.clearThreadStorage();
638        }
639        return result;
640    }
641
642    /**
643     * FInds a category in the given tree.<p>
644     *
645     * @param tree the the tree to search in
646     * @param path the path to search for
647     *
648     * @return the category with the given path or <code>null</code> if not found
649     */
650    private static CmsCategoryTreeEntry findCategory(List<CmsCategoryTreeEntry> tree, String path) {
651
652        if (path == null) {
653            return null;
654        }
655        // we assume that the category to find is descendant of tree
656        List<CmsCategoryTreeEntry> children = tree;
657        boolean found = true;
658        while (found) {
659            if (children == null) {
660                return null;
661            }
662            // since the categories are sorted it is faster to go backwards
663            found = false;
664            for (int i = children.size() - 1; i >= 0; i--) {
665                CmsCategoryTreeEntry child = children.get(i);
666                if (path.equals(child.getPath())) {
667                    return child;
668                }
669                if (path.startsWith(child.getPath())) {
670                    children = child.getChildren();
671                    found = true;
672                    break;
673                }
674            }
675        }
676        return null;
677    }
678
679    /**
680     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#changePassword(java.lang.String, java.lang.String, java.lang.String)
681     */
682    public String changePassword(String oldPassword, String newPassword, String newPasswordConfirm)
683    throws CmsRpcException {
684
685        CmsObject cms = getCmsObject();
686        CmsPasswordInfo passwordBean = new CmsPasswordInfo(cms);
687        Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
688        try {
689            passwordBean.setCurrentPwd(oldPassword);
690            passwordBean.setNewPwd(newPassword);
691            passwordBean.setConfirmation(newPasswordConfirm);
692            passwordBean.applyChanges();
693            return null;
694        } catch (CmsSecurityException e) {
695            LOG.error(e.getLocalizedMessage(), e);
696            return e.getMessageContainer().key(wpLocale);
697        } catch (CmsIllegalArgumentException e) {
698            LOG.warn(e.getLocalizedMessage(), e);
699            return e.getMessageContainer().key(wpLocale);
700        } catch (Exception e) {
701            error(e);
702            return null; // will never be executed
703        }
704    }
705
706    /**
707     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#createUUID()
708     */
709    public CmsUUID createUUID() {
710
711        return new CmsUUID();
712    }
713
714    /**
715     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getBroadcast()
716     */
717    @SuppressWarnings("unchecked")
718    public List<CmsBroadcastMessage> getBroadcast() {
719
720        setBroadcastPoll();
721        Set<CmsBroadcast> repeatedBroadcasts = new HashSet<CmsBroadcast>();
722        OpenCms.getWorkplaceManager().checkWorkplaceRequest(getRequest(), getCmsObject());
723        CmsSessionInfo sessionInfo = OpenCms.getSessionManager().getSessionInfo(getRequest().getSession());
724        if (sessionInfo == null) {
725            return null;
726        }
727        String sessionId = sessionInfo.getSessionId().toString();
728        Buffer messageQueue = OpenCms.getSessionManager().getBroadcastQueue(sessionId);
729        if (!messageQueue.isEmpty()) {
730            CmsMessages messages = org.opencms.workplace.Messages.get().getBundle(
731                OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject()));
732            List<CmsBroadcastMessage> result = new ArrayList<CmsBroadcastMessage>();
733            // the user has pending messages, display them all
734            while (!messageQueue.isEmpty()) {
735
736                CmsBroadcast broadcastMessage = (CmsBroadcast)messageQueue.remove();
737                if ((broadcastMessage.getLastDisplay()
738                    + CmsBroadcast.DISPLAY_AGAIN_TIME) < System.currentTimeMillis()) {
739                    CmsUserIconHelper helper = OpenCms.getWorkplaceAppManager().getUserIconHelper();
740                    String picPath = "";
741                    if (broadcastMessage.getUser() != null) {
742                        picPath = helper.getSmallIconPath(getCmsObject(), broadcastMessage.getUser());
743                    }
744                    CmsBroadcastMessage message = new CmsBroadcastMessage(
745                        broadcastMessage.getUser() != null
746                        ? broadcastMessage.getUser().getName()
747                        : messages.key(org.opencms.workplace.Messages.GUI_LABEL_BROADCAST_FROM_SYSTEM_0),
748                        picPath,
749                        messages.getDateTime(broadcastMessage.getSendTime()),
750                        broadcastMessage.getMessage());
751                    result.add(message);
752                    if (broadcastMessage.isRepeat()) {
753                        repeatedBroadcasts.add(broadcastMessage.withLastDisplay(System.currentTimeMillis()));
754                    }
755                } else {
756                    repeatedBroadcasts.add(broadcastMessage);
757                }
758            }
759            if (!repeatedBroadcasts.isEmpty()) {
760                for (CmsBroadcast broadcast : repeatedBroadcasts) {
761                    messageQueue.add(broadcast);
762                }
763            }
764            return result;
765        }
766        // no message pending, return null
767        return null;
768    }
769
770    /**
771     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getCategories(java.lang.String, boolean, java.lang.String)
772     */
773    public List<CmsCategoryTreeEntry> getCategories(String fromPath, boolean includeSubCats, String refPath)
774    throws CmsRpcException {
775
776        return getCategories(fromPath, includeSubCats, refPath, false);
777    }
778
779    /**
780     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getCategories(java.lang.String, boolean, java.lang.String, boolean)
781     */
782    public List<CmsCategoryTreeEntry> getCategories(
783        String fromPath,
784        boolean includeSubCats,
785        String refPath,
786        boolean showWithRepositories)
787    throws CmsRpcException {
788
789        CmsObject cms = getCmsObject();
790        CmsCategoryService catService = CmsCategoryService.getInstance();
791
792        List<String> repositories = new ArrayList<String>();
793        repositories.addAll(catService.getCategoryRepositories(getCmsObject(), refPath));
794
795        List<CmsCategoryTreeEntry> result = null;
796        try {
797            // get the categories
798            List<CmsCategory> categories = catService.readCategoriesForRepositories(
799                cms,
800                fromPath,
801                includeSubCats,
802                repositories,
803                showWithRepositories);
804            categories = catService.localizeCategories(
805                cms,
806                categories,
807                OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
808            result = buildCategoryTree(cms, categories);
809        } catch (Throwable e) {
810            error(e);
811        }
812        return result;
813    }
814
815    /**
816     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getCategoriesForSitePath(java.lang.String)
817     */
818    public List<CmsCategoryTreeEntry> getCategoriesForSitePath(String sitePath) throws CmsRpcException {
819
820        List<CmsCategoryTreeEntry> result = null;
821        CmsObject cms = getCmsObject();
822        try {
823            result = getCategoriesForSitePathStatic(cms, sitePath);
824        } catch (Throwable e) {
825            error(e);
826        }
827        return result;
828    }
829
830    /**
831     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getCategoryInfo(org.opencms.util.CmsUUID)
832     */
833    public CmsResourceCategoryInfo getCategoryInfo(CmsUUID structureId) throws CmsRpcException {
834
835        CmsObject cms = getCmsObject();
836        CmsCategoryService catService = CmsCategoryService.getInstance();
837        try {
838            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.ignoreExpirationOffline(cms));
839            List<CmsCategory> categories = catService.readResourceCategories(cms, resource);
840            List<String> currentCategories = new ArrayList<String>();
841            for (CmsCategory category : categories) {
842                currentCategories.add(category.getPath());
843            }
844            return new CmsResourceCategoryInfo(
845                structureId,
846                CmsVfsService.getPageInfoWithLock(cms, resource),
847                currentCategories,
848                getCategories(
849                    null,
850                    true,
851                    cms.getSitePath(resource),
852                    OpenCms.getWorkplaceManager().isDisplayCategoriesByRepository()));
853        } catch (CmsException e) {
854            error(e);
855        }
856        return null;
857    }
858
859    /**
860     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getContextMenuEntries(org.opencms.util.CmsUUID, org.opencms.gwt.shared.CmsCoreData.AdeContext)
861     */
862    public List<CmsContextMenuEntryBean> getContextMenuEntries(CmsUUID structureId, AdeContext context)
863    throws CmsRpcException {
864
865        List<CmsContextMenuEntryBean> result = null;
866        try {
867            result = getContextMenuEntries(getCmsObject(), structureId, context);
868        } catch (Throwable e) {
869            error(e);
870        }
871        return result;
872    }
873
874    /**
875     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getLinkForReturnCode(java.lang.String)
876     */
877    public CmsReturnLinkInfo getLinkForReturnCode(String returnCode) throws CmsRpcException {
878
879        try {
880            return internalGetLinkForReturnCode(getCmsObject(), returnCode);
881        } catch (Throwable e) {
882            error(e);
883            return null;
884
885        }
886    }
887
888    /**
889     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getResourceState(org.opencms.util.CmsUUID)
890     */
891    public CmsResourceState getResourceState(CmsUUID structureId) throws CmsRpcException {
892
893        CmsObject cms = getCmsObject();
894        CmsResourceState result = null;
895        try {
896            try {
897                CmsResource res = cms.readResource(structureId, CmsResourceFilter.ONLY_VISIBLE_NO_DELETED);
898                result = res.getState();
899            } catch (CmsVfsResourceNotFoundException e) {
900                LOG.debug(e.getLocalizedMessage(), e);
901                result = CmsResourceState.STATE_DELETED;
902            }
903        } catch (CmsException e) {
904            error(e);
905        }
906        return result;
907    }
908
909    /**
910     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getUniqueFileName(java.lang.String, java.lang.String)
911     */
912    public String getUniqueFileName(String parentFolder, String baseName) {
913
914        return OpenCms.getResourceManager().getNameGenerator().getUniqueFileName(
915            getCmsObject(),
916            parentFolder,
917            baseName);
918    }
919
920    /**
921     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getUserInfo()
922     */
923    public UserInfo getUserInfo() {
924
925        CmsObject cms = getCmsObject();
926        CmsRoleManager roleManager = OpenCms.getRoleManager();
927        boolean isAdmin = roleManager.hasRole(cms, CmsRole.ADMINISTRATOR);
928        boolean isDeveloper = roleManager.hasRole(cms, CmsRole.DEVELOPER);
929        boolean isCategoryManager = roleManager.hasRole(cms, CmsRole.CATEGORY_EDITOR);
930        boolean isWorkplaceUser = roleManager.hasRole(cms, CmsRole.WORKPLACE_USER);
931        UserInfo userInfo = new UserInfo(
932            cms.getRequestContext().getCurrentUser().getName(),
933            OpenCms.getWorkplaceAppManager().getUserIconHelper().getSmallIconPath(
934                cms,
935                cms.getRequestContext().getCurrentUser()),
936            isAdmin,
937            isDeveloper,
938            isCategoryManager,
939            isWorkplaceUser,
940            cms.getRequestContext().getCurrentUser().isManaged());
941        return userInfo;
942    }
943
944    /**
945     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getWorkplaceLink(org.opencms.util.CmsUUID)
946     */
947    public String getWorkplaceLink(CmsUUID structureId) throws CmsRpcException {
948
949        String result = null;
950        CmsObject cms = getCmsObject();
951        try {
952            String resourceRootFolder = structureId != null
953            ? CmsResource.getFolderPath(
954                cms.readResource(structureId, CmsResourceFilter.ALL.addRequireVisible()).getRootPath())
955            : cms.getRequestContext().getSiteRoot();
956            result = getVaadinWorkplaceLink(cms, resourceRootFolder);
957        } catch (Exception e) {
958            error(e);
959        }
960        return result;
961    }
962
963    /**
964     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#getWorkplaceLinkForPath(java.lang.String)
965     */
966    public String getWorkplaceLinkForPath(String path) throws CmsRpcException {
967
968        CmsObject cms = getCmsObject();
969        try {
970            CmsObject workCms = cms;
971            if (path.startsWith("/sites/")) {
972                workCms = OpenCms.initCmsObject(cms);
973                workCms.getRequestContext().setSiteRoot("");
974            }
975            String currentPath = CmsResource.getParentFolder(path);
976            CmsResource folder = null;
977            try {
978                folder = workCms.readResource(currentPath, CmsResourceFilter.IGNORE_EXPIRATION.addRequireVisible());
979            } catch (CmsVfsResourceNotFoundException | CmsSecurityException e) {
980                throw new CmsException(Messages.get().container(Messages.ERR_COULD_NOT_FIND_PARENT_FOLDER_1, path), e);
981            }
982            return getVaadinWorkplaceLink(cms, folder.getRootPath());
983        } catch (Exception e) {
984            error(e);
985            return null;
986        }
987    }
988
989    /**
990     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#loadUserSettings()
991     */
992    public CmsUserSettingsBean loadUserSettings() throws CmsRpcException {
993
994        CmsObject cms = getCmsObject();
995        CmsClientUserSettingConverter converter = new CmsClientUserSettingConverter(cms, getRequest(), getResponse());
996        try {
997            return converter.loadSettings();
998        } catch (Exception e) {
999            error(e);
1000            return null;
1001        }
1002    }
1003
1004    /**
1005     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#lockIfExists(java.lang.String)
1006     */
1007    public String lockIfExists(String sitePath) throws CmsRpcException {
1008
1009        CmsObject cms = getCmsObject();
1010        String errorMessage = null;
1011        try {
1012            if (cms.existsResource(sitePath, CmsResourceFilter.IGNORE_EXPIRATION)) {
1013
1014                try {
1015                    ensureLock(cms.readResource(sitePath, CmsResourceFilter.IGNORE_EXPIRATION));
1016                } catch (CmsException e) {
1017                    errorMessage = e.getLocalizedMessage(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
1018                }
1019
1020            } else {
1021                // check if parent folder may be locked by the current user
1022                String parentFolder = CmsResource.getParentFolder(sitePath);
1023                while ((parentFolder != null)
1024                    && !cms.existsResource(parentFolder, CmsResourceFilter.IGNORE_EXPIRATION)) {
1025                    parentFolder = CmsResource.getParentFolder(parentFolder);
1026                }
1027                if (parentFolder != null) {
1028                    CmsResource ancestorFolder = cms.readResource(parentFolder, CmsResourceFilter.IGNORE_EXPIRATION);
1029                    CmsUser user = cms.getRequestContext().getCurrentUser();
1030                    CmsLock lock = cms.getLock(ancestorFolder);
1031                    if (!lock.isLockableBy(user)) {
1032                        errorMessage = "Can not lock parent folder '" + parentFolder + "'.";
1033                    }
1034                } else {
1035                    errorMessage = "Can not access any parent folder.";
1036                }
1037            }
1038        } catch (Throwable e) {
1039            error(e);
1040        }
1041
1042        return errorMessage;
1043    }
1044
1045    /**
1046     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#lockIfExists(java.lang.String, long)
1047     */
1048    public String lockIfExists(String sitePath, long loadTime) throws CmsRpcException {
1049
1050        CmsObject cms = getCmsObject();
1051        String errorMessage = null;
1052        try {
1053            if (cms.existsResource(sitePath, CmsResourceFilter.IGNORE_EXPIRATION)) {
1054
1055                try {
1056                    CmsResource resource = cms.readResource(sitePath, CmsResourceFilter.IGNORE_EXPIRATION);
1057                    if (resource.getDateLastModified() > loadTime) {
1058                        // the resource has been changed since it was loaded
1059                        CmsUser user = null;
1060                        try {
1061                            user = cms.readUser(resource.getUserLastModified());
1062                        } catch (CmsException e) {
1063                            // ignore
1064                        }
1065                        CmsMessages messages = Messages.get().getBundle(
1066                            OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
1067                        return user != null
1068                        ? messages.key(
1069                            Messages.ERR_LOCKING_MODIFIED_RESOURCE_2,
1070                            resource.getRootPath(),
1071                            user.getFullName())
1072                        : messages.key(Messages.ERR_LOCKING_MODIFIED_RESOURCE_1, resource.getRootPath());
1073                    }
1074                    ensureLock(resource);
1075                } catch (CmsException e) {
1076                    errorMessage = e.getLocalizedMessage(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
1077                }
1078
1079            } else {
1080                // check if parent folder may be locked by the current user
1081                String parentFolder = CmsResource.getParentFolder(sitePath);
1082                while ((parentFolder != null)
1083                    && !cms.existsResource(parentFolder, CmsResourceFilter.IGNORE_EXPIRATION)) {
1084                    parentFolder = CmsResource.getParentFolder(parentFolder);
1085                }
1086                if (parentFolder != null) {
1087                    CmsResource ancestorFolder = cms.readResource(parentFolder, CmsResourceFilter.IGNORE_EXPIRATION);
1088                    CmsUser user = cms.getRequestContext().getCurrentUser();
1089                    CmsLock lock = cms.getLock(ancestorFolder);
1090                    if (!lock.isLockableBy(user)) {
1091                        errorMessage = "Can not lock parent folder '" + parentFolder + "'.";
1092                    }
1093                } else {
1094                    errorMessage = "Can not access any parent folder.";
1095                }
1096            }
1097        } catch (Throwable e) {
1098            error(e);
1099        }
1100
1101        return errorMessage;
1102    }
1103
1104    /**
1105     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#lockTemp(org.opencms.util.CmsUUID)
1106     */
1107    public String lockTemp(CmsUUID structureId) throws CmsRpcException {
1108
1109        CmsObject cms = getCmsObject();
1110        try {
1111            try {
1112                ensureLock(structureId);
1113            } catch (CmsException e) {
1114                return e.getLocalizedMessage(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
1115            }
1116        } catch (Throwable e) {
1117            error(e);
1118        }
1119        return null;
1120    }
1121
1122    /**
1123     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#lockTemp(org.opencms.util.CmsUUID, long)
1124     */
1125    public String lockTemp(CmsUUID structureId, long loadTime) throws CmsRpcException {
1126
1127        CmsObject cms = getCmsObject();
1128        try {
1129            try {
1130                CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1131                if (resource.getDateLastModified() > loadTime) {
1132                    // the resource has been changed since it was loaded
1133                    CmsUser user = null;
1134                    try {
1135                        user = cms.readUser(resource.getUserLastModified());
1136                    } catch (CmsException e) {
1137                        // ignore
1138                    }
1139                    CmsMessages messages = Messages.get().getBundle(
1140                        OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
1141                    return user != null
1142                    ? messages.key(Messages.ERR_LOCKING_MODIFIED_RESOURCE_2, resource.getRootPath(), user.getFullName())
1143                    : messages.key(Messages.ERR_LOCKING_MODIFIED_RESOURCE_1, resource.getRootPath());
1144                }
1145                ensureLock(resource);
1146            } catch (CmsException e) {
1147                return e.getLocalizedMessage(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
1148            }
1149        } catch (Throwable e) {
1150            error(e);
1151        }
1152        return null;
1153    }
1154
1155    /**
1156     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#prefetch()
1157     */
1158    public CmsCoreData prefetch() {
1159
1160        CmsObject cms = getCmsObject();
1161        String navigationUri = cms.getRequestContext().getUri();
1162        CmsADEConfigData sitemapConfig = OpenCms.getADEManager().lookupConfigurationWithCache(
1163            cms,
1164            cms.getRequestContext().getRootUri());
1165        boolean toolbarVisible = CmsADESessionCache.getCache(getRequest(), getCmsObject()).isToolbarVisible();
1166        boolean isShowHelp = OpenCms.getADEManager().isShowEditorHelp(cms);
1167
1168        CmsUUID structureId = null;
1169
1170        try {
1171            CmsResource requestedResource = cms.readResource(
1172                cms.getRequestContext().getUri(),
1173                CmsResourceFilter.ignoreExpirationOffline(cms));
1174            structureId = requestedResource.getStructureId();
1175        } catch (CmsException e) {
1176            // may happen in case of VAADIN UI
1177            LOG.debug("Could not read resource for URI.", e);
1178            structureId = CmsUUID.getNullUUID();
1179        }
1180        String loginUrl = CmsWorkplaceLoginHandler.LOGIN_FORM;
1181        try {
1182            loginUrl = cms.readPropertyObject(
1183                cms.getRequestContext().getUri(),
1184                CmsPropertyDefinition.PROPERTY_LOGIN_FORM,
1185                true).getValue(loginUrl);
1186        } catch (CmsException e) {
1187            log(e.getLocalizedMessage(), e);
1188        }
1189        String defaultWorkplaceLink = OpenCms.getSystemInfo().getWorkplaceContext();
1190        Locale wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms);
1191        UserInfo userInfo = getUserInfo();
1192        String aboutLink = OpenCms.getLinkManager().substituteLink(
1193            getCmsObject(),
1194            "/system/workplace/commons/about.jsp");
1195        String tinyMCE = CmsWorkplace.getStaticResourceUri("/editors/tinymce/jscripts/tinymce/tinymce.min.js");
1196        boolean uploadDisabled = !OpenCms.getRoleManager().hasRole(cms, CmsRole.EDITOR);
1197        CmsUploadRestrictionInfo uploadRestrictionInfo = OpenCms.getWorkplaceManager().getUploadRestriction().getUploadRestrictionInfo(
1198            cms);
1199        String categoryBaseFolder = CmsCategoryService.getInstance().getRepositoryBaseFolderName(cms);
1200        CmsGalleryDisabledTypesMode disabledTypesMode = sitemapConfig.getDisabledTypeMode(
1201            CmsGalleryDisabledTypesMode.mark);
1202        boolean hideDisabledTypes = disabledTypesMode == CmsGalleryDisabledTypesMode.hide;
1203
1204        CmsCoreData data = new CmsCoreData(
1205            EDITOR_URI,
1206            EDITOR_BACKLINK_URI,
1207            loginUrl,
1208            OpenCms.getStaticExportManager().getVfsPrefix(),
1209            getFileExplorerLink(cms, cms.getRequestContext().getSiteRoot()),
1210            OpenCms.getSystemInfo().getStaticResourceContext(),
1211            CmsEmbeddedDialogsUI.getEmbeddedDialogsContextPath(),
1212            cms.getRequestContext().getSiteRoot(),
1213            OpenCms.getSiteManager().getSharedFolder(),
1214            cms.getRequestContext().getCurrentProject().getId(),
1215            cms.getRequestContext().getLocale().toString(),
1216            wpLocale.toString(),
1217            cms.getRequestContext().getUri(),
1218            navigationUri,
1219            structureId,
1220            new HashMap<String, String>(OpenCms.getResourceManager().getExtensionMapping()),
1221            CmsIconUtil.getExtensionIconMapping(),
1222            System.currentTimeMillis(),
1223            isShowHelp,
1224            toolbarVisible,
1225            defaultWorkplaceLink,
1226            aboutLink,
1227            userInfo,
1228            OpenCms.getWorkplaceManager().getFileBytesMaxUploadSize(getCmsObject()),
1229            OpenCms.getWorkplaceManager().isKeepAlive(),
1230            uploadDisabled,
1231            OpenCms.getADEManager().getParameters(getCmsObject()),
1232            uploadRestrictionInfo,
1233            categoryBaseFolder,
1234            hideDisabledTypes);
1235        CmsTinyMCEData tinyMCEData = new CmsTinyMCEData();
1236        tinyMCEData.setLink(tinyMCE);
1237        data.setTinymce(tinyMCEData);
1238        return data;
1239    }
1240
1241    /**
1242     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#saveUserSettings(java.util.Map, java.util.Set)
1243     */
1244    public void saveUserSettings(Map<String, String> userSettings, Set<String> edited) throws CmsRpcException {
1245
1246        try {
1247            CmsObject cms = getCmsObject();
1248            CmsClientUserSettingConverter converter = new CmsClientUserSettingConverter(
1249                cms,
1250                getRequest(),
1251                getResponse());
1252            userSettings.keySet().retainAll(edited);
1253            converter.saveSettings(userSettings);
1254        } catch (Exception e) {
1255            error(e);
1256        }
1257    }
1258
1259    /**
1260     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#setResourceCategories(org.opencms.util.CmsUUID, java.util.List)
1261     */
1262    public void setResourceCategories(CmsUUID structureId, List<String> categories) throws CmsRpcException {
1263
1264        CmsObject cms = getCmsObject();
1265        CmsCategoryService catService = CmsCategoryService.getInstance();
1266        try {
1267            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1268            ensureLock(resource);
1269            String sitePath = cms.getSitePath(resource);
1270            List<CmsCategory> previousCategories = catService.readResourceCategories(cms, resource);
1271            for (CmsCategory category : previousCategories) {
1272                if (categories.contains(category.getPath())) {
1273                    categories.remove(category.getPath());
1274                } else {
1275                    catService.removeResourceFromCategory(cms, sitePath, category);
1276                }
1277            }
1278            for (String path : categories) {
1279                if (!path.isEmpty()) { // Prevent adding category repositories itself.
1280                    catService.addResourceToCategory(cms, sitePath, path);
1281                }
1282            }
1283            tryUnlock(resource);
1284        } catch (Throwable t) {
1285            error(t);
1286        }
1287    }
1288
1289    /**
1290     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#setShowEditorHelp(boolean)
1291     */
1292    public void setShowEditorHelp(boolean visible) throws CmsRpcException {
1293
1294        try {
1295            OpenCms.getADEManager().setShowEditorHelp(getCmsObject(), visible);
1296        } catch (Throwable e) {
1297            error(e);
1298        }
1299    }
1300
1301    /**
1302     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#setToolbarVisible(boolean)
1303     */
1304    public void setToolbarVisible(boolean visible) throws CmsRpcException {
1305
1306        try {
1307            ensureSession();
1308            CmsADESessionCache.getCache(getRequest(), getCmsObject()).setToolbarVisible(visible);
1309        } catch (Throwable e) {
1310            error(e);
1311        }
1312    }
1313
1314    /**
1315     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#unlock(org.opencms.util.CmsUUID)
1316     */
1317    public String unlock(CmsUUID structureId) throws CmsRpcException {
1318
1319        CmsObject cms = getCmsObject();
1320        try {
1321            CmsResource resource = cms.readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1322            tryUnlock(resource);
1323        } catch (CmsException e) {
1324            return e.getLocalizedMessage(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms));
1325        } catch (Throwable e) {
1326            error(e);
1327        }
1328        return null;
1329    }
1330
1331    /**
1332     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#unlock(java.lang.String)
1333     */
1334    public String unlock(String sitePath) throws CmsRpcException {
1335
1336        try {
1337            CmsObject cms = OpenCms.initCmsObject(getCmsObject());
1338            cms.getRequestContext().setSiteRoot("");
1339            if (cms.existsResource(sitePath, CmsResourceFilter.IGNORE_EXPIRATION)) {
1340                CmsResource resource = cms.readResource(sitePath, CmsResourceFilter.IGNORE_EXPIRATION);
1341                tryUnlock(resource);
1342            }
1343        } catch (CmsException e) {
1344            return e.getLocalizedMessage(OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject()));
1345        } catch (Throwable e) {
1346            error(e);
1347        }
1348        return null;
1349    }
1350
1351    /**
1352     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#validate(java.util.Map)
1353     */
1354    public Map<String, CmsValidationResult> validate(Map<String, CmsValidationQuery> validationQueries)
1355    throws CmsRpcException {
1356
1357        try {
1358            Map<String, CmsValidationResult> result = new HashMap<String, CmsValidationResult>();
1359            for (Map.Entry<String, CmsValidationQuery> queryEntry : validationQueries.entrySet()) {
1360                String fieldName = queryEntry.getKey();
1361                CmsValidationQuery query = queryEntry.getValue();
1362                result.put(fieldName, validate(query.getValidatorId(), query.getValue(), query.getConfig()));
1363            }
1364            return result;
1365        } catch (Throwable e) {
1366            error(e);
1367        }
1368        return null;
1369    }
1370
1371    /**
1372     * @see org.opencms.gwt.shared.rpc.I_CmsCoreService#validate(java.lang.String, java.util.Map, java.util.Map, java.lang.String)
1373     */
1374    public Map<String, CmsValidationResult> validate(
1375        String formValidatorClass,
1376        Map<String, CmsValidationQuery> validationQueries,
1377        Map<String, String> values,
1378        String config)
1379    throws CmsRpcException {
1380
1381        try {
1382            I_CmsFormValidator formValidator = instantiate(I_CmsFormValidator.class, formValidatorClass);
1383            return formValidator.validate(getCmsObject(), validationQueries, values, config);
1384        } catch (Throwable e) {
1385            error(e);
1386        }
1387        return null;
1388    }
1389
1390    /**
1391     * Collect GWT build ids from the different ADE modules.<p>
1392     *
1393     * @return the map of GWT build ids
1394     */
1395    protected Map<String, String> getBuildIds() {
1396
1397        List<CmsModule> modules = OpenCms.getModuleManager().getAllInstalledModules();
1398        Map<String, String> result = new HashMap<String, String>();
1399        for (CmsModule module : modules) {
1400            String buildid = module.getParameter(CmsCoreData.KEY_GWT_BUILDID);
1401            if (buildid != null) {
1402                result.put(module.getName(), buildid);
1403            }
1404        }
1405        return result;
1406    }
1407
1408    /**
1409     * Helper method for locking a resource which returns some information on whether the locking
1410     * failed, and why.<p>
1411     *
1412     * @param structureId the structure id of the resource
1413     * @return the locking information
1414     *
1415     * @throws CmsException if something went wrong
1416     */
1417    protected CmsLockInfo getLock(CmsUUID structureId) throws CmsException {
1418
1419        CmsResource res = getCmsObject().readResource(structureId, CmsResourceFilter.IGNORE_EXPIRATION);
1420        return getLock(getCmsObject().getSitePath(res));
1421    }
1422
1423    /**
1424     * Helper method for locking a resource which returns some information on whether the locking
1425     * failed, and why.<p>
1426     *
1427     * @param sitepath the site path of the resource to lock
1428     * @return the locking information
1429     *
1430     * @throws CmsException if something went wrong
1431     */
1432    protected CmsLockInfo getLock(String sitepath) throws CmsException {
1433
1434        CmsObject cms = getCmsObject();
1435        CmsUser user = cms.getRequestContext().getCurrentUser();
1436        CmsLock lock = cms.getLock(sitepath);
1437        if (lock.isOwnedBy(user)) {
1438            return CmsLockInfo.forSuccess();
1439        }
1440        if (lock.getUserId().isNullUUID()) {
1441            cms.lockResourceTemporary(sitepath);
1442            return CmsLockInfo.forSuccess();
1443        }
1444        CmsUser owner = cms.readUser(lock.getUserId());
1445        return CmsLockInfo.forLockedResource(owner.getName());
1446    }
1447
1448    /**
1449     * Internal helper method for validating a single value.<p>
1450     *
1451     * @param validator the class name of the validation service
1452     * @param value the value to validate
1453     * @param config the configuration for the validation service
1454     *
1455     * @return the result of the validation
1456     *
1457     * @throws Exception if something goes wrong
1458     */
1459    private CmsValidationResult validate(String validator, String value, String config) throws Exception {
1460
1461        I_CmsValidationService validationService = getValidationService(validator);
1462        return validationService.validate(getCmsObject(), value, config);
1463    }
1464}