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.widgets; 029 030import org.opencms.file.CmsObject; 031import org.opencms.file.CmsResource; 032import org.opencms.gwt.shared.I_CmsCodeMirrorClientConfiguration; 033import org.opencms.gwt.shared.I_CmsCodeMirrorClientConfigurationFactory; 034import org.opencms.i18n.CmsMessages; 035import org.opencms.json.JSONException; 036import org.opencms.json.JSONObject; 037import org.opencms.main.CmsLog; 038import org.opencms.main.OpenCms; 039import org.opencms.util.CmsFileUtil; 040import org.opencms.util.CmsStringUtil; 041import org.opencms.xml.content.I_CmsXmlContentHandler.DisplayType; 042import org.opencms.xml.types.A_CmsXmlContentValue; 043 044import java.io.InputStream; 045import java.nio.charset.StandardCharsets; 046import java.util.List; 047import java.util.Locale; 048 049import org.apache.commons.logging.Log; 050 051import com.google.web.bindery.autobean.shared.AutoBean; 052import com.google.web.bindery.autobean.shared.AutoBeanCodex; 053import com.google.web.bindery.autobean.vm.AutoBeanFactorySource; 054 055/** 056 * Widget for editing source code. 057 * 058 * <p>The current implementation uses the CodeMirror editor on the client side. 059 * 060 * <p>The configuration string is a JSON string (in the form parseable by org.opencms.json.JSONObject) with the following possible optional attributes: 061 * <ul> 062 * <li>mode: the initially selected editor mode (text|javascript|jsp|java|html|xml) 063 * <li>height: the height in pixels (if 'grow' is set to true, this is used as minimum height instead). 064 * </ul> 065 */ 066public class CmsCodeWidget extends A_CmsWidget implements I_CmsADEWidget { 067 068 /** The logger instance for this class. */ 069 private static final Log LOG = CmsLog.getLog(CmsCodeWidget.class); 070 071 /** The factory for the client-side configuration. */ 072 private static I_CmsCodeMirrorClientConfigurationFactory m_configFactory = AutoBeanFactorySource.create( 073 I_CmsCodeMirrorClientConfigurationFactory.class); 074 075 /** 076 * Creates a new instance. 077 */ 078 public CmsCodeWidget() { 079 080 this("{}"); 081 082 } 083 084 /** 085 * Creates a new instance. 086 * 087 * @param configuration the configuration 088 */ 089 public CmsCodeWidget(String configuration) { 090 091 setConfiguration(configuration); 092 } 093 094 /** 095 * @see org.opencms.widgets.I_CmsADEWidget#getConfiguration(org.opencms.file.CmsObject, org.opencms.xml.types.A_CmsXmlContentValue, org.opencms.i18n.CmsMessages, org.opencms.file.CmsResource, java.util.Locale) 096 */ 097 public String getConfiguration( 098 CmsObject cms, 099 A_CmsXmlContentValue contentValue, 100 CmsMessages messages, 101 CmsResource resource, 102 Locale contentLocale) { 103 104 try { 105 JSONObject serverConfig = new JSONObject(); 106 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(getConfiguration())) { 107 try { 108 serverConfig = new JSONObject(getConfiguration()); 109 } catch (JSONException e) { 110 LOG.error(e.getLocalizedMessage(), e); 111 } 112 } 113 String mode = serverConfig.optString("mode", "html"); 114 String heightStr = serverConfig.optString("height"); 115 Integer height = null; 116 if ((heightStr != null) && !("none".equals(heightStr))) { 117 try { 118 height = Integer.valueOf(heightStr); 119 } catch (NumberFormatException e) { 120 LOG.warn(e.getLocalizedMessage(), e); 121 } 122 } 123 AutoBean<I_CmsCodeMirrorClientConfiguration> clientConfig = m_configFactory.createConfiguration(); 124 Locale userLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 125 clientConfig.as().setPhrasesJSON(getPhrases(userLocale)); 126 clientConfig.as().setHeight(height); 127 clientConfig.as().setStartMode(mode); 128 String clientConfigJsonString = AutoBeanCodex.encode(clientConfig).getPayload(); 129 return clientConfigJsonString; 130 } catch (Exception e) { 131 LOG.error(e); 132 return "{}"; 133 } 134 } 135 136 /** 137 * @see org.opencms.widgets.I_CmsADEWidget#getCssResourceLinks(org.opencms.file.CmsObject) 138 */ 139 public List<String> getCssResourceLinks(CmsObject cms) { 140 141 return null; 142 } 143 144 /** 145 * @see org.opencms.widgets.I_CmsADEWidget#getDefaultDisplayType() 146 */ 147 public DisplayType getDefaultDisplayType() { 148 149 return DisplayType.wide; 150 } 151 152 /** 153 * @see org.opencms.widgets.I_CmsWidget#getDialogWidget(org.opencms.file.CmsObject, org.opencms.widgets.I_CmsWidgetDialog, org.opencms.widgets.I_CmsWidgetParameter) 154 */ 155 public String getDialogWidget(CmsObject cms, I_CmsWidgetDialog widgetDialog, I_CmsWidgetParameter param) { 156 157 return null; 158 } 159 160 /** 161 * @see org.opencms.widgets.I_CmsADEWidget#getInitCall() 162 */ 163 public String getInitCall() { 164 165 return null; 166 } 167 168 /** 169 * @see org.opencms.widgets.I_CmsADEWidget#getJavaScriptResourceLinks(org.opencms.file.CmsObject) 170 */ 171 public List<String> getJavaScriptResourceLinks(CmsObject cms) { 172 173 return null; 174 } 175 176 /** 177 * @see org.opencms.widgets.I_CmsADEWidget#getWidgetName() 178 */ 179 public String getWidgetName() { 180 181 return CmsCodeWidget.class.getName(); 182 } 183 184 /** 185 * @see org.opencms.widgets.I_CmsADEWidget#isInternal() 186 */ 187 public boolean isInternal() { 188 189 return true; 190 } 191 192 /** 193 * @see org.opencms.widgets.I_CmsWidget#newInstance() 194 */ 195 public I_CmsWidget newInstance() { 196 197 return new CmsCodeWidget(getConfiguration()); 198 } 199 200 /** 201 * Gets the i18n phrases for CodeMirror. 202 * 203 * @param userLocale the current locale 204 * @return the phrases as JSON 205 */ 206 private String getPhrases(Locale userLocale) { 207 208 try { 209 InputStream stream = null; 210 stream = getClass().getResourceAsStream("codemirror_phrases_" + userLocale.getLanguage() + ".json"); 211 if (stream != null) { 212 try { 213 byte[] data = CmsFileUtil.readFully(stream, false); 214 String result = new String(data, StandardCharsets.UTF_8); 215 @SuppressWarnings("unused") 216 JSONObject dummy = new JSONObject(result); // throw and log exception if invalid JSON 217 return result; 218 } finally { 219 stream.close(); 220 } 221 } else { 222 return "{}"; 223 } 224 } catch (Exception e) { 225 LOG.error(e.getLocalizedMessage(), e); 226 return "{}"; 227 } 228 } 229 230}