SEC-2208: Use std docbook plugin and workspace cleanup

This commit is contained in:
Rob Winch 2013-07-16 14:34:46 -05:00
parent 7d9f0d688a
commit 955a60cf49
8 changed files with 88 additions and 406 deletions

View File

@ -1,3 +1,4 @@
import sun.awt.geom.AreaOp.IntOp;
import groovy.text.SimpleTemplateEngine
buildscript {
@ -6,6 +7,7 @@ buildscript {
}
dependencies {
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.3")
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.7")
classpath("org.springframework.build.gradle:bundlor-plugin:0.1.2")
}
}
@ -22,7 +24,8 @@ allprojects {
group = 'org.springframework.security'
repositories {
maven { url "http://repo.springsource.org/plugins-release" }
maven { url "http://repo.springsource.org/libs-release" }
maven { url "http://repo.springsource.org/plugins-release" }
}
}
@ -57,7 +60,7 @@ configure(subprojects - coreModuleProjects) {
configure(javaProjects) {
apply from: "$rootDir/gradle/javaprojects.gradle"
apply from: "$rootDir/gradle/release-checks.gradle"
apply from: "$rootDir/gradle/maven-deployment.gradle"
apply from: "$rootDir/gradle/maven-deployment.gradle"
}
configure(coreModuleProjects) {
@ -94,7 +97,7 @@ task coreBuild {
// Task for creating the distro zip
task dist(type: Zip) {
dependsOn subprojects*.tasks*.matching { task -> task.name == 'assemble' || task.name.endsWith('Zip') }
dependsOn subprojects*.tasks*.matching { task -> task.name == 'assemble' || task.name.endsWith('Zip') || task.name.endsWith('generatePom') }
classifier = 'dist'
evaluationDependsOn(':docs')
@ -110,8 +113,14 @@ task dist(type: Zip) {
}
into('dist') {
from coreModuleProjects.collect {project -> project.libsDir }
from project(':spring-security-samples-tutorial').libsDir
from project(':spring-security-samples-contacts').libsDir
}
sampleProjects.each { project->
into("$zipRootDir/samples/$project.name") {
from(project.projectDir) {
include "src/main/**"
include "pom.xml"
}
}
}
}
}

View File

@ -12,28 +12,6 @@ repositories {
}
}
// Docbook Plugin
dependencies {
def fopDeps = [ 'org.apache.xmlgraphics:fop:0.95-1@jar',
'org.apache.xmlgraphics:xmlgraphics-commons:1.3',
'org.apache.xmlgraphics:batik-bridge:1.7@jar',
'org.apache.xmlgraphics:batik-util:1.7@jar',
'org.apache.xmlgraphics:batik-css:1.7@jar',
'org.apache.xmlgraphics:batik-dom:1.7',
'org.apache.xmlgraphics:batik-svg-dom:1.7@jar',
'org.apache.avalon.framework:avalon-framework-api:4.3.1']
groovy localGroovy()
compile gradleApi(),
'xml-resolver:xml-resolver:1.2',
'xerces:xercesImpl:2.9.1',
'saxon:saxon:6.5.3',
'net.java.dev.jets3t:jets3t:0.6.1',
fopDeps
runtime 'net.sf.xslthl:xslthl:2.0.1',
'net.sf.docbook:docbook-xsl:1.75.2:ns-resources@zip'
}
// GAE
dependencies {
compile 'com.google.appengine:appengine-tools-sdk:1.4.2'

View File

@ -1,301 +0,0 @@
package docbook;
import org.gradle.api.Plugin;
import org.gradle.api.GradleException;
import org.gradle.api.DefaultTask;
import org.gradle.api.Task;
import org.gradle.api.Project;
import org.gradle.api.Action;
import org.gradle.api.tasks.*;
import org.gradle.api.file.FileCollection;
import org.xml.sax.XMLReader;
import org.xml.sax.InputSource;
import org.apache.xml.resolver.CatalogManager;
import org.apache.xml.resolver.tools.CatalogResolver;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.*;
import javax.xml.transform.sax.SAXSource;
import javax.xml.transform.sax.SAXResult;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.*;
import java.util.*;
import java.util.zip.*;
import java.net.*;
import org.apache.fop.apps.*;
import com.icl.saxon.TransformerFactoryImpl;
/**
* Gradle Docbook plugin implementation.
* <p>
* Creates three tasks: docbookHtml, docbookHtmlSingle and docbookPdf. Each task takes a single File on
* which it operates.
*/
class DocbookPlugin implements Plugin<Project> {
public void apply(Project project) {
// Add the plugin tasks to the project
Task docbookHtml = project.tasks.add('docbookHtml', DocbookHtml.class);
docbookHtml.setDescription('Generates chunked docbook html output');
Task docbookHtmlSingle = project.tasks.add('docbookHtmlSingle', Docbook.class);
docbookHtmlSingle.setDescription('Generates single page docbook html output')
docbookHtmlSingle.suffix = '-single'
Task docbookFoPdf = project.tasks.add("docbookFoPdf", DocbookFoPdf.class);
docbookFoPdf.setDescription('Generates PDF output');
docbookFoPdf.extension = 'fo'
Task docbook = project.tasks.add("docbook", DefaultTask.class);
docbook.dependsOn (docbookHtml, docbookHtmlSingle, docbookFoPdf)
}
}
/**
*/
public class Docbook extends DefaultTask {
@Input
String extension = 'html';
@Input
String suffix = '';
@Input
boolean XIncludeAware = true;
@Input
boolean highlightingEnabled = true;
String admonGraphicsPath;
String imgSrcPath;
@InputDirectory
File sourceDirectory = new File(project.getProjectDir(), "src/docbook");
@Input
String sourceFileName;
@InputFile
File stylesheet;
@OutputDirectory
File docsDir = new File(project.getBuildDir(), "docs");
@TaskAction
public final void transform() {
SAXParserFactory factory = new org.apache.xerces.jaxp.SAXParserFactoryImpl();
factory.setXIncludeAware(XIncludeAware);
docsDir.mkdirs();
File srcFile = new File(filterDocbookSources(sourceDirectory), sourceFileName);
String outputFilename = srcFile.getName().substring(0, srcFile.getName().length() - 4) + suffix + '.' + extension;
File outputFile = new File(getDocsDir(), outputFilename);
Result result = new StreamResult(outputFile.getAbsolutePath());
CatalogResolver resolver = new CatalogResolver(createCatalogManager());
InputSource inputSource = new InputSource(srcFile.getAbsolutePath());
XMLReader reader = factory.newSAXParser().getXMLReader();
reader.setEntityResolver(resolver);
TransformerFactory transformerFactory = new TransformerFactoryImpl();
transformerFactory.setURIResolver(resolver);
URL url = stylesheet.toURL();
Source source = new StreamSource(url.openStream(), url.toExternalForm());
Transformer transformer = transformerFactory.newTransformer(source);
if (highlightingEnabled) {
File highlightingDir = new File(getProject().getBuildDir(), "highlighting");
if (!highlightingDir.exists()) {
highlightingDir.mkdirs();
extractHighlightFiles(highlightingDir);
}
transformer.setParameter("highlight.xslthl.config", new File(highlightingDir, "xslthl-config.xml").toURI().toURL());
}
if (admonGraphicsPath != null) {
transformer.setParameter("admon.graphics", "1");
transformer.setParameter("admon.graphics.path", admonGraphicsPath);
}
if (imgSrcPath != null) {
transformer.setParameter("img.src.path", imgSrcPath);
}
preTransform(transformer, srcFile, outputFile);
transformer.transform(new SAXSource(reader, inputSource), result);
postTransform(outputFile);
}
/**
* @param sourceDir directory of unfiltered sources
* @return directory of filtered sources
* @author Chris Beams
*/
private File filterDocbookSources(File sourceDir) {
def docbookWorkDir = new File("${project.buildDir}/reference-work")
docbookWorkDir.mkdirs()
// copy everything but springsecurity.xml
project.copy {
into(docbookWorkDir)
from(sourceDir) { exclude '**/springsecurity.xml' }
}
// copy index.xml and expand ${...} variables along the way
// e.g.: ${version} needs to be replaced in the header
project.copy {
into(docbookWorkDir)
from(sourceDir) { include '**/springsecurity.xml' }
expand(version: "${project.version}")
}
return docbookWorkDir
}
private void extractHighlightFiles(File toDir) {
URLClassLoader cl = (URLClassLoader) getClass().getClassLoader();
URL[] urls = cl.getURLs();
URL docbookZip = null;
for (URL url : urls) {
if (url.toString().contains("docbook-xsl-")) {
docbookZip = url;
break;
}
}
if (docbookZip == null) {
throw new GradleException("Docbook zip file not found");
}
ZipFile zipFile = new ZipFile(new File(docbookZip.toURI()));
Enumeration e = zipFile.entries();
while (e.hasMoreElements()) {
ZipEntry ze = (ZipEntry) e.nextElement();
if (ze.getName().matches(".*/highlighting/.*\\.xml")) {
String filename = ze.getName().substring(ze.getName().lastIndexOf("/highlighting/") + 14);
copyFile(zipFile.getInputStream(ze), new File(toDir, filename));
}
}
}
private void copyFile(InputStream source, File destFile) {
destFile.createNewFile();
FileOutputStream to = null;
try {
to = new FileOutputStream(destFile);
byte[] buffer = new byte[4096];
int bytesRead;
while ((bytesRead = source.read(buffer)) > 0) {
to.write(buffer, 0, bytesRead);
}
} finally {
if (source != null) {
source.close();
}
if (to != null) {
to.close();
}
}
}
protected void preTransform(Transformer transformer, File sourceFile, File outputFile) {
}
protected void postTransform(File outputFile) {
}
private CatalogManager createCatalogManager() {
CatalogManager manager = new CatalogManager();
manager.setIgnoreMissingProperties(true);
ClassLoader classLoader = this.getClass().getClassLoader();
StringBuilder builder = new StringBuilder();
String docbookCatalogName = "docbook/catalog.xml";
URL docbookCatalog = classLoader.getResource(docbookCatalogName);
if (docbookCatalog == null) {
throw new IllegalStateException("Docbook catalog " + docbookCatalogName + " could not be found in " + classLoader);
}
builder.append(docbookCatalog.toExternalForm());
Enumeration enumeration = classLoader.getResources("/catalog.xml");
while (enumeration.hasMoreElements()) {
builder.append(';');
URL resource = (URL) enumeration.nextElement();
builder.append(resource.toExternalForm());
}
String catalogFiles = builder.toString();
manager.setCatalogFiles(catalogFiles);
return manager;
}
}
/**
*/
class DocbookHtml extends Docbook {
@Override
protected void preTransform(Transformer transformer, File sourceFile, File outputFile) {
String rootFilename = outputFile.getName();
rootFilename = rootFilename.substring(0, rootFilename.lastIndexOf('.'));
transformer.setParameter("root.filename", rootFilename);
transformer.setParameter("base.dir", outputFile.getParent() + File.separator);
}
}
/**
*/
class DocbookFoPdf extends Docbook {
/**
* <a href="http://xmlgraphics.apache.org/fop/0.95/embedding.html#render">From the FOP usage guide</a>
*/
@Override
protected void postTransform(File foFile) {
FopFactory fopFactory = FopFactory.newInstance();
OutputStream out = null;
final File pdfFile = getPdfOutputFile(foFile);
logger.debug("Transforming 'fo' file "+ foFile + " to PDF: " + pdfFile);
try {
out = new BufferedOutputStream(new FileOutputStream(pdfFile));
Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);
TransformerFactory factory = TransformerFactory.newInstance();
Transformer transformer = factory.newTransformer();
Source src = new StreamSource(foFile);
Result res = new SAXResult(fop.getDefaultHandler());
transformer.transform(src, res);
} finally {
if (out != null) {
out.close();
}
}
/* if (!foFile.delete()) {
logger.warn("Failed to delete 'fo' file " + foFile);
}*/
}
private File getPdfOutputFile(File foFile) {
String name = foFile.getAbsolutePath();
return new File(name.substring(0, name.length() - 2) + "pdf");
}
}

View File

@ -1 +0,0 @@
implementation-class=docbook.DocbookPlugin

View File

@ -200,6 +200,12 @@
<version>1.6.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>3.2.0.CI-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId>

View File

@ -2,53 +2,42 @@
apply plugin: 'base'
task docs {
dependsOn 'manual:docbook', 'faq:docbookHtmlSingle', 'apidocs'
dependsOn 'manual:reference', 'faq:referenceHtmlSingle', 'apidocs'
}
subprojects {
apply plugin: 'base'
apply plugin: 'docbook'
apply plugin: 'docbook-reference'
docbookHtmlSingle.stylesheet = new File(projectDir, 'src/xsl/html-single-custom.xsl')
[referenceHtmlMulti, referencePdf, referenceHtmlSingle]*.sourceDir = file('src/docbook')
}
project('faq') {
defaultTasks 'docbookHtmlSingle'
[docbookHtml, docbookFoPdf, docbookHtmlSingle]*.sourceFileName = 'faq.xml'
docbookHtmlSingle.suffix = ''
defaultTasks 'referenceHtmlSingle'
referenceHtmlSingle.stylesheet = 'html-single-custom.xsl'
[referenceHtmlMulti, referencePdf, referenceHtmlSingle]*.sourceFileName = 'faq.xml'
ext.spec = copySpec {
into ('faq') {
from("$buildDir/docs")
from("$buildDir/reference/htmlsingle")
from("$projectDir/src/resources")
}
}
}
project('manual') {
defaultTasks 'docbookHtml', 'docbookHtmlSingle', 'docbookFoPdf'
[docbookHtml, docbookFoPdf, docbookHtmlSingle]*.sourceFileName = 'springsecurity.xml'
docbookHtml.stylesheet = new File(projectDir, 'src/xsl/html-custom.xsl')
docbookHtmlSingle.stylesheet = new File(projectDir, 'src/xsl/html-single-custom.xsl')
docbookFoPdf.stylesheet = new File(projectDir, 'src/xsl/pdf-custom.xsl')
defaultTasks 'referenceHtmlMulti', 'referenceHtmlSingle', 'referencePdf'
def imagesDir = new File(projectDir, 'src/docbook/images');
// docbookFoPdf.admonGraphicsPath = "${imagesDir}/"
docbookFoPdf.imgSrcPath = "${projectDir}/src/docbook/"
ext.spec = copySpec {
into ('reference') {
from("$buildDir/docs")
from("$projectDir/src/resources")
}
into ('reference/images') {
from (imagesDir)
from("$buildDir/reference")
}
}
}
task reference (type: Copy) {
dependsOn 'manual:docbook'
dependsOn 'manual:reference'
destinationDir = buildDir
with(project('manual').spec)
}
@ -99,7 +88,7 @@ ext.apiSpec = copySpec {
}
}
assemble.dependsOn = [apidocs, 'manual:docbook']
assemble.dependsOn = [apidocs, 'manual:reference']
task docsZip(type: Zip) {
dependsOn docs

View File

@ -18,60 +18,62 @@
<toc/>
<preface xml:id="preface">
<title>Preface</title>
<para>Spring Security provides a comprehensive security solution for J2EE-based enterprise
software applications. As you will discover as you venture through this reference guide,
we have tried to provide you a useful and highly configurable security system.</para>
<para>Security is an ever-moving target, and it's important to pursue a comprehensive,
system-wide approach. In security circles we encourage you to adopt "layers of
security", so that each layer tries to be as secure as possible in its own right, with
successive layers providing additional security. The "tighter" the security of each
layer, the more robust and safe your application will be. At the bottom level you'll
need to deal with issues such as transport security and system identification, in order
to mitigate man-in-the-middle attacks. Next you'll generally utilise firewalls, perhaps
with VPNs or IP security to ensure only authorised systems can attempt to connect. In
corporate environments you may deploy a DMZ to separate public-facing servers from
backend database and application servers. Your operating system will also play a
critical part, addressing issues such as running processes as non-privileged users and
maximising file system security. An operating system will usually also be configured
with its own firewall. Hopefully somewhere along the way you'll be trying to prevent
denial of service and brute force attacks against the system. An intrusion detection
system will also be especially useful for monitoring and responding to attacks, with
such systems able to take protective action such as blocking offending TCP/IP addresses
in real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be
configured to minimize the permissions granted to different Java types, and then your
application will add its own problem domain-specific security configuration. Spring
Security makes this latter area - application security - much easier. </para>
<para>Of course, you will need to properly address all security layers mentioned above,
together with managerial factors that encompass every layer. A non-exhaustive list of
such managerial factors would include security bulletin monitoring, patching, personnel
vetting, audits, change control, engineering management systems, data backup, disaster
recovery, performance benchmarking, load monitoring, centralised logging, incident
response procedures etc.</para>
<para>With Spring Security being focused on helping you with the enterprise application
security layer, you will find that there are as many different requirements as there are
business problem domains. A banking application has different needs from an ecommerce
application. An ecommerce application has different needs from a corporate sales force
automation tool. These custom requirements make application security interesting,
challenging and rewarding. </para>
<para>Please read <xref linkend="getting-started"/>, in its entirety to begin with. This
will introduce you to the framework and the namespace-based configuration system with
which you can get up and running quite quickly. To get more of an understanding of how
Spring Security works, and some of the classes you might need to use, you should then
read <xref linkend="overall-architecture"/>. The remaining parts of this guide are
structured in a more traditional reference style, designed to be read on an as-required
basis. We'd also recommend that you read up as much as possible on application security
issues in general. Spring Security is not a panacea which will solve all security
issues. It is important that the application is designed with security in mind from the
start. Attempting to retrofit it is not a good idea. In particular, if you are building
a web application, you should be aware of the many potential vulnerabilities such as
cross-site scripting, request-forgery and session-hijacking which you should be taking
into account from the start. The OWASP web site (http://www.owasp.org/) maintains a top
ten list of web application vulnerabilities as well as a lot of useful reference
information. </para>
<para>We hope that you find this reference guide useful, and we welcome your feedback and
<link xlink:href="#jira">suggestions</link>. </para>
<para>Finally, welcome to the Spring Security <link xlink:href="#community"
>community</link>. </para>
<partintro>
<para>Spring Security provides a comprehensive security solution for J2EE-based enterprise
software applications. As you will discover as you venture through this reference guide,
we have tried to provide you a useful and highly configurable security system.</para>
<para>Security is an ever-moving target, and it's important to pursue a comprehensive,
system-wide approach. In security circles we encourage you to adopt "layers of
security", so that each layer tries to be as secure as possible in its own right, with
successive layers providing additional security. The "tighter" the security of each
layer, the more robust and safe your application will be. At the bottom level you'll
need to deal with issues such as transport security and system identification, in order
to mitigate man-in-the-middle attacks. Next you'll generally utilise firewalls, perhaps
with VPNs or IP security to ensure only authorised systems can attempt to connect. In
corporate environments you may deploy a DMZ to separate public-facing servers from
backend database and application servers. Your operating system will also play a
critical part, addressing issues such as running processes as non-privileged users and
maximising file system security. An operating system will usually also be configured
with its own firewall. Hopefully somewhere along the way you'll be trying to prevent
denial of service and brute force attacks against the system. An intrusion detection
system will also be especially useful for monitoring and responding to attacks, with
such systems able to take protective action such as blocking offending TCP/IP addresses
in real-time. Moving to the higher layers, your Java Virtual Machine will hopefully be
configured to minimize the permissions granted to different Java types, and then your
application will add its own problem domain-specific security configuration. Spring
Security makes this latter area - application security - much easier. </para>
<para>Of course, you will need to properly address all security layers mentioned above,
together with managerial factors that encompass every layer. A non-exhaustive list of
such managerial factors would include security bulletin monitoring, patching, personnel
vetting, audits, change control, engineering management systems, data backup, disaster
recovery, performance benchmarking, load monitoring, centralised logging, incident
response procedures etc.</para>
<para>With Spring Security being focused on helping you with the enterprise application
security layer, you will find that there are as many different requirements as there are
business problem domains. A banking application has different needs from an ecommerce
application. An ecommerce application has different needs from a corporate sales force
automation tool. These custom requirements make application security interesting,
challenging and rewarding. </para>
<para>Please read <xref linkend="getting-started"/>, in its entirety to begin with. This
will introduce you to the framework and the namespace-based configuration system with
which you can get up and running quite quickly. To get more of an understanding of how
Spring Security works, and some of the classes you might need to use, you should then
read <xref linkend="overall-architecture"/>. The remaining parts of this guide are
structured in a more traditional reference style, designed to be read on an as-required
basis. We'd also recommend that you read up as much as possible on application security
issues in general. Spring Security is not a panacea which will solve all security
issues. It is important that the application is designed with security in mind from the
start. Attempting to retrofit it is not a good idea. In particular, if you are building
a web application, you should be aware of the many potential vulnerabilities such as
cross-site scripting, request-forgery and session-hijacking which you should be taking
into account from the start. The OWASP web site (http://www.owasp.org/) maintains a top
ten list of web application vulnerabilities as well as a lot of useful reference
information. </para>
<para>We hope that you find this reference guide useful, and we welcome your feedback and
<link xlink:href="#jira">suggestions</link>. </para>
<para>Finally, welcome to the Spring Security <link xlink:href="#community"
>community</link>. </para>
</partintro>
</preface>
<part xml:id="getting-started">
<title>Getting Started</title>
@ -168,7 +170,7 @@
<xi:include href="cas-auth-provider.xml"/>
<xi:include href="x509-auth-provider.xml"/>
<xi:include href="runas-auth-provider.xml"/>
<xi:include href="crypto.xml"/>
<xi:include href="crypto.xml"/>
</part>
<xi:include href="appendix-db-schema.xml"/>
<xi:include href="appendix-namespace.xml"/>