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