Java tutorial
//============================================================================ // // Copyright (C) 2002-2014 David Schneider, Lars Kdderitzsch // // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Lesser General Public // License as published by the Free Software Foundation; either // version 2.1 of the License, or (at your option) any later version. // // This library is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU // Lesser General Public License for more details. // // You should have received a copy of the GNU Lesser General Public // License along with this library; if not, write to the Free Software // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA // //============================================================================ package net.sf.eclipsecs.core.config; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.regex.Pattern; import net.sf.eclipsecs.core.config.meta.MetadataFactory; import net.sf.eclipsecs.core.config.meta.RuleMetadata; import net.sf.eclipsecs.core.util.CheckstylePluginException; import net.sf.eclipsecs.core.util.XMLUtil; import org.apache.commons.lang.StringUtils; import org.dom4j.Document; import org.dom4j.DocumentException; import org.dom4j.Element; import org.dom4j.VisitorSupport; import org.dom4j.io.SAXReader; import org.xml.sax.InputSource; /** * Utitlity class to read a checkstyle configuration and transform to the plugins module objects. * * @author Lars Kdderitzsch */ public final class ConfigurationReader { private static final Pattern PROPERTY_REF_PATTERN = Pattern.compile("^.*\\$\\{.*\\}.*$"); // // Mapping from public DTD to internal dtd resource. // @see com.puppycrawl.tools.checkstyle.api.AbstractLoader // /** Map containing the public - internal DTD mapping. */ private static final Map<String, String> PUBLIC2INTERNAL_DTD_MAP = new HashMap<String, String>(); static { PUBLIC2INTERNAL_DTD_MAP.put("-//Puppy Crawl//DTD Check Configuration 1.0//EN", //$NON-NLS-1$ "com/puppycrawl/tools/checkstyle/configuration_1_0.dtd"); //$NON-NLS-1$ PUBLIC2INTERNAL_DTD_MAP.put("-//Puppy Crawl//DTD Check Configuration 1.1//EN", //$NON-NLS-1$ "com/puppycrawl/tools/checkstyle/configuration_1_1.dtd"); //$NON-NLS-1$ PUBLIC2INTERNAL_DTD_MAP.put("-//Puppy Crawl//DTD Check Configuration 1.2//EN", //$NON-NLS-1$ "com/puppycrawl/tools/checkstyle/configuration_1_2.dtd"); //$NON-NLS-1$ PUBLIC2INTERNAL_DTD_MAP.put("-//Puppy Crawl//DTD Check Configuration 1.3//EN", //$NON-NLS-1$ "com/puppycrawl/tools/checkstyle/configuration_1_3.dtd"); //$NON-NLS-1$ } // // constructors // /** Hidden default constructor to prevent instantiation. */ private ConfigurationReader() { // NOOP } // // methods // /** * Reads the checkstyle configuration from the given stream an returs a list of all modules within this * configuration. * * @param in * the stream the configuration is loaded from * @return the list of modules * @throws CheckstylePluginException * error while reading the configuration */ public static List<Module> read(InputSource in) throws CheckstylePluginException { List<Module> rules = null; try { final SAXReader reader = new SAXReader(); reader.setEntityResolver(new XMLUtil.InternalDtdEntityResolver(PUBLIC2INTERNAL_DTD_MAP)); final Document document = reader.read(in); rules = getModules(document); } catch (final DocumentException ex) { CheckstylePluginException.rethrow(ex); } return rules != null ? rules : new ArrayList<Module>(); } /** * Gets additional data about the Checkstyle configuration. This data is used by the plugin for special purposes, * like determining the correct offset of a checkstyle violation. * * @param in * the input stream * @return the additional configuration data * @throws CheckstylePluginException * error while reading the configuration */ public static AdditionalConfigData getAdditionalConfigData(InputSource in) throws CheckstylePluginException { final List<Module> modules = read(in); int tabWidth = 8; for (final Module module : modules) { if ((module.getMetaData() != null) && module.getMetaData().getInternalName().equals(XMLTags.TREEWALKER_MODULE)) { final ConfigProperty prop = module.getProperty("tabWidth"); //$NON-NLS-1$ String tabWidthProp = null; if (prop != null) { tabWidthProp = prop.getValue(); } if (tabWidthProp == null && prop != null && prop.getMetaData() != null) { tabWidthProp = prop.getMetaData().getDefaultValue(); } try { tabWidth = Integer.parseInt(tabWidthProp); } catch (final Exception e) { // ignore } break; } } return new AdditionalConfigData(tabWidth); } private static List<Module> getModules(final Document document) { final List<Module> modules = new ArrayList<Module>(); document.accept(new VisitorSupport() { @Override public void visit(final Element node) { if (XMLTags.MODULE_TAG.equals(node.getName())) { final String name = node.attributeValue(XMLTags.NAME_TAG); final RuleMetadata metadata = MetadataFactory.getRuleMetadata(name); Module module = null; if (metadata != null) { module = new Module(metadata, true); } else { module = new Module(name); } addProperties(node, module); addMessages(node, module); addMetadata(node, module); // if the module has not metadata attached we create some // generic metadata if (module.getMetaData() == null) { MetadataFactory.createGenericMetadata(module); } modules.add(module); } } }); return modules; } private static void addProperties(final Element moduleEl, final Module module) { @SuppressWarnings("unchecked") final List<Element> propertyEls = moduleEl.elements(XMLTags.PROPERTY_TAG); for (final Element propertyEl : propertyEls) { final String name = propertyEl.attributeValue(XMLTags.NAME_TAG); final String value = propertyEl.attributeValue(XMLTags.VALUE_TAG); final boolean isPropertyRef = (value != null) && PROPERTY_REF_PATTERN.matcher(value).matches(); if (name.equals(XMLTags.SEVERITY_TAG) && (module.getMetaData() != null) && module.getMetaData().hasSeverity()) { try { module.setSeverity(Severity.valueOf(value)); } catch (final IllegalArgumentException e) { module.setSeverity(Severity.inherit); } } else if (name.equals(XMLTags.ID_TAG)) { module.setId(StringUtils.trimToNull(value)); } else if (module.getMetaData() != null) { final ConfigProperty property = module.getProperty(name); if (property != null) { property.setValue(value); property.setPropertyReference(isPropertyRef); } // properties that are not within the meta data are omitted } else { // if module has no meta data defined create property final ConfigProperty property = new ConfigProperty(name, value); property.setPropertyReference(isPropertyRef); module.getProperties().add(property); } } } private static void addMessages(final Element moduleEl, final Module module) { @SuppressWarnings("unchecked") final List<Element> messageEls = moduleEl.elements(XMLTags.MESSAGE_TAG); for (final Element messageEl : messageEls) { final String key = messageEl.attributeValue(XMLTags.KEY_TAG); final String value = messageEl.attributeValue(XMLTags.VALUE_TAG); module.getCustomMessages().put(key, value); } } private static void addMetadata(final Element moduleEl, final Module module) { @SuppressWarnings("unchecked") final List<Element> metaEls = moduleEl.elements(XMLTags.METADATA_TAG); for (final Element metaEl : metaEls) { final String name = metaEl.attributeValue(XMLTags.NAME_TAG); final String value = metaEl.attributeValue(XMLTags.VALUE_TAG); if (XMLTags.COMMENT_ID.equals(name)) { module.setComment(value); } else if (XMLTags.LAST_ENABLED_SEVERITY_ID.equals(name)) { module.setLastEnabledSeverity(Severity.valueOf(value)); } else { module.getCustomMetaData().put(name, value); } } } /** * Holds additional data about the Checkstyle configuration file, for special uses. * * @author Lars Kdderitzsch */ public static class AdditionalConfigData { private final int mTabWidth; /** * @param tabWidth * the tab width setting of the Checkstyle configuration */ public AdditionalConfigData(final int tabWidth) { super(); mTabWidth = tabWidth; } /** * The tab width of the check configuration. * * @return the tab width setting */ public int getTabWidth() { return mTabWidth; } } }