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;
029
030import org.opencms.file.CmsObject;
031import org.opencms.gwt.shared.CmsCoreData;
032import org.opencms.gwt.shared.rpc.I_CmsCoreService;
033import org.opencms.i18n.CmsEncoder;
034import org.opencms.i18n.CmsLocaleManager;
035import org.opencms.jsp.CmsJspActionElement;
036import org.opencms.main.OpenCms;
037import org.opencms.util.CmsStringUtil;
038import org.opencms.workplace.CmsWorkplace;
039
040import java.lang.reflect.Method;
041import java.util.Arrays;
042import java.util.Collection;
043import java.util.Locale;
044
045import javax.servlet.http.HttpServletRequest;
046import javax.servlet.http.HttpServletResponse;
047import javax.servlet.jsp.PageContext;
048
049import com.google.gwt.user.client.rpc.SerializationException;
050import com.google.gwt.user.server.rpc.RPC;
051
052/**
053 * Sitemap action used to generate the sitemap editor.<p>
054 *
055 * see jsp file <tt>/system/workplace/commons/sitemap.jsp</tt>.<p>
056 *
057 * @since 8.0.0
058 */
059public class CmsGwtActionElement extends CmsJspActionElement {
060
061    /** The closing script tag. */
062    protected static final String SCRIPT_TAG_CLOSE = "\n//-->\n</script>";
063
064    /** The opening script tag. */
065    protected static final String SCRIPT_TAG_OPEN = "<script>\n<!--\n";
066
067    /** In page variable name for missing permutation message. */
068    private static final String CMS_NO_PERMUTATION_MESSAGE = "CMS_NO_PERMUTATION_MESSAGE";
069
070    /** The resource icon CSS URI. */
071    private static final String ICON_CSS_URI = "/system/workplace/commons/resourceIcon.css";
072
073    /** The current core data. */
074    private CmsCoreData m_coreData;
075
076    /**
077     * Constructor.<p>
078     *
079     * @param context the JSP page context object
080     * @param req the JSP request
081     * @param res the JSP response
082     */
083    public CmsGwtActionElement(PageContext context, HttpServletRequest req, HttpServletResponse res) {
084
085        super(context, req, res);
086    }
087
088    /**
089     * Returns the script tag for the "*.nocache.js".<p>
090     *
091     * @param moduleName the module name to get the script tag for
092     * @param moduleVersion the module version
093     *
094     * @return the <code>"&lt;script&gt;"</code> tag for the "*.nocache.js".<p>
095     */
096    public static String createNoCacheScript(String moduleName, String moduleVersion) {
097
098        String result = "<script src=\""
099            + CmsWorkplace.getResourceUri("ade/" + moduleName + "/" + moduleName + ".nocache.js");
100        if (CmsStringUtil.isNotEmptyOrWhitespaceOnly(moduleVersion)) {
101            result += "?version=" + moduleVersion + "_" + OpenCms.getSystemInfo().getVersionNumber().hashCode();
102        }
103        result += "\"></script>";
104        return result;
105    }
106
107    /**
108     * Returns the serialized data for the core provider wrapped into a script tag.<p>
109     *
110     * @param cms the CMS context
111     * @param coreData the core data to write into the page
112     *
113     * @return the data
114     *
115     * @throws Exception if something goes wrong
116     */
117    public static String exportCommon(CmsObject cms, CmsCoreData coreData) throws Exception {
118
119        // determine the workplace locale
120        String wpLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms).toString();
121        if (CmsStringUtil.isEmptyOrWhitespaceOnly(wpLocale)) {
122            // if no locale was found, take English as locale
123            wpLocale = Locale.ENGLISH.toString();
124        }
125        StringBuffer sb = new StringBuffer();
126        // append meta tag to set the IE to standard document mode
127        sb.append("<meta http-equiv=\"X-UA-Compatible\" content=\"IE=edge\" />\n");
128
129        sb.append(
130            "<script src=\""
131                + OpenCms.getStaticExportManager().getVfsPrefix()
132                + "/"
133                + CmsMessagesService.class.getName()
134                + ".gwt?"
135                + CmsLocaleManager.PARAMETER_LOCALE
136                + "="
137                + wpLocale
138                + "\"></script>\n");
139
140        // print out the missing permutation message to be used from the nocache.js generated by custom linker
141        // see org.opencms.gwt.linker.CmsIFrameLinker
142        sb.append(
143            wrapScript(
144                "var ",
145                CMS_NO_PERMUTATION_MESSAGE,
146                "='",
147                Messages.get().getBundle(OpenCms.getWorkplaceManager().getWorkplaceLocale(cms)).key(
148                    Messages.ERR_NO_PERMUTATION_AVAILABLE_0),
149                "';\n"));
150
151        String prefetchedData = exportDictionary(
152            CmsCoreData.DICT_NAME,
153            I_CmsCoreService.class.getMethod("prefetch"),
154            coreData);
155        sb.append(prefetchedData);
156        //       sb.append(ClientMessages.get().export(wpLocale));
157        sb.append("<style type=\"text/css\">\n @import url(\"").append(iconCssLink(cms)).append("\");\n </style>\n");
158
159        // append additional style sheets
160        Collection<String> stylesheets = OpenCms.getWorkplaceAppManager().getAdditionalStyleSheets();
161        for (String stylesheet : stylesheets) {
162            sb.append("<style type=\"text/css\">\n @import url(\"").append(stylesheet).append("\");\n </style>\n");
163        }
164        // append the workplace locale information
165        sb.append("<meta name=\"gwt:property\" content=\"locale=").append(wpLocale).append("\" />\n");
166        return sb.toString();
167    }
168
169    /**
170     * Serializes the result of the given method for RPC-prefetching.<p>
171     *
172     * @param name the dictionary name
173     * @param method the method
174     * @param data the result to serialize
175     *
176     * @return the serialized data
177     *
178     * @throws SerializationException if something goes wrong
179     */
180    public static String exportDictionary(String name, Method method, Object data) throws SerializationException {
181
182        return exportDictionary(name, serialize(method, data));
183    }
184
185    /**
186     * Exports a dictionary by the given name as the content attribute of a meta tag.<p>
187     *
188     * @param name the dictionary name
189     * @param data the data
190     *
191     * @return the meta tag
192     */
193    public static String exportDictionary(String name, String data) {
194
195        StringBuffer sb = new StringBuffer();
196        sb.append("<meta name=\"").append(name).append("\" content=\"").append(data).append("\" />");
197        return sb.toString();
198    }
199
200    /**
201     * Generates the HTML for a meta tag with given name and content.<p>
202     *
203     * @param name the name of the meta tag
204     * @param data the content of the meta tag
205     *
206     * @return the HTML for the meta tag
207     */
208    public static String exportMeta(String name, String data) {
209
210        String escName = CmsEncoder.escapeXml(name);
211        String escData = CmsEncoder.escapeXml(data);
212        return ("<meta name=\"" + escName + "\" content=\"" + escData + "\" />");
213    }
214
215    /**
216     * Returns the OpenCms font icon CSS link.<p>
217     *
218     * @return the CSS link
219     */
220    public static String getFontIconCssLink() {
221
222        return CmsStringUtil.joinPaths(
223            OpenCms.getSystemInfo().getContextPath(),
224            "VAADIN/themes/opencms/opencmsFonts.css");
225    }
226
227    /**
228     * Serializes the result of the given method for RPC-prefetching.<p>
229     *
230     * @param method the method
231     * @param data the result to serialize
232     *
233     * @return the serialized data
234     *
235     * @throws SerializationException if something goes wrong
236     */
237    public static String serialize(Method method, Object data) throws SerializationException {
238
239        String result = RPC.encodeResponseForSuccess(method, data, CmsPrefetchSerializationPolicy.instance());
240        result = CmsEncoder.escapeXml(result, true);
241        return result;
242    }
243
244    /**
245     * Concatenates the given strings and surrounds them with script tags.<p>
246     *
247     * @param s the array of strings to concatenate and wrap
248     *
249     * @return the concatenation of the input strings, wrapped in script tags
250     */
251    public static String wrapScript(String... s) {
252
253        return SCRIPT_TAG_OPEN + CmsStringUtil.listAsString(Arrays.asList(s), "") + SCRIPT_TAG_CLOSE;
254    }
255
256    /**
257     * Generates the link to the icon CSS JSP, and appends a "prefix" request parameter with the given value.<p>
258     *
259     * @param cms the CMS context
260     *
261     * @return the link to the icon CSS
262     */
263    private static String iconCssLink(CmsObject cms) {
264
265        return OpenCms.getLinkManager().substituteLinkForUnknownTarget(cms, ICON_CSS_URI);
266    }
267
268    /**
269     * Returns the script tag for the "*.nocache.js".<p>
270     *
271     * @param moduleName the module name to get the script tag for
272     *
273     * @return the <code>"&lt;script&gt;"</code> tag for the "*.nocache.js".<p>
274     */
275    @Deprecated
276    public String createNoCacheScript(String moduleName) {
277
278        return createNoCacheScript(moduleName, null);
279    }
280
281    /**
282     * Returns the serialized data for the core provider wrapped in a script tag.<p>
283     *
284     * @return the data
285     *
286     * @throws Exception if something goes wrong
287     */
288    public String export() throws Exception {
289
290        return export(true);
291    }
292
293    /**
294     * Returns the serialized data for the core provider wrapped into a script tag.<p>
295     *
296     * @param includeFontCss <code>true</code> to include the OpenCms font CSS, not necessary in case VAADIN theme is loaded also
297     *
298     * @return the data
299     *
300     * @throws Exception if something goes wrong
301     */
302    public String export(boolean includeFontCss) throws Exception {
303
304        StringBuffer buffer = new StringBuffer(exportCommon(getCmsObject(), getCoreData()));
305        if (includeFontCss || !OpenCms.getWorkplaceAppManager().getWorkplaceCssUris().isEmpty()) {
306            buffer.append("\n<style type=\"text/css\">\n");
307            if (includeFontCss) {
308                buffer.append("@import url(\"").append(getFontIconCssLink()).append("\");\n");
309            }
310            for (String cssURI : OpenCms.getWorkplaceAppManager().getWorkplaceCssUris()) {
311                buffer.append("@import url(\"").append(CmsWorkplace.getResourceUri(cssURI)).append("\");\n");
312            }
313            buffer.append("</style>\n");
314        }
315        return buffer.toString();
316    }
317
318    /**
319     * Returns the serialized data for the core provider.<p>
320     *
321     * @return the data
322     *
323     * @throws Exception if something goes wrong
324     */
325    public String exportAll() throws Exception {
326
327        return export();
328    }
329
330    /**
331     * Returns the needed server data for client-side usage.<p>
332     *
333     * @return the needed server data for client-side usage
334     */
335    public CmsCoreData getCoreData() {
336
337        if (m_coreData == null) {
338            m_coreData = CmsCoreService.prefetch(getRequest());
339        }
340        return m_coreData;
341    }
342
343    /**
344     * Returns the workplace locale for the current user.<p>
345     *
346     * @return the workplace locale
347     */
348    public Locale getWorkplaceLocale() {
349
350        return OpenCms.getWorkplaceManager().getWorkplaceLocale(getCmsObject());
351    }
352
353    /**
354     * Exports script tag to the main OpenCms GWT no-cache js script tag.<p>
355     *
356     * @param moduleName the client module to start
357     *
358     * @return the HTML string
359     */
360    protected String exportModuleScriptTag(String moduleName) {
361
362        String result = "<meta name=\""
363            + CmsCoreData.META_PARAM_MODULE_KEY
364            + "\" content=\""
365            + moduleName
366            + "\" >\n<script src=\""
367            + CmsWorkplace.getStaticResourceUri("gwt/opencms/opencms.nocache.js");
368        result += "\"></script>\n";
369        return result;
370    }
371}