diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java index 434a72622..36306e915 100644 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/analyzer/NuspecAnalyzer.java @@ -17,14 +17,15 @@ */ package org.owasp.dependencycheck.analyzer; -import java.io.File; +import java.io.FileInputStream; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; -import javax.xml.parsers.SAXParser; -import javax.xml.parsers.SAXParserFactory; + import org.owasp.dependencycheck.Engine; -import org.owasp.dependencycheck.data.nuget.NuspecHandler; +import org.owasp.dependencycheck.data.nuget.NugetPackage; +import org.owasp.dependencycheck.data.nuget.NuspecParser; +import org.owasp.dependencycheck.data.nuget.XPathNuspecParser; import org.owasp.dependencycheck.dependency.Confidence; import org.owasp.dependencycheck.dependency.Dependency; @@ -55,11 +56,6 @@ public class NuspecAnalyzer extends AbstractAnalyzer { */ private static final Set SUPPORTED_EXTENSIONS = newHashSet("nuspec"); - /** - * The SAXParser we'll use to parse nuspec files. - */ - private SAXParser parser; - /** * Initializes the analyzer once before any analysis is performed. * @@ -67,9 +63,6 @@ public class NuspecAnalyzer extends AbstractAnalyzer { */ @Override public void initialize() throws Exception { - final SAXParserFactory factory = SAXParserFactory.newInstance(); - factory.setNamespaceAware(true); - parser = factory.newSAXParser(); } /** @@ -124,30 +117,26 @@ public class NuspecAnalyzer extends AbstractAnalyzer { public void analyze(Dependency dependency, Engine engine) throws AnalysisException { LOGGER.log(Level.INFO, "Checking Nuspec file {0}", dependency.toString()); try { - final NuspecHandler nh = new NuspecHandler(); - parser.parse(new File(dependency.getActualFilePath()), nh); - if (nh.getVersion() != null && !"".equals(nh.getVersion())) { - dependency.getVersionEvidence().addEvidence("nuspec", "version", nh.getVersion(), - Confidence.HIGHEST); + final NuspecParser parser = new XPathNuspecParser(); + NugetPackage np = null; + FileInputStream fis = null; + try { + fis = new FileInputStream(dependency.getActualFilePath()); + np = parser.parse(fis); + } finally { + if (fis != null) { + try { fis.close(); } catch (Exception e) { } + } } - if (nh.getId() != null && !"".equals(nh.getId())) { - dependency.getProductEvidence().addEvidence("nuspec", "id", nh.getId(), - Confidence.HIGHEST); + + if (np.getOwners() != null) { + dependency.getVendorEvidence().addEvidence("nuspec", "owners", np.getOwners(), Confidence.HIGHEST); } - if (nh.getOwners() != null && !"".equals(nh.getOwners())) { - dependency.getVendorEvidence().addEvidence("nuspec", "owners", nh.getOwners(), - Confidence.HIGHEST); - } - if (nh.getAuthors() != null && !"".equals(nh.getAuthors())) { - dependency.getVendorEvidence().addEvidence("nuspec", "authors", nh.getAuthors(), - Confidence.MEDIUM); - } - if (nh.getTitle() != null && !"".equals(nh.getTitle())) { - dependency.getProductEvidence().addEvidence("nuspec", "title", nh.getTitle(), - Confidence.MEDIUM); - } - if (nh.getLicenseUrl() != null && !"".equals(nh.getLicenseUrl())) { - dependency.setLicense(nh.getLicenseUrl()); + dependency.getVendorEvidence().addEvidence("nuspec", "authors", np.getAuthors(), Confidence.HIGH); + dependency.getVersionEvidence().addEvidence("nuspec", "version", np.getVersion(), Confidence.HIGHEST); + dependency.getProductEvidence().addEvidence("nuspec", "id", np.getId(), Confidence.HIGHEST); + if (np.getTitle() != null) { + dependency.getProductEvidence().addEvidence("nuspec", "title", np.getTitle(), Confidence.MEDIUM); } } catch (Exception e) { throw new AnalysisException(e); diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NugetPackage.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NugetPackage.java new file mode 100644 index 000000000..ae03901e1 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NugetPackage.java @@ -0,0 +1,186 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2014 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.data.nuget; + +/** + * Represents the contents of a Nuspec manifest. + * + * @author colezlaw + */ +public class NugetPackage { + /** + * The id. + */ + private String id; + + /** + * The version. + */ + private String version; + + /** + * The title. + */ + private String title; + + /** + * The authors. + */ + private String authors; + + /** + * The owners. + */ + private String owners; + + /** + * The licenseUrl. + */ + private String licenseUrl; + + /** + * Creates an empty NugetPackage. + */ + public NugetPackage() { + } + + /** + * Sets the id. + * @param id the id + */ + public void setId(String id) { + this.id = id; + } + + /** + * Gets the id. + * @return the id + */ + public String getId() { + return id; + } + + /** + * Sets the version. + * @param version the version + */ + public void setVersion(String version) { + this.version = version; + } + + /** + * Gets the version. + * @return the version + */ + public String getVersion() { + return version; + } + + /** + * Sets the title. + * @param title the title + */ + public void setTitle(String title) { + this.title = title; + } + + /** + * Gets the title. + * @return the title + */ + public String getTitle() { + return title; + } + + /** + * Sets the authors. + * @param authors the authors + */ + public void setAuthors(String authors) { + this.authors = authors; + } + + /** + * Gets the authors. + * @return the authors + */ + public String getAuthors() { + return authors; + } + + /** + * Sets the owners. + * @param owners the owners + */ + public void setOwners(String owners) { + this.owners = owners; + } + + /** + * Gets the owners. + * @return the owners + */ + public String getOwners() { + return owners; + } + + /** + * Sets the licenseUrl. + * @param licenseUrl the licenseUrl + */ + public void setLicenseUrl(String licenseUrl) { + this.licenseUrl = licenseUrl; + } + + /** + * Gets the licenseUrl. + * @return the licenseUrl + */ + public String getLicenseUrl() { + return licenseUrl; + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (other == null || other.getClass() != this.getClass()) { + return false; + } + final NugetPackage o = (NugetPackage) other; + return o.getId().equals(id) + && o.getVersion().equals(version) + && o.getTitle().equals(title) + && o.getAuthors().equals(authors) + && o.getOwners().equals(owners) + && o.getLicenseUrl().equals(licenseUrl); + } + + @Override + public int hashCode() { + int hash = 7; + hash = 31 * hash + (null == id ? 0 : id.hashCode()); + hash = 31 * hash + (null == version ? 0 : version.hashCode()); + hash = 31 * hash + (null == title ? 0 : title.hashCode()); + hash = 31 * hash + (null == authors ? 0 : authors.hashCode()); + hash = 31 * hash + (null == owners ? 0 : owners.hashCode()); + hash = 31 * hash + (null == licenseUrl ? 0 : licenseUrl.hashCode()); + return hash; + } +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecHandler.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecHandler.java deleted file mode 100644 index 68dc0afd1..000000000 --- a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecHandler.java +++ /dev/null @@ -1,240 +0,0 @@ -/* - * This file is part of dependency-check-core. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Copyright (c) 2014 Jeremy Long. All Rights Reserved. - */ -package org.owasp.dependencycheck.data.nuget; - -import java.util.logging.Logger; - -import org.xml.sax.Attributes; -import org.xml.sax.SAXException; -import org.xml.sax.helpers.DefaultHandler; - -/** - * A DefaultHandler for parsing a Nuspec - * file. - * @author colezlaw - */ -public class NuspecHandler extends DefaultHandler { - /** - * Holds the id - */ - private String id; - /** - * Holds the version - */ - private String version; - /** - * Holds the title - */ - private String title; - /** - * Holds the authors - */ - private String authors; - /** - * Holds the owners - */ - private String owners; - /** - * Holds the licenseUrl - */ - private String licenseUrl; - - /** - * Indicates whether we're currently processing the id. - */ - private boolean inId; - /** - * Indicates whether we're currently processing the version. - */ - private boolean inVersion; - /** - * Indicates whether we're currently processing the title. - */ - private boolean inTitle; - /** - * Indicates whether we're currently processing the authors. - */ - private boolean inAuthors; - /** - * Indicates whether we're currently processing the owners. - */ - private boolean inOwners; - /** - * Indicates whether we're currently processing the licenseUrl. - */ - private boolean inLicenseUrl; - - /** - * The Namespace for Nuspec documents. - */ - private static final String NS_NUSPEC = - "http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd"; - - /** - * Creates a NugetHandler. - */ - public NuspecHandler() { - inId = false; - inVersion = false; - inTitle = false; - inAuthors = false; - inOwners = false; - inLicenseUrl = false; - } - - /** - * Gets the id. - * @return the id - */ - public String getId() { - return id; - } - - /** - * Gets the version. - * @return the version - */ - public String getVersion() { - return version; - } - - /** - * Gets the title. - * @return the title - */ - public String getTitle() { - return title; - } - - /** - * Gets the authors. - * @return the authors - */ - public String getAuthors() { - return authors; - } - - /** - * Gets the owners. - * @return the owners - */ - public String getOwners() { - return owners; - } - - /** - * Gets the licenseUrl. - * @return the licenseUrl - */ - public String getLicenseUrl() { - return licenseUrl; - } - - /** - * Receive notification of the start of an element. - * @param uri The Namespace URL, or the empty string if the element has no - * Namespace URI or if Namespace processing is not being - * performed. - * @param localName The loca name (without prefix), or the empty string if - * Namespace processing is not being performed. - * @param qName The qualified name (with prefix), or the empty string if - * qualified names are not available. - * @param attributes The attributes attached to the element. If there are - * no attributes, it shall be an empty Attributes object. - * @throws SAXException Any SAX exception, possibly wrapping another - * exception. - */ - public void startElement(String uri, String localName, String qName, - Attributes attributes) throws SAXException { - if (NS_NUSPEC.equals(uri) && "id".equals(localName)) { - id = ""; - inId = true; - } else if (NS_NUSPEC.equals(uri) && "version".equals(localName)) { - version = ""; - inVersion = true; - } else if (NS_NUSPEC.equals(uri) && "title".equals(localName)) { - title = ""; - inTitle = true; - } else if (NS_NUSPEC.equals(uri) && "authors".equals(localName)) { - authors = ""; - inAuthors = true; - } else if (NS_NUSPEC.equals(uri) && "owners".equals(localName)) { - owners = ""; - inOwners = true; - } else if (NS_NUSPEC.equals(uri) && "licenseUrl".equals(localName)) { - licenseUrl = ""; - inLicenseUrl = true; - } - } - - /** - * Receive notification of the end of an element. - * By default, do nothing. Application writers may override this method in - * a subclass to take specific actions at the end of each element (such as - * finalising a tree node or writing output to a file). - * @param uri The Namespace URI, or the empty string if the element has no - * Namespace URI or if Namespace processing is not being - * performed. - * @param localName The local name (without prefix), or the empty string if - * Namespace processing is not being performed. - * @param qName The qualified name (with prefix), or the empty string if - * qualified names are not available. - * @throws SAXException Any SAX exception, possibly wrapping another - * exception. - */ - public void endElement(String uri, String localName, String qName) - throws SAXException { - inId = false; - inVersion = false; - inTitle = false; - inAuthors = false; - inOwners = false; - inLicenseUrl = false; - } - - /** - * Receive notification of character data inside an element. - * By default, do nothing. Application writers may override this method to - * take specific actions for each chunk of character data (such as adding - * the data to a node or buffer, or printing it to a file). - * @param ch The characters. - * @param start The start position in the character array. - * @param length The number of characters to use from the character array. - * @throws SAXException Any SAX exception, possibly wrapping another - * exception. - */ - public void characters(char[] ch, int start, int length) - throws SAXException { - final String toAppend = new String(ch, start, length); - if (inId) { - id += toAppend; - } else if (inVersion) { - version += toAppend; - } else if (inTitle) { - title += toAppend; - } else if (inAuthors) { - authors += toAppend; - } else if (inOwners) { - owners += toAppend; - } else if (inLicenseUrl) { - licenseUrl += toAppend; - } - } -} - -// vim: cc=120:sw=4:ts=4:sts=4 diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParseException.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParseException.java new file mode 100644 index 000000000..027bf4d00 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParseException.java @@ -0,0 +1,68 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2014 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.data.nuget; + +/** + * Exception during the parsing of a Nuspec file. + * + * @author colezlaw + */ +public class NuspecParseException extends Exception { + /** + * The serialVersionUID + */ + private static final long serialVersionUID = 1; + + /** + * Constructs a new exception with null as its detail message. + * + * The cause is not initialized, and may subsequently be initialized by a call + * to {@link java.lang.Throwable#initCause(java.lang.Throwable)}. + */ + public NuspecParseException() { + super(); + } + + /** + * Constructs a new exception with the specified detail message. The cause is + * not initialized, and may subsequently be initialized by a call to + * {@link java.lang.Throwable#initCause(java.lang.Throwable). + * + * @param message the detail message. The detail message is saved for later retrieval + * by the {@link java.lang.Throwable#getMessage()} method. + */ + public NuspecParseException(String message) { + super(message); + } + + /** + * Constructs a new exception with the specified detail message and cause. + * + * Note that the detail message associated with cause is not + * automatically incorporated in this exception's detail message. + * + * @param message the detail message (whcih is saved for later retrieval by the + * {@link java.lang.Throwable#getMessage()} method. + * @param cause the cause (which is saved for later retrieval by the + * {@link java.lang.Throwable#getCause()} method). (A null value is permitted, + * and indicates that the cause is nonexistent or unknown). + */ + public NuspecParseException(String message, Throwable cause) { + super(message, cause); + } +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParser.java new file mode 100644 index 000000000..e752946d6 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/NuspecParser.java @@ -0,0 +1,37 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2014 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.data.nuget; + +import java.io.InputStream; + +/** + * Interface defining methods for parsing a Nuspec file. + * + * @author willstranathan + * + */ +public interface NuspecParser { + /** + * Parse an input stream and return the resulting {@link NugetPackage}. + * + * @param stream the input stream to parse + * @return the populated bean + * @throws NuspecParseException when an exception occurs + */ + NugetPackage parse(InputStream stream) throws NuspecParseException; +} diff --git a/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java new file mode 100644 index 000000000..cadf36aa7 --- /dev/null +++ b/dependency-check-core/src/main/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParser.java @@ -0,0 +1,82 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2014 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.data.nuget; + +import java.io.InputStream; + +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathConstants; +import javax.xml.xpath.XPathFactory; + +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Parse a Nuspec file using XPath. + * + * @author willstranathan + */ +public class XPathNuspecParser implements NuspecParser { + /** + * Gets the string value of a node or null if it's not present + * + * @param n the node to test + * @return the string content of the node, or null if the node itself is null + */ + private String getOrNull(Node n) { + if (n != null) { + return n.getTextContent(); + } else { + return null; + } + } + + /** + * Parse an input stream and return the resulting {@link NugetPackage}. + * + * @param stream the input stream to parse + * @return the populated bean + * @throws NuspecParseException when an exception occurs + */ + @Override + public NugetPackage parse(InputStream stream) throws NuspecParseException { + try { + final Document d = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(stream); + final XPath xpath = XPathFactory.newInstance().newXPath(); + final NugetPackage nuspec = new NugetPackage(); + + if (xpath.evaluate("/package/metadata/id", d, XPathConstants.NODE) == null + || xpath.evaluate("/package/metadata/version", d, XPathConstants.NODE) == null + || xpath.evaluate("/package/metadata/authors", d, XPathConstants.NODE) == null + || xpath.evaluate("/package/metadata/description", d, XPathConstants.NODE) == null) { + throw new NuspecParseException("Invalid Nuspec format"); + } + + nuspec.setId(xpath.evaluate("/package/metadata/id", d)); + nuspec.setVersion(xpath.evaluate("/package/metadata/version", d)); + nuspec.setAuthors(xpath.evaluate("/package/metadata/authors", d)); + nuspec.setOwners(getOrNull((Node) xpath.evaluate("/package/metadata/owners", d, XPathConstants.NODE))); + nuspec.setLicenseUrl(getOrNull((Node) xpath.evaluate("/package/metadata/licenseUrl", d, XPathConstants.NODE))); + nuspec.setTitle(getOrNull((Node) xpath.evaluate("/package/metadata/title", d, XPathConstants.NODE))); + return nuspec; + } catch (Exception e) { + throw new NuspecParseException("Unable to parse nuspec", e); + } + } +} diff --git a/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParserTest.java b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParserTest.java new file mode 100644 index 000000000..dface467e --- /dev/null +++ b/dependency-check-core/src/test/java/org/owasp/dependencycheck/data/nuget/XPathNuspecParserTest.java @@ -0,0 +1,73 @@ +/* + * This file is part of dependency-check-core. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * Copyright (c) 2014 Jeremy Long. All Rights Reserved. + */ +package org.owasp.dependencycheck.data.nuget; + +import java.io.InputStream; + +import org.junit.Test; +import static org.junit.Assert.*; + + +/** + * + * @author willstranathan + * + */ +public class XPathNuspecParserTest { + /** + * Test all the valid components. + * + * @throws Exception if anything goes sideways. + */ + @Test + public void testGoodDocument() throws Exception { + NuspecParser parser = new XPathNuspecParser(); + InputStream is = XPathNuspecParserTest.class.getClassLoader().getResourceAsStream("log4net.2.0.3.nuspec"); + NugetPackage np = parser.parse(is); + assertEquals("log4net", np.getId()); + assertEquals("2.0.3", np.getVersion()); + assertEquals("log4net [1.2.13]", np.getTitle()); + assertEquals("Apache Software Foundation", np.getAuthors()); + assertEquals("Apache Software Foundation", np.getOwners()); + assertEquals("http://logging.apache.org/log4net/license.html", np.getLicenseUrl()); + } + + /** + * Expect a NuspecParseException when what we pass isn't even XML. + * + * @throws Exception we expect this. + */ + @Test(expected=NuspecParseException.class) + public void testMissingDocument() throws Exception { + NuspecParser parser = new XPathNuspecParser(); + InputStream is = XPathNuspecParserTest.class.getClassLoader().getResourceAsStream("dependencycheck.properties"); + NugetPackage np = parser.parse(is); + } + + /** + * Expect a NuspecParseException when it's valid XML, but not a Nuspec. + * + * @throws Exception we expect this. + */ + @Test(expected=NuspecParseException.class) + public void testNotNuspec() throws Exception { + NuspecParser parser = new XPathNuspecParser(); + InputStream is = XPathNuspecParserTest.class.getClassLoader().getResourceAsStream("suppressions.xml"); + NugetPackage np = parser.parse(is); + } +} diff --git a/dependency-check-core/src/test/resources/log4net.2.0.3.nuspec b/dependency-check-core/src/test/resources/log4net.2.0.3.nuspec new file mode 100644 index 000000000..99ad59ab7 --- /dev/null +++ b/dependency-check-core/src/test/resources/log4net.2.0.3.nuspec @@ -0,0 +1,20 @@ + + + + log4net + 2.0.3 + log4net [1.2.13] + Apache Software Foundation + Apache Software Foundation + http://logging.apache.org/log4net/license.html + http://logging.apache.org/log4net/ + false + log4net is a tool to help the programmer output log statements to a variety of output targets. In case of problems with an application, it is helpful to enable logging so that the problem can be located. With log4net it is possible to enable logging at runtime without modifying the application binary. The log4net package is designed so that log statements can remain in shipped code without incurring a high performance cost. It follows that the speed of logging (or rather not logging) is crucial. + +At the same time, log output can be so voluminous that it quickly becomes overwhelming. One of the distinctive features of log4net is the notion of hierarchical loggers. Using these loggers it is possible to selectively control which log statements are output at arbitrary granularity. + +log4net is designed with two distinct goals in mind: speed and flexibility + The Apache log4net library is a tool to help the programmer output log statements to a variety of output targets. + logging log tracing logfiles + + \ No newline at end of file