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    /** Keeps the dialog frame on window close. */
084    private boolean m_keepFrameOnClose;
085
086    /** The list of resources. */
087    private List<CmsResource> m_resources;
088
089    /** The window used to display the dialog. */
090    private Window m_window;
091
092    /** The extension used for communicating with the client. */
093    private CmsEmbeddedDialogExtension m_extension;
094
095    /** The parameters. */
096    private Map<String, String> m_parameters;
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     * @see org.opencms.ui.I_CmsDialogContext#setWindow(com.vaadin.ui.Window)
355     */
356    public void setWindow(Window window) {
357
358        m_window = window;
359        m_window.addCloseListener(new CloseListener() {
360
361            private static final long serialVersionUID = 1L;
362
363            public void windowClose(CloseEvent e) {
364
365                handleWindowClose();
366            }
367        });
368    }
369
370    /**
371     * @see org.opencms.ui.I_CmsDialogContext#start(java.lang.String, com.vaadin.ui.Component)
372     */
373    public void start(String title, Component dialog) {
374
375        start(title, dialog, DialogWidth.narrow);
376    }
377
378    /**
379     * @see org.opencms.ui.I_CmsDialogContext#start(java.lang.String, com.vaadin.ui.Component, org.opencms.ui.components.CmsBasicDialog.DialogWidth)
380     */
381    public void start(String title, Component dialog, DialogWidth width) {
382
383        if (dialog != null) {
384            m_keepFrameOnClose = false;
385            m_window = CmsBasicDialog.prepareWindow(width);
386            m_window.setCaption(title);
387            m_window.setContent(dialog);
388            UI.getCurrent().addWindow(m_window);
389            m_window.addCloseListener(new CloseListener() {
390
391                private static final long serialVersionUID = 1L;
392
393                public void windowClose(CloseEvent e) {
394
395                    handleWindowClose();
396                }
397            });
398            if (dialog instanceof CmsBasicDialog) {
399                ((CmsBasicDialog)dialog).initActionHandler(m_window);
400            }
401        }
402    }
403
404    /**
405     * @see org.opencms.ui.I_CmsDialogContext#updateUserInfo()
406     */
407    public void updateUserInfo() {
408
409        getClientRPC().reloadParent();
410    }
411
412    /**
413     * Returns the client RPC.<p>
414     *
415     * @return the client RPC
416     */
417    protected I_CmsEmbeddedDialogClientRPC getClientRPC() {
418
419        return m_extension.getClientRPC();
420    }
421
422    /**
423     * Handles the window close event.<p>
424     */
425    void handleWindowClose() {
426
427        if (!m_keepFrameOnClose) {
428            removeDialogFrame();
429        }
430    }
431
432    /**
433     * Removes the dialog iFrame.<p>
434     */
435    void removeDialogFrame() {
436
437        getClientRPC().finish(null);
438    }
439
440    /**
441     * Reloads the parent window.<p>
442     */
443    private void reloadParent() {
444
445        getClientRPC().reloadParent();
446    }
447}