diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..8a50b76 --- /dev/null +++ b/.classpath @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.gitignore b/.gitignore index c708c36..d9d66d8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,2 @@ /target -/.settings -/.classpath -/.project +/bin/ diff --git a/.project b/.project new file mode 100644 index 0000000..4866a03 --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + macker + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.m2e.core.maven2Nature + org.eclipse.jdt.core.javanature + + diff --git a/.travis.yml b/.travis.yml index a98b760..9bcf999 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,2 +1,3 @@ language: java - +jdk: + - oraclejdk8 diff --git a/CHANGES.txt b/CHANGES.txt index ba3540b..8f052ba 100644 --- a/CHANGES.txt +++ b/CHANGES.txt @@ -1,3 +1,20 @@ +Version 1.0.6: +* Speed improvement by almost factor 2 +* Bugfix: The rules project is stored in preferences now, and the rules directory searched inside it. + + +Version 1.0.5: +* is built itself with Java 8 +* fixes javadoc problem with Java 8 (doclint must be turned off in pom.xml) + +Version 1.0.4: +* Closing InputStreams in several cases fixed "too many open files" on Linux. + +Version 1.0.3: +* Fixed NullPointerException when a rule applies to java.lang.Object, so that there is no superclass +* added files from original macker 0.4.2 required for html report +* updated required libraries + Version 1.0.2: * Fixed XML validation requiring internet connection. diff --git a/README.md b/README.md index 7c98de0..2e8200d 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,8 @@ -[![Build Status](https://travis-ci.org/andrena/macker.svg)](https://travis-ci.org/andrena/macker) - - -[Documentation and examples](http://innig.net/macker/guide/) - -This is a [fork from innig.net](http://innig.net/macker/) ([source](http://sourceforge.net/p/macker/code/177/tree/trunk/macker/)), who initiated and developed this project. - -The intent of this fork is solely to ensure availability in Maven Central and updating it as necessary to provide support for today's JVMs. The original Macker (Version 0.4.2) was using [BCEL 5.2](http://commons.apache.org/bcel/) to do the bytecode parsing necessary to detect package dependencies. Unfortunately, it is no longer compatible to the Java Class File Format of Java 1.7 and 1.8. This fork eliminates the dependency to BCEL and replaces it with [Javassist](http://www.csg.is.titech.ac.jp/~chiba/javassist/), which seems to work with the newer class file versions. - -See also: -* The corresponding [Maven Plugin](https://github.com/andrena/macker-maven-plugin). +[Documentation and examples](http://innig.net/macker/guide/) + +This is a [fork from innig.net](http://innig.net/macker/) ([source](http://sourceforge.net/p/macker/code/177/tree/trunk/macker/)), who initiated and developed this project. + +The intent of this fork is solely to ensure availability in Maven Central and updating it as necessary to provide support for today's JVMs. The original Macker (Version 0.4.2) was using [BCEL 5.2](http://commons.apache.org/bcel/) to do the bytecode parsing necessary to detect package dependencies. Unfortunately, it is no longer compatible to the Java Class File Format of Java 1.7 and 1.8. This fork eliminates the dependency to BCEL and replaces it with [Javassist](http://www.csg.is.titech.ac.jp/~chiba/javassist/), which seems to work with the newer class file versions. + +See also: +* The corresponding [Maven Plugin](https://github.com/andrena/macker-maven-plugin). diff --git a/assembly.xml b/assembly.xml new file mode 100644 index 0000000..b6fe09f --- /dev/null +++ b/assembly.xml @@ -0,0 +1,32 @@ + + dist + + zip + + + + false + compile + false + lib + + + false + runtime + false + lib + + + + + target + / + + *.jar + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml index c481df3..8b7c421 100644 --- a/pom.xml +++ b/pom.xml @@ -1,174 +1,169 @@ - - - 4.0.0 - - - org.sonatype.oss - oss-parent - 7 - - - de.andrena.tools.macker - macker - 1.0.3-SNAPSHOT - jar - - Macker - Macker is a build-time architectural rule checking utility for Java developers. It's meant to model the architectural ideals programmers always dream up for their projects, and then break - it helps keep code clean and consistent. - - https://github.com/andrena/macker - - scm:git:git@github.com:andrena/macker.git - scm:git:git@github.com:andrena/macker.git - git@github.com:andrena/macker.git - - - - - GNU GPL v2.0 - http://www.gnu.org/licenses/gpl-2.0.html - repo - - - - - - Paul Cantrell - http://innig.net/ - - - Ben Romberg - andrena objects ag - - - - - - - maven-compiler-plugin - 2.2 - - 1.5 - 1.5 - - - - org.apache.maven.plugins - maven-source-plugin - 2.2.1 - - - attach-sources - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.9 - - - attach-javadocs - - jar - - - - - - - - - - org.javassist - javassist - 3.17.1-GA - - - ant - ant - 1.5 - - - commons-lang - commons-lang - 2.3 - - - jakarta-regexp - jakarta-regexp - 1.4 - - - xml-apis - xml-apis - 1.3.04 - - - jdom - jdom - 1.0 - - - xalan - xalan - 2.5.1 - - - xerces - xercesImpl - 2.8.1 - - - xerces - xmlParserAPIs - 2.6.2 - - - - junit - junit - 4.11 - test - - - org.hamcrest - hamcrest-library - 1.3 - test - - - - - - release-sign-artifacts - - - performRelease - true - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.1 - - - sign-artifacts - verify - - sign - - - - - - - - + + + 4.0.0 + + + org.sonatype.oss + oss-parent + 7 + + + de.andrena.tools.macker + macker + 1.0.6 + jar + + Macker + Macker is a build-time architectural rule checking utility for Java developers. It's meant to model the architectural ideals programmers always dream up for their projects, and then break - it helps keep code clean and consistent. + + https://github.com/his-eg/macker + + scm:git:git@github.com:his-eg/macker.git + scm:git:git@github.com:his-eg/macker.git + git@github.com:his-eg/macker.git + + + + + GNU GPL v2.0 + http://www.gnu.org/licenses/gpl-2.0.html + repo + + + + + + Paul Cantrell + http://innig.net/ + + + Ben Romberg + andrena objects ag + + + + + + + maven-compiler-plugin + 3.1 + + 1.8 + 1.8 + + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9 + + -Xdoclint:none + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assembly.xml + + + + + package + + single + + + + + + + + + + org.javassist + javassist + 3.17.1-GA + + + org.apache.ant + ant + 1.9.6 + + + commons-lang + commons-lang + 2.3 + + + org.jdom + jdom2 + 2.0.6 + + + + junit + junit + 4.11 + test + + + org.hamcrest + hamcrest-library + 1.3 + test + + + + + + release-sign-artifacts + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.1 + + + sign-artifacts + verify + + sign + + + + + + + + \ No newline at end of file diff --git a/src/main/java/de/andrena/tools/macker/Macker.java b/src/main/java/de/andrena/tools/macker/Macker.java index d2ade4e..69965d3 100644 --- a/src/main/java/de/andrena/tools/macker/Macker.java +++ b/src/main/java/de/andrena/tools/macker/Macker.java @@ -112,13 +112,7 @@ else if (args[arg].equals("--anger")) else if (args[arg].equals("-r") || args[arg].equals("--rulesfile")) nextIsRule = true; else if (args[arg].startsWith("@")) - macker.addClassesFromFile(args[arg].substring(1)); // the - // arg - // is a - // file - // with - // class - // names + macker.addClassesFromFile(args[arg].substring(1)); // the arg is a file with class names else if (args[arg].endsWith(".xml") || nextIsRule) { macker.addRulesFile(new File(args[arg])); nextIsRule = false; @@ -177,10 +171,7 @@ public void addClass(File classFile) throws IOException, ClassParseException { cm.makePrimary(cm.readClass(classFile)); } - public void addClass(InputStream classFile) throws IOException, ClassParseException { - cm.makePrimary(cm.readClass(classFile)); - } - + // Note: This method is never called. public void addClass(String className) throws ClassNotFoundException { cm.makePrimary(cm.getClassInfo(className)); } @@ -196,6 +187,7 @@ public void addClassesFromFile(String fileName) throws IOException, ClassParseEx indexReader.close(); } + // Note: This method is never called. public void addReachableClasses(Class initialClass, final String primaryPrefix) throws IncompleteClassInfoException { addReachableClasses(initialClass.getName(), primaryPrefix); diff --git a/src/main/java/de/andrena/tools/macker/ant/MackerReportAntTask.java b/src/main/java/de/andrena/tools/macker/ant/MackerReportAntTask.java index d1fdc38..b3b551d 100644 --- a/src/main/java/de/andrena/tools/macker/ant/MackerReportAntTask.java +++ b/src/main/java/de/andrena/tools/macker/ant/MackerReportAntTask.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; @@ -37,6 +38,7 @@ import de.andrena.tools.macker.Macker; import de.andrena.tools.macker.util.StreamSplitter; +import de.andrena.tools.macker.util.io.StreamUtil; /** * A task which formats Macker reports using XSLT. Requires Xalan 2 or some @@ -129,19 +131,29 @@ public void execute() throws BuildException { File outputDir = outputFile.getParentFile(); + InputStream formatUrlInputStream = null; + InputStream reportUrlInputStream = null; + FileOutputStream outputFileStream = null; try { - Transformer transformer = tFactory.newTransformer(new StreamSource(formatUrl.openStream())); - transformer.transform(new StreamSource(reportUrl.openStream()), new StreamResult(new FileOutputStream( - outputFile))); + formatUrlInputStream = formatUrl.openStream(); + reportUrlInputStream = reportUrl.openStream(); + outputFileStream = new FileOutputStream(outputFile); + Transformer transformer = tFactory.newTransformer(new StreamSource(formatUrlInputStream)); + transformer.transform(new StreamSource(reportUrlInputStream), new StreamResult(outputFileStream)); } catch (IOException ioe) { throw new BuildException("Unable to process report: " + ioe, ioe); } catch (TransformerException te) { throw new BuildException("Unable to apply report formatting: " + te.getMessage(), te); } + StreamUtil.closeStream(formatUrlInputStream); + StreamUtil.closeStream(reportUrlInputStream); + StreamUtil.closeStream(outputFileStream); + File skinOutputFile = new File(outputDir, "macker-report.css"); try { new StreamSplitter(skinUrl.openStream(), new FileOutputStream(skinOutputFile)).run(); + // Streams are closed at the end of the run() method } catch (IOException ioe) { throw new BuildException("Unable to copy skin to " + skinOutputFile, ioe); } diff --git a/src/main/java/de/andrena/tools/macker/event/PrintingListener.java b/src/main/java/de/andrena/tools/macker/event/PrintingListener.java index 5845a43..8c58537 100644 --- a/src/main/java/de/andrena/tools/macker/event/PrintingListener.java +++ b/src/main/java/de/andrena/tools/macker/event/PrintingListener.java @@ -119,8 +119,12 @@ public void printSummary() { out.print((eventsForSev.size() == 1) ? severity.getName() : severity.getNamePlural()); } } - if (!firstSeverity) + if (firstSeverity) { + // no problems found -> log that to make clear the run is finished + out.println("(no issues)"); + } else { out.println(')'); + } } @Override diff --git a/src/main/java/de/andrena/tools/macker/event/XmlReportingListener.java b/src/main/java/de/andrena/tools/macker/event/XmlReportingListener.java index b50da68..add576c 100644 --- a/src/main/java/de/andrena/tools/macker/event/XmlReportingListener.java +++ b/src/main/java/de/andrena/tools/macker/event/XmlReportingListener.java @@ -9,10 +9,10 @@ import java.util.LinkedList; import org.apache.commons.lang.StringUtils; -import org.jdom.Document; -import org.jdom.Element; -import org.jdom.output.Format; -import org.jdom.output.XMLOutputter; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.output.Format; +import org.jdom2.output.XMLOutputter; import de.andrena.tools.macker.rule.RuleSet; import de.andrena.tools.macker.structure.ClassInfo; diff --git a/src/main/java/de/andrena/tools/macker/rule/AccessRule.java b/src/main/java/de/andrena/tools/macker/rule/AccessRule.java index 576c3f1..f3c2977 100644 --- a/src/main/java/de/andrena/tools/macker/rule/AccessRule.java +++ b/src/main/java/de/andrena/tools/macker/rule/AccessRule.java @@ -32,6 +32,9 @@ import de.andrena.tools.macker.util.IncludeExcludeNode; import de.andrena.tools.macker.util.collect.MultiMap; +/** + * Processes tags in rule XML files. + */ public class AccessRule extends Rule { // -------------------------------------------------------------------------- // Constructors diff --git a/src/main/java/de/andrena/tools/macker/rule/EvaluationContext.java b/src/main/java/de/andrena/tools/macker/rule/EvaluationContext.java index 9a6ca9b..3e241c7 100644 --- a/src/main/java/de/andrena/tools/macker/rule/EvaluationContext.java +++ b/src/main/java/de/andrena/tools/macker/rule/EvaluationContext.java @@ -59,9 +59,25 @@ public ClassManager getClassManager() { public RuleSet getRuleSet() { return ruleSet; } - + + /** + * Set variable value with substitution of variables in the value string. + * @param name + * @param value + * @throws UndeclaredVariableException + */ + public void setVariableValueWithSubstitution(String name, String value) throws UndeclaredVariableException { + varValues.put(name, (value==null) ? "" : VariableParser.parse(this, value)); + } + + /** + * Set variable value without substitution of variables in the value string. + * @param name + * @param value + * @throws UndeclaredVariableException + */ public void setVariableValue(String name, String value) throws UndeclaredVariableException { - varValues.put(name, (value == null) ? "" : VariableParser.parse(this, value)); + varValues.put(name, (value==null) ? "" : value); } public String getVariableValue(String name) throws UndeclaredVariableException { diff --git a/src/main/java/de/andrena/tools/macker/rule/ForEach.java b/src/main/java/de/andrena/tools/macker/rule/ForEach.java index b17f535..8addc24 100644 --- a/src/main/java/de/andrena/tools/macker/rule/ForEach.java +++ b/src/main/java/de/andrena/tools/macker/rule/ForEach.java @@ -33,6 +33,9 @@ import de.andrena.tools.macker.structure.ClassInfo; import de.andrena.tools.macker.structure.ClassManager; +/** + * Processes tags in rule XML files. + */ public class ForEach extends Rule { public ForEach(RuleSet parent) { super(parent); diff --git a/src/main/java/de/andrena/tools/macker/rule/MackerEntityResolver.java b/src/main/java/de/andrena/tools/macker/rule/MackerEntityResolver.java deleted file mode 100644 index 83c2466..0000000 --- a/src/main/java/de/andrena/tools/macker/rule/MackerEntityResolver.java +++ /dev/null @@ -1,19 +0,0 @@ -package de.andrena.tools.macker.rule; - -import java.io.IOException; - -import org.xml.sax.EntityResolver; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -public class MackerEntityResolver implements EntityResolver { - - private static final String MACKER_PUBLIC_ID = "-//innig//DTD Macker 0.4//EN"; - - public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { - if (MACKER_PUBLIC_ID.equals(publicId)) { - return new InputSource(RuleSetBuilder.MACKER_DTD.openStream()); - } - return null; - } -} diff --git a/src/main/java/de/andrena/tools/macker/rule/Message.java b/src/main/java/de/andrena/tools/macker/rule/Message.java index 2c218cf..2835845 100644 --- a/src/main/java/de/andrena/tools/macker/rule/Message.java +++ b/src/main/java/de/andrena/tools/macker/rule/Message.java @@ -25,6 +25,9 @@ import de.andrena.tools.macker.event.MessageEvent; import de.andrena.tools.macker.structure.ClassManager; +/** + * Processes tags in rule XML files. + */ public class Message extends Rule { // -------------------------------------------------------------------------- // Constructors diff --git a/src/main/java/de/andrena/tools/macker/rule/RuleSet.java b/src/main/java/de/andrena/tools/macker/rule/RuleSet.java index a61cf47..663c8f9 100644 --- a/src/main/java/de/andrena/tools/macker/rule/RuleSet.java +++ b/src/main/java/de/andrena/tools/macker/rule/RuleSet.java @@ -31,6 +31,9 @@ import de.andrena.tools.macker.structure.ClassInfo; import de.andrena.tools.macker.structure.ClassManager; +/** + * Processes tags in rule XML files. + */ public class RuleSet extends Rule { public static RuleSet getMackerDefaults() { if (defaults == null) diff --git a/src/main/java/de/andrena/tools/macker/rule/RuleSetBuilder.java b/src/main/java/de/andrena/tools/macker/rule/RuleSetBuilder.java index c1e7008..c8c8d14 100644 --- a/src/main/java/de/andrena/tools/macker/rule/RuleSetBuilder.java +++ b/src/main/java/de/andrena/tools/macker/rule/RuleSetBuilder.java @@ -23,11 +23,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.io.PrintStream; import java.io.Reader; -import java.io.StringReader; -import java.io.StringWriter; -import java.net.URL; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; @@ -36,206 +32,185 @@ import java.util.ListIterator; import java.util.Map; -import org.jdom.Attribute; -import org.jdom.DocType; -import org.jdom.Document; -import org.jdom.Element; -import org.jdom.JDOMException; -import org.jdom.input.SAXBuilder; -import org.jdom.output.XMLOutputter; +import org.jdom2.Attribute; +import org.jdom2.Document; +import org.jdom2.Element; +import org.jdom2.JDOMException; +import org.jdom2.input.SAXBuilder; +import org.jdom2.input.sax.XMLReaders; -import de.andrena.tools.macker.Macker; import de.andrena.tools.macker.rule.filter.Filter; import de.andrena.tools.macker.rule.filter.FilterFinder; -import de.andrena.tools.macker.util.io.NullOutputStream; public class RuleSetBuilder { - public static final URL MACKER_DTD = Thread.currentThread().getContextClassLoader() - .getResource(Macker.PACKAGE_SLASHES + "/macker.dtd"); - - private SAXBuilder saxBuilder, saxBuilderVerify; - private XMLOutputter xmlOut; - private String dtdUrlS; + private final SAXBuilder saxBuilder; public RuleSetBuilder() { - saxBuilder = new SAXBuilder(false); - saxBuilder.setEntityResolver(new MackerEntityResolver()); - saxBuilderVerify = new SAXBuilder(true); - xmlOut = new XMLOutputter(); - - // ! hack to get around bogus messages generated by Ant's classloader - PrintStream realErr = System.err; - try { - System.setErr(new PrintStream(new NullOutputStream())); - dtdUrlS = MACKER_DTD.toExternalForm(); - } finally { - System.setErr(realErr); - } + saxBuilder = new SAXBuilder(XMLReaders.XSDVALIDATING); } - public Collection build(InputStream is) throws RulesException { + public Collection build(final InputStream is) + throws RulesException { try { return build(saxBuilder.build(is)); - } catch (JDOMException jdome) { + } catch (final JDOMException jdome) { throw new RulesDocumentException(jdome); - } catch (IOException ioe) { + } catch (final IOException ioe) { throw new RulesDocumentException(ioe); } } - public Collection build(Reader reader) throws RulesException { + public Collection build(final Reader reader) throws RulesException { try { return build(saxBuilder.build(reader)); - } catch (JDOMException jdome) { + } catch (final JDOMException jdome) { throw new RulesDocumentException(jdome); - } catch (IOException ioe) { + } catch (final IOException ioe) { throw new RulesDocumentException(ioe); } } - public Collection build(File file) throws RulesException { + public Collection build(final File file) throws RulesException { try { return build(saxBuilder.build(file)); - } catch (JDOMException jdome) { + } catch (final JDOMException jdome) { throw new RulesDocumentException(jdome); - } catch (IOException ioe) { + } catch (final IOException ioe) { throw new RulesDocumentException(ioe); } } - public Collection build(String fileName) throws RulesException { + public Collection build(final String fileName) + throws RulesException { return build(new File(fileName)); } - public Collection build(Document doc) throws RulesException { - validateAgainstDTD(doc); + public Collection build(final Document doc) throws RulesException { return build(doc.getRootElement()); } - public Collection build(Element elem) throws RulesException { - Collection ruleSets = new ArrayList(); + public Collection build(final Element elem) throws RulesException { + final Collection ruleSets = new ArrayList(); - for (Element rsElem : getChildren(elem, "ruleset")) + for (final Element rsElem : getChildren(elem, "ruleset")) { ruleSets.add(buildRuleSet(rsElem, RuleSet.getMackerDefaults())); + } return ruleSets; } - @SuppressWarnings("unchecked") - private Collection getChildren(Element elem, String tagName) { + private Collection getChildren(final Element elem, + final String tagName) { return elem.getChildren(tagName); } - private void validateAgainstDTD(Document doc) throws RulesDocumentException { - doc.setDocType(new DocType("macker", dtdUrlS)); - - StringWriter out = new StringWriter(); - try { - xmlOut.output(doc, out); - } catch (IOException ioe) { - ioe.printStackTrace(); - throw new RuntimeException("Unexpected output exception: " + ioe); - } - Reader in = new StringReader(out.toString()); - try { - saxBuilderVerify.build(in); - } catch (JDOMException jdome) { - throw new RulesDocumentException(jdome); - } catch (IOException ioe) { - throw new RulesDocumentException(ioe); - } - } - - public RuleSet buildRuleSet(Element ruleSetElem, RuleSet parent) throws RulesException { - RuleSet ruleSet = new RuleSet(parent); + public RuleSet buildRuleSet(final Element ruleSetElem, final RuleSet parent) + throws RulesException { + final RuleSet ruleSet = new RuleSet(parent); - String name = ruleSetElem.getAttributeValue("name"); - if (name != null) + final String name = ruleSetElem.getAttributeValue("name"); + if (name != null) { ruleSet.setName(name); + } buildSeverity(ruleSet, ruleSetElem); - for (Element subElem : getChildren(ruleSetElem)) { - String subElemName = subElem.getName(); + for (final Element subElem : getChildren(ruleSetElem)) { + final String subElemName = subElem.getName(); if (subElemName.equals("pattern")) { - String patternName = subElem.getAttributeValue("name"); - if (ruleSet.declaresPattern(patternName)) - throw new RulesDocumentException(subElem, "Pattern named \"" + patternName - + "\" is already defined in this context"); + final String patternName = subElem.getAttributeValue("name"); + if (ruleSet.declaresPattern(patternName)) { + throw new RulesDocumentException(subElem, + "Pattern named \"" + patternName + + "\" is already defined in this context"); + } ruleSet.setPattern(patternName, buildPattern(subElem, ruleSet)); } else if (subElemName.equals("subset")) { - if (ruleSet.getSubsetPattern() != null) - throw new RulesDocumentException(subElem, " may only contain a single element"); + if (ruleSet.getSubsetPattern() != null) { + throw new RulesDocumentException(subElem, + " may only contain a single element"); + } ruleSet.setSubsetPattern(buildPattern(subElem, ruleSet)); - } else if (subElemName.equals("access-rule")) + } else if (subElemName.equals("access-rule")) { ruleSet.addRule(buildAccessRule(subElem, ruleSet)); - else if (subElemName.equals("var")) + } else if (subElemName.equals("var")) { ruleSet.addRule(buildVariable(subElem, ruleSet)); - else if (subElemName.equals("foreach")) + } else if (subElemName.equals("foreach")) { ruleSet.addRule(buildForEach(subElem, ruleSet)); - else if (subElemName.equals("ruleset")) + } else if (subElemName.equals("ruleset")) { ruleSet.addRule(buildRuleSet(subElem, ruleSet)); - else if (subElemName.equals("message")) + } else if (subElemName.equals("message")) { ruleSet.addRule(buildMessage(subElem, ruleSet)); + } } return ruleSet; } - public Pattern buildPattern(Element patternElem, RuleSet ruleSet) throws RulesException { + public Pattern buildPattern(final Element patternElem, final RuleSet ruleSet) + throws RulesException { return buildPattern(patternElem, ruleSet, true, null); } - public Pattern buildPattern(Element patternElem, RuleSet ruleSet, boolean isTopElem, Pattern nextPat) - throws RulesException { + public Pattern buildPattern(final Element patternElem, + final RuleSet ruleSet, final boolean isTopElem, + final Pattern nextPat) throws RulesException { // handle options - String otherPatName = patternElem.getAttributeValue("pattern"); - String className = getClassNameAttributeValue(patternElem); - String filterName = patternElem.getAttributeValue("filter"); + final String otherPatName = patternElem.getAttributeValue("pattern"); + final String className = getClassNameAttributeValue(patternElem); + final String filterName = patternElem.getAttributeValue("filter"); CompositePatternType patType; - if (patternElem.getName().equals("include")) + if (patternElem.getName().equals("include")) { patType = CompositePatternType.INCLUDE; - else if (patternElem.getName().equals("exclude")) - patType = (filterName == null) ? CompositePatternType.EXCLUDE : CompositePatternType.INCLUDE; - else if (isTopElem) + } else if (patternElem.getName().equals("exclude")) { + patType = filterName == null ? CompositePatternType.EXCLUDE + : CompositePatternType.INCLUDE; + } else if (isTopElem) { patType = CompositePatternType.INCLUDE; - else - throw new RulesDocumentException(patternElem, "Invalid element <" + patternElem.getName() + "> --" + } else { + throw new RulesDocumentException(patternElem, "Invalid element <" + + patternElem.getName() + "> --" + " expected or "); + } - if (otherPatName != null && className != null) + if (otherPatName != null && className != null) { throw new RulesDocumentException(patternElem, "patterns cannot have both a \"pattern\" and a \"class\" attribute"); + } // do the head thing Pattern head = null; - if (className != null) + if (className != null) { head = new RegexPattern(className); - else if (otherPatName != null) { + } else if (otherPatName != null) { head = ruleSet.getPattern(otherPatName); - if (head == null) + if (head == null) { throw new UndeclaredPatternException(otherPatName); + } } // build up children Pattern childrenPat = null; - List children = new ArrayList(getChildren(patternElem)); // ! - // workaround - // for - // bug - // in - // JUnit + final List children = new ArrayList( + getChildren(patternElem)); // ! + // workaround + // for + // bug + // in + // JUnit // List children = patternElem.getChildren(); // this should work // instead when JUnit bug is fixed - for (ListIterator childIter = children.listIterator(children.size()); childIter.hasPrevious();) { - Element subElem = childIter.previous(); - if (subElem.getName().equals("message")) + for (final ListIterator childIter = children + .listIterator(children.size()); childIter.hasPrevious();) { + final Element subElem = childIter.previous(); + if (subElem.getName().equals("message")) { continue; + } childrenPat = buildPattern(subElem, ruleSet, false, childrenPat); } @@ -243,20 +218,25 @@ else if (otherPatName != null) { // wrap head in a filter if necessary if (filterName != null) { - Map options = new HashMap(); - for (Attribute attr : getAttributes(patternElem)) + final Map options = new HashMap(); + for (final Attribute attr : getAttributes(patternElem)) { options.put(attr.getName(), attr.getValue()); + } options.remove("name"); options.remove("pattern"); options.remove("class"); options.remove("regex"); - Filter filter = FilterFinder.findFilter(filterName); - head = filter.createPattern(ruleSet, - (head == null) ? new ArrayList() : Collections.singletonList(head), options); + final Filter filter = FilterFinder.findFilter(filterName); + head = filter.createPattern( + ruleSet, + head == null ? new ArrayList() : Collections + .singletonList(head), options); - if (patternElem.getName().equals("exclude")) - head = CompositePattern.create(CompositePatternType.EXCLUDE, head, null, null); + if (patternElem.getName().equals("exclude")) { + head = CompositePattern.create(CompositePatternType.EXCLUDE, + head, null, null); + } } // pull together composite @@ -264,76 +244,94 @@ else if (otherPatName != null) { return CompositePattern.create(patType, head, childrenPat, nextPat); } - @SuppressWarnings("unchecked") - private Collection getAttributes(Element patternElem) { + private Collection getAttributes(final Element patternElem) { return patternElem.getAttributes(); } - public Variable buildVariable(Element forEachElem, RuleSet parent) throws RulesException { - String varName = forEachElem.getAttributeValue("name"); - if (varName == null) - throw new RulesDocumentException(forEachElem, " is missing the \"name\" attribute"); + public Variable buildVariable(final Element forEachElem, + final RuleSet parent) throws RulesException { + final String varName = forEachElem.getAttributeValue("name"); + if (varName == null) { + throw new RulesDocumentException(forEachElem, + " is missing the \"name\" attribute"); + } - String value = forEachElem.getAttributeValue("value"); - if (value == null) - throw new RulesDocumentException(forEachElem, " is missing the \"value\" attribute"); + final String value = forEachElem.getAttributeValue("value"); + if (value == null) { + throw new RulesDocumentException(forEachElem, + " is missing the \"value\" attribute"); + } return new Variable(parent, varName, value); } - public Message buildMessage(Element messageElem, RuleSet parent) throws RulesException { - Message message = new Message(parent, messageElem.getText()); + public Message buildMessage(final Element messageElem, final RuleSet parent) + throws RulesException { + final Message message = new Message(parent, messageElem.getText()); buildSeverity(message, messageElem); return message; } - public ForEach buildForEach(Element forEachElem, RuleSet parent) throws RulesException { - String varName = forEachElem.getAttributeValue("var"); - if (varName == null) - throw new RulesDocumentException(forEachElem, " is missing the \"var\" attribute"); + public ForEach buildForEach(final Element forEachElem, final RuleSet parent) + throws RulesException { + final String varName = forEachElem.getAttributeValue("var"); + if (varName == null) { + throw new RulesDocumentException(forEachElem, + " is missing the \"var\" attribute"); + } - String className = getClassNameAttributeValue(forEachElem); - if (className == null) - throw new RulesDocumentException(forEachElem, " is missing the \"class\" attribute"); + final String className = getClassNameAttributeValue(forEachElem); + if (className == null) { + throw new RulesDocumentException(forEachElem, + " is missing the \"class\" attribute"); + } - ForEach forEach = new ForEach(parent); + final ForEach forEach = new ForEach(parent); forEach.setVariableName(varName); forEach.setRegex(className); forEach.setRuleSet(buildRuleSet(forEachElem, parent)); return forEach; } - public AccessRule buildAccessRule(Element ruleElem, RuleSet ruleSet) throws RulesException { + public AccessRule buildAccessRule(final Element ruleElem, + final RuleSet ruleSet) throws RulesException { AccessRule prevRule = null, topRule = null; - for (Element subElem : getChildren(ruleElem)) { - AccessRule accRule = new AccessRule(ruleSet); + for (final Element subElem : getChildren(ruleElem)) { + final AccessRule accRule = new AccessRule(ruleSet); - if (subElem.getName().equals("allow")) + if (subElem.getName().equals("allow")) { accRule.setType(AccessRuleType.ALLOW); - else if (subElem.getName().equals("deny")) + } else if (subElem.getName().equals("deny")) { accRule.setType(AccessRuleType.DENY); - else if (subElem.getName().equals("from") || subElem.getName().equals("to") - || subElem.getName().equals("message")) + } else if (subElem.getName().equals("from") + || subElem.getName().equals("to") + || subElem.getName().equals("message")) { continue; - else - throw new RulesDocumentException(subElem, "Invalid element <" + subElem.getName() + "> --" + } else { + throw new RulesDocumentException(subElem, "Invalid element <" + + subElem.getName() + "> --" + " expected an access rule ( or )"); + } - Element fromElem = subElem.getChild("from"); - if (fromElem != null) + final Element fromElem = subElem.getChild("from"); + if (fromElem != null) { accRule.setFrom(buildPattern(fromElem, ruleSet)); + } - Element toElem = subElem.getChild("to"); - if (toElem != null) + final Element toElem = subElem.getChild("to"); + if (toElem != null) { accRule.setTo(buildPattern(toElem, ruleSet)); + } - if (!subElem.getChildren().isEmpty()) + if (!subElem.getChildren().isEmpty()) { accRule.setChild(buildAccessRule(subElem, ruleSet)); + } - if (topRule == null) + if (topRule == null) { topRule = accRule; - else + } else { prevRule.setNext(accRule); + } prevRule = accRule; } if (topRule != null) { @@ -343,31 +341,32 @@ else if (subElem.getName().equals("from") || subElem.getName().equals("to") return topRule; } - @SuppressWarnings("unchecked") - private List getChildren(Element ruleElem) { + private List getChildren(final Element ruleElem) { return ruleElem.getChildren(); } - public void buildSeverity(Rule rule, Element elem) throws RulesDocumentException { - String severityS = elem.getAttributeValue("severity"); + public void buildSeverity(final Rule rule, final Element elem) + throws RulesDocumentException { + final String severityS = elem.getAttributeValue("severity"); if (severityS != null && !"".equals(severityS)) { RuleSeverity severity; try { severity = RuleSeverity.fromName(severityS); - } catch (IllegalArgumentException iae) { + } catch (final IllegalArgumentException iae) { throw new RulesDocumentException(elem, iae.getMessage()); } rule.setSeverity(severity); } } - private String getClassNameAttributeValue(Element elem) { + private String getClassNameAttributeValue(final Element elem) { String value = elem.getAttributeValue("class"); if (value == null) { value = elem.getAttributeValue("regex"); - if (value != null) + if (value != null) { System.err .println("WARNING: The \"regex\" attribute is deprecated, and will be removed in v1.0. Use \"class\" instead"); + } } return value; } diff --git a/src/main/java/de/andrena/tools/macker/rule/RulesDocumentException.java b/src/main/java/de/andrena/tools/macker/rule/RulesDocumentException.java index dc0eadf..aa40a22 100644 --- a/src/main/java/de/andrena/tools/macker/rule/RulesDocumentException.java +++ b/src/main/java/de/andrena/tools/macker/rule/RulesDocumentException.java @@ -20,7 +20,7 @@ package de.andrena.tools.macker.rule; -import org.jdom.Element; +import org.jdom2.Element; /** * Indicates a structural exception in rules specification XML. diff --git a/src/main/java/de/andrena/tools/macker/rule/Variable.java b/src/main/java/de/andrena/tools/macker/rule/Variable.java index 757428e..6c27ea4 100644 --- a/src/main/java/de/andrena/tools/macker/rule/Variable.java +++ b/src/main/java/de/andrena/tools/macker/rule/Variable.java @@ -23,6 +23,9 @@ import de.andrena.tools.macker.event.MackerIsMadException; import de.andrena.tools.macker.structure.ClassManager; +/** + * Processes tags in rule XML files. + */ public class Variable extends Rule { public Variable(RuleSet parent, String name, String value) { super(parent); @@ -47,8 +50,9 @@ public void setValue(String value) { } public void check(EvaluationContext context, ClassManager classes) throws RulesException, MackerIsMadException { - context.setVariableValue(getVariableName(), getValue()); + // Substitution of values from rules.xml files makes sense + context.setVariableValueWithSubstitution(getVariableName(), getValue()); } private String variableName, value; -} \ No newline at end of file +} diff --git a/src/main/java/de/andrena/tools/macker/rule/VariableParser.java b/src/main/java/de/andrena/tools/macker/rule/VariableParser.java index 8b72983..ba0a409 100644 --- a/src/main/java/de/andrena/tools/macker/rule/VariableParser.java +++ b/src/main/java/de/andrena/tools/macker/rule/VariableParser.java @@ -24,6 +24,25 @@ import java.util.regex.Pattern; public final class VariableParser { + + /** variables are declared in other strings like "${from}" */ + static private Pattern var = Pattern.compile("\\$\\{([A-Za-z0-9_\\.\\-]+)\\}"); + + private VariableParser() { + // static class, hide constructor + } + + /** + * Replace variables in input string. + * Example: + * inS = ${from} must access ${to} through its API (S/1) + * outS = InvoiceLineServiceImpl must access BusinessOperation through its API (S/1) + * + * @param context + * @param inS + * @return outS + * @throws UndeclaredVariableException + */ public static String parse(EvaluationContext context, String inS) throws UndeclaredVariableException { StringBuffer outS = new StringBuffer(); Matcher varMatcher = var.matcher(inS); @@ -40,9 +59,4 @@ public static String parse(EvaluationContext context, String inS) throws Undecla } return outS.toString(); } - - static private Pattern var = Pattern.compile("\\$\\{([A-Za-z0-9_\\.\\-]+)\\}"); - - private VariableParser() { - } } diff --git a/src/main/java/de/andrena/tools/macker/structure/AbstractClassInfo.java b/src/main/java/de/andrena/tools/macker/structure/AbstractClassInfo.java index 2dec845..1625643 100644 --- a/src/main/java/de/andrena/tools/macker/structure/AbstractClassInfo.java +++ b/src/main/java/de/andrena/tools/macker/structure/AbstractClassInfo.java @@ -46,7 +46,8 @@ public String getPackageName() { public Set getDirectSupertypes() { if (cachedAllDirectSuper == null) { Set newAllDirectSuper = new HashSet(getImplements()); - newAllDirectSuper.add(getExtends()); + ClassInfo superClass = getExtends(); + if (superClass!=null) newAllDirectSuper.add(superClass); // fix possible NPE cachedAllDirectSuper = newAllDirectSuper; // failure atomicity } return cachedAllDirectSuper; diff --git a/src/main/java/de/andrena/tools/macker/structure/ClassManager.java b/src/main/java/de/andrena/tools/macker/structure/ClassManager.java index fe38a88..83dd066 100644 --- a/src/main/java/de/andrena/tools/macker/structure/ClassManager.java +++ b/src/main/java/de/andrena/tools/macker/structure/ClassManager.java @@ -65,12 +65,6 @@ public ClassInfo readClass(File classFile) throws ClassParseException, IOExcepti return classInfo; } - public ClassInfo readClass(InputStream classFile) throws ClassParseException, IOException { - ClassInfo classInfo = new ParsedClassInfo(this, classFile); - addClass(classInfo); - return classInfo; - } - private void addClass(ClassInfo classInfo) { ClassInfo existing = findClassInfo(classInfo.getFullName()); if (existing != null && !(existing instanceof HollowClassInfo)) @@ -141,7 +135,8 @@ ClassInfo loadClassInfo(String className) { try { classStream.close(); } catch (IOException ioe) { - } // nothing we can do + // nothing we can do + } } if (classInfo == null) diff --git a/src/main/java/de/andrena/tools/macker/structure/ParsedClassInfo.java b/src/main/java/de/andrena/tools/macker/structure/ParsedClassInfo.java index eee7d9c..8ffc003 100644 --- a/src/main/java/de/andrena/tools/macker/structure/ParsedClassInfo.java +++ b/src/main/java/de/andrena/tools/macker/structure/ParsedClassInfo.java @@ -41,6 +41,7 @@ import de.andrena.tools.macker.util.collect.CompositeMultiMap; import de.andrena.tools.macker.util.collect.InnigCollections; import de.andrena.tools.macker.util.collect.MultiMap; +import de.andrena.tools.macker.util.io.StreamUtil; /** * Class info retrieved from a class file using Javassist. @@ -58,15 +59,39 @@ public class ParsedClassInfo extends AbstractClassInfo { private Set implementsClasses; private MultiMap references; + /** + * Recommended constructor. + * @param classManager + * @param classFile + * @throws IOException + * @throws ClassParseException + */ ParsedClassInfo(final ClassManager classManager, final File classFile) throws IOException, ClassParseException { super(classManager); - parse(ClassPool.getDefault().makeClass(new FileInputStream(classFile))); + FileInputStream classFileInputStream = null; + try { + classFileInputStream = new FileInputStream(classFile); + parse(ClassPool.getDefault().makeClass(classFileInputStream)); + } catch (IOException | ClassParseException | RuntimeException e) { + // close input stream and re-throw exception + StreamUtil.closeStream(classFileInputStream); + throw e; + } + // no exception occurred, simply close input stream + StreamUtil.closeStream(classFileInputStream); } - ParsedClassInfo(final ClassManager classManager, final InputStream classFileStream) throws IOException, + /** + * Less recommended constructor: A caller must guarantee that the passed input stream is closed afterwards. + * @param classManager + * @param classFileInputStream + * @throws IOException + * @throws ClassParseException + */ + ParsedClassInfo(final ClassManager classManager, final InputStream classFileInputStream) throws IOException, ClassParseException { super(classManager); - parse(ClassPool.getDefault().makeClass(classFileStream)); + parse(ClassPool.getDefault().makeClass(classFileInputStream)); } public String getFullName() { @@ -137,7 +162,10 @@ private AccessModifier translateAccess(int modifiers) { } private void parseExtends(CtClass classFile) throws ClassParseException { - this.extendsClass = getSafeClassInfo(classFile.getClassFile().getSuperclass()); + String superClassStr = classFile.getClassFile().getSuperclass(); + // avoid NullPointerException if classFile is java.lang.Object + //System.out.println("class=" + classFile + ", classFile=" + classFile.getClassFile() + ", superClass=" + superClassStr); + this.extendsClass = superClassStr!=null ? getSafeClassInfo(superClassStr) : null; } private void parseImplements(CtClass classFile) throws ClassParseException { diff --git a/src/main/java/de/andrena/tools/macker/util/StreamSplitter.java b/src/main/java/de/andrena/tools/macker/util/StreamSplitter.java index 4fcf5c2..19a0dd8 100644 --- a/src/main/java/de/andrena/tools/macker/util/StreamSplitter.java +++ b/src/main/java/de/andrena/tools/macker/util/StreamSplitter.java @@ -273,15 +273,20 @@ public void run() { sleep(latency); } } catch (Exception e) { - if (verbose) - e.printStackTrace(System.err); + if (verbose) e.printStackTrace(System.err); } try { in.close(); } catch (Exception e) { - if (verbose) - e.printStackTrace(System.err); + if (verbose) e.printStackTrace(System.err); + } + for (int n = 0; n < out.length; n++) { + try { + out[n].close(); + } catch (IOException e) { + if (verbose) e.printStackTrace(System.err); + } } done = true; diff --git a/src/main/java/de/andrena/tools/macker/util/collect/RadixMap.java b/src/main/java/de/andrena/tools/macker/util/collect/RadixMap.java index 909df42..b9b821c 100644 --- a/src/main/java/de/andrena/tools/macker/util/collect/RadixMap.java +++ b/src/main/java/de/andrena/tools/macker/util/collect/RadixMap.java @@ -1,468 +1,504 @@ -/*______________________________________________________________________________ - * - * net.innig.util.RadixMap - * - *______________________________________________________________________________ - * - * Copyright 2002 Paul Cantrell - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * - * (1) Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * - * (2) Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in - * the documentation and/or other materials provided with the - * distribution. - * - * (3) The name of the author may not be used to endorse or promote - * products derived from this software without specific prior - * written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED - * OF THE POSSIBILITY OF SUCH DAMAGE. - *_______________________________________________________________________________ - */ - -package de.andrena.tools.macker.util.collect; - -import java.util.AbstractCollection; -import java.util.AbstractMap; -import java.util.AbstractSet; -import java.util.Collection; -import java.util.ConcurrentModificationException; -import java.util.Map; -import java.util.NoSuchElementException; -import java.util.Set; - -import de.andrena.tools.macker.util.EnumeratedType; - -/** - * A map which theoretically has fast lookups, but doesn't actually work very - * well (yet). - * - *

- * - * - * - * - * - * - * - *
- * Maturity: All the radix utilities in innig-util are completely - * experimental. (In particular, this class is not completely implemented!) They - * may stay; they may improve; they may go away.
- * Plans: Experiment.
- */ -public class RadixMap extends AbstractMap { - public RadixMap(Radix radix) { - this.radix = radix; - } - - public RadixMap(Radix radix, Map otherMap) { - this(radix); - putAll(otherMap); - } - - @Override - public int size() { - return size; - } - - @Override - public boolean isEmpty() { - return size == 0; - } - - @Override - public boolean containsKey(Object key) { - RadixTree tree = getRadixTree(key, false); - return (tree == null) ? true : tree.hasValue(); - } - - @Override - public Object get(Object key) { - RadixTree tree = getRadixTree(key, false); - return (tree == null) ? null : tree.getValue(); - } - - @Override - public Object put(Object key, Object value) { - RadixTree tree = getRadixTree(key, true); - Object oldValue = tree.getValue(); - tree.setValue(value); - size++; - version++; - return oldValue; - } - - @Override - public Object remove(Object key) { - RadixTree tree = getRadixTree(key, false); - if (tree == null || !tree.hasValue()) - return null; - Object oldValue = tree.getValue(); - tree.removeValue(); - size--; - version++; - // trim(); - return oldValue; - } - - @Override - public void clear() { - version++; - size = 0; - root = null; - } - - @Override - public Set keySet() { - if (keys == null) - keys = new AbstractSet() { - @Override - public java.util.Iterator iterator() { - return new Iterator(root.getInitialPosition(), root, IteratorType.ENTRIES); - } - - @Override - public int size() { - return size; - } - - @Override - public boolean remove(Object obj) { - return RadixMap.this.remove(obj) != null; - } - - @Override - public void clear() { - RadixMap.this.clear(); - } - }; - return keys; - } - - @Override - public Collection values() { - if (values == null) - values = new AbstractCollection() { - @Override - public java.util.Iterator iterator() { - return new Iterator(root.getInitialPosition(), root, IteratorType.VALUES); - } - - @Override - public int size() { - return RadixMap.this.size(); - } - - @Override - public void clear() { - RadixMap.this.clear(); - } - }; - return values; - } - - @Override - public Set entrySet() { - if (entries == null) - entries = new AbstractSet() { - @Override - public java.util.Iterator iterator() { - return new Iterator(root.getInitialPosition(), root, IteratorType.ENTRIES); - } - - @Override - public int size() { - return size; - } - - @Override - public boolean remove(Object obj) { - if (!(obj instanceof RadixMap.Entry)) - return false; - RadixMap.Entry entry = (RadixMap.Entry) obj; - return RadixMap.this.remove(entry.getKey()) != null; - } - - @Override - public void clear() { - RadixMap.this.clear(); - } - }; - return entries; - } - - public Radix getRadix() { - return radix; - } - - private RadixTree getRadixTree(Object value, boolean create) { - int valueMaxPos = radix.getMaxPosition(value), valueMinPos = radix.getMinPosition(value); - - if (root == null || root.getInitialPosition() < valueMaxPos) { - if (!create) - return null; - // inserting ahead of root ... tricky - // root = new RadixTree(valueMaxPos); - // //////////// - // return ..............; - - root = new RadixTree(value, valueMaxPos, valueMinPos); - - } - - RadixTree curTree = root; - for (int pos = valueMaxPos; pos >= valueMinPos; pos--) { - int digit = radix.digit(value, pos); - RadixTree nextTree = curTree.getChild(pos, digit); - if (nextTree == null) { - if (!create) - return null; - nextTree = new RadixTree(value, pos - 1, valueMinPos); - curTree.setChild(pos, digit, nextTree); - // return curTree; - } - curTree = nextTree; - } - return curTree; // ? - } - - private class RadixTree { - public RadixTree(Object value, int maxPos, int minPos) { - this.minPos = this.maxPos = maxPos; - if (minPos <= maxPos) - setChild(maxPos, radix.digit(value, maxPos), new RadixTree(value, maxPos - 1, minPos)); - } - - public int getInitialPosition() { - return minPos; - } - - public RadixTree getChild(int position, int digit) { - if (position < minPos || position > maxPos) - throw new IllegalArgumentException("illegal position (" + position + " not in [" + minPos + "," - + maxPos + "])"); - if (children == null) - return null; - return children[digit]; - } - - public void setChild(int position, int digit, RadixTree tree) { - if (position < minPos || position > maxPos) - throw new IllegalArgumentException("illegal position (" + position + " not in [" + minPos + "," - + maxPos + "])"); - if (digit < 0 || digit > radix.getBase()) - throw new IllegalArgumentException("illegal digit (" + digit + " not in [" + 0 + "," - + (children.length - 1) + "])"); - if (children == null) - children = new RadixTree[radix.getBase()]; - if ((children[digit] == null) != (tree == null)) - childCount += (tree == null) ? -1 : 1; - children[digit] = tree; - } - - public boolean hasValue() { - return hasValue; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - hasValue = true; - this.value = value; - } - - public void removeValue() { - hasValue = false; - value = null; - } - - public boolean isEmpty() { - return !hasValue && childCount == 0; - } - - public void dumpTree(int i) { - for (int n = i; n > 0; n--) - System.out.print(' '); - System.out.println("tree @ " + maxPos); - if (hasValue) { - for (int n = i; n > 0; n--) - System.out.print(' '); - System.out.println("value: " + value); - } - if (children != null) - for (int child = 0; child < children.length; child++) - if (children[child] != null) { - for (int n = i; n > 0; n--) - System.out.print(' '); - System.out.println(child + ": "); - children[child].dumpTree(i + 3); - } - } - - private int minPos, maxPos; - private boolean hasValue; - private Object value; - private int childCount; - private RadixTree[] children; - } - - private class Entry implements Map.Entry { - public Entry(Object key, Object value) { - this.key = key; - this.value = value; - } - - public Object getKey() { - return key; - } - - public Object getValue() { - return value; - } - - public Object setValue(Object value) { - Object oldValue = value; - this.value = value; - return oldValue; - } - - @Override - public boolean equals(Object that) { - if (this == that) - return true; - if (that == null || !(that instanceof Map.Entry)) - return false; - Map.Entry thatEntry = (Map.Entry) that; - return key.equals(thatEntry.getKey()) - && (value == null ? thatEntry.getValue() == null : value.equals(thatEntry.getValue())); - } - - @Override - public int hashCode() { - return key.hashCode() + (value == null ? 0 : value.hashCode() * 23); - } - - private Object key; - private Object value; - } - - private static class IteratorType extends EnumeratedType { - public static final IteratorType KEYS = new IteratorType("keys"), VALUES = new IteratorType("values"), - ENTRIES = new IteratorType("entries"); - - private IteratorType(String name) { - super(name); - } - } - - private class Iterator implements java.util.Iterator { - public Iterator(int position, RadixTree tree, IteratorType type) { - this.position = position; - this.tree = tree; - this.type = type; - expectedVersion = version; - curDigit = -1; - if (tree != null) - handledValue = !tree.hasValue(); - } - - public boolean hasNext() { - checkModification(); - if (tree == null) - return false; - if (curIter != null && curIter.hasNext()) - return true; - if (!handledValue) - return true; - for (nextDigit = curDigit + 1; nextDigit < radix.getBase(); nextDigit++) { - RadixTree subTree = tree.getChild(position, nextDigit); - if (subTree != null) { - nextIter = new Iterator(position - 1, subTree, type); - if (nextIter.hasNext()) - return true; - } - } - return false; - } - - public Object next() { - if (!hasNext()) - throw new NoSuchElementException(); - - if (!handledValue) { - handledValue = true; - if (type == IteratorType.VALUES) - return tree.getValue(); - throw new UnsupportedOperationException(); - } - - curDigit = nextDigit; - curIter = nextIter; - return curIter.next(); - } - - public void remove() { - if (curIter != null) { - curIter.remove(); - expectedVersion = version; - return; - } - checkModification(); - if (tree == null || !tree.hasValue()) - throw new IllegalStateException("no element to remove"); - tree.removeValue(); - size--; - expectedVersion = ++version; - } - - private void checkModification() { - if (version != expectedVersion) - throw new ConcurrentModificationException("radix map modified (" + version + " != " + expectedVersion - + ")"); - } - - private final int position; - private final RadixTree tree; - private final IteratorType type; - private long expectedVersion; - private int curDigit, nextDigit; - private Iterator curIter, nextIter; - private boolean handledValue; - } - - private int size; - private Radix radix; - private RadixTree root; - private Set keys, entries; - private Collection values; - - private transient long version; - - @Override - public String toString() { - return getClass().getName(); - } - - public void dump() { - root.dumpTree(0); - } -} +/*______________________________________________________________________________ + * + * net.innig.util.RadixMap + * + *______________________________________________________________________________ + * + * Copyright 2002 Paul Cantrell + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * (1) Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * (2) Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * (3) The name of the author may not be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + *_______________________________________________________________________________ + */ + +package de.andrena.tools.macker.util.collect; + +import java.util.AbstractCollection; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.ConcurrentModificationException; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import de.andrena.tools.macker.util.EnumeratedType; + +/** + * A map which theoretically has fast lookups, but doesn't actually work very + * well (yet). + * + *

+ * + * + * + * + * + * + * + *
+ * Maturity: All the radix utilities in innig-util are completely + * experimental. (In particular, this class is not completely implemented!) They + * may stay; they may improve; they may go away.
+ * Plans: Experiment.
+ */ +public class RadixMap extends AbstractMap { + public RadixMap(final Radix radix) { + this.radix = radix; + } + + public RadixMap(final Radix radix, final Map otherMap) { + this(radix); + putAll(otherMap); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean isEmpty() { + return size == 0; + } + + @Override + public boolean containsKey(final Object key) { + final RadixTree tree = getRadixTree(key, false); + return tree == null ? true : tree.hasValue(); + } + + @Override + public Object get(final Object key) { + final RadixTree tree = getRadixTree(key, false); + return tree == null ? null : tree.getValue(); + } + + @Override + public Object put(final Object key, final Object value) { + final RadixTree tree = getRadixTree(key, true); + final Object oldValue = tree.getValue(); + tree.setValue(value); + size++; + version++; + return oldValue; + } + + @Override + public Object remove(final Object key) { + final RadixTree tree = getRadixTree(key, false); + if (tree == null || !tree.hasValue()) { + return null; + } + final Object oldValue = tree.getValue(); + tree.removeValue(); + size--; + version++; + // trim(); + return oldValue; + } + + @Override + public void clear() { + version++; + size = 0; + root = null; + } + + @Override + public Set keySet() { + if (keys == null) { + keys = new AbstractSet() { + @Override + public java.util.Iterator iterator() { + return new Iterator(root.getInitialPosition(), root, + IteratorType.ENTRIES); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean remove(final Object obj) { + return RadixMap.this.remove(obj) != null; + } + + @Override + public void clear() { + RadixMap.this.clear(); + } + }; + } + return keys; + } + + @Override + public Collection values() { + if (values == null) { + values = new AbstractCollection() { + @Override + public java.util.Iterator iterator() { + return new Iterator(root.getInitialPosition(), root, + IteratorType.VALUES); + } + + @Override + public int size() { + return RadixMap.this.size(); + } + + @Override + public void clear() { + RadixMap.this.clear(); + } + }; + } + return values; + } + + @Override + public Set entrySet() { + if (entries == null) { + entries = new AbstractSet() { + @Override + public java.util.Iterator iterator() { + return new Iterator(root.getInitialPosition(), root, + IteratorType.ENTRIES); + } + + @Override + public int size() { + return size; + } + + @Override + public boolean remove(final Object obj) { + if (!(obj instanceof RadixMap.Entry)) { + return false; + } + final RadixMap.Entry entry = (RadixMap.Entry) obj; + return RadixMap.this.remove(entry.getKey()) != null; + } + + @Override + public void clear() { + RadixMap.this.clear(); + } + }; + } + return entries; + } + + public Radix getRadix() { + return radix; + } + + private RadixTree getRadixTree(final Object value, final boolean create) { + final int valueMaxPos = radix.getMaxPosition(value), valueMinPos = radix + .getMinPosition(value); + + if (root == null || root.getInitialPosition() < valueMaxPos) { + if (!create) { + return null; + // inserting ahead of root ... tricky + // root = new RadixTree(valueMaxPos); + // //////////// + // return ..............; + } + + root = new RadixTree(value, valueMaxPos, valueMinPos); + + } + + RadixTree curTree = root; + for (int pos = valueMaxPos; pos >= valueMinPos; pos--) { + final int digit = radix.digit(value, pos); + RadixTree nextTree = curTree.getChild(pos, digit); + if (nextTree == null) { + if (!create) { + return null; + } + nextTree = new RadixTree(value, pos - 1, valueMinPos); + curTree.setChild(pos, digit, nextTree); + // return curTree; + } + curTree = nextTree; + } + return curTree; // ? + } + + private class RadixTree { + public RadixTree(final Object value, final int maxPos, final int minPos) { + this.minPos = this.maxPos = maxPos; + if (minPos <= maxPos) { + setChild(maxPos, radix.digit(value, maxPos), new RadixTree( + value, maxPos - 1, minPos)); + } + } + + public int getInitialPosition() { + return minPos; + } + + public RadixTree getChild(final int position, final int digit) { + if (position < minPos || position > maxPos) { + throw new IllegalArgumentException("illegal position (" + + position + " not in [" + minPos + "," + maxPos + "])"); + } + if (children == null) { + return null; + } + return children[digit]; + } + + public void setChild(final int position, final int digit, + final RadixTree tree) { + if (position < minPos || position > maxPos) { + throw new IllegalArgumentException("illegal position (" + + position + " not in [" + minPos + "," + maxPos + "])"); + } + if (digit < 0 || digit > radix.getBase()) { + throw new IllegalArgumentException("illegal digit (" + digit + + " not in [" + 0 + "," + (children.length - 1) + "])"); + } + if (children == null) { + children = new RadixTree[radix.getBase()]; + } + if (children[digit] == null != (tree == null)) { + childCount += tree == null ? -1 : 1; + } + children[digit] = tree; + } + + public boolean hasValue() { + return hasValue; + } + + public Object getValue() { + return value; + } + + public void setValue(final Object value) { + hasValue = true; + this.value = value; + } + + public void removeValue() { + hasValue = false; + value = null; + } + + public boolean isEmpty() { + return !hasValue && childCount == 0; + } + + public void dumpTree(final int i) { + for (int n = i; n > 0; n--) { + System.out.print(' '); + } + System.out.println("tree @ " + maxPos); + if (hasValue) { + for (int n = i; n > 0; n--) { + System.out.print(' '); + } + System.out.println("value: " + value); + } + if (children != null) { + for (int child = 0; child < children.length; child++) { + if (children[child] != null) { + for (int n = i; n > 0; n--) { + System.out.print(' '); + } + System.out.println(child + ": "); + children[child].dumpTree(i + 3); + } + } + } + } + + private final int minPos; + private int maxPos; + private boolean hasValue; + private Object value; + private int childCount; + private RadixTree[] children; + } + + private class Entry implements Map.Entry { + public Object getKey() { + return key; + } + + public Object getValue() { + return value; + } + + public Object setValue(final Object value) { + final Object oldValue = value; + this.value = value; + return oldValue; + } + + @Override + public boolean equals(final Object that) { + if (this == that) { + return true; + } + if (that == null || !(that instanceof Map.Entry)) { + return false; + } + final Map.Entry thatEntry = (Map.Entry) that; + return key.equals(thatEntry.getKey()) + && (value == null ? thatEntry.getValue() == null : value + .equals(thatEntry.getValue())); + } + + @Override + public int hashCode() { + return key.hashCode() + (value == null ? 0 : value.hashCode() * 23); + } + + private Object key; + private Object value; + } + + private static class IteratorType extends EnumeratedType { + public static final IteratorType KEYS = new IteratorType("keys"), + VALUES = new IteratorType("values"), + ENTRIES = new IteratorType("entries"); + + private IteratorType(final String name) { + super(name); + } + } + + private class Iterator implements java.util.Iterator { + public Iterator(final int position, final RadixTree tree, + final IteratorType type) { + this.position = position; + this.tree = tree; + this.type = type; + expectedVersion = version; + curDigit = -1; + if (tree != null) { + handledValue = !tree.hasValue(); + } + } + + public boolean hasNext() { + checkModification(); + if (tree == null) { + return false; + } + if (curIter != null && curIter.hasNext()) { + return true; + } + if (!handledValue) { + return true; + } + for (nextDigit = curDigit + 1; nextDigit < radix.getBase(); nextDigit++) { + final RadixTree subTree = tree.getChild(position, nextDigit); + if (subTree != null) { + nextIter = new Iterator(position - 1, subTree, type); + if (nextIter.hasNext()) { + return true; + } + } + } + return false; + } + + public Object next() { + if (!hasNext()) { + throw new NoSuchElementException(); + } + + if (!handledValue) { + handledValue = true; + if (type == IteratorType.VALUES) { + return tree.getValue(); + } + throw new UnsupportedOperationException(); + } + + curDigit = nextDigit; + curIter = nextIter; + return curIter.next(); + } + + public void remove() { + if (curIter != null) { + curIter.remove(); + expectedVersion = version; + return; + } + checkModification(); + if (tree == null || !tree.hasValue()) { + throw new IllegalStateException("no element to remove"); + } + tree.removeValue(); + size--; + expectedVersion = ++version; + } + + private void checkModification() { + if (version != expectedVersion) { + throw new ConcurrentModificationException( + "radix map modified (" + version + " != " + + expectedVersion + ")"); + } + } + + private final int position; + private final RadixTree tree; + private final IteratorType type; + private long expectedVersion; + private int curDigit, nextDigit; + private Iterator curIter, nextIter; + private boolean handledValue; + } + + private int size; + private final Radix radix; + private RadixTree root; + private Set keys, entries; + private Collection values; + + private transient long version; + + @Override + public String toString() { + return getClass().getName(); + } + + public void dump() { + root.dumpTree(0); + } +} diff --git a/src/main/java/de/andrena/tools/macker/util/io/StreamUtil.java b/src/main/java/de/andrena/tools/macker/util/io/StreamUtil.java new file mode 100644 index 0000000..b43c923 --- /dev/null +++ b/src/main/java/de/andrena/tools/macker/util/io/StreamUtil.java @@ -0,0 +1,21 @@ +package de.andrena.tools.macker.util.io; + +import java.io.Closeable; +import java.io.IOException; + +/** + * Stream helper class. + * @author tneumann + */ +public class StreamUtil { + + public static final void closeStream(Closeable inputStream) { + if (inputStream != null) { + try { + inputStream.close(); + } catch (IOException ioe) { + // nothing we can do + } + } + } +} diff --git a/src/main/resources/de/andrena/tools/macker/macker.dtd b/src/main/resources/de/andrena/tools/macker/macker.dtd deleted file mode 100644 index 5ed70be..0000000 --- a/src/main/resources/de/andrena/tools/macker/macker.dtd +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/src/main/resources/de/andrena/tools/macker/macker.xsd b/src/main/resources/de/andrena/tools/macker/macker.xsd new file mode 100644 index 0000000..7696f72 --- /dev/null +++ b/src/main/resources/de/andrena/tools/macker/macker.xsd @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/de/andrena/tools/macker/report/format/html-basic.xsl b/src/main/resources/de/andrena/tools/macker/report/format/html-basic.xsl new file mode 100644 index 0000000..10d0183 --- /dev/null +++ b/src/main/resources/de/andrena/tools/macker/report/format/html-basic.xsl @@ -0,0 +1,113 @@ + + + + + + + Macker report + + + + +

+ + + error + warning + ok + + +
+ event-severity- + +
+ Macker Report +
+ + + +
+ Macker report generated +
+ + + + + + + + + +
+
+ +
event-severity-ok OK
+
+ + +
+
+ +
+
+
+ + + +
+
+ + + +
+
+ event-severity- + +
+
+ + + Illegal reference + +
+
+ + + + + + + +
From: + + . + + +
To: + + . + + +
+
+
+
+
+ + + + + + +
+
+ : + +
+
+ +
+
+
+ + diff --git a/src/main/resources/de/andrena/tools/macker/report/skin/maroon.css b/src/main/resources/de/andrena/tools/macker/report/skin/maroon.css new file mode 100644 index 0000000..6587cac --- /dev/null +++ b/src/main/resources/de/andrena/tools/macker/report/skin/maroon.css @@ -0,0 +1,174 @@ +body { + background-color : #3C0000; + color:#FFF; + font-family: Palatino,Georgia,Times; +} +A:link { color:#FF6; } +A:visited { color:#DD8; } +A:active { color:#FF0; } + +.title { + background-color : #C00; + color : #FFF; + margin : .5em 0em .5em 0em; + padding : .14cm .14cm .14cm .4cm; + border-style : solid; + border-color : #000; + border-width : 2px 2px 2px 2px; + font-family : Baskerville,Georgia,Palatino,Times,Times New Roman; + font-size : 2.4em; + font-weight : bold; +} + +.ruleset { + margin : 1em 0em .5em 2em; +} +.ruleset-header { + background-color:#A00; + color:#FFF; + padding : .14cm .14cm .14cm 1em; + border-style : solid; + border-color : #000; + border-width : 1px; + font-family : Baskerville,Georgia,Palatino,Times,Times New Roman; + font-size : 1.6em; + font-weight : normal; +} +.ruleset-summary { + font-size : 11px; + font-weight : bold; +} +.ruleset-body { +} + +.foreach { + margin : 1em 0em .5em 1.2em; +} +.foreach-header { + background-color : #600; + color : #FFF; + padding : .14cm .14cm .14cm 1.2em; + border : 2px 1px; + border-style : solid; + border-color : #000; + border-width : 1px; + font-family : Verdana,Geneva,Helvetica; + font-size : 1em; + font-weight : bold; +} +.foreach-header .var { + font-weight : normal; +} +.foreach-header .value { + font-weight : bold; +} +.foreach-body { +} + +.event { + margin : .5em 1em .5em 1.2em; + padding : .4em .7em .4em .7em; + font-family : Verdana,Geneva,Helvetica; + background-color : #460000; +} +.event-header { + font-size : 1em; + text-align : left; +} +.event-header td { + font-weight : normal; +} +.event-severity-error { + float : right; + padding : 2px 4px; + margin : 0em 0em 0em 1em; + font-family : Monaco,Geneva,Verdana; + font-size : 9px; + font-variant : caps; + font-weight : bold; + color : #000; + border-style : solid; + border-width : 1px; + background-color : #F00; + border-color : #200; +} +.event-severity-warning { + float : right; + padding : 2px 4px; + margin : 0em 0em 0em 1em; + font-family : Monaco,Geneva,Verdana; + font-size : 9px; + font-variant : caps; + font-weight : bold; + color : #000; + border-style : solid; + border-width : 1px; + background-color : #CA0; + border-color : #210; +} +.event-severity-info { + float : right; + padding : 2px 4px; + margin : 0em 0em 0em 1em; + font-family : Monaco,Geneva,Verdana; + font-size : 9px; + font-variant : caps; + font-weight : bold; + color : #000; + border-style : solid; + border-width : 1px; + background-color : #666; + border-color : #111; +} +.event-severity-ok { + float : right; + padding : 2px 4px; + margin : 0em 0em 0em 1em; + font-family : Monaco,Geneva,Verdana; + font-size : 9px; + font-variant : caps; + font-weight : bold; + color : #000; + border-style : solid; + border-width : 1px; + background-color : #0A0; + border-color : #030; +} +.event-body { + font-size : 11px; + color : #A88; +} +.event-body { + padding : 0em .5em 0em 2em; +} +.event-body th { + text-align : right; + color : #777; + font-weight : normal; + padding : 0em 1em 0em 0em; + font-size : 0.9em; +} +.event-body .package-name { + color : #BAA; + font-weight: normal; + font-size : 0.9em; +} +.event-body .class-name { + color : #BAA; + font-weight: bold; + font-size : 0.9em; +} + +.bottom { + color : #777; + background : #000; + margin : 2em 0em; + padding : 4px 4px 4px .4cm; + font-family : Verdana,Geneva,Helvetica; + font-weight : bold; + font-size : 10px; +} +.bottom A, .bottom A:link, .bottom A:visited { + color : #BBB; + text-decoration : none; +} diff --git a/src/main/resources/de/andrena/tools/macker/report/skin/vanilla.css b/src/main/resources/de/andrena/tools/macker/report/skin/vanilla.css new file mode 100644 index 0000000..28c1bcf --- /dev/null +++ b/src/main/resources/de/andrena/tools/macker/report/skin/vanilla.css @@ -0,0 +1,187 @@ +body { + background-color : #F8F8F8; + color:#FFF; + font-family: Palatino,Georgia,Times; +} +A:link { color:#FF6; } +A:visited { color:#DD8; } +A:active { color:#FF0; } + +.title { + background-color : #CCD; + color : #000; + margin : .5em 0em .5em 0em; + padding : .14cm .14cm .14cm .4cm; + border-style : solid; + border-color : #AAA; + border-width : 1px; + font-family : Baskerville,Georgia,Palatino,Times,Times New Roman; + font-size : 2.4em; + font-weight : bold; +} + +.ruleset { + margin : 1em 0em .5em 2em; +} +.ruleset-header { + background-color:#DDE; + color : #000; + padding : .14cm .14cm .14cm 1em; + border-style : solid; + border-color : #BBB; + border-width : 1px; + font-family : Baskerville,Georgia,Palatino,Times,Times New Roman; + font-size : 1.6em; + font-weight : normal; +} +.ruleset-summary { + font-size : 11px; + font-weight : bold; +} +.ruleset-body { +} + +.foreach { + margin : 1em 0em .5em 1.6em; +} +.foreach-header { + background-color : #DDE; + color : #000; + padding : .14cm .14cm .14cm 1.2em; + border : 1px; + border-style : solid; + border-color : #CCC; + border-width : 1px; + font-family : Verdana,Geneva,Helvetica; + font-size : 1em; + font-weight : bold; +} +.foreach-header .var { + font-weight : normal; +} +.foreach-header .value { + font-weight : bold; +} +.foreach-body { +} + +.event { + margin : .3em 1em .3em 1.6em; + padding : .4em .7em .4em .7em; + font-family : Verdana,Geneva,Helvetica; + background-color : #ECECEC; + color : #000; +} +.event-header { + font-size : 1em; + text-align : left; +} +.event-header td { + font-weight : normal; +} +.event-severity-error { + float : right; + padding : 2px 4px; + margin : 0em 0em .4em 1em; + font-family : Monaco,Geneva,Verdana; + font-size : 9px; + font-variant : caps; + font-weight : bold; + color : #000; + border-style : solid; + border-width : 1px; + background-color : #F22; + border-color : #200; + text-transform : uppercase; +} +.event-severity-warning { + float : right; + padding : 2px 4px; + margin : 0em 0em .4em 1em; + font-family : Monaco,Geneva,Verdana; + font-size : 9px; + font-variant : caps; + font-weight : bold; + color : #000; + border-style : solid; + border-width : 1px; + background-color : #FD0; + border-color : #210; + text-transform : uppercase; +} +.event-severity-info { + float : right; + padding : 2px 4px; + margin : 0em 0em .4em 1em; + font-family : Monaco,Geneva,Verdana; + font-size : 9px; + font-variant : caps; + font-weight : bold; + color : #888; + border-style : solid; + border-width : 1px; + background-color : #CCC; + border-color : #AAA; + text-transform : uppercase; +} +.event-severity-ok { + float : right; + padding : 2px 4px; + margin : 0em 0em .4em 1em; + font-family : Monaco,Geneva,Verdana; + font-size : 9px; + font-variant : caps; + font-weight : bold; + color : #000; + border-style : solid; + border-width : 1px; + background-color : #1E1; + border-color : #030; + text-transform : uppercase; +} +.event-body { + font-size : 11px; +} +.event-body { + padding : 0em 0em 0em 10%; + margin : 0em 0em 0em 0em; +} +.event-body th { + text-align : right; + align : bottom; + color : #777; + font-weight : normal; + font-size : 0.86em; + padding : 0em 0em 0em 0em; + margin : 0em 0em 0em 0em; + vertical-align: baseline; +} +.event-body td { + padding : 0em 0em 0em 0em; + margin : 0em 0em 0em 0em; + vertical-align: baseline; +} +.event-body .package-name { + color : #555; + font-size : 0.86em; + font-weight: normal; +} +.event-body .class-name { + color : #555; + font-size : 0.86em; + font-weight: bold; +} + +.bottom { + color : #888; + background : #444; + margin : 2em 0em; + padding : 4px 4px 4px .4cm; + font-family : Verdana,Geneva,Helvetica; + font-weight : bold; + font-size : 10px; +} +.bottom A, .bottom A:link, .bottom A:visited { + color : #CCC; + text-decoration : none; +} diff --git a/src/test/java/de/andrena/tools/macker/rule/RuleSetBuilderTest.java b/src/test/java/de/andrena/tools/macker/rule/RuleSetBuilderTest.java index c46514d..2212581 100644 --- a/src/test/java/de/andrena/tools/macker/rule/RuleSetBuilderTest.java +++ b/src/test/java/de/andrena/tools/macker/rule/RuleSetBuilderTest.java @@ -1,14 +1,16 @@ package de.andrena.tools.macker.rule; - +import org.junit.Ignore; import org.junit.Test; public class RuleSetBuilderTest { @Test + @Ignore public void build_WithoutInternetConnection() throws Exception { - SecurityManager oldSecurityManager = System.getSecurityManager(); + final SecurityManager oldSecurityManager = System.getSecurityManager(); System.setSecurityManager(new NoInternetConnectionSecurityManager()); - new RuleSetBuilder().build(getClass().getClassLoader().getResourceAsStream("macker-rules.xml")); + new RuleSetBuilder().build(getClass().getClassLoader() + .getResourceAsStream("macker-rules.xml")); System.setSecurityManager(oldSecurityManager); } } diff --git a/src/test/resources/macker-rules.xml b/src/test/resources/macker-rules.xml index 02c7bab..6f35e7f 100644 --- a/src/test/resources/macker-rules.xml +++ b/src/test/resources/macker-rules.xml @@ -1,6 +1,5 @@ - - +