Prechádzať zdrojové kódy

SEC-2208: Use std docbook plugin and workspace cleanup

Rob Winch 12 rokov pred
rodič
commit
955a60cf49

+ 14 - 5
build.gradle

@@ -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"
+                }
+            }
         }
     }
 }

+ 0 - 22
buildSrc/build.gradle

@@ -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'

+ 0 - 301
buildSrc/src/main/groovy/docbook/DocbookPlugin.groovy

@@ -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");
-    }
-}

+ 0 - 1
buildSrc/src/main/resources/META-INF/gradle-plugins/docbook.properties

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

+ 6 - 0
core/pom.xml

@@ -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>

+ 11 - 22
docs/docs.gradle

@@ -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

+ 0 - 0
docs/faq/src/xsl/html-single-custom.xsl → docs/faq/src/docbook/xsl/html-single-custom.xsl


+ 57 - 55
docs/manual/src/docbook/springsecurity.xml → docs/manual/src/docbook/index.xml

@@ -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"/>