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 import groovy.text.SimpleTemplateEngine
buildscript { buildscript {
@ -6,6 +7,7 @@ buildscript {
} }
dependencies { dependencies {
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.3") 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") classpath("org.springframework.build.gradle:bundlor-plugin:0.1.2")
} }
} }
@ -22,7 +24,8 @@ allprojects {
group = 'org.springframework.security' group = 'org.springframework.security'
repositories { 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) { configure(javaProjects) {
apply from: "$rootDir/gradle/javaprojects.gradle" apply from: "$rootDir/gradle/javaprojects.gradle"
apply from: "$rootDir/gradle/release-checks.gradle" apply from: "$rootDir/gradle/release-checks.gradle"
apply from: "$rootDir/gradle/maven-deployment.gradle" apply from: "$rootDir/gradle/maven-deployment.gradle"
} }
configure(coreModuleProjects) { configure(coreModuleProjects) {
@ -94,7 +97,7 @@ task coreBuild {
// Task for creating the distro zip // Task for creating the distro zip
task dist(type: 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' classifier = 'dist'
evaluationDependsOn(':docs') evaluationDependsOn(':docs')
@ -110,8 +113,14 @@ task dist(type: Zip) {
} }
into('dist') { into('dist') {
from coreModuleProjects.collect {project -> project.libsDir } 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 // GAE
dependencies { dependencies {
compile 'com.google.appengine:appengine-tools-sdk:1.4.2' 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> <version>1.6.1</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-crypto</artifactId>
<version>3.2.0.CI-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency> <dependency>
<groupId>org.springframework</groupId> <groupId>org.springframework</groupId>
<artifactId>spring-test</artifactId> <artifactId>spring-test</artifactId>

View File

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

View File

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