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_CmsAutoBeanFactory; 033import org.opencms.gwt.shared.I_CmsCodeMirrorClientConfiguration; 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_CmsAutoBeanFactory m_configFactory = AutoBeanFactorySource.create(I_CmsAutoBeanFactory.class); 073 074 /** 075 * Creates a new instance. 076 */ 077 public CmsCodeWidget() { 078 079 this("{}"); 080 081 } 082 083 /** 084 * Creates a new instance. 085 * 086 * @param configuration the configuration 087 */ 088 public CmsCodeWidget(String configuration) { 089 090 setConfiguration(configuration); 091 } 092 093 /** 094 * @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) 095 */ 096 public String getConfiguration( 097 CmsObject cms, 098 A_CmsXmlContentValue contentValue, 099 CmsMessages messages, 100 CmsResource resource, 101 Locale contentLocale) { 102 103 try { 104 JSONObject serverConfig = new JSONObject(); 105 if (!CmsStringUtil.isEmptyOrWhitespaceOnly(getConfiguration())) { 106 try { 107 serverConfig = new JSONObject(getConfiguration()); 108 } catch (JSONException e) { 109 LOG.error(e.getLocalizedMessage(), e); 110 } 111 } 112 String mode = serverConfig.optString("mode", "html"); 113 String heightStr = serverConfig.optString("height"); 114 Integer height = null; 115 if ((heightStr != null) && !("none".equals(heightStr))) { 116 try { 117 height = Integer.valueOf(heightStr); 118 } catch (NumberFormatException e) { 119 LOG.warn(e.getLocalizedMessage(), e); 120 } 121 } 122 AutoBean<I_CmsCodeMirrorClientConfiguration> clientConfig = m_configFactory.createConfiguration(); 123 Locale userLocale = OpenCms.getWorkplaceManager().getWorkplaceLocale(cms); 124 clientConfig.as().setPhrasesJSON(getPhrases(userLocale)); 125 clientConfig.as().setHeight(height); 126 clientConfig.as().setStartMode(mode); 127 String clientConfigJsonString = AutoBeanCodex.encode(clientConfig).getPayload(); 128 return clientConfigJsonString; 129 } catch (Exception e) { 130 LOG.error(e); 131 return "{}"; 132 } 133 } 134 135 /** 136 * @see org.opencms.widgets.I_CmsADEWidget#getCssResourceLinks(org.opencms.file.CmsObject) 137 */ 138 public List<String> getCssResourceLinks(CmsObject cms) { 139 140 return null; 141 } 142 143 /** 144 * @see org.opencms.widgets.I_CmsADEWidget#getDefaultDisplayType() 145 */ 146 public DisplayType getDefaultDisplayType() { 147 148 return DisplayType.wide; 149 } 150 151 /** 152 * @see org.opencms.widgets.I_CmsWidget#getDialogWidget(org.opencms.file.CmsObject, org.opencms.widgets.I_CmsWidgetDialog, org.opencms.widgets.I_CmsWidgetParameter) 153 */ 154 public String getDialogWidget(CmsObject cms, I_CmsWidgetDialog widgetDialog, I_CmsWidgetParameter param) { 155 156 return null; 157 } 158 159 /** 160 * @see org.opencms.widgets.I_CmsADEWidget#getInitCall() 161 */ 162 public String getInitCall() { 163 164 return null; 165 } 166 167 /** 168 * @see org.opencms.widgets.I_CmsADEWidget#getJavaScriptResourceLinks(org.opencms.file.CmsObject) 169 */ 170 public List<String> getJavaScriptResourceLinks(CmsObject cms) { 171 172 return null; 173 } 174 175 /** 176 * @see org.opencms.widgets.I_CmsADEWidget#getWidgetName() 177 */ 178 public String getWidgetName() { 179 180 return CmsCodeWidget.class.getName(); 181 } 182 183 /** 184 * @see org.opencms.widgets.I_CmsADEWidget#isInternal() 185 */ 186 public boolean isInternal() { 187 188 return true; 189 } 190 191 /** 192 * @see org.opencms.widgets.I_CmsWidget#newInstance() 193 */ 194 public I_CmsWidget newInstance() { 195 196 return new CmsCodeWidget(getConfiguration()); 197 } 198 199 /** 200 * Gets the i18n phrases for CodeMirror. 201 * 202 * @param userLocale the current locale 203 * @return the phrases as JSON 204 */ 205 private String getPhrases(Locale userLocale) { 206 207 try { 208 InputStream stream = null; 209 stream = getClass().getResourceAsStream("codemirror_phrases_" + userLocale.getLanguage() + ".json"); 210 if (stream != null) { 211 try { 212 byte[] data = CmsFileUtil.readFully(stream, false); 213 String result = new String(data, StandardCharsets.UTF_8); 214 @SuppressWarnings("unused") 215 JSONObject dummy = new JSONObject(result); // throw and log exception if invalid JSON 216 return result; 217 } finally { 218 stream.close(); 219 } 220 } else { 221 return "{}"; 222 } 223 } catch (Exception e) { 224 LOG.error(e.getLocalizedMessage(), e); 225 return "{}"; 226 } 227 } 228 229}