2 * Copyright (C) 2001, 2002 The Mir-coders group
4 * This file is part of Mir.
6 * Mir is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Mir is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Mir; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * In addition, as a special exception, The Mir-coders gives permission to link
21 * the code of this program with any library licensed under the Apache Software License,
22 * The Sun (tm) Java Advanced Imaging library (JAI), The Sun JIMI library
23 * (or with modified versions of the above that use the same license as the above),
24 * and distribute linked combinations including the two. You must obey the
25 * GNU General Public License in all respects for all of the code used other than
26 * the above mentioned libraries. If you modify this file, you may extend this
27 * exception to your version of the file, but you are not obligated to do so.
28 * If you do not wish to do so, delete this exception statement from your version.
30 package mircoders.localizer.basic;
33 import mir.config.MirPropertiesConfiguration;
34 import mir.entity.adapter.EntityAdapter;
35 import mir.entity.adapter.EntityIteratorAdapter;
36 import mir.generator.Generator;
37 import mir.generator.GeneratorExc;
38 import mir.generator.GeneratorFailure;
39 import mir.log.LoggerWrapper;
40 import mir.util.GeneratorDateTimeFunctions;
41 import mir.util.GeneratorFormatAdapters;
42 import mir.util.HTMLStripper;
43 import mir.util.StringRoutines;
44 import mir.util.generator.ReflectionGeneratorFunctionsAdapter;
45 import mircoders.global.MirGlobal;
46 import mircoders.localizer.MirLocalizerExc;
47 import mircoders.localizer.MirLocalizerFailure;
48 import mircoders.localizer.MirProducerAssistantLocalizer;
49 import org.w3c.dom.Document;
50 import org.w3c.dom.NamedNodeMap;
51 import org.w3c.dom.Node;
52 import org.w3c.dom.NodeList;
53 import org.w3c.tidy.Configuration;
54 import org.w3c.tidy.Tidy;
56 import java.io.ByteArrayInputStream;
57 import java.io.IOException;
58 import java.io.StringWriter;
59 import java.util.GregorianCalendar;
60 import java.util.HashMap;
61 import java.util.Iterator;
62 import java.util.List;
65 public class MirBasicProducerAssistantLocalizer implements MirProducerAssistantLocalizer {
66 protected LoggerWrapper logger;
68 private HTMLStripper stripper;
69 private RE regularExpressionLT;
70 private RE regularExpressionGT;
71 private RE regularExpressionWhitespace;
72 private RE regularExpressionLeadingSlashes;
75 public MirBasicProducerAssistantLocalizer() throws MirLocalizerFailure {
77 stripper = new HTMLStripper();
79 regularExpressionLT = new RE("<");
80 regularExpressionGT = new RE(">");
81 regularExpressionWhitespace = new RE("\\s+|
|
");
82 regularExpressionLeadingSlashes = new RE("^//+");
85 throw new MirLocalizerFailure(t);
89 public void initializeGenerationValueSet(Map aValueSet) throws MirLocalizerExc, MirLocalizerFailure {
93 Map configMap = new HashMap();
95 logger = new LoggerWrapper("Localizer.ProducerAssistant");
98 configMap.put("producerDocRoot", MirGlobal.config().getString("Producer.DocRoot"));
99 configMap.put("storageRoot", MirGlobal.config().getString("Producer.StorageRoot"));
100 configMap.put("productionHost", MirGlobal.config().getString("Producer.ProductionHost"));
101 configMap.put("openAction", MirGlobal.config().getString("Producer.OpenAction"));
102 configMap.put("docRoot", MirGlobal.config().getString("RootUri"));
103 configMap.put("actionRoot", MirGlobal.config().getString("RootUri") + "/servlet/Mir");
104 configMap.put("now", new GeneratorFormatAdapters.DateFormatAdapter(new GregorianCalendar().getTime(), MirGlobal.config().getString("Mir.DefaultTimezone")));
105 configMap.put("videoHost", MirGlobal.config().getString("Producer.Video.Host"));
106 configMap.put("audioHost", MirGlobal.config().getString("Producer.Audio.Host"));
107 configMap.put("imageHost", MirGlobal.config().getString("Producer.Image.Host"));
108 configMap.put("imagePath", MirGlobal.config().getString("Producer.Image.Path"));
109 configMap.put("mirVersion", MirGlobal.config().getString("Mir.Version"));
110 configMap.put("defEncoding", MirGlobal.config().getString("Mir.DefaultEncoding"));
113 configMap.putAll(MirPropertiesConfiguration.instance().allSettings());
115 aValueSet.put("config", configMap);
117 aValueSet.put("utility", new Utility());
119 aValueSet.put("languages",
120 new EntityIteratorAdapter("", "", 20, MirGlobal.localizer().dataModel().adapterModel(), "language"));
122 aValueSet.put("topics",
123 new EntityIteratorAdapter("", "", 20, MirGlobal.localizer().dataModel().adapterModel(), "topic"));
125 Map articleTypeMap = new HashMap();
126 articleTypeMap.put("openposting", "0");
127 articleTypeMap.put("newswire", "1");
128 articleTypeMap.put("feature", "2");
129 articleTypeMap.put("topicspecial", "3");
130 articleTypeMap.put("startspecial", "4");
132 i = new EntityIteratorAdapter("", "", 20, MirGlobal.localizer().dataModel().adapterModel(), "articleType");
133 while (i.hasNext()) {
134 EntityAdapter articleType = (EntityAdapter) i.next();
136 articleTypeMap.put(articleType.get("name"), articleType.get("id"));
138 aValueSet.put("articletype", articleTypeMap);
140 Map commentStatusMap = new HashMap();
141 i = new EntityIteratorAdapter("", "", 20, MirGlobal.localizer().dataModel().adapterModel(), "commentStatus");
142 while (i.hasNext()) {
143 EntityAdapter commentStatus = (EntityAdapter) i.next();
145 commentStatusMap.put(commentStatus.get("name"), commentStatus.get("id"));
147 aValueSet.put("commentstatus", commentStatusMap);
148 aValueSet.put("languageCodeToId", new getLanguageIdFunction());
150 catch (Throwable t) {
151 logger.error("initializeGenerationValueSet: Exception while collecting comment statuses" + t.getMessage());
153 throw new MirLocalizerFailure(t);
158 public static class getLanguageIdFunction implements Generator.Function {
159 private Map languageCodeToId;
160 private String otherLanguageId;
161 private LoggerWrapper logger = new LoggerWrapper("Localizer.Earth.getLanguageIdFunction");
163 public getLanguageIdFunction() throws MirLocalizerFailure {
165 otherLanguageId = "";
166 languageCodeToId = new HashMap();
168 Iterator i = new EntityIteratorAdapter("", "", 20, MirGlobal.localizer().dataModel().adapterModel(), "language");
169 while (i.hasNext()) {
170 EntityAdapter language = (EntityAdapter) i.next();
171 if (language.get("code").equals("ot")) {
172 otherLanguageId = (String) language.get("id");
175 languageCodeToId.put(language.get("code"), language.get("id"));
178 catch (Throwable t) {
179 logger.error(t.toString());
181 throw new MirLocalizerFailure(t);
185 public Object perform(List aParameters) throws GeneratorExc, GeneratorFailure {
187 if (aParameters.size() != 1) {
188 throw new GeneratorExc("getLanguageIdFunction: 1 parameter expected: language-code");
191 String result = (String) languageCodeToId.get(aParameters.get(0));
192 if (result == null) {
193 result = otherLanguageId;
198 catch (GeneratorExc e) {
201 catch (Throwable t) {
202 throw new GeneratorFailure("getLanguageIdFunction: " + t.getMessage(), t);
208 public String filterNonHTMLText(String aText) {
210 logger.debug("about to filter non HTML Text of length " + aText.length());
214 stripper.removeHTMLTags(aText),
215 MirGlobal.config().getString("Producer.ImageRoot"),
216 MirGlobal.config().getString("Producer.MailLinkName"),
217 MirGlobal.config().getString("Producer.ExtLinkName"),
218 MirGlobal.config().getString("Producer.IntLinkName"));
219 logger.debug("done filtering non-HTML text ");
222 catch (Throwable t) {
223 logger.error("error while filtering non-HTML text: " + t.toString());
225 throw new RuntimeException(t.toString());
229 public Generator.Interceptor createGenerationInterceptor() throws MirLocalizerExc, MirLocalizerFailure {
231 if (MirGlobal.config().getBoolean("Mir.Producer.UseInterceptor", true)) {
232 return new Generator.Interceptor() {
234 public Object intercept(Object anObject) {
235 if (anObject instanceof EntityAdapter) {
236 return new InterceptedEntityAdapter((EntityAdapter) anObject);
248 public class InterceptedEntityAdapter {
249 private EntityAdapter adapter;
251 InterceptedEntityAdapter(EntityAdapter anEntityAdapter) {
252 adapter = anEntityAdapter;
255 public Object get(String aField) {
256 Object result = adapter.get(aField);
257 if (result instanceof String) {
258 return filterHTMLText((String) result);
265 public Object getRaw() {
266 return new RawEntityAdapter(adapter);
270 public class RawEntityAdapter {
271 private EntityAdapter adapter;
273 RawEntityAdapter(EntityAdapter anEntityAdapter) {
274 adapter = anEntityAdapter;
277 public Object get(String aField) {
278 return adapter.get(aField);
282 public String filterHTMLText(String aText) {
284 StringWriter out = new StringWriter();
285 Tidy tidy = new Tidy();
286 ByteArrayInputStream in = new ByteArrayInputStream(aText.getBytes("UTF8"));
287 tidy.setMakeClean(true);
288 tidy.setCharEncoding(Configuration.UTF8);
289 tidy.setErrout(logger.asPrintWriter(LoggerWrapper.DEBUG_MESSAGE));
290 print(tidy.parseDOM(in, null), out);
292 return out.toString();
294 catch (IOException e) {
295 return e.getMessage();
301 private boolean isBadAttr(String attrName) {
302 List badAttributes = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.BadAttributes"), ";");
303 Iterator i = badAttributes.iterator();
304 while (i.hasNext()) {
305 if (((String) i.next()).toLowerCase().equals(attrName.toLowerCase())) {
312 private String stripWhitespace(String aString) {
314 return regularExpressionWhitespace.substituteAll(aString, "");
316 catch (Throwable t) {
321 private boolean checkAttr(String attrName) {
322 if (isBadAttr(attrName)) {
329 private boolean checkAttrValue(String attrValue) {
330 List badPrefixes = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.BadAttributeValuePrefixes"), ";");
331 Iterator i = badPrefixes.iterator();
332 while (i.hasNext()) {
333 if ((stripWhitespace(attrValue.toLowerCase())).startsWith(((String) i.next()).toLowerCase() + ":")) {
341 private boolean checkNode(String nodeName) {
342 List acceptableNodes = StringRoutines.splitString(MirGlobal.config().getString("Localizer.HTML.Whitelist"), ";");
344 Iterator i = acceptableNodes.iterator();
345 while (i.hasNext()) {
346 if (nodeName.equals(i.next())) {
353 private void print(Node node, StringWriter out) throws IOException {
357 int type = node.getNodeType();
358 boolean canOutput = checkNode(node.getNodeName());
362 case Node.DOCUMENT_NODE:
364 print(((Document) node).getDocumentElement(), out);
368 case Node.ELEMENT_NODE:
372 out.write(node.getNodeName());
373 NamedNodeMap attrs = node.getAttributes();
375 for (int i = 0; i < attrs.getLength(); i++) {
376 String attrName = attrs.item(i).getNodeName();
377 String attrValue = attrs.item(i).getNodeValue();
378 if (attrValue.startsWith("//")){
379 attrValue=regularExpressionLeadingSlashes.substitute(attrValue, "/");
382 if (checkAttr(attrName) && checkAttrValue(attrValue)) {
384 out.write(attrs.item(i).getNodeName());
387 out.write(attrs.item(i).getNodeValue());
392 if (node.getChildNodes() == null || node.getChildNodes().getLength() == 0) {
397 NodeList children = node.getChildNodes();
398 if (children != null) {
399 int len = children.getLength();
400 for (int i = 0; i < len; i++) {
401 print(children.item(i), out);
407 String value = node.getNodeValue();
409 value = regularExpressionLT.substituteAll(value, "<");
410 value = regularExpressionGT.substituteAll(value, ">");
412 catch (Throwable t) {
421 if (type == Node.ELEMENT_NODE && canOutput && node.getChildNodes() != null && node.getChildNodes().getLength() > 0) {
423 out.write(node.getNodeName());
430 public static class Utility extends ReflectionGeneratorFunctionsAdapter {
432 super(new MirBasicUtilityFunctions());
435 public Object getDatetime() {
436 return new GeneratorDateTimeFunctions.DateTimeFunctions(
437 MirPropertiesConfiguration.instance().getString("Mir.DefaultTimezone"));
440 public Object getCompressWhitespace() {
441 return new freemarker.template.utility.CompressWhitespace();