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.ui.dialogs;
029
030import org.opencms.ade.configuration.CmsADEManager;
031import org.opencms.file.CmsObject;
032import org.opencms.file.CmsProject;
033import org.opencms.file.CmsResource;
034import org.opencms.gwt.CmsCoreService;
035import org.opencms.main.CmsException;
036import org.opencms.main.CmsLog;
037import org.opencms.main.OpenCms;
038import org.opencms.ui.A_CmsUI;
039import org.opencms.ui.CmsVaadinUtils;
040import org.opencms.ui.I_CmsDialogContext;
041import org.opencms.ui.apps.CmsQuickLaunchLocationCache;
042import org.opencms.ui.components.CmsBasicDialog;
043import org.opencms.ui.components.CmsBasicDialog.DialogWidth;
044import org.opencms.ui.components.CmsErrorDialog;
045import org.opencms.ui.components.CmsExtendedSiteSelector.SiteSelectorOption;
046import org.opencms.ui.components.extensions.CmsEmbeddedDialogExtension;
047import org.opencms.ui.shared.rpc.I_CmsEmbeddedDialogClientRPC;
048import org.opencms.util.CmsStringUtil;
049import org.opencms.util.CmsUUID;
050
051import java.util.Collection;
052import java.util.Collections;
053import java.util.List;
054import java.util.Map;
055import java.util.regex.Pattern;
056
057import org.apache.commons.logging.Log;
058
059import com.vaadin.server.Page;
060import com.vaadin.ui.Component;
061import com.vaadin.ui.UI;
062import com.vaadin.ui.Window;
063import com.vaadin.ui.Window.CloseEvent;
064import com.vaadin.ui.Window.CloseListener;
065
066/**
067 * Context for dialogs embedded into plain GWT modules.<p>
068 */
069public class CmsEmbeddedDialogContext implements I_CmsDialogContext {
070
071    /** Logger instance for this class. */
072    private static final Log LOG = CmsLog.getLog(CmsEmbeddedDialogContext.class);
073
074    /** Pattern to check if a given server link starts with with a protocol string. */
075    private static Pattern PROTOCOL_PATTERN = Pattern.compile("^http.?://.*");
076
077    /** The app id. */
078    private String m_appId;
079
080    /** The context type. */
081    private ContextType m_contextType;
082
083    /** The extension used for communicating with the client. */
084    private CmsEmbeddedDialogExtension m_extension;
085
086    /** Keeps the dialog frame on window close. */
087    private boolean m_keepFrameOnClose;
088
089    /** The parameters. */
090    private Map<String, String> m_parameters;
091
092    /** The list of resources. */
093    private List<CmsResource> m_resources;
094
095    /** The window used to display the dialog. */
096    private Window m_window;
097
098    /**
099     * Constructor.<p>
100     *
101     * @param appId the app id
102     * @param extension the extension used to communicate with the client
103     * @param contextType the context type
104     * @param resources the resources
105     * @param parameters the additional parameters
106     */
107    public CmsEmbeddedDialogContext(
108        String appId,
109        CmsEmbeddedDialogExtension extension,
110        ContextType contextType,
111        List<CmsResource> resources,
112        Map<String, String> parameters) {
113
114        m_extension = extension;
115        m_appId = appId;
116        m_contextType = contextType;
117        m_resources = resources != null ? resources : Collections.<CmsResource> emptyList();
118        m_parameters = parameters;
119    }
120
121    /**
122     * Closes the dialog window.<p>
123     *
124     * @param keepFrame <code>true</code> to keep the embedded iFrame.<p>
125     */
126    public void closeWindow(boolean keepFrame) {
127
128        if (m_window != null) {
129            m_keepFrameOnClose = keepFrame;
130            m_window.close();
131            m_window = null;
132        }
133    }
134
135    /**
136     * @see org.opencms.ui.I_CmsDialogContext#error(java.lang.Throwable)
137     */
138    public void error(Throwable error) {
139
140        closeWindow(true);
141        CmsErrorDialog.showErrorDialog(error, new Runnable() {
142
143            public void run() {
144
145                removeDialogFrame();
146            }
147        });
148    }
149
150    /**
151     * @see org.opencms.ui.I_CmsDialogContext#finish(org.opencms.file.CmsProject, java.lang.String)
152     */
153    public void finish(CmsProject project, String siteRoot) {
154
155        if ((project != null) || (siteRoot != null)) {
156            String sitePath = null;
157            if (siteRoot != null) {
158                CmsQuickLaunchLocationCache locationCache = CmsQuickLaunchLocationCache.getLocationCache(
159                    A_CmsUI.get().getHttpSession());
160                sitePath = locationCache.getPageEditorLocation(A_CmsUI.getCmsObject(), siteRoot);
161                if (sitePath == null) {
162                    sitePath = locationCache.getFileExplorerLocation(siteRoot);
163                    if (sitePath != null) {
164                        int index = sitePath.indexOf("/" + CmsADEManager.CONTENT_FOLDER_NAME);
165                        if (index >= 0) {
166                            sitePath = sitePath.substring(0, index);
167                        }
168                    }
169                }
170            } else if ((m_resources != null) && !m_resources.isEmpty()) {
171                sitePath = A_CmsUI.getCmsObject().getSitePath(m_resources.get(0));
172            }
173            if (CmsStringUtil.isEmptyOrWhitespaceOnly(sitePath)) {
174                sitePath = "/";
175            }
176            String serverLink = OpenCms.getLinkManager().getServerLink(getCms(), sitePath);
177            if (!PROTOCOL_PATTERN.matcher(serverLink).matches()) {
178                serverLink = "http://" + serverLink;
179            }
180            getClientRPC().finishForProjectOrSiteChange(sitePath, serverLink);
181        } else {
182            finish((Collection<CmsUUID>)null);
183        }
184    }
185
186    /**
187     * @see org.opencms.ui.I_CmsDialogContext#finish(java.util.Collection)
188     */
189    public void finish(Collection<CmsUUID> result) {
190
191        closeWindow(true);
192        String resources = "";
193        if (result != null) {
194            for (CmsUUID id : result) {
195                resources += id.toString() + ";";
196            }
197        }
198        getClientRPC().finish(resources);
199    }
200
201    /**
202     * Opens the location from the site selector option.
203     *
204     * @param option the site selector option
205     */
206    public void finish(SiteSelectorOption option) {
207
208        String path = option.getPath();
209        CmsObject cms = A_CmsUI.getCmsObject();
210        if (path == null) {
211            finish(null, option.getSite());
212        } else {
213            String sitePath = option.getPath();
214            boolean foundPage = false;
215            try {
216                CmsResource res = cms.readDefaultFile(sitePath);
217                if (res != null) {
218                    foundPage = true;
219                }
220            } catch (CmsException e) {
221                LOG.warn(e.getLocalizedMessage(), e);
222            }
223            if (foundPage) {
224                if (CmsStringUtil.isEmptyOrWhitespaceOnly(sitePath)) {
225                    sitePath = "/";
226                }
227                String serverLink = OpenCms.getLinkManager().getServerLink(getCms(), sitePath);
228                if (!PROTOCOL_PATTERN.matcher(serverLink).matches()) {
229                    serverLink = "http://" + serverLink;
230                }
231                getClientRPC().finishForProjectOrSiteChange(sitePath, serverLink);
232            } else {
233                Page.getCurrent().open(CmsCoreService.getFileExplorerLink(cms, option.getSite()) + sitePath, "_top");
234            }
235        }
236    }
237
238    /**
239     * Finishes the dialog and returns an arbitrary string to the opener.
240     *
241     * @param str the string to pass to the opener
242     */
243    public void finishWithString(String str) {
244
245        closeWindow(true);
246        getClientRPC().selectString(str);
247    }
248
249    /**
250     * @see org.opencms.ui.I_CmsDialogContext#focus(org.opencms.util.CmsUUID)
251     */
252    public void focus(CmsUUID structureId) {
253
254        // does not apply
255    }
256
257    /**
258     * @see org.opencms.ui.I_CmsDialogContext#getAllStructureIdsInView()
259     */
260    public List<CmsUUID> getAllStructureIdsInView() {
261
262        return Collections.emptyList();
263    }
264
265    /**
266     * @see org.opencms.ui.I_CmsDialogContext#getAppId()
267     */
268    public String getAppId() {
269
270        return m_appId;
271    }
272
273    /**
274     * @see org.opencms.ui.I_CmsDialogContext#getCms()
275     */
276    public CmsObject getCms() {
277
278        return A_CmsUI.getCmsObject();
279    }
280
281    /**
282     * @see org.opencms.ui.I_CmsDialogContext#getContextType()
283     */
284    public ContextType getContextType() {
285
286        return m_contextType;
287    }
288
289    /**
290     * @see org.opencms.ui.I_CmsDialogContext#getParameters()
291     */
292    public Map<String, String> getParameters() {
293
294        return Collections.unmodifiableMap(m_parameters);
295    }
296
297    /**
298     * @see org.opencms.ui.I_CmsDialogContext#getResources()
299     */
300    public List<CmsResource> getResources() {
301
302        return m_resources;
303    }
304
305    /**
306     * Leaves page by navigating to given URI.
307     *
308     * @param uri the URI to navigate to
309     */
310    public void leavePage(String uri) {
311
312        getClientRPC().leavePage(uri);
313    }
314
315    /**
316     * @see org.opencms.ui.I_CmsDialogContext#navigateTo(java.lang.String)
317     */
318    public void navigateTo(String appId) {
319
320        String targetUri = CmsVaadinUtils.getWorkplaceLink(appId);
321        getClientRPC().leavePage(targetUri);
322    }
323
324    /**
325     * @see org.opencms.ui.I_CmsDialogContext#onViewChange()
326     */
327    public void onViewChange() {
328
329        if (m_window != null) {
330            m_window.center();
331        }
332    }
333
334    /**
335     * @see org.opencms.ui.I_CmsDialogContext#reload()
336     */
337    public void reload() {
338
339        closeWindow(true);
340        reloadParent();
341    }
342
343    /**
344     * Sets the principal.<p>
345     *
346     * @param principalName the principal name
347     */
348    public void selectString(String principalName) {
349
350        getClientRPC().selectString(principalName);
351    }
352
353    /**
354     * Send a notification to the client to display.
355     *
356     * @param error true if this is an error notification
357     * @param notification the notification HTML
358     */
359    public void sendNotification(boolean error, String notification) {
360
361        getClientRPC().sendNotification(error, notification);
362    }
363
364    /**
365     * @see org.opencms.ui.I_CmsDialogContext#setWindow(com.vaadin.ui.Window)
366     */
367    public void setWindow(Window window) {
368
369        m_window = window;
370        m_window.addCloseListener(new CloseListener() {
371
372            private static final long serialVersionUID = 1L;
373
374            public void windowClose(CloseEvent e) {
375
376                handleWindowClose();
377            }
378        });
379    }
380
381    /**
382     * @see org.opencms.ui.I_CmsDialogContext#start(java.lang.String, com.vaadin.ui.Component)
383     */
384    public void start(String title, Component dialog) {
385
386        start(title, dialog, DialogWidth.narrow);
387    }
388
389    /**
390     * @see org.opencms.ui.I_CmsDialogContext#start(java.lang.String, com.vaadin.ui.Component, org.opencms.ui.components.CmsBasicDialog.DialogWidth)
391     */
392    public void start(String title, Component dialog, DialogWidth width) {
393
394        if (dialog != null) {
395            m_keepFrameOnClose = false;
396            m_window = CmsBasicDialog.prepareWindow(width);
397            m_window.setCaption(title);
398            m_window.setContent(dialog);
399            UI.getCurrent().addWindow(m_window);
400            m_window.addCloseListener(new CloseListener() {
401
402                private static final long serialVersionUID = 1L;
403
404                public void windowClose(CloseEvent e) {
405
406                    handleWindowClose();
407                }
408            });
409            if (dialog instanceof CmsBasicDialog) {
410                ((CmsBasicDialog)dialog).initActionHandler(m_window);
411            }
412        }
413    }
414
415    /**
416     * @see org.opencms.ui.I_CmsDialogContext#updateUserInfo()
417     */
418    public void updateUserInfo() {
419
420        getClientRPC().reloadParent();
421    }
422
423    /**
424     * Returns the client RPC.<p>
425     *
426     * @return the client RPC
427     */
428    protected I_CmsEmbeddedDialogClientRPC getClientRPC() {
429
430        return m_extension.getClientRPC();
431    }
432
433    /**
434     * Handles the window close event.<p>
435     */
436    void handleWindowClose() {
437
438        if (!m_keepFrameOnClose) {
439            removeDialogFrame();
440        }
441    }
442
443    /**
444     * Removes the dialog iFrame.<p>
445     */
446    void removeDialogFrame() {
447
448        getClientRPC().finish(null);
449    }
450
451    /**
452     * Reloads the parent window.<p>
453     */
454    private void reloadParent() {
455
456        getClientRPC().reloadParent();
457    }
458}