001/* 002 * Copyright 2012 Anyware Services 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.ametys.core.cocoon; 017 018import java.io.IOException; 019import java.util.Map; 020 021import org.apache.avalon.framework.configuration.Configuration; 022import org.apache.avalon.framework.configuration.ConfigurationException; 023import org.apache.avalon.framework.configuration.DefaultConfiguration; 024import org.apache.avalon.framework.context.ContextException; 025import org.apache.avalon.framework.context.Contextualizable; 026import org.apache.avalon.framework.parameters.Parameters; 027import org.apache.avalon.framework.service.ServiceException; 028import org.apache.avalon.framework.service.ServiceManager; 029import org.apache.cocoon.Constants; 030import org.apache.cocoon.ProcessingException; 031import org.apache.cocoon.environment.Context; 032import org.apache.cocoon.xml.ParamSaxBuffer; 033import org.apache.excalibur.source.SourceResolver; 034import org.xml.sax.SAXException; 035 036import org.ametys.core.util.I18nUtils; 037import org.ametys.runtime.plugin.PluginsManager; 038import org.ametys.runtime.workspace.WorkspaceManager; 039 040 041/** 042 * This class extends the classic I18nTransormer by automatically filling it with plugins catalogues. 043 * It also handles special sitemap parameters :<br> 044 * <ul> 045 * <li><code>plugin</code> : when specified and when the given plugin exists, the default catalogue id is set to plugin.<code>plugin</code> 046 * <li><code>workspace</code> : when specified and when the given workspace exists, the default catalogue id is set to workspace.<code>workspace</code> 047 * </ul> 048 * If the specified pugin or workspace does not exist, the specified default catalogue id is used, if any. 049 */ 050public class I18nTransformer extends org.apache.cocoon.transformation.I18nTransformer implements Contextualizable 051{ 052 /** Cocoon context */ 053 protected Context _context; 054 055 /** Source Resolver */ 056 protected SourceResolver _resolver; 057 058 /** The i18n utils */ 059 protected I18nUtils _i18nUtils; 060 061 public void contextualize(org.apache.avalon.framework.context.Context context) throws ContextException 062 { 063 _context = (Context) context.get(Constants.CONTEXT_ENVIRONMENT_CONTEXT); 064 } 065 066 @Override 067 public void service(ServiceManager smanager) throws ServiceException 068 { 069 super.service(smanager); 070 _resolver = (SourceResolver) smanager.lookup(SourceResolver.ROLE); 071 _i18nUtils = (I18nUtils) smanager.lookup(I18nUtils.ROLE); 072 } 073 074 @Override 075 public void configure(Configuration conf) throws ConfigurationException 076 { 077 // Add plugins catalogues to the configuration 078 DefaultConfiguration newConf = new DefaultConfiguration("i18n"); 079 newConf.addChild(conf.getChild("untranslated-text")); 080 newConf.addChild(conf.getChild("cache-at-startup")); 081 082 Configuration cataloguesConf = conf.getChild("catalogues", false); 083 DefaultConfiguration catalogues = new DefaultConfiguration("catalogues"); 084 newConf.addChild(catalogues); 085 086 if (cataloguesConf != null) 087 { 088 catalogues.addAll(cataloguesConf); 089 } 090 091 _configurePlugins(catalogues); 092 _configureWorkspaces(catalogues); 093 _configureParams(catalogues); 094 095 // Load the configuration 096 super.configure(newConf); 097 } 098 099 /** 100 * Search for all i18n folders in WEB-INF/param/* 101 * @param catalogues catalog to use 102 */ 103 private void _configureParams(DefaultConfiguration catalogues) 104 { 105 for (String name : _i18nUtils.getParamsFoldersWithI18n()) 106 { 107 String id = "param." + name; 108 109 DefaultConfiguration catalogue = new DefaultConfiguration("catalogue"); 110 catalogue.setAttribute("id", id); 111 catalogue.setAttribute("name", "messages"); 112 113 DefaultConfiguration location = new DefaultConfiguration("location"); 114 location.setValue("context://WEB-INF/param/" + name + "/i18n"); 115 catalogue.addChild(location); 116 117 catalogues.addChild(catalogue); 118 } 119 } 120 121 private void _configurePlugins(DefaultConfiguration catalogues) 122 { 123 PluginsManager pm = PluginsManager.getInstance(); 124 125 for (String pluginName : pm.getPluginNames()) 126 { 127 String id = "plugin." + pluginName; 128 129 DefaultConfiguration catalogue = new DefaultConfiguration("catalogue"); 130 catalogue.setAttribute("id", id); 131 catalogue.setAttribute("name", "messages"); 132 133 DefaultConfiguration location1 = new DefaultConfiguration("location"); 134 location1.setValue("context://WEB-INF/i18n/plugins/" + pluginName); 135 catalogue.addChild(location1); 136 137 DefaultConfiguration location2 = new DefaultConfiguration("location"); 138 location2.setValue("plugin:" + pluginName + "://i18n"); 139 catalogue.addChild(location2); 140 141 catalogues.addChild(catalogue); 142 } 143 } 144 145 private void _configureWorkspaces(DefaultConfiguration catalogues) 146 { 147 WorkspaceManager wm = WorkspaceManager.getInstance(); 148 149 for (String workspace : wm.getWorkspaceNames()) 150 { 151 String id = "workspace." + workspace; 152 153 DefaultConfiguration catalogue = new DefaultConfiguration("catalogue"); 154 catalogue.setAttribute("id", id); 155 catalogue.setAttribute("name", "messages"); 156 157 DefaultConfiguration location1 = new DefaultConfiguration("location"); 158 location1.setValue("context://WEB-INF/i18n/workspaces/" + workspace); 159 catalogue.addChild(location1); 160 161 DefaultConfiguration location2 = new DefaultConfiguration("location"); 162 location2.setValue("workspace:" + workspace + "://i18n"); 163 catalogue.addChild(location2); 164 165 catalogues.addChild(catalogue); 166 } 167 } 168 169 @Override 170 public void setup(org.apache.cocoon.environment.SourceResolver resolver, Map objModel, String source, Parameters parameters) throws ProcessingException, SAXException, IOException 171 { 172 Parameters newParam = new Parameters(); 173 174 // Copie de tous les paramètres qui ne sont pas directement utilisés ici 175 String[] names = parameters.getNames(); 176 177 for (int i = 0; i < names.length; i++) 178 { 179 String name = names[i]; 180 181 if (!"plugin".equals(name) && !"workspace".equals(name) && !I18N_DEFAULT_CATALOGUE_ID.equals(name)) 182 { 183 String value = parameters.getParameter(name, null); 184 newParam.setParameter(name, value); 185 } 186 } 187 188 String defaultCatalogueId = parameters.getParameter(I18N_DEFAULT_CATALOGUE_ID, null); 189 String pluginName = parameters.getParameter("plugin", null); 190 String workspaceName = parameters.getParameter("workspace", null); 191 192 boolean useDefault = true; 193 194 if (pluginName != null) 195 { 196 if (PluginsManager.getInstance().getPluginNames().contains(pluginName)) 197 { 198 newParam.setParameter(I18N_DEFAULT_CATALOGUE_ID, "plugin." + pluginName); 199 useDefault = false; 200 } 201 } 202 else if (workspaceName != null) 203 { 204 if (WorkspaceManager.getInstance().getWorkspaceNames().contains(workspaceName)) 205 { 206 newParam.setParameter(I18N_DEFAULT_CATALOGUE_ID, "workspace." + workspaceName); 207 useDefault = false; 208 } 209 } 210 211 if (useDefault) 212 { 213 newParam.setParameter(I18N_DEFAULT_CATALOGUE_ID, defaultCatalogueId); 214 } 215 216 super.setup(resolver, objModel, source, newParam); 217 } 218 219 @Override 220 protected ParamSaxBuffer getMessage(String catalogueID, String key) 221 { 222 ParamSaxBuffer message = super.getMessage(catalogueID, key); 223 if (message == null) 224 { 225 return getUntranslatedMessage (catalogueID, key); 226 } 227 228 return message; 229 } 230 231 /** 232 * Retrieve the message when the key is not found 233 * 234 * @param catalogueID The catalogue id 235 * @param key The i18n key 236 * @return SaxBuffer containing the message for untranslated key 237 */ 238 protected ParamSaxBuffer getUntranslatedMessage(String catalogueID, String key) 239 { 240 if (getLogger().isWarnEnabled()) 241 { 242 getLogger().warn("Translation not found for key " + key + " in catalogue " + catalogueID); 243 } 244 245 try 246 { 247 String value = catalogueID + ':' + key; 248 ParamSaxBuffer paramSaxBuffer = new ParamSaxBuffer(); 249 paramSaxBuffer.characters(value.toCharArray(), 0, value.length()); 250 251 return paramSaxBuffer; 252 } 253 catch (SAXException e) 254 { 255 throw new RuntimeException(e); 256 } 257 } 258}