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