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 GmbH & Co. KG, 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.client;
029
030import org.opencms.db.CmsResourceState;
031import org.opencms.gwt.client.rpc.CmsRpcAction;
032import org.opencms.gwt.client.rpc.CmsRpcPrefetcher;
033import org.opencms.gwt.client.ui.CmsErrorDialog;
034import org.opencms.gwt.client.ui.CmsNotification;
035import org.opencms.gwt.client.ui.input.upload.CmsFileInfo;
036import org.opencms.gwt.client.util.CmsJsUtil;
037import org.opencms.gwt.client.util.CmsMediaQuery;
038import org.opencms.gwt.client.util.CmsUniqueActiveItemContainer;
039import org.opencms.gwt.client.util.I_CmsSimpleCallback;
040import org.opencms.gwt.shared.CmsCoreData;
041import org.opencms.gwt.shared.CmsGwtConstants;
042import org.opencms.gwt.shared.I_CmsAutoBeanFactory;
043import org.opencms.gwt.shared.rpc.I_CmsCoreService;
044import org.opencms.gwt.shared.rpc.I_CmsCoreServiceAsync;
045import org.opencms.gwt.shared.rpc.I_CmsVfsService;
046import org.opencms.gwt.shared.rpc.I_CmsVfsServiceAsync;
047import org.opencms.util.CmsStringUtil;
048import org.opencms.util.CmsUUID;
049
050import com.google.gwt.core.client.GWT;
051import com.google.gwt.dom.client.Document;
052import com.google.gwt.dom.client.Element;
053import com.google.gwt.dom.client.NodeList;
054import com.google.gwt.user.client.Window.Location;
055import com.google.gwt.user.client.rpc.AsyncCallback;
056import com.google.gwt.user.client.rpc.SerializationException;
057import com.google.gwt.user.client.rpc.ServiceDefTarget;
058import com.google.web.bindery.event.shared.Event;
059import com.google.web.bindery.event.shared.EventBus;
060import com.google.web.bindery.event.shared.SimpleEventBus;
061
062import elemental2.dom.DomGlobal;
063import elemental2.webstorage.WebStorageWindow;
064
065/**
066 * Client side core data provider.<p>
067 *
068 * @since 8.0.0
069 *
070 * @see org.opencms.gwt.CmsGwtActionElement
071 */
072public final class CmsCoreProvider extends CmsCoreData {
073
074    /** AutoBean factory instance. */
075    public static final I_CmsAutoBeanFactory AUTO_BEAN_FACTORY = GWT.create(I_CmsAutoBeanFactory.class);
076
077    /** The media query string to detect touch only devices. */
078    public static final String TOUCH_ONLY_RULE = "(hover: none) or (pointer: coarse)";
079
080    /** Media query do detect device with no hover capability. */
081    public static final CmsMediaQuery TOUCH_ONLY = CmsMediaQuery.parse(TOUCH_ONLY_RULE);
082
083    /** Path to system folder. */
084    public static final String VFS_PATH_SYSTEM = "/system/";
085
086    /** Internal instance. */
087    private static CmsCoreProvider INSTANCE;
088
089    /** The core service instance. */
090    private static I_CmsCoreServiceAsync SERVICE;
091
092    /** The vfs-service instance. */
093    private static I_CmsVfsServiceAsync VFS_SERVICE;
094
095    /** The unique active item container for the flyout menu. */
096    private CmsUniqueActiveItemContainer m_activeFlyoutMenu = new CmsUniqueActiveItemContainer();
097
098    /** The client time when the data is loaded. */
099    private long m_clientTime;
100
101    /** Event bus for client side events. */
102    private EventBus m_eventBus = new SimpleEventBus();
103
104    /** Flag which indicates whether we are in Internet Explorer 7. */
105    private boolean m_isIe7;
106
107    /**
108     * Prevent instantiation.<p>
109     *
110     * @throws SerializationException if deserialization failed
111     */
112    protected CmsCoreProvider()
113    throws SerializationException {
114
115        super((CmsCoreData)CmsRpcPrefetcher.getSerializedObjectFromDictionary(getService(), DICT_NAME));
116        m_clientTime = System.currentTimeMillis();
117
118        I_CmsUserAgentInfo userAgentInfo = GWT.create(I_CmsUserAgentInfo.class);
119        m_isIe7 = userAgentInfo.isIE7();
120    }
121
122    /**
123     * Returns the client message instance.<p>
124     *
125     * @return the client message instance
126     */
127    public static CmsCoreProvider get() {
128
129        if (INSTANCE == null) {
130            try {
131                INSTANCE = new CmsCoreProvider();
132            } catch (SerializationException e) {
133                CmsErrorDialog.handleException(
134                    new Exception(
135                        "Deserialization of core data failed. This may be caused by expired java-script resources, please clear your browser cache and try again.",
136                        e));
137            }
138        }
139        return INSTANCE;
140    }
141
142    /**
143     * Gets the content attribute of a meta tag with a given name.<p>
144     *
145     * @param nameToFind the name of the meta tag
146     *
147     * @return the content attribute value of the found meta tag, or null if no meta tag with the given name was found
148     */
149    public static String getMetaElementContent(String nameToFind) {
150
151        NodeList<Element> metas = Document.get().getDocumentElement().getElementsByTagName("meta");
152        for (int i = 0; i < metas.getLength(); i++) {
153            Element meta = metas.getItem(i);
154            String name = meta.getAttribute("name");
155            if (nameToFind.equals(name)) {
156                return meta.getAttribute("content");
157            }
158        }
159        return null;
160    }
161
162    /**
163     * Returns the core service instance.<p>
164     *
165     * @return the core service instance
166     */
167    public static I_CmsCoreServiceAsync getService() {
168
169        if (SERVICE == null) {
170            SERVICE = GWT.create(I_CmsCoreService.class);
171            String serviceUrl = CmsCoreProvider.get().link("org.opencms.gwt.CmsCoreService.gwt");
172            ((ServiceDefTarget)SERVICE).setServiceEntryPoint(serviceUrl);
173        }
174        return SERVICE;
175    }
176
177    /**
178     * Returns the vfs service instance.<p>
179     *
180     * @return the vfs service instance
181     */
182    public static I_CmsVfsServiceAsync getVfsService() {
183
184        if (VFS_SERVICE == null) {
185            VFS_SERVICE = GWT.create(I_CmsVfsService.class);
186            String serviceUrl = CmsCoreProvider.get().link("org.opencms.gwt.CmsVfsService.gwt");
187            ((ServiceDefTarget)VFS_SERVICE).setServiceEntryPoint(serviceUrl);
188        }
189        return VFS_SERVICE;
190    }
191
192    /**
193     * Checks if the client is touch-only.
194     *
195     * <p>This uses media queries, but the touch-only status can also be forcibly turned on with the request parameter __touchOnly=1.
196     *
197     * @return true if the client is touch-only
198     */
199    public static boolean isTouchOnly() {
200
201        return TOUCH_ONLY.matches()
202            || "1".equals(Location.getParameter("__touchOnly"))
203            || "1".equals(CmsJsUtil.getLocalStorage("__touchOnly"));
204    }
205
206    /**
207     * Adds the current site root of this context to the given resource name.<p>
208     *
209     * @param sitePath the resource name
210     *
211     * @return the translated resource name including site root
212     *
213     * @see #removeSiteRoot(String)
214     */
215    public String addSiteRoot(String sitePath) {
216
217        if (sitePath == null) {
218            return null;
219        }
220        String siteRoot = getAdjustedSiteRoot(getSiteRoot(), sitePath);
221        StringBuffer result = new StringBuffer(128);
222        result.append(siteRoot);
223        if (((siteRoot.length() == 0) || (siteRoot.charAt(siteRoot.length() - 1) != '/'))
224            && ((sitePath.length() == 0) || (sitePath.charAt(0) != '/'))) {
225            // add slash between site root and resource if required
226            result.append('/');
227        }
228        result.append(sitePath);
229        return result.toString();
230    }
231
232    /**
233     * Creates a new CmsUUID.<p>
234     *
235     * @param callback the callback to execute
236     */
237    public void createUUID(final AsyncCallback<CmsUUID> callback) {
238
239        // do not stop/start since we do not want to give any feedback to the user
240        CmsRpcAction<CmsUUID> action = new CmsRpcAction<CmsUUID>() {
241
242            /**
243             * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
244             */
245            @Override
246            public void execute() {
247
248                getService().createUUID(this);
249            }
250
251            /**
252             * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
253             */
254            @Override
255            protected void onResponse(CmsUUID result) {
256
257                callback.onSuccess(result);
258            }
259        };
260        action.execute();
261    }
262
263    /**
264     * Fires a client side event.<p>
265     *
266     * @param event the event to fire
267     */
268    public void fireEvent(Event<?> event) {
269
270        m_eventBus.fireEvent(event);
271    }
272
273    /**
274     * Returns the adjusted site root for a resource using the provided site root as a base.<p>
275     *
276     * Usually, this would be the site root for the current site.
277     * However, if a resource from the <code>/system/</code> folder is requested,
278     * this will be the empty String.<p>
279     *
280     * @param siteRoot the site root of the current site
281     * @param resourcename the resource name to get the adjusted site root for
282     *
283     * @return the adjusted site root for the resource
284     */
285    public String getAdjustedSiteRoot(String siteRoot, String resourcename) {
286
287        if (resourcename.startsWith(VFS_PATH_SYSTEM) || resourcename.startsWith(getSharedFolder())) {
288            return "";
289        } else {
290            return siteRoot;
291        }
292    }
293
294    /**
295     * Returns the approximate time on the server.<p>
296     *
297     * @return the approximate server time
298     */
299    public long getEstimatedServerTime() {
300
301        return m_clientTime + (System.currentTimeMillis() - m_clientTime);
302    }
303
304    /**
305     * Gets the core event bus.<p>
306     *
307     * @return the core event bus
308     */
309    public EventBus getEventBus() {
310
311        return m_eventBus;
312    }
313
314    /**
315     * Returns the link to view the given resource in the file explorer.<p>
316     *
317     * @param sitePath the resource site path
318     *
319     * @return the link
320     */
321    public String getExplorerLink(String sitePath) {
322
323        return getFileExplorerLink() + sitePath;
324    }
325
326    /**
327     * Gets the unique active item container which holds a reference to the currently active content element flyout menu.<p>
328     *
329     * @return the unique active item container for flyout menus
330     */
331    public CmsUniqueActiveItemContainer getFlyoutMenuContainer() {
332
333        return m_activeFlyoutMenu;
334
335    }
336
337    /**
338     * Gets the page id that was last stored in sessionStorage.
339     *
340     * @return the page id that was last stored in session storage
341     */
342    public CmsUUID getLastPageId() {
343
344        WebStorageWindow window = WebStorageWindow.of(DomGlobal.window);
345        String lastPageStr = window.sessionStorage.getItem(CmsGwtConstants.LAST_CONTAINER_PAGE_ID);
346        if (lastPageStr != null) {
347            return new CmsUUID(lastPageStr);
348        } else {
349            return null;
350        }
351    }
352
353    /**
354     * Fetches the state of a resource from the server.<p>
355     *
356     * @param structureId the structure id of the resource
357     * @param callback the callback which should receive the result
358     */
359    public void getResourceState(final CmsUUID structureId, final AsyncCallback<CmsResourceState> callback) {
360
361        CmsRpcAction<CmsResourceState> action = new CmsRpcAction<CmsResourceState>() {
362
363            /**
364             * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
365             */
366            @Override
367            public void execute() {
368
369                start(0, false);
370                getService().getResourceState(structureId, this);
371            }
372
373            /**
374             * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
375             */
376            @Override
377            protected void onResponse(CmsResourceState result) {
378
379                stop(false);
380                callback.onSuccess(result);
381            }
382        };
383        action.execute();
384    }
385
386    /**
387     * Returns the resource type name for a given filename.<p>
388     *
389     * @param file the file info
390     *
391     * @return the resource type name
392     */
393    public String getResourceType(CmsFileInfo file) {
394
395        String typeName = null;
396        typeName = getExtensionMapping().get(file.getFileSuffix().toLowerCase());
397        if (typeName == null) {
398            typeName = "plain";
399        }
400        return typeName;
401    }
402
403    /**
404     * Returns the resource type name for a given filename.<p>
405     *
406     * @param file the file info
407     *
408     * @return the resource type name
409     */
410    public String getResourceTypeIcon(CmsFileInfo file) {
411
412        String typeName = null;
413        typeName = getIconMapping().get(file.getFileSuffix().toLowerCase());
414        if (typeName == null) {
415            typeName = getIconMapping().get("");
416        }
417        return typeName;
418    }
419
420    /**
421     * Gets the resource type icon for the given path.
422     *
423     * @param path a path
424     * @return the resource type icon
425     */
426    public String getResourceTypeIcon(String path) {
427
428        String typeName = null;
429        String name = null;
430        int slashPos = path.lastIndexOf("/");
431        if (slashPos >= 0) {
432            name = path.substring(slashPos + 1);
433        } else {
434            name = path;
435        }
436        int dotPos = name.lastIndexOf(".");
437        String ext = "";
438        if (dotPos >= 0) {
439            ext = name.substring(dotPos).toLowerCase();
440        }
441        typeName = getIconMapping().get(ext);
442        if (typeName == null) {
443            typeName = getIconMapping().get("");
444        }
445        return typeName;
446    }
447
448    /**
449     * Returns if the current user agent is IE7.<p>
450     *
451     * @return <code>true</code> if the current user agent is IE7
452     */
453    public boolean isIe7() {
454
455        return m_isIe7;
456    }
457
458    /**
459     * Returns an absolute link given a site path.<p>
460     *
461     * @param sitePath the site path
462     *
463     * @return the absolute link
464     */
465    public String link(String sitePath) {
466
467        return CmsStringUtil.joinPaths(getVfsPrefix(), sitePath);
468    }
469
470    /**
471     * Locks the given resource with a temporary lock.<p>
472     *
473     * @param structureId the resource structure id
474     * @param callback the callback to execute
475     */
476    public void lock(final CmsUUID structureId, final I_CmsSimpleCallback<Boolean> callback) {
477
478        CmsRpcAction<String> lockAction = new CmsRpcAction<String>() {
479
480            /**
481            * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
482            */
483            @Override
484            public void execute() {
485
486                start(200, false);
487                getService().lockTemp(structureId, this);
488            }
489
490            /**
491            * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
492            */
493            @Override
494            public void onResponse(String result) {
495
496                stop(false);
497                if (result != null) {
498                    // unable to lock
499                    String text = Messages.get().key(Messages.GUI_LOCK_NOTIFICATION_2, structureId, result);
500                    CmsNotification.get().sendDeferred(CmsNotification.Type.WARNING, text);
501                }
502                callback.execute(result == null ? Boolean.TRUE : Boolean.FALSE);
503            }
504        };
505        lockAction.execute();
506    }
507
508    /**
509     * Locks the given resource with a temporary lock.<p>
510     *
511     * @param structureId the resource structure id
512     * @param loadTime the time when the requested resource was loaded
513     * @param callback the callback to execute
514     */
515    public void lock(final CmsUUID structureId, long loadTime, final I_CmsSimpleCallback<Boolean> callback) {
516
517        CmsRpcAction<String> lockAction = new CmsRpcAction<String>() {
518
519            /**
520            * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
521            */
522            @Override
523            public void execute() {
524
525                start(200, false);
526                getService().lockTemp(structureId, loadTime, this);
527            }
528
529            /**
530            * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
531            */
532            @Override
533            public void onResponse(String result) {
534
535                stop(false);
536                if (result != null) {
537                    // unable to lock
538                    String text = Messages.get().key(Messages.GUI_LOCK_NOTIFICATION_2, structureId, result);
539                    CmsNotification.get().sendDeferred(CmsNotification.Type.WARNING, text);
540                }
541                callback.execute(result == null ? Boolean.TRUE : Boolean.FALSE);
542            }
543        };
544        lockAction.execute();
545    }
546
547    /**
548     * Locks the given resource with a temporary lock.<p>
549     *
550     * @param sitePath the site path of the resource to lock
551     * @param loadTime the time when the requested resource was loaded
552     * @param callback the callback to execute
553     */
554    public void lock(final String sitePath, long loadTime, final I_CmsSimpleCallback<Boolean> callback) {
555
556        CmsRpcAction<String> lockAction = new CmsRpcAction<String>() {
557
558            /**
559            * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
560            */
561            @Override
562            public void execute() {
563
564                start(200, false);
565                getService().lockIfExists(sitePath, loadTime, this);
566            }
567
568            /**
569            * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
570            */
571            @Override
572            public void onResponse(String result) {
573
574                stop(false);
575                if (result != null) {
576                    // unable to lock
577                    String text = Messages.get().key(Messages.GUI_LOCK_NOTIFICATION_2, sitePath, result);
578                    CmsNotification.get().sendDeferred(CmsNotification.Type.WARNING, text);
579                }
580                callback.execute(result == null ? Boolean.TRUE : Boolean.FALSE);
581            }
582        };
583        lockAction.execute();
584    }
585
586    /**
587     * Tries to lock a resource with a given structure id and returns an error if the locking fails.<p>
588     *
589     * @param structureId the structure id of the resource to lock
590     * @param callback the callback to execute
591     */
592    public void lockOrReturnError(final CmsUUID structureId, final I_CmsSimpleCallback<String> callback) {
593
594        CmsRpcAction<String> lockAction = new CmsRpcAction<String>() {
595
596            /**
597            * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
598            */
599            @Override
600            public void execute() {
601
602                start(200, false);
603                getService().lockTemp(structureId, this);
604            }
605
606            /**
607            * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
608            */
609            @Override
610            public void onResponse(String result) {
611
612                stop(false);
613                if (result != null) {
614                    // unable to lock
615                    final String text = Messages.get().key(Messages.GUI_LOCK_NOTIFICATION_2, structureId, result);
616                    CmsNotification.get().sendDeferred(CmsNotification.Type.WARNING, text);
617                }
618                callback.execute(result);
619            }
620        };
621        lockAction.execute();
622    }
623
624    /**
625     * Tries to lock a resource with a given structure id and returns an error if the locking fails.<p>
626     *
627     * @param structureId the structure id of the resource to lock
628     * @param loadTime the time when the requested resource was loaded
629     * @param callback the callback to execute
630     */
631    public void lockOrReturnError(
632        final CmsUUID structureId,
633        final long loadTime,
634        final I_CmsSimpleCallback<String> callback) {
635
636        CmsRpcAction<String> lockAction = new CmsRpcAction<String>() {
637
638            /**
639            * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
640            */
641            @Override
642            public void execute() {
643
644                start(200, false);
645                getService().lockTemp(structureId, loadTime, this);
646            }
647
648            /**
649            * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
650            */
651            @Override
652            public void onResponse(String result) {
653
654                stop(false);
655                if (result != null) {
656                    // unable to lock
657                    final String text = Messages.get().key(Messages.GUI_LOCK_NOTIFICATION_2, structureId, result);
658                    CmsNotification.get().sendDeferred(CmsNotification.Type.WARNING, text);
659                }
660                callback.execute(result);
661            }
662        };
663        lockAction.execute();
664    }
665
666    /**
667     * Tries to lock a resource with a given site path and returns an error if the locking fails.<p>
668     * If the resource does not exist yet, the next existing ancestor folder will be checked if it is lockable.<p>
669     *
670     * @param sitePath the site path of the resource to lock
671     * @param callback the callback to execute
672     */
673    public void lockOrReturnError(final String sitePath, final I_CmsSimpleCallback<String> callback) {
674
675        CmsRpcAction<String> lockAction = new CmsRpcAction<String>() {
676
677            /**
678            * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
679            */
680            @Override
681            public void execute() {
682
683                start(200, false);
684                getService().lockIfExists(sitePath, this);
685            }
686
687            /**
688            * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
689            */
690            @Override
691            public void onResponse(String result) {
692
693                stop(false);
694                if (result != null) {
695                    // unable to lock
696                    final String text = Messages.get().key(Messages.GUI_LOCK_NOTIFICATION_2, sitePath, result);
697                    CmsNotification.get().sendDeferred(CmsNotification.Type.WARNING, text);
698                }
699                callback.execute(result);
700            }
701        };
702        lockAction.execute();
703    }
704
705    /**
706     * Tries to lock a resource with a given site path and returns an error if the locking fails.<p>
707     * If the resource does not exist yet, the next existing ancestor folder will be checked if it is lockable.<p>
708     *
709     * @param sitePath the site path of the resource to lock
710     * @param loadTime the time when the requested resource was loaded
711     * @param callback the callback to execute
712     */
713    public void lockOrReturnError(
714        final String sitePath,
715        final long loadTime,
716        final I_CmsSimpleCallback<String> callback) {
717
718        CmsRpcAction<String> lockAction = new CmsRpcAction<String>() {
719
720            /**
721            * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
722            */
723            @Override
724            public void execute() {
725
726                start(200, false);
727                getService().lockIfExists(sitePath, loadTime, this);
728            }
729
730            /**
731            * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
732            */
733            @Override
734            public void onResponse(String result) {
735
736                stop(false);
737                if (result != null) {
738                    // unable to lock
739                    final String text = Messages.get().key(Messages.GUI_LOCK_NOTIFICATION_2, sitePath, result);
740                    CmsNotification.get().sendDeferred(CmsNotification.Type.WARNING, text);
741                }
742                callback.execute(result);
743            }
744        };
745        lockAction.execute();
746    }
747
748    /**
749     * Removes the current site root prefix from the given root path,
750     * that is adjusts the resource name for the current site root.<p>
751     *
752     * If the resource name does not start with the current site root,
753     * it is left untouched.<p>
754     *
755     * @param rootPath the resource name
756     *
757     * @return the resource name adjusted for the current site root
758     *
759     * @see #addSiteRoot(String)
760     */
761    public String removeSiteRoot(String rootPath) {
762
763        String siteRoot = getAdjustedSiteRoot(getSiteRoot(), rootPath);
764        if ((siteRoot != null)
765            && (siteRoot.equals(getSiteRoot()))
766            && rootPath.startsWith(siteRoot)
767            && ((rootPath.length() == siteRoot.length()) || (rootPath.charAt(siteRoot.length()) == '/'))) {
768            rootPath = rootPath.substring(siteRoot.length());
769        }
770        return rootPath;
771    }
772
773    /**
774     * @see org.opencms.gwt.shared.CmsCoreData#setShowEditorHelp(boolean)
775     */
776    @Override
777    public void setShowEditorHelp(final boolean show) {
778
779        super.setShowEditorHelp(show);
780        CmsRpcAction<Void> action = new CmsRpcAction<Void>() {
781
782            /**
783             * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
784             */
785            @Override
786            public void execute() {
787
788                getService().setShowEditorHelp(show, this);
789            }
790
791            /**
792             * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
793             */
794            @Override
795            protected void onResponse(Void result) {
796
797                //nothing to do
798            }
799        };
800        action.execute();
801    }
802
803    /**
804     * Returns the absolute link to the given root path.<p>
805     *
806     * @param rootPath the root path
807     * @param callback the callback to execute
808     */
809    public void substituteLinkForRootPath(final String rootPath, final I_CmsSimpleCallback<String> callback) {
810
811        CmsRpcAction<String> action = new CmsRpcAction<String>() {
812
813            @Override
814            public void execute() {
815
816                getVfsService().substituteLinkForRootPath(getSiteRoot(), rootPath, this);
817            }
818
819            @Override
820            protected void onResponse(String result) {
821
822                callback.execute(result);
823            }
824        };
825        action.execute();
826    }
827
828    /**
829     * Unlocks the given resource, synchronously.<p>
830     *
831     * @param structureId the resource structure id
832     *
833     * @return <code>true</code> if succeeded, if not a a warning is already shown to the user
834     */
835    public boolean unlock(final CmsUUID structureId) {
836
837        // lock the sitemap
838        CmsRpcAction<String> unlockAction = new CmsRpcAction<String>() {
839
840            /**
841            * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
842            */
843            @Override
844            public void execute() {
845
846                start(200, false);
847                getService().unlock(structureId, this);
848            }
849
850            /**
851            * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
852            */
853            @Override
854            public void onResponse(String result) {
855
856                stop(false);
857                if (result == null) {
858                    // ok
859                    return;
860                }
861                // unable to lock
862                String text = Messages.get().key(Messages.GUI_UNLOCK_NOTIFICATION_2, structureId.toString(), result);
863                CmsNotification.get().send(CmsNotification.Type.WARNING, text);
864            }
865        };
866        return unlockAction.executeSync() == null;
867    }
868
869    /**
870     * Unlocks the given resource, synchronously.<p>
871     *
872     * @param sitePath the resource site path
873     *
874     * @return <code>true</code> if succeeded, if not a a warning is already shown to the user
875     */
876    public boolean unlock(final String sitePath) {
877
878        // lock the sitemap
879        CmsRpcAction<String> unlockAction = new CmsRpcAction<String>() {
880
881            /**
882            * @see org.opencms.gwt.client.rpc.CmsRpcAction#execute()
883            */
884            @Override
885            public void execute() {
886
887                start(200, false);
888                getService().unlock(sitePath, this);
889            }
890
891            /**
892            * @see org.opencms.gwt.client.rpc.CmsRpcAction#onResponse(java.lang.Object)
893            */
894            @Override
895            public void onResponse(String result) {
896
897                stop(false);
898                if (result == null) {
899                    // ok
900                    return;
901                }
902                // unable to lock
903                String text = Messages.get().key(Messages.GUI_UNLOCK_NOTIFICATION_2, sitePath, result);
904                CmsNotification.get().send(CmsNotification.Type.WARNING, text);
905            }
906        };
907        return unlockAction.executeSync() == null;
908    }
909
910}