001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2009 SonarSource SA
004 * mailto:contact AT sonarsource DOT com
005 *
006 * Sonar is free software; you can redistribute it and/or
007 * modify it under the terms of the GNU Lesser General Public
008 * License as published by the Free Software Foundation; either
009 * version 3 of the License, or (at your option) any later version.
010 *
011 * Sonar is distributed in the hope that it will be useful,
012 * but WITHOUT ANY WARRANTY; without even the implied warranty of
013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
014 * Lesser General Public License for more details.
015 *
016 * You should have received a copy of the GNU Lesser General Public
017 * License along with Sonar; if not, write to the Free Software
018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
019 */
020 package org.sonar.api.rules;
021
022 import com.thoughtworks.xstream.XStream;
023 import com.thoughtworks.xstream.converters.basic.AbstractSingleValueConverter;
024 import com.thoughtworks.xstream.core.util.QuickWriter;
025 import com.thoughtworks.xstream.io.HierarchicalStreamWriter;
026 import com.thoughtworks.xstream.io.xml.PrettyPrintWriter;
027 import com.thoughtworks.xstream.io.xml.XppDriver;
028 import org.apache.commons.io.IOUtils;
029 import org.apache.commons.lang.CharEncoding;
030 import org.apache.commons.lang.StringUtils;
031 import org.sonar.api.utils.SonarException;
032
033 import java.io.*;
034 import java.lang.ref.WeakReference;
035 import java.util.*;
036
037 @Deprecated
038 public class StandardRulesXmlParser {
039
040 /**
041 * see the XML format into the unit test src/test/java/.../StandardRulesXmlParserTest
042 */
043 public List<Rule> parse(String xml) {
044 InputStream inputStream = null;
045 try {
046 inputStream = IOUtils.toInputStream(xml, CharEncoding.UTF_8);
047 return setDefaultRulePriorities((List<Rule>) getXStream().fromXML(inputStream));
048
049 } catch (IOException e) {
050 throw new SonarException("Can't parse xml file", e);
051
052 } finally {
053 IOUtils.closeQuietly(inputStream);
054 }
055 }
056
057 public List<Rule> parse(Reader reader) {
058 return setDefaultRulePriorities((List<Rule>) getXStream().fromXML(reader));
059 }
060
061 public List<Rule> parse(InputStream input) {
062 try {
063 return setDefaultRulePriorities((List<Rule>) getXStream().fromXML(new InputStreamReader(input, CharEncoding.UTF_8)));
064
065 } catch (UnsupportedEncodingException e) {
066 throw new SonarException("Can't parse xml file", e);
067 }
068 }
069
070 private List<Rule> setDefaultRulePriorities(List<Rule> rules) {
071 for (Rule rule : rules) {
072 if (rule.getPriority() == null) {
073 rule.setPriority(RulePriority.MAJOR);
074 }
075 }
076 return rules;
077 }
078
079 public String toXml(List<Rule> rules) {
080 return getXStream().toXML(rules);
081 }
082
083 private static class CDataXppDriver extends XppDriver {
084 @Override
085 public HierarchicalStreamWriter createWriter(Writer out) {
086 return new XDataPrintWriter(out);
087 }
088 }
089
090 private static class XDataPrintWriter extends PrettyPrintWriter {
091 public XDataPrintWriter(Writer writer) {
092 super(writer);
093 }
094
095 @Override
096 protected void writeText(QuickWriter writer, String text) {
097 writer.write("<![CDATA[");
098 writer.write(text);
099 writer.write("]]>");
100 }
101 }
102
103 private XStream getXStream() {
104 XStream xstream = new XStream(new CDataXppDriver());
105 xstream.registerConverter(new TrimStringConverter());
106 xstream.alias("rules", ArrayList.class);
107
108 xstream.alias("categ", RulesCategory.class);
109 xstream.useAttributeFor(RulesCategory.class, "name");
110 xstream.aliasField("category", Rule.class, "rulesCategory");
111
112 xstream.alias("rule", Rule.class);
113 xstream.useAttributeFor(Rule.class, "key");
114 xstream.useAttributeFor("priority", RulePriority.class);
115
116 xstream.addImplicitCollection(Rule.class, "params");
117
118 xstream.alias("param", RuleParam.class);
119 xstream.useAttributeFor(RuleParam.class, "key");
120 xstream.useAttributeFor(RuleParam.class, "type");
121
122 // only for backward compatibility with sonar 1.4.
123 xstream.omitField(RuleParam.class, "defaultValue");
124 return xstream;
125 }
126
127 /**
128 * See http://svn.codehaus.org/xstream/trunk/xstream/src/java/com/thoughtworks/xstream/converters/basic/StringConverter.java
129 */
130 public static class TrimStringConverter extends AbstractSingleValueConverter {
131
132 private final Map cache;
133
134 public TrimStringConverter(final Map map) {
135 cache = map;
136 }
137
138 public TrimStringConverter() {
139 this(Collections.synchronizedMap(new WeakHashMap()));
140 }
141
142 public boolean canConvert(final Class type) {
143 return type.equals(String.class);
144 }
145
146 public Object fromString(final String str) {
147 String trim = StringUtils.trim(str);
148 final WeakReference ref = (WeakReference) cache.get(trim);
149 String s = (String) (ref == null ? null : ref.get());
150
151 if (s == null) {
152 // fill cache
153 cache.put(str, new WeakReference(trim));
154 s = trim;
155 }
156
157 return s;
158 }
159 }
160 }