Merging from revision 787:HEAD on /branches/jetty-7.0.1/ to /trunk/

* Bumping up version to 7.0.1-SNAPSHOT
* Adding jetty-webapp-verifier from /sandbox/
* Changes to jetty-webapp for jetty-centralized-logging from /sandbox/
* Fixes to jetty-policy to support jetty-webapp-verifier



git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@835 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Joakim Erdfelt 2009-09-08 20:31:00 +00:00
parent 92f1b1801f
commit db1479e571
259 changed files with 6282 additions and 86 deletions

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>example-jetty-embedded</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.aggregate</groupId>

View File

@ -4,7 +4,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty.aggregate</groupId>
<artifactId>jetty-aggregate-project</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-ajp</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-annotations</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-client</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-continuation</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-deploy</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<artifactId>jetty-distribution</artifactId>
<name>Jetty :: Distribution Assemblies</name>
@ -140,6 +140,16 @@
<includes>**</includes>
<outputDirectory>${assembly.directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp-verifier</artifactId>
<version>${project.version}</version>
<classifier>config</classifier>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly.directory}</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-plus</artifactId>
@ -261,6 +271,15 @@
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly.directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp-verifier</artifactId>
<version>${project.version}</version>
<type>jar</type>
<overWrite>true</overWrite>
<includes>**</includes>
<outputDirectory>${assembly.directory}/lib</outputDirectory>
</artifactItem>
<artifactItem>
<groupId>org.eclipse.jetty</groupId>
@ -496,4 +515,4 @@
<version>${project.version}</version>
</dependency>
</dependencies>
</project>
</project>

View File

@ -2,7 +2,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty</groupId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jaspi</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jmx</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-jndi</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-plus</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-policy</artifactId>

View File

@ -0,0 +1,23 @@
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<!-- =============================================================== -->
<!-- mechanic for starting jetty policy -->
<!-- -->
<!-- =============================================================== -->
<Configure id="Policy" class="org.eclipse.jetty.policy.JettyPolicyConfigurator">
<Call name="addPolicy">
<Arg><SystemProperty name="jetty.home"/>/lib/policy/jetty.policy</Arg>
</Call>
<Call name="addProperty">
<Arg>jetty.home</Arg>
<Arg><SystemProperty name="jetty.home"/></Arg>
</Call>
<Call name="initialize"/>
</Configure>

View File

@ -73,6 +73,8 @@ public class JettyPolicy extends Policy
public JettyPolicy(Set<String> policies, Map<String, String> properties)
{
System.out.println("Activating the JettyPolicy");
try
{
__DEBUG = Boolean.getBoolean("org.eclipse.jetty.policy.DEBUG");
@ -288,11 +290,13 @@ public class JettyPolicy extends Policy
initialize();
}
for (Iterator<Object> i = _cache.keySet().iterator(); i.hasNext();)
synchronized (_cache)
{
System.out.println(i.next().toString());
for (Iterator<Object> i = _cache.keySet().iterator(); i.hasNext();)
{
System.out.println(i.next().toString());
}
}
if (__DEBUG)
{

View File

@ -0,0 +1,58 @@
package org.eclipse.jetty.policy;
//========================================================================
//Copyright (c) Webtide LLC
//------------------------------------------------------------------------
//All rights reserved. This program and the accompanying materials
//are made available under the terms of the Eclipse Public License v1.0
//and Apache License v2.0 which accompanies this distribution.
//
//The Eclipse Public License is available at
//http://www.eclipse.org/legal/epl-v10.html
//
//The Apache License v2.0 is available at
//http://www.opensource.org/licenses/apache2.0.php
//
//You may elect to redistribute this code under either of these licenses.
//========================================================================
import java.security.Policy;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
*
*
*/
public class JettyPolicyConfigurator
{
Set<String> _policies= new HashSet<String>();
Map<String, String> _properties = new HashMap<String,String>();
public JettyPolicyConfigurator()
{
}
public void addPolicy( String policy )
{
_policies.add(policy);
}
public void addProperty( String name, String value )
{
_properties.put(name,value);
}
public void initialize()
{
System.out.println("Initializing Jetty Policy");
JettyPolicy jpolicy = new JettyPolicy( _policies, _properties );
Policy.setPolicy(jpolicy);
System.setSecurityManager(new SecurityManager());
}
}

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-rewrite</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-security</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-server</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlet</artifactId>

View File

@ -3,7 +3,7 @@
<parent>
<artifactId>jetty-project</artifactId>
<groupId>org.eclipse.jetty</groupId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-servlets</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-start</artifactId>

View File

@ -2,7 +2,7 @@
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.0.RC6-SNAPSHOT</version>
<version>7.0.1-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<artifactId>jetty-util</artifactId>

9
jetty-webapp-verifier/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
target/
.classpath
.project
.settings
*.swp
*.patch
*.diff
*.log
cobertura.ser

View File

@ -0,0 +1,111 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-project</artifactId>
<version>7.0.1-SNAPSHOT</version>
</parent>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp-verifier</artifactId>
<name>Jetty :: Webapp Verifier Tool</name>
<packaging>jar</packaging>
<properties>
<war.file.repo>target/war-files</war.file.repo>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>copy</id>
<phase>generate-resources</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>test-webapp-logging-java</artifactId>
<version>${project.version}</version>
<type>war</type>
<outputDirectory>${war.file.repo}</outputDirectory>
<destFileName>test-webapp-logging-java.war</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<configuration>
<descriptors>
<descriptor>config.xml</descriptor>
</descriptors>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-xml</artifactId>
<version>${version}</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!--
*
* Dependencies that should be provided should their respected verifiers be used
*
*-->
<dependency>
<groupId>asm</groupId>
<artifactId>asm</artifactId>
<version>3.1</version>
<optional>true</optional>
</dependency>
<dependency>
<groupId>asm</groupId>
<artifactId>asm-tree</artifactId>
<version>3.1</version>
<optional>true</optional>
</dependency>
</dependencies>
<reporting>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jxr-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>cobertura-maven-plugin</artifactId>
</plugin>
</plugins>
</reporting>
</project>

View File

@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "http://www.eclipse.org/jetty/configure.dtd">
<Configure id="basicRuleSet"
class="org.eclipse.jetty.webapp.verifier.RuleSet">
<Set name="rules">
<Array type="org.eclipse.jetty.webapp.verifier.Rule">
<Item>
<New class="org.eclipse.jetty.webapp.verifier.rules.RequiredContentsVerifier">
<Call name="addPath">
<Arg>/WEB-INF/web.xml</Arg>
</Call>
</New>
</Item>
<!--
<Item>
<New class="org.eclipse.jetty.webapp.verifier.rules.SignedJarVerifier">
<Call name="setType">
<Arg>JKS</Arg>
</Call>
<Call name="setAlias">
<Arg>verisignclass3ca</Arg>
</Call>
<Call name="setKeystoreLocation">
<Arg><SystemProperty name="java.home" default="."/>/lib/security/cacerts</Arg>
</Call>
</New>
</Item>
-->
</Array>
</Set>
</Configure>

View File

@ -0,0 +1,94 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier;
import java.io.File;
import java.util.Enumeration;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
/**
* AbstractArchiveScanningRule for Rules that scan the archive contents.
*/
public abstract class AbstractArchiveScanningRule extends AbstractRule
{
public abstract String getDescription();
public abstract String getName();
@Override
public void visitWebInfLibJar(String path, File archive, JarFile jar)
{
scanClassesInArchive(path,jar);
}
@Override
public void visitWebInfLibZip(String path, File archive, ZipFile zip)
{
scanClassesInArchive(path,zip);
}
private String asClassname(String path)
{
StringBuffer name = new StringBuffer();
for (char c : path.toCharArray())
{
if (c == '/')
{
name.append(".");
}
else
{
name.append(c);
}
}
if (name.toString().endsWith(".class"))
{
name.delete(name.length() - 6,name.length() - 1);
}
return name.toString();
}
private void scanClassesInArchive(String path, ZipFile zip)
{
String className;
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements())
{
ZipEntry entry = entries.nextElement();
if (entry.getName().endsWith(".class"))
{
className = asClassname(entry.getName());
visitArchiveClass(path + "!/" + entry.getName(),className,zip,entry);
}
else
{
visitArchiveResource(path + "!/" + entry.getName(),zip,entry);
}
}
}
public void visitArchiveResource(String path, ZipFile zip, ZipEntry entry)
{
/* override to do something with */
}
public void visitArchiveClass(String path, String className, ZipFile archive, ZipEntry archiveEntry)
{
/* override to do something with */
}
}

View File

@ -0,0 +1,215 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier;
import java.io.File;
import java.util.jar.JarFile;
import java.util.zip.ZipFile;
public abstract class AbstractRule implements Rule
{
private ViolationListener violationListener;
private File rootDir;
protected void error(String path, String detail)
{
Violation violation = new Violation(Severity.ERROR,path,detail);
violation.setVerifierInfo(this);
violationListener.reportViolation(violation);
}
protected void exception(String path, String detail, Throwable t)
{
Violation violation = new Violation(Severity.ERROR,path,detail,t);
violation.setVerifierInfo(this);
violationListener.reportViolation(violation);
}
protected String getWebappRelativePath(File dir)
{
if (rootDir == null)
{
throw new RuntimeException("rootDir is not initialized, can't get relative path. "
+ "Did you overide .visitWebappStart() and not call super.visitWebappStart()?");
}
return rootDir.toURI().relativize(dir.toURI()).toASCIIString();
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#setViolationListener(ViolationListener)
*/
public void setViolationListener(ViolationListener listener)
{
this.violationListener = listener;
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#initialize()
*/
public void initialize() throws Throwable
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitDirectoryEnd(java.lang.String, java.io.File)
*/
public void visitDirectoryEnd(String path, File dir)
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitDirectoryStart(java.lang.String, java.io.File)
*/
public void visitDirectoryStart(String path, File dir)
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitFile(java.lang.String, java.io.File, java.io.File)
*/
public void visitFile(String path, File dir, File file)
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebappEnd(java.lang.String, java.io.File)
*/
public void visitWebappEnd(String path, File dir)
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* NOTE: be sure to call super.{@link #visitWebappStart(String, File)} in your overriden method.
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebappStart(java.lang.String, java.io.File)
*/
public void visitWebappStart(String path, File dir)
{
if (path.equals(ROOT_PATH))
{
rootDir = new File(path);
}
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfClass(java.lang.String, java.lang.String,
* java.io.File)
*/
public void visitWebInfClass(String path, String className, File classFile)
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfClassesEnd(java.lang.String, java.io.File)
*/
public void visitWebInfClassesEnd(String path, File dir)
{
// TODO Auto-generated method stub
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfClassesStart(java.lang.String, java.io.File)
*/
public void visitWebInfClassesStart(String path, File dir)
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfClassResource(java.lang.String, java.lang.String,
* java.io.File)
*/
public void visitWebInfClassResource(String path, String resourcePath, File resourceFile)
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfLibEnd(java.lang.String, java.io.File)
*/
public void visitWebInfLibEnd(String path, File dir)
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfLibJar(String, File, JarFile)
*/
public void visitWebInfLibJar(String path, File archive, JarFile jar)
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfLibStart(java.lang.String, java.io.File)
*/
public void visitWebInfLibStart(String path, File dir)
{
/* override to implement */
}
/**
* {@inheritDoc}
*
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfLibZip(String, File, ZipFile)
*/
public void visitWebInfLibZip(String path, File archive, ZipFile zip)
{
/* override to implement */
}
protected void warning(String path, String detail)
{
Violation violation = new Violation(Severity.WARNING,path,detail);
violation.setVerifierInfo(this);
violationListener.reportViolation(violation);
}
}

View File

@ -0,0 +1,222 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier;
import java.io.File;
import java.net.URLClassLoader;
import java.util.jar.JarFile;
import java.util.zip.ZipFile;
/**
* <p>
* Rule is the interface that the {@link WebappVerifier} uses to notify Rule implementations of events in the Iteration
* of a Webapp contents.
* </p>
*
* <p>
* The visitor pattern used here has the following order ..
* </p>
*
* <pre>
* 1) [1] {@link #visitWebappStart(String, File)}
* Iterate Contents:
* 2) [1..n] {@link #visitDirectoryStart(String, File)}
* 3) [0..n] {@link #visitFile(String, File, File)}
* 4) [1..n] {@link #visitDirectoryEnd(String, File)}
* Iterate WEB-INF/classes:
* 5) [0..1] {@link #visitWebInfClassesStart(String, File)}
* 6) [0..n] {@link #visitWebInfClass(String, String, File)}
* 7) [0..n] {@link #visitWebInfClassResource(String, String, File)}
* 8) [0..1] {@link #visitWebInfClassesEnd(String, File)}
* Iterate WEB-INF/lib:
* 9) [0..1] {@link #visitWebInfLibStart(String, File)}
* 10) [0..n] {@link #visitWebInfLibJar(String, File, JarFile)}
* 11) [0..n] {@link #visitWebInfLibZip(String, File, ZipFile)}
* 12) [0..1] {@link #visitWebInfLibEnd(String, File)}
* 13) [1] {@link #visitWebappEnd(String, File)}
* </pre>
*/
public interface Rule
{
public static final String ROOT_PATH = "";
/**
* A short name for the rule.
*/
public String getName();
/**
* A Description of the purpose of the rule. What does it check for? Why?
*/
public String getDescription();
/**
* Initialization logic for the rule, exceptions from initialization will be logged as a {@link Severity#ERROR}
* level {@link Violation} with the {@link Violation#getThrowable()} set.
*
* If you want more meaningful violation messages than default, be sure to capture your own initialization related
* failures and report them to the {@link ViolationListener} at a {@link Severity#ERROR} level.
*/
public void initialize() throws Throwable;
/**
* Set the listener to report violations back to.
*/
public void setViolationListener(ViolationListener listener);
/**
* The iteration of the webapp has begun.
*
* @param path
* the war relative path to this directory.
* @param dir
* the real File System directory to the webapp work directory
*/
public void visitWebappStart(String path, File dir);
/**
* A visit of a directory has begun.
*
* @param path
* the war relative path to this directory.
* @param dir
* the real File System directory object for this directory.
*/
public void visitDirectoryStart(String path, File dir);
/**
* A visit of a file.
*
* @param path
* the war relative path to this file.
* @param dir
* the real File System directory object for this file. This is the same directory as seen in
* {@link #visitDirectoryStart(String, File)} and {@link #visitDirectoryEnd(String, File)}
* @param file
* the real File System {@link File} object to this file
*/
public void visitFile(String path, File dir, File file);
/**
* A visit of a directory has ended.
*
* @param path
* the war relative path to this directory.
* @param dir
* the real File System directory.
*/
public void visitDirectoryEnd(String path, File dir);
/**
* The visit to WEB-INF/classes is starting
*
* @param path
* the war relative path to the WEB-INF/classes dir. (Note: Will always be "WEB-INF/classes")
* @param dir
* the real File System directory.
*/
public void visitWebInfClassesStart(String path, File dir);
/**
* A visit of a Class found in WEB-INF/classes.
*
* @param path
* the war relative path to this directory.
* @param className
* the full classname of the class found. TODO: Base this off of class bytecode?
* @param classFile
* the real File System directory object for this directory.
*/
public void visitWebInfClass(String path, String className, File classFile);
/**
* A visit of a Resource available in "WEB-INF/classes" which is not a Class (such as an XML file or a properties
* file)
*
* @param path
* the war relative path to this directory.
* @param resourcePath
* the full resourcePath to the file found. Returned in a format that is compatible to
* {@link URLClassLoader#findResource(String)} call.
* @param resourceFile
* the real File System directory object for this directory.
*/
public void visitWebInfClassResource(String path, String resourcePath, File resourceFile);
/**
* The visit to WEB-INF/classes has ended
*
* @param path
* the war relative path to the WEB-INF/classes dir. (Note: Will always be "WEB-INF/classes")
* @param dir
* the real File System directory.
*/
public void visitWebInfClassesEnd(String path, File dir);
/**
* The visit to WEB-INF/lib is starting.
*
* @param path
* the war relative path to the WEB-INF/lib dir. (Note: Will always be "WEB-INF/lib")
* @param dir
* the real File System directory.
*/
public void visitWebInfLibStart(String path, File dir);
/**
* A visit to a JAR archive in the WEB-INF/lib directory.
*
* @param path
* the war relative path to the JAR archive in the WEB-INF/lib dir.
* @param archive
* the real File System file.
* @param jar
* the {@link JarFile}
*/
public void visitWebInfLibJar(String path, File archive, JarFile jar);
/**
* A visit to an archive in the WEB-INF/lib directory has begun.
*
* @param path
* the war relative path to the archive in the WEB-INF/lib dir.
* @param archive
* the real File System file.
* @param zip
* the {@link ZipFile}
*/
public void visitWebInfLibZip(String path, File archive, ZipFile zip);
/**
* The visit to WEB-INF/lib has ended.
*
* @param path
* the war relative path to the WEB-INF/lib dir. (Note: Will always be "WEB-INF/lib")
* @param dir
* the real File System directory.
*/
public void visitWebInfLibEnd(String path, File dir);
/**
* The iteration of the webapp has ended.
*
* @param path
* the war relative path to this directory.
* @param dir
* the real File System directory to the webapp work directory
*/
public void visitWebappEnd(String path, File dir);
}

View File

@ -0,0 +1,89 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier;
import java.io.File;
import java.net.URI;
import java.net.URL;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.eclipse.jetty.xml.XmlConfiguration;
/**
* RuleSet holds the set of configured {@link Rule}s that the WebappVerifier will use.
*/
public class RuleSet
{
private String name;
private List<Rule> rules = new ArrayList<Rule>();
public String getName()
{
return name;
}
public void setName(String name)
{
this.name = name;
}
public List<Rule> getRules()
{
return rules;
}
public void setRules(List<Rule> rules)
{
this.rules = rules;
}
public void setRules(Rule[] ruleArray)
{
this.rules.clear();
this.rules.addAll(Arrays.asList(ruleArray));
}
public void addRule(Rule rule)
{
this.rules.add(rule);
}
public WebappVerifier createWebappVerifier(URI webappURI)
{
WebappVerifier webappVerifier = new WebappVerifier(webappURI);
webappVerifier.setRules(rules);
return webappVerifier;
}
public static RuleSet load(URL configuration) throws Exception
{
XmlConfiguration xml;
xml = new XmlConfiguration(configuration);
return (RuleSet)xml.configure();
}
public static RuleSet load(URI configuration) throws Exception
{
return load(configuration.toURL());
}
public static RuleSet load(File configuration) throws Exception
{
return load(configuration.toURL());
}
}

View File

@ -0,0 +1,39 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier;
public enum Severity
{
WARNING, ERROR;
public static Severity parse(String value)
{
if (value == null)
{
return null;
}
for (Severity sev : Severity.values())
{
if (sev.name().equalsIgnoreCase(value))
{
return sev;
}
}
return null;
}
}

View File

@ -0,0 +1,186 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier;
public class Violation
{
private String path;
private Severity severity;
private String detail;
private Throwable throwable;
private String ruleId;
private Class<? extends Rule> ruleClass;
public Violation(Severity severity, String path, String detail)
{
this.severity = severity;
this.path = path;
this.detail = detail;
}
public Violation(Severity severity, String path, String detail, Rule verifier)
{
this.severity = severity;
this.path = path;
this.detail = detail;
setVerifierInfo(verifier);
}
public Violation(Severity severity, String path, String detail, Throwable throwable)
{
this.severity = severity;
this.path = path;
this.detail = detail;
this.throwable = throwable;
}
public void setVerifierInfo(Rule verifier)
{
this.ruleId = verifier.getName();
this.ruleClass = verifier.getClass();
}
@Override
public String toString()
{
StringBuffer msg = new StringBuffer();
msg.append("Violation[");
msg.append("severity=").append(severity.name());
msg.append(",path=").append(path);
msg.append(",detail=").append(detail);
if (ruleId != null)
{
msg.append(",verifierId=").append(ruleId);
}
if (ruleClass != null)
{
msg.append(",verifierClass=").append(ruleClass.getName());
}
if (throwable != null)
{
msg.append(",throwable=").append(throwable.getClass().getName());
}
msg.append("]");
return msg.toString();
}
public String toDelimString()
{
StringBuffer msg = new StringBuffer();
msg.append(severity.name());
msg.append("|").append(path);
msg.append("|").append(detail);
return msg.toString();
}
@Override
public int hashCode()
{
final int prime = 31;
int result = 1;
result = prime * result + ((detail == null)?0:detail.hashCode());
result = prime * result + ((path == null)?0:path.hashCode());
result = prime * result + ((severity == null)?0:severity.hashCode());
return result;
}
@Override
public boolean equals(Object obj)
{
if (this == obj)
{
return true;
}
if (obj == null)
{
return false;
}
if (getClass() != obj.getClass())
{
return false;
}
Violation other = (Violation)obj;
if (detail == null)
{
if (other.detail != null)
{
return false;
}
}
else if (!detail.equals(other.detail))
{
return false;
}
if (path == null)
{
if (other.path != null)
{
return false;
}
}
else if (!path.equals(other.path))
{
return false;
}
if (severity == null)
{
if (other.severity != null)
{
return false;
}
}
else if (!severity.equals(other.severity))
{
return false;
}
return true;
}
public Class<? extends Rule> getRuleClass()
{
return ruleClass;
}
public String getRuleId()
{
return ruleId;
}
public String getDetail()
{
return detail;
}
public String getPath()
{
return path;
}
public Severity getSeverity()
{
return severity;
}
public Throwable getThrowable()
{
return throwable;
}
}

View File

@ -0,0 +1,49 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier;
import java.text.CollationKey;
import java.text.Collator;
import java.util.Comparator;
public class ViolationComparator implements Comparator<Violation>
{
private static ViolationComparator INSTANCE = new ViolationComparator();
public static ViolationComparator getInstance()
{
return INSTANCE;
}
private Collator collator = Collator.getInstance();
public int compare(Violation o1, Violation o2)
{
CollationKey pathKey1 = collator.getCollationKey(o1.getPath());
CollationKey pathKey2 = collator.getCollationKey(o2.getPath());
int diff = pathKey1.compareTo(pathKey2);
if (diff != 0)
{
// different paths.
return diff;
}
CollationKey detailKey1 = collator.getCollationKey(o1.getDetail());
CollationKey detailKey2 = collator.getCollationKey(o2.getDetail());
return detailKey1.compareTo(detailKey2);
}
}

View File

@ -0,0 +1,21 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier;
public interface ViolationListener
{
void reportViolation(Violation violation);
}

View File

@ -0,0 +1,570 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.jar.JarFile;
import java.util.zip.ZipFile;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.util.resource.JarResource;
import org.eclipse.jetty.util.resource.Resource;
/**
* The Webapp Verifier is a component that can be configured to run and arbitrary number of {@link Rule}s that analyze
* the contents of a war file and report rule violations.
*/
public class WebappVerifier implements ViolationListener
{
/**
* <p>
* Represents the source webappURI.
* </p>
* <p>
* Can be http, file, jar, etc ...
* </p>
* <p>
* Verification does not occur directly against this URI.
* </p>
*/
private URI _webappURI;
/**
* Represents the local webapp file directory, often times points to the working (unpacked) webapp directory.
*
* NOTE: if _webappURI is a "file://" access URI, and points to a directory, then the _webappDir will point to the
* the same place, otherwise it will point to the webapp directory.
*/
private File _webappDir;
private File _workdir;
private List<Rule> _rules;
private Map<String, List<Violation>> _violations;
/**
* Instantiate a WebappVerifier, against the specific webappURI, using the default workdir.
*
* @param webappURI
* the webappURI to verify
*/
public WebappVerifier(URI webappURI)
{
this._webappURI = webappURI;
this._workdir = new File(System.getProperty("java.io.tmpdir"),"jetty-waver");
this._rules = new ArrayList<Rule>();
this._violations = new HashMap<String, List<Violation>>();
}
public void addRule(Rule rule)
{
_rules.add(rule);
try
{
rule.setViolationListener(this);
rule.initialize();
}
catch (Throwable t)
{
// Capture any errors out of initialize or setViolationListener() that might occur.
String msg = String.format("Unable to add rule [%s]: %s",rule.getName(),t.getMessage());
reportException(Rule.ROOT_PATH,msg,rule,t);
}
}
private String cleanFilename(URI uri)
{
// Need a filename to store this download to.
String destname = uri.getPath();
int idx = destname.lastIndexOf('/');
if (idx > 0)
{
destname = destname.substring(idx);
}
destname = destname.trim().toLowerCase();
if (destname.length() <= 0)
{
// whoops, there's nothing left.
// could be caused by urls that point to paths.
destname = new SimpleDateFormat("yyyy-MM-dd_hh-mm-ss").format(new Date());
}
// Neuter illegal characters
char cleaned[] = new char[destname.length()];
for (int i = 0; i < destname.length(); i++)
{
char c = destname.charAt(i);
if (c == '|' || c == '/' || c == '\\' || c == '*' || c == '?' || c == ':' || c == '#')
{
cleaned[i] = '_';
}
else
{
cleaned[i] = c;
}
}
destname = new String(cleaned);
if (!destname.endsWith(".war"))
{
destname += ".war";
}
return destname;
}
private File download(URI uri) throws MalformedURLException, IOException
{
// Establish destfile
File destfile = new File(_workdir,cleanFilename(uri));
InputStream in = null;
FileOutputStream out = null;
try
{
in = uri.toURL().openStream();
out = new FileOutputStream(destfile);
IO.copy(in,out);
}
finally
{
IO.close(in);
}
return destfile;
}
private File establishLocalWebappDir() throws URISyntaxException, IOException
{
if ("file".equals(_webappURI.getScheme()))
{
File path = new File(_webappURI);
if (path.isDirectory())
{
return path;
}
return unpack(path);
}
File downloadedFile = download(_webappURI);
return unpack(downloadedFile);
}
public List<Rule> getRules()
{
return _rules;
}
public Collection<Violation> getViolations()
{
// TODO: Icky! I need a better way of getting the list of raw
// violations, complete, without path mapping in place.
// Yet, I need path mapping as well, right?
List<Violation> violations = new ArrayList<Violation>();
for (List<Violation> pathviol : _violations.values())
{
violations.addAll(pathviol);
}
return violations;
}
public File getWebappDir()
{
return _webappDir;
}
private String getWebappRelativePath(File dir)
{
return _webappDir.toURI().relativize(dir.toURI()).toASCIIString();
}
public File getWorkDir()
{
return _workdir;
}
/**
* Tests a filesystem path for webapp expected files, like "WEB-INF/web.xml"
*/
private boolean isValidWebapp(File path)
{
File webXml = new File(path,"WEB-INF" + File.separator + "web.xml");
if (!webXml.exists())
{
reportViolation(Severity.ERROR,Rule.ROOT_PATH,"Missing WEB-INF/web.xml");
return false;
}
if (!webXml.isFile())
{
reportViolation(Severity.ERROR,Rule.ROOT_PATH,"The WEB-INF/web.xml is not a File");
return false;
}
return true;
}
private void reportException(String path, String detail, Rule rule, Throwable t)
{
Violation viol = new Violation(Severity.ERROR,path,detail,t);
viol.setVerifierInfo(rule);
reportViolation(viol);
}
public void reportViolation(Severity error, String path, String detail)
{
reportViolation(new Violation(error,path,detail));
}
public void reportViolation(Violation violation)
{
List<Violation> pathviol = _violations.get(violation.getPath());
if (pathviol == null)
{
pathviol = new ArrayList<Violation>();
}
pathviol.add(violation);
_violations.put(violation.getPath(),pathviol);
}
public void setRules(Collection<Rule> rules)
{
this._rules.clear();
// Add each rule separately, to establish initialization & listeners
for (Rule verifier : rules)
{
addRule(verifier);
}
}
public void setWorkDir(File workDir)
{
this._workdir = workDir;
}
private File unpack(File path) throws URISyntaxException, IOException
{
String destname = path.getName().substring(0,path.getName().length() - 4);
File destDir = new File(_workdir,destname);
URI warURI = new URI("jar",path.toURI() + "!/",null);
JarResource warResource = (JarResource)Resource.newResource(warURI);
warResource.extract(destDir,false);
return destDir;
}
public void visitAll()
{
try
{
_webappDir = establishLocalWebappDir();
// Issue start.
for (Rule rule : _rules)
{
rule.visitWebappStart(Rule.ROOT_PATH,_webappDir);
}
if (isValidWebapp(_webappDir))
{
// Iterate through content
visitContents();
// Iterate through WEB-INF/classes
visitWebInfClasses();
// Iterate through WEB-INF/lib
visitWebInfLib();
}
// Issue end.
for (Rule rule : _rules)
{
rule.visitWebappEnd(Rule.ROOT_PATH,_webappDir);
}
}
catch (IOException e)
{
reportViolation(new Violation(Severity.ERROR,Rule.ROOT_PATH,e.getMessage(),e));
}
catch (URISyntaxException e)
{
reportViolation(new Violation(Severity.ERROR,Rule.ROOT_PATH,e.getMessage(),e));
}
}
private void visitWebInfClasses()
{
File classesDir = new File(_webappDir,"WEB-INF" + File.separator + "classes");
if (!classesDir.exists())
{
// skip this path.
return;
}
String classesPath = getWebappRelativePath(classesDir);
if (!classesDir.isDirectory())
{
reportViolation(Severity.ERROR,classesPath,"WEB-INF/classes is not a Directory?");
return;
}
// Issue start.
for (Rule rule : _rules)
{
rule.visitWebInfClassesStart(classesPath,classesDir);
}
visitClassesDir(classesDir,classesDir);
// Issue end.
for (Rule rule : _rules)
{
rule.visitWebInfClassesEnd(classesPath,classesDir);
}
}
private void visitClassesDir(File classesRoot, File classesDir)
{
File files[] = classesDir.listFiles();
for (File file : files)
{
if (file.isFile())
{
if (file.getName().endsWith(".class"))
{
visitClass(classesRoot,file);
}
else
{
visitClassResource(classesRoot,file);
}
}
else if (file.isDirectory())
{
// recurse
visitClassesDir(classesRoot,file);
}
}
}
private void visitClassResource(File classesRoot, File file)
{
String path = getWebappRelativePath(file);
String resourcePath = classesRoot.toURI().relativize(file.toURI()).toASCIIString();
for (Rule rule : _rules)
{
rule.visitWebInfClassResource(path,resourcePath,file);
}
}
private void visitClass(File classesRoot, File file)
{
String path = getWebappRelativePath(file);
String className = classesRoot.toURI().relativize(file.toURI()).toASCIIString();
className = className.replace("/",".");
if (className.endsWith(".class"))
{
className = className.substring(0,className.length() - 6);
}
for (Rule rule : _rules)
{
rule.visitWebInfClass(path,className,file);
}
}
private void visitWebInfLib()
{
File libDir = new File(_webappDir,"WEB-INF" + File.separator + "lib");
if (!libDir.exists())
{
// skip this path.
return;
}
String libPath = getWebappRelativePath(libDir);
if (!libDir.isDirectory())
{
reportViolation(Severity.ERROR,libPath,"WEB-INF/lib is not a Directory?");
return;
}
// Issue start.
for (Rule rule : _rules)
{
rule.visitWebInfLibStart(libPath,libDir);
}
// Iterator through contents of WEB-INF/lib
File archives[] = libDir.listFiles();
for (File archive : archives)
{
if (!archive.isFile())
{
reportViolation(Severity.WARNING,Rule.ROOT_PATH,"Found non-file in WEB-INF/lib. Remove it, "
+ "as it cannot be accessed by the Servlet container or the Webapp: " + archive);
continue;
}
if (archive.getName().toLowerCase().endsWith(".jar"))
{
visitWebInfLibJar(libPath,archive);
continue;
}
if (archive.getName().toLowerCase().endsWith(".zip"))
{
visitWebInfLibZip(libPath,archive);
continue;
}
reportViolation(Severity.WARNING,Rule.ROOT_PATH,"Found non-archive in WEB-INF/lib. Remove it, "
+ "as it cannot be accessed by the Servlet container or the Webapp: " + archive);
}
// Issue end.
for (Rule rule : _rules)
{
rule.visitWebInfLibEnd(libPath,libDir);
}
}
private void visitWebInfLibJar(String libPath, File archive)
{
String jarPath = libPath + archive.getName();
// Issue visit on Jar
for (Rule rule : _rules)
{
JarFile jar = null;
try
{
jar = new JarFile(archive);
rule.visitWebInfLibJar(jarPath,archive,jar);
}
catch (Throwable t)
{
reportViolation(new Violation(Severity.ERROR,jarPath,t.getMessage(),t));
}
finally
{
if (jar != null)
{
try
{
jar.close();
}
catch (IOException ignore)
{
/* ignore */
}
}
}
}
}
private void visitWebInfLibZip(String libPath, File archive)
{
String zipPath = libPath + archive.getName();
// Issue visit on Zip
for (Rule rule : _rules)
{
ZipFile zip = null;
try
{
zip = new ZipFile(archive);
rule.visitWebInfLibZip(zipPath,archive,zip);
}
catch (Throwable t)
{
reportViolation(new Violation(Severity.ERROR,zipPath,t.getMessage(),t));
}
finally
{
if (zip != null)
{
try
{
zip.close();
}
catch (IOException ignore)
{
/* ignore */
}
}
}
}
}
private void visitContents()
{
visitDirectoryRecursively(_webappDir);
}
private void visitDirectoryRecursively(File dir)
{
String path = getWebappRelativePath(dir);
// Start Dir
for (Rule rule : this._rules)
{
rule.visitDirectoryStart(path,dir);
}
File entries[] = dir.listFiles();
// Individual Files
for (File file : entries)
{
if (file.isFile())
{
String filepath = path + file.getName();
for (Rule rule : this._rules)
{
rule.visitFile(filepath,dir,file);
}
}
}
// Sub dirs
for (File file : entries)
{
if (file.isDirectory())
{
visitDirectoryRecursively(file);
}
}
// End Dir
for (Rule rule : this._rules)
{
rule.visitDirectoryEnd(path,dir);
}
}
}

View File

@ -0,0 +1,90 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.jetty.webapp.verifier.AbstractArchiveScanningRule;
/**
* ForbiddenClassesVerifier checks the various classes available to the Webapp to ensure that they do not contain and
* forbidden classes.
*/
public class ForbiddenClassesRule extends AbstractArchiveScanningRule
{
private Map<String, Pattern> classPatterns = new HashMap<String, Pattern>();
public void addClassPattern(String classPattern)
{
StringBuffer regex = new StringBuffer();
for (char c : classPattern.toCharArray())
{
if (c == '.')
{
regex.append("\\.");
}
else if (c == '*')
{
regex.append(".*");
}
else
{
regex.append(c);
}
}
classPatterns.put(classPattern,Pattern.compile(regex.toString()));
}
@Override
public String getDescription()
{
return "Ensures that forbidden packages are not present in the war file";
}
@Override
public String getName()
{
return "forbidden-class";
}
private void validateClassname(String path, String className)
{
for (Map.Entry<String, Pattern> pattern : this.classPatterns.entrySet())
{
if (pattern.getValue().matcher(className).matches())
{
error(path,"Class forbidden by pattern: " + pattern.getKey());
}
}
}
@Override
public void visitWebInfClass(String path, String className, File classFile)
{
validateClassname(path,className);
}
@Override
public void visitArchiveClass(String path, String className, ZipFile archive, ZipEntry archiveEntry)
{
validateClassname(path,className);
}
}

View File

@ -0,0 +1,58 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.webapp.verifier.AbstractRule;
import org.eclipse.jetty.webapp.verifier.support.PathGlob;
/**
* ForbiddenContentsVerifier ensures that content matching a pattern does not exist in the webapp.
*/
public class ForbiddenContentsRule extends AbstractRule
{
private List<String> _patterns = new ArrayList<String>();
public void addPattern(String pattern)
{
_patterns.add(pattern);
}
public String getDescription()
{
return "Checks for forbidden content";
}
public String getName()
{
return "forbidden-content";
}
@Override
public void visitFile(String path, File dir, File file)
{
for (String pattern : _patterns)
{
if (PathGlob.match(pattern,path))
{
error(path,"Forbidden content detected");
}
}
}
}

View File

@ -0,0 +1,231 @@
// ========================================================================
// Copyright (c) 2009-2009 Mort Bay Consulting Pty. Ltd.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import org.eclipse.jetty.util.IO;
import org.eclipse.jetty.webapp.verifier.AbstractRule;
/**
* Signed Jar Verifier
*/
public class JarSignatureRule extends AbstractRule
{
private String _keystoreLocation = System.getProperty("java.home") + "/lib/security/cacerts";
private String _type = "JKS"; // default
private String _alias = "verisignclass3ca"; // default
private KeyStore _keystore;
private static X509Certificate[] _trustedCertificates;
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.webapp.verifier.AbstractRule#getDescription()
*/
public String getDescription()
{
return "verifies that the given keystore contains the certificates required for all jar files present";
}
/* ------------------------------------------------------------ */
/**
* @see org.eclipse.jetty.webapp.verifier.AbstractRule#getName()
*/
public String getName()
{
return "jar-signature";
}
/* ------------------------------------------------------------ */
/**
* @param jar
* @return
*/
private List<JarEntry> resolveJar(JarFile jar)
{
List<JarEntry> entries = new ArrayList<JarEntry>();
Enumeration<JarEntry> e = jar.entries();
while (e.hasMoreElements())
{
JarEntry jarEntry = e.nextElement();
try
{
entries.add(jarEntry); // for further verification
IO.toString(jar.getInputStream(jar.getEntry(jarEntry.getName())));
}
catch (IOException e1)
{
throw new SecurityException(e1);
}
}
return entries;
}
/* ------------------------------------------------------------ */
/**
* Set the _keystore.
*
* @param keystore
* the _keystore to set
*/
public void setKeystoreLocation( String keyStoreLocation )
{
_keystoreLocation = keyStoreLocation;
}
@Override
public void initialize()
{
try
{
_keystore = KeyStore.getInstance(_type);
InputStream istream = new File( _keystoreLocation ).toURL().openStream();
_keystore.load(istream,null);
_trustedCertificates = new X509Certificate[]
{ (X509Certificate)_keystore.getCertificate(_alias) };
}
catch (Throwable t)
{
exception(_keystoreLocation, t.getMessage(), t);
}
}
public void setType(String type)
{
_type = type;
}
/**
* @see org.eclipse.jetty.webapp.verifier.Rule#visitWebInfLibJar(java.lang.String, java.io.File, java.util.jar.JarFile)
*/
@Override
public void visitWebInfLibJar(String path, File archive, JarFile jar)
{
try
{
if (jar.getManifest() == null)
{
error(jar.toString(),"missing manifest.mf, can not be signed");
}
List<JarEntry> entries = resolveJar(jar);
for (JarEntry jarEntry : entries)
{
if (!jarEntry.isDirectory() && !jarEntry.getName().startsWith("META-INF"))
{
Certificate[] certs = jarEntry.getCertificates();
if (certs == null || certs.length == 0)
{
error(jarEntry.getName(),"entry has not been signed");
}
else
{
X509Certificate[] chainRoots = getChainRoots(certs);
boolean signed = false;
for (int i = 0; i < chainRoots.length; i++)
{
if (isTrusted(chainRoots[i]))
{
signed = true;
break;
}
}
if (!signed)
{
error(jarEntry.getName(),"Untrusted provider's JAR");
}
}
}
}
}
catch (Exception e)
{
exception(jar.getName(), e.getMessage(), e);
}
}
private boolean isTrusted(X509Certificate certificate)
{
for (int i = 0; i < _trustedCertificates.length; i++)
{
if (certificate.getSubjectDN().equals(_trustedCertificates[i].getSubjectDN()))
{
if (certificate.equals(_trustedCertificates[i]))
{
return true;
}
}
}
for (int i = 0; i < _trustedCertificates.length; i++)
{
if (certificate.getIssuerDN().equals(_trustedCertificates[i].getSubjectDN()))
{
try
{
certificate.verify(_trustedCertificates[i].getPublicKey());
return true;
}
catch (Exception e)
{
}
}
}
return false;
}
/**
* Returns a array of certificates with the root certificate of each chain
*
* @param certificates an array of X509 certificate's
* @return an array of X509 certificate's with the root certificate of each chain
*/
private X509Certificate[] getChainRoots(Certificate[] certificates)
{
List<X509Certificate> chainRoots = new ArrayList<X509Certificate>();
for (int i = 0; i < certificates.length - 1; i++)
{
if (!((X509Certificate)certificates[i + 1]).getSubjectDN().equals(((X509Certificate)certificates[i]).getIssuerDN()))
{
chainRoots.add((X509Certificate)certificates[i]);
}
}
chainRoots.add((X509Certificate)certificates[certificates.length - 1]);
return chainRoots.toArray(new X509Certificate[chainRoots.size()]);
}
}

View File

@ -0,0 +1,166 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.jetty.webapp.verifier.AbstractArchiveScanningRule;
import org.eclipse.jetty.webapp.verifier.rules.asm.ASMUtil;
import org.eclipse.jetty.webapp.verifier.rules.asm.AbstractClassVisitor;
/**
* Ensure all compiled classes within webapp are within the supported JVM range.
*/
public class JavaSupportLevelRule extends AbstractArchiveScanningRule
{
class ClassVersionVisitor extends AbstractClassVisitor
{
private double classVersion = -1;
public double getClassVersion()
{
return classVersion;
}
@Override
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
this.classVersion = getJavaClassVersion(version);
}
private double getJavaClassVersion(int version)
{
int major = version & 0xFFFF;
int minor = version >>> 16;
// Java Versions to Class Version (major.minor)
// Java 1.6 = 50.0
// Java 1.5 = 49.0
// Java 1.4 = 48.0
// Java 1.3 = 47.0
// Java 1.2 = 46.0
// Java 1.1 = 45.3
// TODO: check these since they are > instead of >=
if (major >= 50)
{
return 1.6;
}
else if (major >= 49)
{
return 1.5;
}
else if (major >= 48)
{
return 1.4;
}
else if (major >= 47)
{
return 1.3;
}
else if (major >= 46)
{
return 1.2;
}
else if (major >= 45)
{
if (minor >= 3)
{
return 1.1;
}
return 1.0;
}
return 0.0;
}
public void reset()
{
this.classVersion = (-1);
}
}
private double supportedVersion = 1.5;
private ClassVersionVisitor visitor;
@Override
public String getDescription()
{
return "Ensure all compiled classes within webapp are within the supported JVM";
}
@Override
public String getName()
{
return "java-support-level";
}
public double getSupportedVersion()
{
return supportedVersion;
}
public void setSupportedVersion(double supportedVersion)
{
this.supportedVersion = supportedVersion;
}
@Override
public void visitWebappStart(String path, File dir)
{
visitor = new ClassVersionVisitor();
}
@Override
public void visitWebInfClass(String path, String className, File classFile)
{
try
{
visitor.reset();
ASMUtil.visitClassFile(classFile,visitor,0);
if (visitor.classVersion > supportedVersion)
{
error(path,"Class is compiled for java version [" + visitor.classVersion + "] which is over supported java version [" + supportedVersion + "]");
}
}
catch (IOException e)
{
exception(path,"Unable to read class",e);
}
}
@Override
public void visitArchiveClass(String path, String className, ZipFile archive, ZipEntry archiveEntry)
{
try
{
visitor.reset();
ASMUtil.visitClass(archive.getInputStream(archiveEntry),visitor,0);
if (visitor.classVersion > supportedVersion)
{
error(path,"Class is compiled for java version [" + visitor.classVersion + "] which is over supported java version [" + supportedVersion + "]");
}
}
catch (IOException e)
{
exception(path,"Unable to read class",e);
}
}
}

View File

@ -0,0 +1,43 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import org.eclipse.jetty.webapp.verifier.AbstractRule;
/**
* Perform a JSP pre-compile to ensure all JSPs are valid.
*/
public class JspPrecompileRule extends AbstractRule
{
public String getDescription()
{
return "Perform JSP precompile to ensure all jsps are valid";
}
public String getName()
{
return "jsp-precompile";
}
@Override
public void visitWebappStart(String path, File dir)
{
// TODO: implement rule.
error(path,"Rule [" + getClass().getName() + "] not yet implemented");
}
}

View File

@ -0,0 +1,43 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import org.eclipse.jetty.webapp.verifier.AbstractRule;
/**
* Ensure any included JSPs are supported by the Container.
*/
public class JspSupportLevelRule extends AbstractRule
{
public String getDescription()
{
return "Ensure include JSP are supported by the Container";
}
public String getName()
{
return "jsp-support-level";
}
@Override
public void visitWebappStart(String path, File dir)
{
// TODO: implement rule.
error(path,"Rule [" + getClass().getName() + "] not yet implemented");
}
}

View File

@ -0,0 +1,46 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import org.eclipse.jetty.webapp.verifier.AbstractRule;
/**
* Prevent inclusion of *.jsp in webapp.
*/
public class NoJspRule extends AbstractRule
{
public String getDescription()
{
return "Prevent inclusion of JSPs in webapp";
}
public String getName()
{
return "no-jsp";
}
@Override
public void visitFile(String path, File dir, File file)
{
String name = file.getName().toLowerCase();
if (name.endsWith(".jsp") || name.endsWith(".jspf"))
{
error(path,"No JSP's are allowed");
}
}
}

View File

@ -0,0 +1,68 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.jetty.webapp.verifier.AbstractArchiveScanningRule;
import org.eclipse.jetty.webapp.verifier.support.PathGlob;
/**
* Prevent use of native code in webapp.
*/
public class NoNativeRule extends AbstractArchiveScanningRule
{
private String[] nativePatterns =
{ "*.so", "*.so.*", "*.o", "*.dll", "*.com", "*.exe" };
@Override
public String getDescription()
{
return "Prevent use of native code in webapp";
}
@Override
public String getName()
{
return "no-native";
}
@Override
public void visitFile(String path, File dir, File file)
{
for (String pattern : nativePatterns)
{
if (PathGlob.match(pattern,path))
{
error(path,"Native code is forbidden");
}
}
}
@Override
public void visitArchiveResource(String path, ZipFile zip, ZipEntry entry)
{
for (String pattern : nativePatterns)
{
if (PathGlob.match(pattern,entry.getName()))
{
error(path,"Native code is forbidden");
}
}
}
}

View File

@ -0,0 +1,235 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.jetty.webapp.verifier.AbstractRule;
/**
* NoScriptingRule ensure that no scripting languages are used in the webapp.
*
* Checks for actual script files in webapp filesystem, and existance of popular scripting language libraries as well.
*/
public class NoScriptingRule extends AbstractRule
{
class Forbidden
{
public String key;
public String msg;
public Forbidden(String key, String msg)
{
super();
this.key = key;
this.msg = msg;
}
}
private boolean allowJRuby = false;
private boolean allowBeanshell = false;
private boolean allowGroovy = false;
private boolean allowJython = false;
private boolean allowShell = false;
private List<Forbidden> forbiddenFileExtensions = new ArrayList<Forbidden>();
private List<Forbidden> forbiddenClassIds = new ArrayList<Forbidden>();
public boolean isAllowShell()
{
return allowShell;
}
public void setAllowShell(boolean allowShell)
{
this.allowShell = allowShell;
}
public boolean isAllowJRuby()
{
return allowJRuby;
}
public void setAllowJRuby(boolean allowJruby)
{
this.allowJRuby = allowJruby;
}
public boolean isAllowBeanshell()
{
return allowBeanshell;
}
public void setAllowBeanshell(boolean allowBeanshell)
{
this.allowBeanshell = allowBeanshell;
}
public boolean isAllowGroovy()
{
return allowGroovy;
}
public void setAllowGroovy(boolean allowGroovy)
{
this.allowGroovy = allowGroovy;
}
public boolean isAllowJython()
{
return allowJython;
}
public void setAllowJython(boolean allowJython)
{
this.allowJython = allowJython;
}
public String getDescription()
{
return "Do not allow scripting languages in webapp";
}
public String getName()
{
return "forbidden-scripting";
}
@Override
public void initialize() throws Throwable
{
forbiddenFileExtensions.clear();
forbiddenClassIds.clear();
if (!allowJRuby)
{
String msg = "JRuby scripting not allowed";
forbiddenFileExtensions.add(new Forbidden(".rb",msg));
forbiddenFileExtensions.add(new Forbidden(".rhtml",msg));
msg = "JRuby dependencies are not allowed";
forbiddenClassIds.add(new Forbidden(".jruby.",msg));
}
if (!allowJython)
{
String msg = "Jython and Python scripting not allowed";
forbiddenFileExtensions.add(new Forbidden(".py",msg));
forbiddenFileExtensions.add(new Forbidden(".pyc",msg));
msg = "Jython dependencies are not allowed";
forbiddenClassIds.add(new Forbidden("org.python.",msg));
}
if (!allowGroovy)
{
String msg = "Groovy scripting not allowed";
forbiddenFileExtensions.add(new Forbidden(".groovy",msg));
msg = "Groovy dependencies are not allowed";
forbiddenClassIds.add(new Forbidden(".groovy.",msg));
}
if (!allowShell)
{
String msg = "Shell scripting not allowed";
forbiddenFileExtensions.add(new Forbidden(".sh",msg));
forbiddenFileExtensions.add(new Forbidden(".bat",msg));
forbiddenFileExtensions.add(new Forbidden(".cmd",msg));
forbiddenFileExtensions.add(new Forbidden(".vbs",msg));
}
}
@Override
public void visitFile(String path, File dir, File file)
{
String name = file.getName().toLowerCase();
for (Forbidden forbidden : forbiddenFileExtensions)
{
if (name.endsWith(forbidden.key))
{
error(path,forbidden.msg);
}
}
}
@Override
public void visitWebInfClass(String path, String className, File classFile)
{
validateClassname(path,className);
}
private void validateClassname(String path, String className)
{
for (Forbidden forbidden : forbiddenClassIds)
{
if (className.contains(forbidden.key))
{
error(path,forbidden.msg);
}
}
}
@Override
public void visitWebInfClassResource(String path, String resourcePath, File resourceFile)
{
super.visitWebInfClassResource(path,resourcePath,resourceFile);
}
@Override
public void visitWebInfLibJar(String path, File archive, JarFile jar)
{
iterateArchive(path,archive,jar);
}
private void iterateArchive(String path, File archive, ZipFile zip)
{
try
{
Enumeration<? extends ZipEntry> entries = zip.entries();
while (entries.hasMoreElements())
{
ZipEntry entry = entries.nextElement();
if (entry.getName().endsWith(".class"))
{
checkArchiveClassname(path,archive,entry.getName());
}
}
}
catch (Throwable t)
{
exception(path,"Unable to iterate archive: Contents invalid?: " + t.getMessage(),t);
}
}
private void checkArchiveClassname(String path, File archive, String name)
{
String className = name.replace("/",".");
if (className.endsWith(".class"))
{
className = className.substring(0,className.length() - 6);
}
validateClassname(path + "!/" + name,className);
}
@Override
public void visitWebInfLibZip(String path, File archive, ZipFile zip)
{
iterateArchive(path,archive,zip);
}
}

View File

@ -0,0 +1,151 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.jetty.webapp.verifier.AbstractArchiveScanningRule;
/**
* Prevent inclusion of Source Control files & directories that might reveal hostnames, userids, and passwords to the
* source control. (CVS, .svn/, .git/)
*/
public class NoSourceControlRule extends AbstractArchiveScanningRule
{
class ScmName
{
String scm;
String name;
public ScmName(String scm, String name)
{
this.scm = scm;
this.name = name;
}
}
private static List<ScmName> scmDirNames = new ArrayList<ScmName>();
private static List<ScmName> scmFileNames = new ArrayList<ScmName>();
public NoSourceControlRule()
{
super();
// The order of patterns is most likely to least likely
scmDirNames.add(new ScmName("Subversion",".svn")); // Standard Unix format
scmDirNames.add(new ScmName("Subversion","_svn")); // Alternate Windows format
scmDirNames.add(new ScmName("CVS","CVS"));
scmFileNames.add(new ScmName("CVS",".cvsignore"));
scmDirNames.add(new ScmName("Git",".git"));
scmFileNames.add(new ScmName("Git",".gitignore"));
scmDirNames.add(new ScmName("RCS","RCS"));
scmDirNames.add(new ScmName("SCCS","SCCS"));
scmFileNames.add(new ScmName("Visual SourceSafe","vssver.scc"));
scmDirNames.add(new ScmName("Arch",".arch-ids"));
scmDirNames.add(new ScmName("Bazaar",".bzr"));
scmFileNames.add(new ScmName("SurroundSCM",".MySCMServerInfo"));
scmDirNames.add(new ScmName("Mercurial",".hg"));
scmDirNames.add(new ScmName("BitKeeper","BitKeeper"));
scmDirNames.add(new ScmName("BitKeeper","ChangeSet"));
scmDirNames.add(new ScmName("Darcs","_darcs"));
scmDirNames.add(new ScmName("Darcs",".darcsrepo"));
scmFileNames.add(new ScmName("Darcs",".darcs-temp-mail"));
}
@Override
public String getDescription()
{
return "Prevent inclusion of source control files in webapp";
}
@Override
public String getName()
{
return "no-source-control";
}
@Override
public void visitDirectoryStart(String path, File dir)
{
for (ScmName scmName : scmDirNames)
{
if (dir.getName().equalsIgnoreCase(scmName.name))
{
error(path,scmName.scm + " Source Control directories are not allowed");
}
}
}
@Override
public void visitFile(String path, File dir, File file)
{
for (ScmName scmName : scmFileNames)
{
if (file.getName().equalsIgnoreCase(scmName.name))
{
error(path,scmName.scm + " Source Control file are not allowed");
}
}
}
@Override
public void visitArchiveResource(String path, ZipFile zip, ZipEntry entry)
{
String basename = toBaseName(entry);
if (entry.isDirectory())
{
for (ScmName scmName : scmDirNames)
{
if (basename.equalsIgnoreCase(scmName.name))
{
error(path,scmName.scm + " Source Control directories are not allowed");
}
}
}
else
{
for (ScmName scmName : scmFileNames)
{
if (basename.equalsIgnoreCase(scmName.name))
{
error(path,scmName.scm + " Source Control file are not allowed");
}
}
}
}
private String toBaseName(ZipEntry entry)
{
String name =entry.getName();
if (name.endsWith("/"))
{
name = name.substring(0,name.length() - 1);
}
int idx = name.lastIndexOf('/');
if (idx >= 0)
{
return name.substring(idx + 1);
}
return name;
}
}

View File

@ -0,0 +1,70 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.eclipse.jetty.webapp.verifier.AbstractArchiveScanningRule;
import org.eclipse.jetty.webapp.verifier.support.PathGlob;
/**
* <p>
* Prevent inclusion of source files in webapp. (*.java)
* </p>
*/
public class NoSourceRule extends AbstractArchiveScanningRule
{
private String[] sourcePatterns =
{ "*.java" };
@Override
public String getDescription()
{
return "Prevent inclusion of source files in webapp";
}
@Override
public String getName()
{
return "no-source";
}
@Override
public void visitFile(String path, File dir, File file)
{
for (String pattern : sourcePatterns)
{
if (PathGlob.match(pattern,path))
{
error(path,"Source code is forbidden");
}
}
}
@Override
public void visitArchiveResource(String path, ZipFile zip, ZipEntry entry)
{
for (String pattern : sourcePatterns)
{
if (PathGlob.match(pattern,entry.getName()))
{
error(path,"Source code is forbidden");
}
}
}
}

View File

@ -0,0 +1,64 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.eclipse.jetty.webapp.verifier.AbstractRule;
/**
* ForbiddenContentsVerifier ensures that content matching a pattern does not exist in the webapp.
*/
public class RequiredContentsRule extends AbstractRule
{
private List<String> _paths = new ArrayList<String>();
public void addPath(String path)
{
_paths.add(path);
}
public String getDescription()
{
return "Ensures that requred content is present";
}
public String getName()
{
return "required-content";
}
@Override
public void visitDirectoryEnd(String path, File dir)
{
if (path.equals(ROOT_PATH))
{
File root = new File(path);
for (String expectedPath : _paths)
{
File file = new File(root,expectedPath);
if (!file.exists())
{
error(getWebappRelativePath(file),"Required content not found");
}
}
}
}
}

View File

@ -0,0 +1,59 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import org.eclipse.jetty.webapp.verifier.AbstractRule;
/**
* <p>
* Sanity check of archive (both war itself, as well as libs) to ensure that various entries within are sane.
* </p>
*
* <p>
* Example checks:
* </p>
*
* <ol>
* <li>Entries cannot contain references to parent "../../my_file.txt"</li>
* <li>Cannot contain multiple entries of the same name with different case.
* <ul>
* <li>/index.jsp</li>
* <li>/Index.jsp</li>
* </ul>
* <li>
* </ol>
*/
public class SaneArchiveRule extends AbstractRule
{
public String getDescription()
{
return "Basic archive (jar & war) sanity checks";
}
public String getName()
{
return "sane-archive";
}
@Override
public void visitWebappStart(String path, File dir)
{
// TODO: implement rule.
error(path,"Rule [" + getClass().getName() + "] not yet implemented");
}
}

View File

@ -0,0 +1,374 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.eclipse.jetty.webapp.verifier.AbstractRule;
import org.w3c.dom.Document;
import org.w3c.dom.DocumentType;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;
/**
* Ensure declared servlet level (servlet spec version) in webapp conforms to supported level.
*/
public class ServletSupportLevelRule extends AbstractRule
{
private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance";
class ServletId
{
String version;
String name;
String type;
public ServletId(String version, String type, String name)
{
super();
this.version = version;
this.type = type;
this.name = name;
}
}
private String supportedVersion = "2.5";
private String fileSep = System.getProperty("file.separator","/");
private List<ServletId> dtdPublicIds = new ArrayList<ServletId>();
private List<ServletId> dtdSystemIds = new ArrayList<ServletId>();
private List<ServletId> nsIds = new ArrayList<ServletId>();
private List<ServletId> schemaIds = new ArrayList<ServletId>();
private String validVersions[] =
{ "2.5", "2.4", "2.3", "2.2" };
public ServletSupportLevelRule()
{
// Servlet 2.5
schemaIds.add(new ServletId("2.5","Schema","http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/j2ee/web-app_2_5.xsd"));
nsIds.add(new ServletId("2.5","XML Namespace","http://java.sun.com/xml/ns/javaee"));
// Servlet 2.4
schemaIds.add(new ServletId("2.4","Schema","http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd"));
nsIds.add(new ServletId("2.4","XML Namespace","http://java.sun.com/xml/ns/j2ee"));
// Servlet 2.3
dtdPublicIds.add(new ServletId("2.3","DOCTYPE Public ID","-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"));
dtdSystemIds.add(new ServletId("2.3","DOCTYPE System ID","http://java.sun.com/dtd/web-app_2_3.dtd"));
// Servlet 2.2
dtdPublicIds.add(new ServletId("2.2","DOCTYPE Public ID","-//Sun Microsystems, Inc.//DTD WebApplication 2.2//EN"));
dtdSystemIds.add(new ServletId("2.2","DOCTYPE System ID","http://java.sun.com/j2ee/dtds/web-app_2.2.dtd"));
}
public String getDescription()
{
return "Ensure webapp works within supported servlet spec";
}
public String getName()
{
return "servlet-support-level";
}
public String getSupportedVersion()
{
return supportedVersion;
}
public void setSupportedVersion(String supportedLevel)
{
this.supportedVersion = supportedLevel;
}
@Override
public void visitWebappStart(String path, File dir)
{
super.visitWebappStart(path,dir);
File webXmlFile = new File(dir,"WEB-INF/web.xml".replaceAll("/",fileSep));
String webxmlpath = getWebappRelativePath(webXmlFile);
if (!webXmlFile.exists())
{
error(webxmlpath,"web.xml does not exist");
return;
}
// Using JAXP to parse the web.xml (SAX pls)
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false);
factory.setNamespaceAware(true);
try
{
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parse(webXmlFile);
List<ServletId> detectedIds = collectServletIds(webxmlpath,doc);
Set<String> versions = new TreeSet<String>();
for (ServletId id : detectedIds)
{
versions.add(id.version);
}
if (versions.size() > 1)
{
String msg = String.format("Found %d versions defined [%s], expected 1",versions.size(),join(versions,", "));
error(webxmlpath,msg);
for (ServletId id : detectedIds)
{
reportConflicting(webxmlpath,id,detectedIds);
}
}
reportOverVersion(webxmlpath,detectedIds);
}
catch (ParserConfigurationException e)
{
exception(webxmlpath,"[internal] Unable to establish XML parser",e);
}
catch (SAXException e)
{
exception(webxmlpath,"Unable to parse web.xml",e);
}
catch (IOException e)
{
exception(webxmlpath,"Unable to parse web.xml",e);
}
}
private void reportOverVersion(String webxmlpath, List<ServletId> detectedIds)
{
double supportedVer = Double.parseDouble(this.supportedVersion);
for (ServletId id : detectedIds)
{
try
{
double detectedVersion = Double.parseDouble(id.version);
if (detectedVersion > supportedVer)
{
String msg = String.format("Specified servlet version %s of %s is over the configured supported servlet version %s",id.version,id.type,
supportedVersion);
error(webxmlpath,msg);
}
}
catch (NumberFormatException e)
{
error(webxmlpath,String.format("Unable to parse version [%s] of %s, not a double",id.version,id.type));
}
}
}
private void reportConflicting(String webxmlpath, ServletId mainId, List<ServletId> otherIds)
{
for (ServletId id : otherIds)
{
if (id.version.equals(mainId.version) == false)
{
String msg = String.format("version %s of %s conflicts with version %s of %s",mainId.version,mainId.type,id.version,id.type);
error(webxmlpath,msg);
}
}
}
private String join(Collection<?> coll, String delim)
{
StringBuffer msg = new StringBuffer();
Iterator<?> it = coll.iterator();
while (it.hasNext())
{
msg.append(String.valueOf(it.next()));
if (it.hasNext())
{
msg.append(delim);
}
}
return msg.toString();
}
private List<ServletId> collectServletIds(String webxmlpath, Document doc)
{
List<ServletId> ids = new ArrayList<ServletId>();
// Check for DOCTYPE defined ids.
DocumentType doctype = doc.getDoctype();
if (doctype != null)
{
if ("web-app".equals(doctype.getName()))
{
boolean valid = false;
for (ServletId id : dtdPublicIds)
{
if (id.name.equals(doctype.getPublicId()))
{
ids.add(id);
valid = true;
}
}
if (!valid)
{
error(webxmlpath,"Invalid DOCTYPE public ID: " + doctype.getPublicId());
}
valid = false;
for (ServletId id : dtdSystemIds)
{
if (id.name.equals(doctype.getSystemId()))
{
ids.add(id);
valid = true;
}
}
if (!valid)
{
error(webxmlpath,"Invalid DOCTYPE system ID: " + doctype.getSystemId());
}
}
else
{
error(webxmlpath,"Invalid DOCTYPE detected, expected 'web-app', but found '" + doctype.getName() + "' instaed.");
}
}
// Check for Root Element Namespace ids.
Element root = doc.getDocumentElement();
if ("web-app".equals(root.getTagName()))
{
String actualXmlNs = root.getAttribute("xmlns");
String actualXsi = root.getAttribute("xmlns:xsi");
String actualSchema = root.getAttribute("xsi:schemaLocation");
String actualVersion = root.getAttribute("version");
if (hasAnyValue(actualXmlNs,actualXsi,actualSchema,actualVersion))
{
if ((actualXmlNs == null) || (actualXmlNs == ""))
{
error(webxmlpath,"Attribute <web-app xmlns=\"\"> must exist with a valid value");
}
else
{
boolean valid = false;
for (ServletId id : nsIds)
{
if (id.name.equals(actualXmlNs))
{
ids.add(id);
valid = true;
}
}
if (!valid)
{
String msg = String.format("Invalid xmlns value for <web-app xmlns=\"%s\">",actualXmlNs);
error(webxmlpath,msg);
}
}
if ((actualXsi == null) || (actualXsi == ""))
{
error(webxmlpath,"Attribute <web-app xmlns:xsi=\"\"> must exist with a valid value");
}
else if (!XSI_NS.equals(actualXsi))
{
String msg = String.format("Attribute mismatch expecting <web-app xmlns:xsi=\"%s\"> but found <web-app xmlns:xsi=\"%s\">",XSI_NS,actualXsi);
error(webxmlpath,msg);
}
if ((actualSchema == null) || (actualSchema == ""))
{
error(webxmlpath,"Attribute <web-app xsi:schemaLocation=\"\"> must exist with a valid value");
}
else
{
boolean valid = false;
for (ServletId id : schemaIds)
{
if (id.name.equals(actualSchema))
{
ids.add(id);
valid = true;
}
}
if (!valid)
{
String msg = String.format("Invalid schemaLocation value <web-app xsi:schemaLocation=\"%s\">",actualSchema);
error(webxmlpath,msg);
}
}
if ((actualVersion == null) || (actualVersion == ""))
{
error(webxmlpath,"Attribute <web-app version=\"\"> must exist with a valid value");
}
else
{
boolean valid = false;
for (String version : validVersions)
{
if (version.equals(actualVersion))
{
ids.add(new ServletId(version,"version attribute",null));
valid = true;
}
}
if (!valid)
{
String msg = String.format("Invalid version value <web-app version=\"%s\">",actualVersion);
error(webxmlpath,msg);
}
}
}
}
else
{
error(webxmlpath,"Invalid web.xml, root element expectd to be <web-app>, but was <" + root.getTagName() + ">");
}
return ids;
}
private boolean hasAnyValue(String... values)
{
for (String value : values)
{
if ((value != null) && (value.length() > 0))
{
return true;
}
}
return false;
}
}

View File

@ -0,0 +1,54 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules.asm;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.jetty.util.IO;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
/**
* Some simple utility methods for working with ASM in a common way.
*/
public class ASMUtil
{
public static void visitClassFile(File classFile, ClassVisitor visitor, int flags) throws IOException
{
FileInputStream fin = null;
ClassReader creader = null;
try
{
fin = new FileInputStream(classFile);
creader = new ClassReader(fin);
creader.accept(visitor,flags);
}
finally
{
IO.close(fin);
}
}
public static void visitClass(InputStream stream, ClassVisitor visitor, int flags) throws IOException
{
ClassReader creader = new ClassReader(stream);
creader.accept(visitor,flags);
}
}

View File

@ -0,0 +1,77 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.rules.asm;
import org.objectweb.asm.AnnotationVisitor;
import org.objectweb.asm.Attribute;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.FieldVisitor;
import org.objectweb.asm.MethodVisitor;
/**
* Abstact implementation of {@link ClassVisitor} to make asm use within Rules easier.
*/
public abstract class AbstractClassVisitor implements ClassVisitor
{
public void visit(int version, int access, String name, String signature, String superName, String[] interfaces)
{
/* Override Ready */
}
public AnnotationVisitor visitAnnotation(String desc, boolean visible)
{
/* Override Ready */
return null;
}
public void visitAttribute(Attribute attr)
{
/* Override Ready */
}
public void visitEnd()
{
/* Override Ready */
}
public FieldVisitor visitField(int access, String name, String desc, String signature, Object value)
{
/* Override Ready */
return null;
}
public void visitInnerClass(String name, String outerName, String innerName, int access)
{
/* Override Ready */
}
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions)
{
/* Override Ready */
return null;
}
public void visitOuterClass(String owner, String name, String desc)
{
/* Override Ready */
}
public void visitSource(String source, String debug)
{
/* Override Ready */
}
}

View File

@ -0,0 +1,58 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.webapp.verifier.support;
public class PathGlob
{
/**
* @return true if match.
*/
public static boolean match(String pathSpec, String path) throws IllegalArgumentException
{
return match(pathSpec,path,false);
}
/**
* @return true if match.
*/
public static boolean match(String pathSpec, String path, boolean noDefault) throws IllegalArgumentException
{
char c = pathSpec.charAt(0);
if (c == '/')
{
if (!noDefault && pathSpec.length() == 1 || pathSpec.equals(path))
return true;
if (isPathWildcardMatch(pathSpec,path))
return true;
}
else if (c == '*')
return path.regionMatches(path.length() - pathSpec.length() + 1,pathSpec,1,pathSpec.length() - 1);
return false;
}
private static boolean isPathWildcardMatch(String pathSpec, String path)
{
// For a spec of "/foo/*" match "/foo" , "/foo/..." but not "/foobar"
int cpl = pathSpec.length() - 2;
if (pathSpec.endsWith("/*") && path.regionMatches(0,pathSpec,0,cpl))
{
if (path.length() == cpl || '/' == path.charAt(cpl))
return true;
}
return false;
}
}

View File

@ -0,0 +1,11 @@
target/
.classpath
.project
.settings/
*.tar.gz
*.zip
bsh*
jruby*
jython*
groovy*
*.swp

View File

@ -0,0 +1,8 @@
target/
.classpath
.project
.settings
*.swp
*.log
*.patch
*.diff

View File

@ -0,0 +1,9 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-groovy-lib</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Jetty :: Webapp Verifier :: Dummy Groovy Lib</name>
</project>

View File

@ -0,0 +1 @@
org.codehaus.groovy.jsr223.GroovyScriptEngineFactory

View File

@ -0,0 +1,4 @@
This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/
It is neither a valid JAR file, nor contains valid Groovy implementations,
in either scripting, source or binary form.

View File

@ -0,0 +1,8 @@
target/
.classpath
.project
.settings
*.swp
*.log
*.patch
*.diff

View File

@ -0,0 +1,22 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-groovy-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Jetty :: Webapp Verifier :: Dummy Groovy Webapp</name>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-groovy-lib</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,4 @@
This is a webapp is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/
It is neither a valid WAR file, nor contains valid Groovy implementations,
in either scripting, source or binary form.

View File

@ -0,0 +1,7 @@
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>

View File

@ -0,0 +1,8 @@
target/
.classpath
.project
.settings
*.swp
*.log
*.patch
*.diff

View File

@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java11-lib</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Jetty :: Webapp Verifier :: Dummy Java1.1 Lib</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<target>1.1</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,27 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.testcase.verifier;
/**
* Dummy class for testcase purposes.
*/
public class DummyLib
{
public void dummyTestClassNotIntendedForUse()
{
/* not intended for use - only used for test case purposes */
}
}

View File

@ -0,0 +1,3 @@
This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/
This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases.

View File

@ -0,0 +1,8 @@
target/
.classpath
.project
.settings
*.swp
*.log
*.patch
*.diff

View File

@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java12-lib</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Jetty :: Webapp Verifier :: Dummy Java1.2 Lib</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<target>1.2</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,27 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.testcase.verifier;
/**
* Dummy class for testcase purposes.
*/
public class DummyUpdatedLib
{
public void dummyTestClassNotIntendedForUse()
{
/* not intended for use - only used for test case purposes */
}
}

View File

@ -0,0 +1,3 @@
This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/
This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases.

View File

@ -0,0 +1,8 @@
target/
.classpath
.project
.settings
*.swp
*.log
*.patch
*.diff

View File

@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java13-lib</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Jetty :: Webapp Verifier :: Dummy Java1.3 Lib</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<target>1.3</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,27 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.testcase.verifier;
/**
* Dummy class for testcase purposes.
*/
public class DummyCurrentLib
{
public void dummyTestClassNotIntendedForUse()
{
/* not intended for use - only used for test case purposes */
}
}

View File

@ -0,0 +1,3 @@
This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/
This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases.

View File

@ -0,0 +1,8 @@
target/
.classpath
.project
.settings
*.swp
*.log
*.patch
*.diff

View File

@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java14-lib</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Jetty :: Webapp Verifier :: Dummy Java1.4 Lib</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<target>1.4</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,27 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.testcase.verifier;
/**
* Dummy class for testcase purposes.
*/
public class DummyFreshLib
{
public void dummyTestClassNotIntendedForUse()
{
/* not intended for use - only used for test case purposes */
}
}

View File

@ -0,0 +1,3 @@
This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/
This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases.

View File

@ -0,0 +1,8 @@
target/
.classpath
.project
.settings
*.swp
*.log
*.patch
*.diff

View File

@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java15-lib</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Jetty :: Webapp Verifier :: Dummy Java1.5 Lib</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,27 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.testcase.verifier;
/**
* Dummy class for testcase purposes.
*/
public class DummyLatestLib
{
public void dummyTestClassNotIntendedForUse()
{
/* not intended for use - only used for test case purposes */
}
}

View File

@ -0,0 +1,3 @@
This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/
This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases.

View File

@ -0,0 +1,8 @@
target/
.classpath
.project
.settings
*.swp
*.log
*.patch
*.diff

View File

@ -0,0 +1,20 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java16-lib</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>Jetty :: Webapp Verifier :: Dummy Java1.6 Lib</name>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@ -0,0 +1,27 @@
// ========================================================================
// Copyright (c) Webtide LLC
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
//
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
//
// The Apache License v2.0 is available at
// http://www.apache.org/licenses/LICENSE-2.0.txt
//
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.testcase.verifier;
/**
* Dummy class for testcase purposes.
*/
public class DummyModernLib
{
public void dummyTestClassNotIntendedForUse()
{
/* not intended for use - only used for test case purposes */
}
}

View File

@ -0,0 +1,3 @@
This dummy lib is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/
This JAR file is not for use outside of the /jetty-webapp-verifier/ test cases.

View File

@ -0,0 +1,8 @@
target/
.classpath
.project
.settings
*.swp
*.log
*.patch
*.diff

View File

@ -0,0 +1,84 @@
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-javaversions-webapp</artifactId>
<packaging>war</packaging>
<version>1.0-SNAPSHOT</version>
<name>Jetty :: Webapp Verifier :: Dummy Java Versions Webapp</name>
<dependencies>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java11-lib</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java12-lib</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java13-lib</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java14-lib</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java15-lib</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.eclipse.jetty.tests</groupId>
<artifactId>dummy-java16-lib</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<executions>
<execution>
<id>explode-jars-to-classes</id>
<phase>process-resources</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<includes>**/*.class</includes>
<outputDirectory>${project.build.directory}/${project.artifactId}-${project.version}/WEB-INF/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
<!--
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-unpacked</id>
<phase>process-resources</phase>
<goals>
<goal>add-resource</goal>
</goals>
<configuration>
<resources>
<resource>
<directory>${project.build.directory}/dependencies</directory>
</resource>
</resources>
</configuration>
</execution>
</executions>
</plugin>
-->
</plugins>
</build>
</project>

View File

@ -0,0 +1,4 @@
This is a webapp is a TEST RESOURCE, used by the jetty project at http://www.eclipse.org/jetty/
It is neither a valid WAR file, nor contains valid JRuby implementations,
in either scripting, source or binary form.

View File

@ -0,0 +1,7 @@
<!DOCTYPE web-app PUBLIC
"-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
"http://java.sun.com/dtd/web-app_2_3.dtd" >
<web-app>
<display-name>Archetype Created Web Application</display-name>
</web-app>

Some files were not shown because too many files have changed in this diff Show More