Switch from Docbook to Markdown for documentation.

Added README.markdown with the current state of the reference docs in Markdown.
This commit is contained in:
Oliver Gierke
2012-02-22 16:03:18 +01:00
parent a9192a1808
commit 6ab36253aa
57 changed files with 295 additions and 1858 deletions

295
README.markdown Normal file
View File

@@ -0,0 +1,295 @@
# The smallest plugin system ever
V0.8 - Oliver Gierke, SpringSource - a division of VMware
© 2008-2012 The original authors
## <a name="revision-history" />Revision History
* 04.11.2008 Oliver Gierke Initial draft
* 05.11.2008 Oliver Gierke Added metadata module documentation
* 24.01.2009 Oliver Gierke Added remark to inner bean usage
* 23.03.2009 Oliver Gierke Added section on plugin ordering
* 21.02.2012 Oliver Gierke Move project to SpringSource
## <a name="preface" />Preface
### <a name="intro" />Introduction
Building extensible architectures nowadays is a core principle to create maintainable applications. This is why fully fledged plugin environments like *OSGi* are so poular these days. Unfortunately the introduction of *OSGi* introduces a lot of complexity to projects.
Spring Plugin provides a more pragmatic approach to plugin development by providing the core flexibility of having plugin implementations extending a core system's functionality but of course not delivering core OSGi features like dynamic class loading or runtime installation and deployment of plugins. Although Spring Plugin thus is not nearly as powerful as OSGi, it servers poor man's requirements to build a modular
extensible application.
### <a name="context" />Context
- You want to build an extensible architecture minimizing overhead as much as possible
- You cannot use OSGi as fully fledged plugin architecture for whatever reasons
- You want to express extensibility by providing dedicated plugin interfaces
- You want to extend the core system by simply providing an implementation of the plugin interface bundled in a JAR file and available in the classpath
- (You use Spring in your application)
The last point actually is not essential although Spring Plugin gains a
lot of momentum in collaborative use with Spring.
### <a name="technologies" />Technologies
#### <a name="spring" />Spring
Spring is the defacto standard application framework for Java applications. Its consistent programming model, easy configuration and wide support for all kinds of third party libraries makes it the first class citizen of application frameworks. Spring Plugin tightly integrates into Spring's component model and extends the core container
with some custom functionality.
## <a name="core" />Core
### <a name="core.intro" />Introduction
Host system provides a plugin interface providers have to implement.
Core system is build to hold a container of instances of this interface
and works with them.
**Example 1.1. Basic example of plugin interface and host**
~~~~java
/**
* Interface contract for the providers to be implemented.
*/
public interface MyPluginInterface {
public void bar();
}
/**
* A host application class working with instances of the plugin
* interface.
*/
public class HostImpl implements Host {
private final List<MyPluginInterface> plugins;
public HostImpl(List<MyPluginInterface> plugins) {
Assert.notNull(plugins);
this.plugins = plugins;
}
/**
* Some business method actually working with the given plugins.
*/
public void someBusinessMethod() {
for (MyPluginInterface plugin : plugins) {
plugin.bar();
}
}
}
~~~~
This is the way you would typically construct a host component in general. Leveraging dependency injection via setters allows flexible usage in a variety of environments. Thus you could easily provide a factory class that is able to lookup `MyPluginInterface`
implementations from the classpath, instantiate them and inject them into `HostImpl`.
Using Spring as component container you could configure something like this:
**Example 1.2. Configuring HostImpl with Spring**
~~~~xml
<bean id="host" class="com.acme.HostImpl">
<property name="plugins">
<list>
<bean class="MyPluginImplementation" />
</list>
</property>
</bean>
~~~~
This is pretty much well known to Spring developers and let's us face the wall that this is rather static. Everytime you want to add a new plugin implementation instance you have to modify configuration of the core. Let's see how we can get this dance a little more.
### <a name="core.beans-dynamically" />Collecting Spring beans dynamically
With the `BeanListBeanFactory` Spring Plugin provides a Spring container extension, that allows to lookup beans of a given type in the current `ApplicationContext` and register them as list under a given name. Take a look at the configuration now:
**Example 1.3. Host and plugin configuration with Spring Plugin
support**
~~~~xml
<import resource="classpath*:com/acme/**/plugins.xml" />
<bean id="host" class="com.acme.HostImpl">
<property name="plugins" ref="plugins" />
</bean>
<bean class="org.springframework.plugin.support.BeanListBeanFactory">
<property name="lists">
<map>
<entry key="plugins" value="org.acme.MyPluginInterface" />
</map>
</property>
</bean>
~~~~
~~~~xml
<!-- In a file called plugins.xml in the plugin project -->
<bean class="MyPluginimplementation" />
~~~~
You can see that we include a wildcarded configurationfile that allows plugin projects to easily contribute plugin implementations by declaring them as beans in configuration files matching the wildcarded path. If you use Spring 2.5 component scanning you don't have to use the import trick at all as Spring would detect the implementation automatically as long as it is annotated with `@Component`, `@Service` a.s.o.
The `BeanListBeanFactory` in turn allows registering a map of lists to be created, where the maps entry key is the id under which the list will be registered and the entry's value is the type to be looked up.
> #### Note
>
> The design of the `BeanListBeanFactory` might seem a little confusing at first
> (especially to set a map on a property named lists). This is due to the posibility to
> register more than one list to be looked up. We think about dropping this
> functionality for the sake of simplicity in future versions.
### <a name="core.namespace" />A whole lotta XML - namespace to help!
Actually this already serves a lot of requirements we listed in [Section “Context”](#context). Nevertheless the amount of XML to be written is quite large. Furthermore it's rather not intuitive to configure a bean id as key, and a type as value. We can heavily shrink the XML required to a single line by providing a Spring namespace boiling configuration down to this:
**Example 1.4. Host configuration using the plugin namespace**
~~~~xml
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:plugin="http://www.springframework.org/schema/plugin"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/plugin http://www.springframework.org/schema/plugin/spring-plugin.xsd">
<import resource="classpath*:com/acme/**/plugins.xml" />
<bean id="host" class="com.acme.HostImpl">
<property name="plugins" ref="plugins" />
</bean>
<plugin:list id="plugins" class="org.acme.MyPluginInterface" />
</beans>
~~~~
Assuming you have added the namespace XSD into Eclipse and installed Spring IDE, you should get code completion on filling the class attribute.
### <a name="core.inner-beans" />Using inner beans
The listing above features an indirection for the `plugin` bean definition. Defining the plugin list as top level bean can have advantages: you easily could place all plugin lists in a dedicated configuration file, presenting all application extension points in one single place. Nevertheless you also might choose to define the list directly in the property declaration:
**Example 1.5. Using inner bean definition**
~~~~xml
<import resource="classpath*:com/acme/**/plugins.xml" />
<bean id="host" class="com.acme.HostImpl">
<property name="plugins">
<plugin:list class="org.acme.MyPluginInterface" />
</property>
</bean>
~~~~
This way you have a more compact configuration, paying the prica of tangling all extention points though possibly various config files.
#### <a name="core.plugin-beans" />Plugin beans
Using plain interfaces and `BeanListBeanFactory` offers an easy way to dynamically lookup beans in Spring environments. Nevertheless, very often you face the situation that you want to have dedicated access to a subset of all plugins, choose plugins by a given criteria or use a decent default plugin or the like. Thus we need a basic infrastructure interface for plugin interfaces to extend and a more sophisticated plugin container.
#### <a name="core.plugin" />Plugin
Hera's central infrastructure interfacte is `Plugin<S>`, where `S` defines the delimiter type you want to let implementations decide on, whether they shall be invoked or not. Thus the plugin implementation have to implement `supports(S delimiter)` to come to the decision. Consider the following example:
**Example 1.6. Usage of Plugin interface**
~~~~java
public enum ProductType {
SOFTWARE, HARDWARE;
}
public interface ProductProcessor extends Plugin<ProductType> {
public void process(Product product);
}
~~~~
This design would allow plugin providers to implement `supports(ProductType productType)` to decide which product types they want to process and provide actual processing logic in `process(Product product)`.
#### <a name="core.plugin-registry" />PluginRegistry
Using a `List` as plugin container as well as the `Plugin` interface you can now select plugins supporting the given delimiter. To not reimplement the lookup logic for common
cases Spring Plugin provides a `PluginRegistry<T extends Plugin<S>, S>` interface that provides sophisticated methods to access certain plugins:
**Example 1.7. Usage of the PluginRegistry**
~~~~java
PluginRegistry<ProductProcessor, ProductType> registry = SimplePluginRegistry.create();
// Add plugin instances
registry.add(new FooImplementation());
// Returns the first plugin supporting SOFTWARE
registry.getPluginFor(ProductType.SOFTWARE);
// Returns the first plugin supporting SOFTWARE, or DefaultPlugin if none found
registry.getPluginFor(ProductType.SOFTWARE, new DefaultPlugin());
// Returns all plugins supporting HARDWARE, throwing the given exception if none found
registry.getPluginsFor(ProductType.HARDWARE, new MyException("Damn!");
~~~~
#### <a name="core.plugin-namespace" />Configuration and namespace
Similar to the `BeanListBeanFactory` described in [Collecting Spring beans
dynamically](#core.beans-dynamically) Spring Plugin provides a `PluginRegistryBeanFactory` to automatically lookup beans of a dedicated type to be aggregated in a `PluginRegistry`. Note that the type has to be assignable to `Plugin` to let the registry work as expected.
Furthermore there is also an element in the namespace to shrink down configuration XML:
**Example 1.8. Using the XML namespace to configure a registry**
~~~~xml
<plugin:registry id="plugins" class="com.acme.MyPluginInterface" />
~~~~
### <a name="core.plugins-order" />Ordering plugins
Declaring plugin beans sometimes it is necessary to preserve a certain order of plugins. Suppose you have a plugin host that already defines one plugin that shall always be executed after all plugins declared by extensions. Actually the Spring container typically returnes beans in the order they were declared, so that you could import you wildcarded config files right before declaring the default plugin. Unfortunately
the order of the beans is not contracted to be preserved for the Spring container. Thus we need a different solution.
Spring provides two ways to order beans. First, you can implement `Ordered` interface and implement `getOrder` to place a plugin at a certain point in the list. Secondly you can user the `@Order` annotation. For more information on ordering capabilities of Spring see the [section on this topic in the Spring reference documentation](http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/core/Ordered.html).
Using the Spring Plugin namespace you will get a `PluginRegistry` instance that is capable of preserving the order defined by the mentioned means. Using Spring Plugin
programatically use `OrderAwarePluginRegistry`.
## <a name="metadata" />Metadata
For plugin architectures it is essential to capture metadata information about plugin instances. A very core set of metadata (name, version) also serves as identifier of a plugin and thus can be used. The Spring Plugin metadata module provides support to capture metadata.
### <a name="metadata.core-concepts" />Core concepts
The metadata module actually builds around two core interfaces, `PluginMetadata` and `MetadataProvider`:
**Example 2.1. Core concepts**
~~~~java
public interface PluginMetadata {
String getName();
String getVersion();
}
public interface MetadataProvider {
PluginMetadata getMetadata();
}
~~~~
The `PluginMetadata` interface captures the required properties to define an identifyable plugin. This means, that implementations should ensure uniqueness through these two properties. With `SimplePluginMetadata` Spring Plugin provides a Java bean style class to capture metadata. Of course applications can and should provide extended metadata information according to their needs. The very narrow interface is only targeted at integrating the metadata concept with the `PluginRegistry` (see [the section called “PluginRegistry”](#core.plugin-registry)) without bothering developers with too much information required.
The `MetadataProvider` interface is to be used in application plugin interfaces to indicate that they can provide metadata. To ease plugin implementation we provide
`AbstractMetadataBasedPlugin` that uses the internal metadata to implement `supports(..)` method of `Plugin`. Extending this base class plugins with metadata as selection criteria can easily be build. This way you could store the metadata in user specific configuration files and use this to select a distinct plugin specific to a given user.
## <a name="glossary" />Glossary
### <a name="glossary.o" />O
OSGi
* Open Services Gateway Initiative - a fully fledged plugin runtime
environment on top of the Java VM -
[http://en.wikipedia.org/wiki/OSGi](http://en.wikipedia.org/wiki/OSGi).
### <a name="glossary.x" />X
XML
* eXtensible Markup Language
XSD
* Xml Schema Definition

View File

@@ -1,317 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter>
<title>Core</title>
<section>
<title>Introduction</title>
<para>Host system provides a plugin interface providers have to implement.
Core system is build to hold a container of instances of this interface
and works with them.</para>
<example>
<title>Basic example of plugin interface and host</title>
<programlisting language="java">/**
* Interface contract for the providers to be implemented.
*/
public interface MyPluginInterface {
public void bar();
}
/**
* A host application class working with instances of the plugin
* interface.
*/
public class HostImpl implements Host {
private List&lt;MyPluginInterface&gt; plugins;
/**
* Setter to inject the plugins
*/
public void setPlugins(List&lt;MyPluginInterface&gt; plugins) {
this.plugins = plugins;
}
/**
* Some business method actually working with the given plugins.
*/
public void someBusinessMethod() {
for (MyPluginInterface plugin : plugins) {
plugin.bar();
}
}
}</programlisting>
</example>
<para>This is the way you would typically construct a host component in
general. Leveraging dependency injection via setters allows flexible usage
in a variety of environments. Thus you could easily provide a factory
class that is able to lookup
<interfacename>MyPluginInterface</interfacename> implementations from the
classpath, instantiate them and inject them into HostImpl.</para>
<para>Using Spring as component container you could configure something
like this:</para>
<example>
<title>Configuring HostImpl with Spring</title>
<programlisting language="xml">&lt;bean id="host" class="com.acme.HostImpl"&gt;
&lt;property name="plugins"&gt;
&lt;list&gt;
&lt;bean class="MyPluginImplementation" /&gt;
&lt;/list&gt;
&lt;/property&gt;
&lt;/bean&gt;</programlisting>
</example>
<para>This is pretty much well known to Spring developers and let's us
face the wall that this is rather static. Everytime you want to add a new
plugin implementation instance you have to modify configuration of the
core. Let's see how we can get this dance a little more.</para>
</section>
<section id="core.collecting-beans">
<title>Collecting Spring beans dynamically</title>
<para>With the <classname>BeanListBeanFactory</classname>
<productname>Spring Plugin</productname> provides a Spring container
extension, that allows to lookup beans of a given type in the current
<interfacename>ApplicationContext</interfacename> and register them as
list under a given name. Take a look at the configuration now:</para>
<example>
<title>Host and plugin configuration with Spring Plugin support</title>
<programlisting lang="" language="xml">&lt;import resource="classpath*:com/acme/**/plugins.xml" /&gt;
&lt;bean id="host" class="com.acme.HostImpl"&gt;
&lt;property name="plugins" ref="plugins" /&gt;
&lt;/bean&gt;
&lt;bean class="org.springframework.plugin.support.BeanListBeanFactory"&gt;
&lt;property name="lists"&gt;
&lt;map&gt;
&lt;entry key="plugins" value="org.acme.MyPluginInterface" /&gt;
&lt;/map&gt;
&lt;/property&gt;
&lt;/bean&gt;</programlisting>
<programlisting language="xml">&lt;!-- In a file called plugins.xml in the plugin project --&gt;
&lt;bean class="MyPluginimplementation" /&gt;</programlisting>
</example>
<para>You can see that we include a wildcarded configurationfile that
allows plugin projects to easily contribute plugin implementations by
declaring them as beans in configuration files matching the wildcarded
path. If you use Spring 2.5 component scanning you don't have to use the
import trick at all as Spring would detect the implementation
automatically as long as it is annotated with <code>@Component</code>,
<code>@Service</code> a.s.o.</para>
<para>The <classname>BeanListBeanFactory</classname> in turn allows
registering a map of lists to be created, where the maps entry key is the
id under which the list will be registered and the entry's value is the
type to be looked up.</para>
<note>
<para>The design of the <classname>BeanListBeanFactory</classname> might
seem a little confusing at first (especially to set a map on a property
named lists). This is due to the posibility to register more than one
list to be looked up. We think about dropping this functionality for the
sake of simplicity in future versions.</para>
</note>
<simplesect>
<title>A whole lotta XML - namespace to help!</title>
<para>Actually this already serves a lot of requirements we listed in
<xref linkend="preface.context" />. Nevertheless the amount of XML to be
written is quite large. Furthermore it's rather not intuitive to
configure a bean id as key, and a type as value. We can heavily shrink
the XML required to a single line by providing a Spring namespace
boiling configuration down to this:</para>
<example>
<title>Host configuration using the plugin namespace</title>
<programlisting language="xml">&lt;beans xmlns="http://www.springframework.org/schema/beans"
xmlns:plugin="http://www.springframework.org/schema/plugin"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/plugin http://www.springframework.org/schema/plugin/spring-plugin.xsd"&gt;
&lt;import resource="classpath*:com/acme/**/plugins.xml" /&gt;
&lt;bean id="host" class="com.acme.HostImpl"&gt;
&lt;property name="plugins" ref="plugins" /&gt;
&lt;/bean&gt;
&lt;plugin:list id="plugins" class="org.acme.MyPluginInterface" /&gt;
&lt;/beans&gt;</programlisting>
</example>
<para>Suggested you have added the namespace XSD into Eclipse and
installed Spring IDE, you should get code completion on filling the
class attribute.</para>
</simplesect>
<simplesect>
<title>Using inner beans</title>
<para>The listing above features an indirection for the
<code>plugin</code> bean definition. Defining the plugin list as top
level bean can have advantages: you easily could place all plugin lists
in a dedicated configuration file, presenting all application extension
points in one single place. Nevertheless you also might choose to define
the list directly in the property declaration:</para>
<example>
<title>Using internal bean definition</title>
<programlisting language="xml">&lt;import resource="classpath*:com/acme/**/plugins.xml" /&gt;
&lt;bean id="host" class="com.acme.HostImpl"&gt;
&lt;property name="plugins"&gt;
&lt;plugin:list class="org.acme.MyPluginInterface" /&gt;
&lt;/property&gt;
&lt;/bean&gt;</programlisting>
</example>
<para>This way you have a more compact configuration, paying the prica
of tangling all extention points though possibly various config
files.</para>
</simplesect>
</section>
<section>
<title>Plugin beans</title>
<para>Using plain interfaces and
<classname>BeanListBeanFactory</classname> offers an easy way to
dynamically lookup beans in Spring environments. Nevertheless, very often
you face the situation that you want to have dedicated access to a subset
of all plugins, choose plugins by a given criteria or use a decent default
plugin or the like. Thus we need a basic infrastructure interface for
plugin interfaces to extend and a more sophisticated plugin
container.</para>
<simplesect>
<title>Plugin</title>
<para>Hera's central infrastructure interfacte is
<interfacename>Plugin&lt;S&gt;</interfacename>, where S defines the
delimiter type you want to let implementations decide on, whether they
shall be invoked or not. Thus the plugin implementation have to
implement <methodname>supports(S delimiter)</methodname> to come to the
decision. Consider the following example:</para>
<example>
<title>Usage of Plugin interface</title>
<programlisting language="java">public enum ProductType {
SOFTWARE, HARDWARE;
}
public interface ProductProcessor extends Plugin&lt;ProductType&gt; {
public void process(Product product);
}</programlisting>
</example>
<para>This design would allow plugin providers to implement
<methodname>supports(ProductType productType)</methodname> to decide
which product types they want to process and provide actual processing
logic in <methodname>process(Product product)</methodname>.</para>
</simplesect>
<simplesect id="core.plugin-registry">
<title>PluginRegistry</title>
<para>Using a <interfacename>List</interfacename> as plugin container as
well as the <interfacename>Plugin</interfacename> interface you can now
select plugins supporting the given delimiter. To not reimplement the
lookup logic for common cases Spring Plugin provides a
<classname>PluginRegistry&lt;T extends Plugin&lt;S&gt;,
S&gt;</classname> interface that provides sophisticated methods to
access certain plugins:</para>
<example>
<title>Usage of the PluginRegistry</title>
<programlisting language="java">PluginRegistry&lt;ProductProcessor, ProductType&gt; registry =
SimplePluginRegistry.create();
// Add plugin instances
registry.add(new FooImplementation());
// Returns the first plugin supporting SOFTWARE
registry.getPluginFor(ProductType.SOFTWARE);
// Returns the first plugin supporting SOFTWARE,
// or DefaultPlugin if none found
registry.getPluginFor(ProductType.SOFTWARE, new DefaultPlugin());
// Returns all plugins supporting HARDWARE,
// throwing the given exception if none found
registry.getPluginsFor(ProductType.HARDWARE, new MyException("Damn!");</programlisting>
</example>
</simplesect>
<simplesect>
<title>Configuration and namespace</title>
<para>Similar to the <classname>BeanListBeanFactory</classname>
described in <xref linkend="core.collecting-beans" /> Spring Plugin
provides a <classname>PluginRegistryBeanFactory</classname> to
automatically lookup beans of a dedicated type to be aggregated in a
<classname>PluginRegistry</classname>. Note that the type has to be
assignable to <interfacename>Plugin</interfacename> to let the registry
work as expected.</para>
<para>Furthermore there is also an element in the namespace to shrink
down configuration XML:</para>
<example>
<title>Using the XML namespace to configure a registry</title>
<programlisting language="xml">&lt;plugin:registry id="plugins" class="com.acme.MyPluginInterface" /&gt;</programlisting>
</example>
</simplesect>
<simplesect>
<title>Ordering plugins</title>
<para>Declaring plugin beans sometimes it is necessary to preserve a
certain order of plugins. Suppose you have a plugin host that already
defines one plugin that shall always be executed after all plugins
declared by extensions. Actually the Spring container typically returnes
beans in the order they were declared, so that you could import you
wildcarded config files right before declaring the default plugin.
Unfortunately the order of the beans is not contracted to be preserved
for the Spring container. Thus we need a different solution.</para>
<para>Spring provides two ways to order beans. First, you can implement
<interfacename>Ordered</interfacename> interface and implement
<methodname>getOrder</methodname> to place a plugin at a certain point
in the list. Secondly you can user the <classname>@Order</classname>
annotation. For more information on ordering capabilities of Spring see
the <ulink url="???">section on this topic in the Spring reference
documentation</ulink>.</para>
<para>Using the Spring Plugin namespace you will get a
<interfacename>PluginRegistry</interfacename> instance that is capable
of preserving the order defined by the mentioned means. Using Spring
Plugin programatically use
<classname>OrderAwarePluginRegistry</classname>.</para>
</simplesect>
</section>
</chapter>

View File

@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapter PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<chapter id="metadata">
<title>Metadata</title>
<para>For plugin architectures it is essential to capture metadata
information about plugin instances. A very core set of metadata (name,
version) also serves as identifier of a plugin and thus can be used. The
Spring Plugin metadata module provides support to capture metadata.</para>
<section id="metadata.core-concepts">
<title>Core concepts</title>
<para>The metadata module actually builds around two core interfaces,
<interfacename>PluginMetadata</interfacename> and
<interfacename>MetadataProvider</interfacename>:</para>
<example>
<title>Core concepts</title>
<programlisting language="java">public interface PluginMetadata {
String getName();
String getVersion();
}
public interface MetadataProvider {
PluginMetadata getMetadata();
}</programlisting>
</example>
<para>The <interfacename>PluginMetadata</interfacename> interface captures
the required properties to define an identifyable plugin. This means, that
implementations should ensure uniqueness through these two properties.
With <classname>SimplePluginMetadata</classname> Spring Plugin provides a
Java bean style class to capture metadata. Of course applications can and
should provide extended metadata information according to their needs. The
very narrow interface is only targeted at integrating the metadata concept
with the <classname>PluginRegistry</classname> (see <xref
linkend="core.plugin-registry" />) without bothering developers with too
much information required.</para>
<para>The <interfacename>MetadataProvider</interfacename> interface is to
be used in application plugin interfaces to indicate that they can provide
metadata. To ease plugin implementation we provide
<classname>AbstractMetadataBasedPlugin</classname> that uses the internal
metadata to implement <methodname>supports(..)</methodname> method of
<interfacename>Plugin</interfacename>. Extending this base class plugins
with metadata as selection criteria can easily be build. This way you
could store the metadata in user specific configuration files and use this
to select a distinct plugin specific to a given user.</para>
</section>
</chapter>

66
pom.xml
View File

@@ -109,72 +109,6 @@
</executions>
</plugin>
<!-- Docbook -->
<plugin>
<groupId>com.agilejava.docbkx</groupId>
<artifactId>docbkx-maven-plugin</artifactId>
<version>2.0.8</version>
<executions>
<execution>
<goals>
<goal>generate-html</goal>
<goal>generate-pdf</goal>
</goals>
<phase>pre-site</phase>
</execution>
</executions>
<inherited>false</inherited>
<dependencies>
<dependency>
<groupId>net.sf.offo</groupId>
<artifactId>fop-hyph</artifactId>
<version>1.2</version>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.docbook</groupId>
<artifactId>docbook-xml</artifactId>
<version>4.4</version>
<scope>runtime</scope>
</dependency>
</dependencies>
<configuration>
<includes>index.xml</includes>
<xincludeSupported>true</xincludeSupported>
<foCustomization>${project.basedir}/src/docbkx/resources/xsl/fopdf.xsl</foCustomization>
<htmlStylesheet>css/html.css</htmlStylesheet>
<chunkedOutput>false</chunkedOutput>
<htmlCustomization>${project.basedir}/src/docbkx/resources/xsl/html.xsl</htmlCustomization>
<useExtensions>1</useExtensions>
<highlightSource>1</highlightSource>
<entities>
<entity>
<name>version</name>
<value>${project.version}</value>
</entity>
</entities>
<postProcess>
<copy todir="${project.basedir}/target/site/reference">
<fileset dir="${project.basedir}/target/docbkx">
<include name="**/*.html" />
<include name="**/*.pdf" />
</fileset>
</copy>
<copy todir="${project.basedir}/target/site/reference/html">
<fileset dir="${project.basedir}/src/docbkx/resources">
<include name="**/*.css" />
<include name="**/*.png" />
<include name="**/*.gif" />
<include name="**/*.jpg" />
</fileset>
</copy>
<move file="${project.basedir}/target/site/reference/pdf/index.pdf" tofile="${project.basedir}/target/site/reference/pdf/${project.artifactId}-reference.pdf" failonerror="false" />
</postProcess>
</configuration>
</plugin>
<plugin>
<groupId>com.springsource.bundlor</groupId>
<artifactId>com.springsource.bundlor.maven</artifactId>

View File

@@ -1,215 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
<book xmlns:xi="http://www.w3.org/2001/XInclude">
<bookinfo>
<title>Spring Plugin</title>
<subtitle>The smallest plugin system ever</subtitle>
<authorgroup>
<author>
<firstname>Oliver</firstname>
<surname>Gierke</surname>
<affiliation>
<jobtitle>Senior Member Technical Staff</jobtitle>
<orgname>SpringSource, a division of VMware</orgname>
</affiliation>
<email>ogierke (at) vmware.com</email>
</author>
</authorgroup>
<releaseinfo>V0.8</releaseinfo>
<pubdate>23.09.2009</pubdate>
<copyright>
<year>2008-2012</year>
<holder>The original authors</holder>
</copyright>
<revhistory>
<revision>
<date>04.11.2008</date>
<author>
<firstname>Oliver</firstname>
<surname>Gierke</surname>
</author>
<revremark>Initial draft</revremark>
</revision>
<revision>
<date>05.11.2008</date>
<author>
<firstname>Oliver</firstname>
<surname>Gierke</surname>
</author>
<revremark>Added metadata module documentation</revremark>
</revision>
<revision>
<date>24.01.2009</date>
<author>
<firstname>Oliver</firstname>
<surname>Gierke</surname>
</author>
<revremark>Added remark to inner bean usage</revremark>
</revision>
<revision>
<date>23.03.2009</date>
<author>
<firstname>Oliver</firstname>
<surname>Gierke</surname>
</author>
<revremark>Added section on plugin ordering</revremark>
</revision>
<revision>
<date>21.02.2012</date>
<author>
<firstname>Oliver</firstname>
<surname>Gierke</surname>
</author>
<revremark>Move project to SpringSource</revremark>
</revision>
</revhistory>
</bookinfo>
<preface>
<title>Preface</title>
<section>
<title>Introduction</title>
<para>Building extensible architectures nowadays is a core principle to
create maintainable applications. This is why fully fledged plugin
environments like <glossterm><abbrev>OSGi</abbrev></glossterm> are so
poular these days. Unfortunately the introduction of
<glossterm><abbrev>OSGi</abbrev></glossterm> introduces a lot of
complexity to projects.</para>
<para>Spring Plugin provides a more pragmatic approach to plugin
development by providing the core flexibility of having plugin
implementations extending a core system's functionality but of course
not delivering core <abbrev>OSGi</abbrev> features like dynamic class
loading or runtime installation and deployment of plugins. Although
Spring Plugin thus is not nearly as powerful as <abbrev>OSGi</abbrev>,
it servers poor man's requirements to build a modular extensible
application.</para>
</section>
<section id="preface.context">
<title>Context</title>
<para><itemizedlist spacing="compact">
<listitem>
<para>You want to build an extensible architecture minimizing
overhead as much as possible</para>
</listitem>
<listitem>
<para>You cannot use OSGi as fully fledged plugin architecture for
whatever reasons</para>
</listitem>
<listitem>
<para>You want to express extensibility by providing dedicated
plugin interfaces</para>
</listitem>
<listitem>
<para>You want to extend the core system by simply providing an
implementation of the plugin interface bundled in a JAR file and
available in the classpath.</para>
</listitem>
<listitem>
<para>(You use Spring in your application)</para>
</listitem>
</itemizedlist></para>
<para>The last point actually is not essential although Spring Plugin
gains a lot of momentum in collaborative use with Spring.</para>
</section>
<section>
<title>Technologies</title>
<simplesect>
<title>Spring</title>
<para>Spring is the defacto standard application framework for Java
applications. Its consistent programming model, easy configuration and
wide support for all kinds of third party libraries makes it the first
class citizen of application frameworks. Spring Plugin tightly
integrates into Spring's component model and extends the core
container with some custom functionality.</para>
</simplesect>
</section>
</preface>
<xi:include href="../../core/src/doc/core.xml">
<xi:fallback href="../../core/src/doc/core.xml" />
</xi:include>
<xi:include href="../../metadata/src/doc/metadata.xml">
<xi:fallback href="../../metadata/src/doc/metadata.xml" />
</xi:include>
<glossary>
<glossdiv>
<title>O</title>
<glossentry>
<glossterm>OSGi</glossterm>
<glossdef>
<para>Open Services Gateway Initiative - a fully fledged plugin
runtime environment on top of the Java VM - <ulink
url="http://en.wikipedia.org/wiki/OSGi">http://en.wikipedia.org/wiki/OSGi</ulink>.</para>
</glossdef>
</glossentry>
</glossdiv>
<glossdiv>
<title>X</title>
<glossentry>
<glossterm>XML</glossterm>
<glossdef>
<para>eXtensible Markup Language</para>
</glossdef>
</glossentry>
<glossentry>
<glossterm>XSD</glossterm>
<glossdef>
<para>Xml Schema Definition</para>
</glossdef>
</glossentry>
</glossdiv>
</glossary>
</book>

View File

@@ -1,35 +0,0 @@
/*
code highlight CSS resemblign the Eclipse IDE default color schema
@author Costin Leau
*/
.hl-keyword {
color: #7F0055;
font-weight: bold;
}
.hl-comment {
color: #3F5F5F;
font-style: italic;
}
.hl-multiline-comment {
color: #3F5FBF;
font-style: italic;
}
.hl-tag {
color: #3F7F7F;
}
.hl-attribute {
color: #7F007F;
}
.hl-value {
color: #2A00FF;
}
.hl-string {
color: #2A00FF;
}

View File

@@ -1,305 +0,0 @@
@IMPORT url("highlight.css");
body {
text-align: justify;
margin-right: 2em;
margin-left: 2em;
}
a,
a[accesskey^="h"],
a[accesskey^="n"],
a[accesskey^="u"],
a[accesskey^="p"] {
font-family: Verdana, Arial, helvetica, sans-serif;
font-size: 12px;
color: #003399;
}
a:active {
color: #003399;
}
a:visited {
color: #888888;
}
p {
font-family: Verdana, Arial, sans-serif;
}
dt {
font-family: Verdana, Arial, sans-serif;
font-size: 12px;
}
p, dl, dt, dd, blockquote {
color: #000000;
margin-bottom: 3px;
margin-top: 3px;
padding-top: 0;
}
ol, ul, p {
margin-top: 6px;
margin-bottom: 6px;
}
p, blockquote {
font-size: 90%;
}
p.releaseinfo {
font-size: 100%;
font-weight: bold;
font-family: Verdana, Arial, helvetica, sans-serif;
padding-top: 10px;
}
p.pubdate {
font-size: 120%;
font-weight: bold;
font-family: Verdana, Arial, helvetica, sans-serif;
}
td {
font-size: 80%;
}
td, th, span {
color: #000000;
}
td[width^="40%"] {
font-family: Verdana, Arial, helvetica, sans-serif;
font-size: 12px;
color: #003399;
}
table[summary^="Navigation header"] tbody tr th[colspan^="3"] {
font-family: Verdana, Arial, helvetica, sans-serif;
}
blockquote {
margin-right: 0;
}
h1, h2, h3, h4, h6 {
color: #000000;
font-weight: 500;
margin-top: 0;
padding-top: 14px;
font-family: Verdana, Arial, helvetica, sans-serif;
margin-bottom: 0;
}
h2.title {
font-weight: 800;
margin-bottom: 8px;
}
h2.subtitle {
font-weight: 800;
margin-bottom: 20px;
}
.firstname, .surname {
font-size: 12px;
font-family: Verdana, Arial, helvetica, sans-serif;
}
table {
border-collapse: collapse;
border-spacing: 0;
border: 1px black;
empty-cells: hide;
margin: 10px 0 30px 50px;
width: 90%;
}
div.table {
margin: 30px 0 10px 0;
border: 1px dashed gray;
padding: 10px;
}
div .table-contents table {
border: 1px solid black;
}
div.table > p.title {
padding-left: 10px;
}
table[summary^="Navigation footer"] {
border-collapse: collapse;
border-spacing: 0;
border: 1px black;
empty-cells: hide;
margin: 0px;
width: 100%;
}
table[summary^="Note"],
table[summary^="Warning"],
table[summary^="Tip"] {
border-collapse: collapse;
border-spacing: 0;
border: 1px black;
empty-cells: hide;
margin: 10px 0px 10px -20px;
width: 100%;
}
td {
padding: 4pt;
font-family: Verdana, Arial, helvetica, sans-serif;
}
div.warning TD {
text-align: justify;
}
h1 {
font-size: 150%;
}
h2 {
font-size: 110%;
}
h3 {
font-size: 100%; font-weight: bold;
}
h4 {
font-size: 90%; font-weight: bold;
}
h5 {
font-size: 90%; font-style: italic;
}
h6 {
font-size: 100%; font-style: italic;
}
tt {
font-size: 110%;
font-family: "Courier New", Courier, monospace;
color: #000000;
}
.navheader, .navfooter {
border: none;
}
div.navfooter table {
border-style: dashed;
border-color: gray;
border-width: 1px 1px 1px 1px;
background-color: #cde48d;
}
pre {
font-size: 110%;
padding: 5px;
border-style: solid;
border-width: 1px;
border-color: #CCCCCC;
background-color: #f3f5e9;
}
ul, ol, li {
list-style: disc;
}
hr {
width: 100%;
height: 1px;
background-color: #CCCCCC;
border-width: 0;
padding: 0;
}
.variablelist {
padding-top: 10px;
padding-bottom: 10px;
margin: 0;
}
.term {
font-weight:bold;
}
.mediaobject {
padding-top: 30px;
padding-bottom: 30px;
}
.legalnotice {
font-family: Verdana, Arial, helvetica, sans-serif;
font-size: 12px;
font-style: italic;
}
.sidebar {
float: right;
margin: 10px 0 10px 30px;
padding: 10px 20px 20px 20px;
width: 33%;
border: 1px solid black;
background-color: #F4F4F4;
font-size: 14px;
}
.property {
font-family: "Courier New", Courier, monospace;
}
a code {
font-family: Verdana, Arial, monospace;
font-size: 12px;
}
td code {
font-size: 110%;
}
div.note * td,
div.tip * td,
div.warning * td,
div.calloutlist * td {
text-align: justify;
font-size: 100%;
}
.programlisting {
clear: both;
}
.programlisting .interfacename,
.programlisting .literal,
.programlisting .classname {
font-size: 95%;
}
.title .interfacename,
.title .literal,
.title .classname {
font-size: 130%;
}
/* everything in a <lineannotation/> is displayed in a coloured, comment-like font */
.programlisting * .lineannotation,
.programlisting * .lineannotation * {
color: green;
}
.question * p {
font-size: 100%;
}
.answer * p {
font-size: 100%;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 374 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 743 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 321 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1003 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 580 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 264 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 613 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 329 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 361 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 565 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 617 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 623 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 411 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 640 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 350 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 345 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 348 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 355 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 357 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 36 KiB

View File

@@ -1,449 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This is the XSL FO (PDF) stylesheet for the Spring Data reference
documentation.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:import href="urn:docbkx:stylesheet"/>
<xsl:import href="highlight-fo.xsl"/>
<!--###################################################
Custom Title Page
################################################### -->
<xsl:template name="book.titlepage.recto">
<fo:block>
<fo:table table-layout="fixed" width="175mm">
<fo:table-column column-width="175mm"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell text-align="center">
<!-- Logo
<fo:block>
<fo:external-graphic src="file:src/docbkx/resources/images/s2_box_logo.png"/>
</fo:block>
-->
<fo:block font-family="Helvetica" font-size="22pt" padding-before="10mm">
<xsl:value-of select="bookinfo/subtitle"/>
</fo:block>
<fo:block font-family="Helvetica" font-size="14pt" padding="10mm">
<xsl:value-of select="bookinfo/title"/>
</fo:block>
<fo:block font-family="Helvetica" font-size="12pt" padding="10mm">
<xsl:value-of select="bookinfo/releaseinfo"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell text-align="center">
<fo:block font-family="Helvetica" font-size="14pt" padding="10mm">
<xsl:value-of select="bookinfo/pubdate"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
<fo:table-row>
<fo:table-cell text-align="center">
<fo:block font-family="Helvetica" font-size="12pt" padding="10mm">
<xsl:for-each select="bookinfo/authorgroup/author">
<xsl:if test="position() > 1">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:value-of select="firstname"/>
<xsl:text> </xsl:text>
<xsl:value-of select="surname"/>
<!-- <xsl:text> (</xsl:text>
<xsl:value-of select="affiliation"/>
<xsl:text>)</xsl:text> -->
</xsl:for-each>
</fo:block>
<fo:block font-family="Helvetica" font-size="12pt" padding="10mm">
<xsl:text>Copyright &#xA9; 2011</xsl:text>
</fo:block>
<fo:block font-family="Helvetica" font-size="10pt" padding="1mm">
<xsl:value-of select="bookinfo/legalnotice"/>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</fo:block>
</xsl:template>
<!-- Prevent blank pages in output -->
<xsl:template name="book.titlepage.before.verso">
</xsl:template>
<xsl:template name="book.titlepage.verso">
</xsl:template>
<xsl:template name="book.titlepage.separator">
</xsl:template>
<!--###################################################
Header
################################################### -->
<!-- More space in the center header for long text -->
<xsl:attribute-set name="header.content.properties">
<xsl:attribute name="font-family">
<xsl:value-of select="$body.font.family"/>
</xsl:attribute>
<xsl:attribute name="margin-left">-5em</xsl:attribute>
<xsl:attribute name="margin-right">-5em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Custom Footer
################################################### -->
<xsl:template name="footer.content">
<xsl:param name="pageclass" select="''"/>
<xsl:param name="sequence" select="''"/>
<xsl:param name="position" select="''"/>
<xsl:param name="gentext-key" select="''"/>
<xsl:variable name="Version">
<xsl:if test="//releaseinfo">
<xsl:text>Spring Data Document (</xsl:text><xsl:value-of select="//releaseinfo" /><xsl:text>)</xsl:text>
</xsl:if>
</xsl:variable>
<xsl:choose>
<xsl:when test="$sequence='blank'">
<xsl:if test="$position = 'center'">
<xsl:value-of select="$Version"/>
</xsl:if>
</xsl:when>
<!-- for double sided printing, print page numbers on alternating sides (of the page) -->
<xsl:when test="$double.sided != 0">
<xsl:choose>
<xsl:when test="$sequence = 'even' and $position='left'">
<fo:page-number/>
</xsl:when>
<xsl:when test="$sequence = 'odd' and $position='right'">
<fo:page-number/>
</xsl:when>
<xsl:when test="$position='center'">
<xsl:value-of select="$Version"/>
</xsl:when>
</xsl:choose>
</xsl:when>
<!-- for single sided printing, print all page numbers on the right (of the page) -->
<xsl:when test="$double.sided = 0">
<xsl:choose>
<xsl:when test="$position='center'">
<xsl:value-of select="$Version"/>
</xsl:when>
<xsl:when test="$position='right'">
<fo:page-number/>
</xsl:when>
</xsl:choose>
</xsl:when>
</xsl:choose>
</xsl:template>
<!--###################################################
Extensions
################################################### -->
<!-- These extensions are required for table printing and other stuff -->
<xsl:param name="tablecolumns.extension">0</xsl:param>
<!-- FOP provide only PDF Bookmarks at the moment -->
<xsl:param name="fop.extensions">1</xsl:param>
<xsl:param name="fop1.extensions">1</xsl:param>
<xsl:param name="ignore.image.scaling">0</xsl:param>
<!--###################################################
Table Of Contents
################################################### -->
<!-- Generate the TOCs for named components only -->
<xsl:param name="generate.toc">
book toc
</xsl:param>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">2</xsl:param>
<!-- Dot and Whitespace as separator in TOC between Label and Title-->
<xsl:param name="autotoc.label.separator" select="'. '"/>
<!--###################################################
Paper & Page Size
################################################### -->
<!-- Paper type, no headers on blank pages, no double sided printing -->
<xsl:param name="paper.type" select="'A4'"/>
<xsl:param name="double.sided">0</xsl:param>
<xsl:param name="headers.on.blank.pages">0</xsl:param>
<xsl:param name="footers.on.blank.pages">0</xsl:param>
<!-- Space between paper border and content (chaotic stuff, don't touch) -->
<xsl:param name="page.margin.top">5mm</xsl:param>
<xsl:param name="region.before.extent">10mm</xsl:param>
<xsl:param name="body.margin.top">10mm</xsl:param>
<xsl:param name="body.margin.bottom">15mm</xsl:param>
<xsl:param name="region.after.extent">10mm</xsl:param>
<xsl:param name="page.margin.bottom">0mm</xsl:param>
<xsl:param name="page.margin.outer">18mm</xsl:param>
<xsl:param name="page.margin.inner">18mm</xsl:param>
<!-- No intendation of Titles -->
<xsl:param name="title.margin.left">0pc</xsl:param>
<!--###################################################
Fonts & Styles
################################################### -->
<!-- Left aligned text and no hyphenation -->
<xsl:param name="alignment">justify</xsl:param>
<xsl:param name="hyphenate">false</xsl:param>
<!-- Default Font size -->
<xsl:param name="body.font.master">11</xsl:param>
<xsl:param name="body.font.small">8</xsl:param>
<!-- Line height in body text -->
<xsl:param name="line-height">1.4</xsl:param>
<!-- Monospaced fonts are smaller than regular text -->
<xsl:attribute-set name="monospace.properties">
<xsl:attribute name="font-family">
<xsl:value-of select="$monospace.font.family"/>
</xsl:attribute>
<xsl:attribute name="font-size">0.8em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Tables
################################################### -->
<!-- The table width should be adapted to the paper size -->
<xsl:param name="default.table.width">17.4cm</xsl:param>
<!-- Some padding inside tables -->
<xsl:attribute-set name="table.cell.padding">
<xsl:attribute name="padding-left">4pt</xsl:attribute>
<xsl:attribute name="padding-right">4pt</xsl:attribute>
<xsl:attribute name="padding-top">4pt</xsl:attribute>
<xsl:attribute name="padding-bottom">4pt</xsl:attribute>
</xsl:attribute-set>
<!-- Only hairlines as frame and cell borders in tables -->
<xsl:param name="table.frame.border.thickness">0.1pt</xsl:param>
<xsl:param name="table.cell.border.thickness">0.1pt</xsl:param>
<!--###################################################
Labels
################################################### -->
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel">1</xsl:param>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<!--###################################################
Titles
################################################### -->
<!-- Chapter title size -->
<xsl:attribute-set name="chapter.titlepage.recto.style">
<xsl:attribute name="text-align">left</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.8"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
</xsl:attribute-set>
<!-- Why is the font-size for chapters hardcoded in the XSL FO templates?
Let's remove it, so this sucker can use our attribute-set only... -->
<xsl:template match="title" mode="chapter.titlepage.recto.auto.mode">
<fo:block xmlns:fo="http://www.w3.org/1999/XSL/Format"
xsl:use-attribute-sets="chapter.titlepage.recto.style">
<xsl:call-template name="component.title">
<xsl:with-param name="node" select="ancestor-or-self::chapter[1]"/>
</xsl:call-template>
</fo:block>
</xsl:template>
<!-- Sections 1, 2 and 3 titles have a small bump factor and padding -->
<xsl:attribute-set name="section.title.level1.properties">
<xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.5"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="section.title.level2.properties">
<xsl:attribute name="space-before.optimum">0.6em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.6em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.6em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.25"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="section.title.level3.properties">
<xsl:attribute name="space-before.optimum">0.4em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.4em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.4em</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 1.0"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<!-- Titles of formal objects (tables, examples, ...) -->
<xsl:attribute-set name="formal.title.properties" use-attribute-sets="normal.para.spacing">
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="hyphenate">false</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.4em</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.6em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.8em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Programlistings
################################################### -->
<!-- Verbatim text formatting (programlistings) -->
<xsl:attribute-set name="monospace.verbatim.properties">
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.small * 1.0"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="verbatim.properties">
<xsl:attribute name="space-before.minimum">1em</xsl:attribute>
<xsl:attribute name="space-before.optimum">1em</xsl:attribute>
<xsl:attribute name="space-before.maximum">1em</xsl:attribute>
<xsl:attribute name="border-color">#444444</xsl:attribute>
<xsl:attribute name="border-style">solid</xsl:attribute>
<xsl:attribute name="border-width">0.1pt</xsl:attribute>
<xsl:attribute name="padding-top">0.5em</xsl:attribute>
<xsl:attribute name="padding-left">0.5em</xsl:attribute>
<xsl:attribute name="padding-right">0.5em</xsl:attribute>
<xsl:attribute name="padding-bottom">0.5em</xsl:attribute>
<xsl:attribute name="margin-left">0.5em</xsl:attribute>
<xsl:attribute name="margin-right">0.5em</xsl:attribute>
</xsl:attribute-set>
<!-- Shade (background) programlistings -->
<xsl:param name="shade.verbatim">1</xsl:param>
<xsl:attribute-set name="shade.verbatim.style">
<xsl:attribute name="background-color">#F0F0F0</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
Callouts
################################################### -->
<!-- Use images for callouts instead of (1) (2) (3) -->
<xsl:param name="callout.graphics">0</xsl:param>
<xsl:param name="callout.unicode">1</xsl:param>
<!-- Place callout marks at this column in annotated areas -->
<xsl:param name="callout.defaultcolumn">90</xsl:param>
<!--###################################################
Admonitions
################################################### -->
<!-- Use nice graphics for admonitions -->
<xsl:param name="admon.graphics">'1'</xsl:param>
<xsl:param name="admon.graphics.path">src/docbkx/resources/images/admons/</xsl:param>
<!--###################################################
Misc
################################################### -->
<!-- Placement of titles -->
<xsl:param name="formal.title.placement">
figure after
example before
equation before
table before
procedure before
</xsl:param>
<!-- Format Variable Lists as Blocks (prevents horizontal overflow) -->
<xsl:param name="variablelist.as.blocks">1</xsl:param>
<!-- The horrible list spacing problems -->
<xsl:attribute-set name="list.block.spacing">
<xsl:attribute name="space-before.optimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.minimum">0.8em</xsl:attribute>
<xsl:attribute name="space-before.maximum">0.8em</xsl:attribute>
<xsl:attribute name="space-after.optimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.minimum">0.1em</xsl:attribute>
<xsl:attribute name="space-after.maximum">0.1em</xsl:attribute>
</xsl:attribute-set>
<!--###################################################
colored and hyphenated links
################################################### -->
<xsl:template match="ulink">
<fo:basic-link external-destination="{@url}"
xsl:use-attribute-sets="xref.properties"
text-decoration="underline"
color="blue">
<xsl:choose>
<xsl:when test="count(child::node())=0">
<xsl:value-of select="@url"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</fo:basic-link>
</xsl:template>
<xsl:template match="link">
<fo:basic-link internal-destination="{@linkend}"
xsl:use-attribute-sets="xref.properties"
text-decoration="underline"
color="blue">
<xsl:choose>
<xsl:when test="count(child::node())=0">
<xsl:value-of select="@linkend"/>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates/>
</xsl:otherwise>
</xsl:choose>
</fo:basic-link>
</xsl:template>
<!--
<xsl:template match="xref">
<fo:basic-link internal-destination="{@linkend}"
xsl:use-attribute-sets="xref.properties"
text-decoration="underline"
color="blue">
<xsl:apply-templates/>
</fo:basic-link>
</xsl:template>
-->
</xsl:stylesheet>

View File

@@ -1,44 +0,0 @@
<?xml version='1.0'?>
<!--
Simple highlighter for FO/PDF output. Follows the Eclipse color scheme.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xslthl="http://xslthl.sf.net"
exclude-result-prefixes="xslthl"
version='1.0'>
<xsl:template match='xslthl:keyword'>
<fo:inline font-weight="bold" color="#7F0055"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:comment'>
<fo:inline font-style="italic" color="#3F5F5F"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:oneline-comment'>
<fo:inline font-style="italic" color="#3F5F5F"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:multiline-comment'>
<fo:inline font-style="italic" color="#3F5FBF"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:tag'>
<fo:inline color="#3F7F7F"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:attribute'>
<fo:inline color="#7F007F"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:value'>
<fo:inline color="#2A00FF"><xsl:apply-templates/></fo:inline>
</xsl:template>
<xsl:template match='xslthl:string'>
<fo:inline color="#2A00FF"><xsl:apply-templates/></fo:inline>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,42 +0,0 @@
<?xml version='1.0'?>
<!--
Simple highlighter for HTML output. Follows the Eclipse color scheme.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xslthl="http://xslthl.sf.net"
exclude-result-prefixes="xslthl"
version='1.0'>
<xsl:template match='xslthl:keyword'>
<span class="hl-keyword"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:comment'>
<span class="hl-comment"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:oneline-comment'>
<span class="hl-comment"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:multiline-comment'>
<span class="hl-multiline-comment"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:tag'>
<span class="hl-tag"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:attribute'>
<span class="hl-attribute"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:value'>
<span class="hl-value"><xsl:value-of select='.'/></span>
</xsl:template>
<xsl:template match='xslthl:string'>
<span class="hl-string"><xsl:value-of select='.'/></span>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,107 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This is the XSL HTML configuration file for the Spring
Reference Documentation.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:xslthl="http://xslthl.sf.net"
exclude-result-prefixes="xslthl"
version="1.0">
<xsl:import href="urn:docbkx:stylesheet"/>
<xsl:import href="highlight.xsl"/>
<!--###################################################
HTML Settings
################################################### -->
<!-- These extensions are required for table printing and other stuff -->
<xsl:param name="tablecolumns.extension">0</xsl:param>
<xsl:param name="graphicsize.extension">0</xsl:param>
<xsl:param name="ignore.image.scaling">1</xsl:param>
<!--###################################################
Table Of Contents
################################################### -->
<!-- Generate the TOCs for named components only -->
<xsl:param name="generate.toc">
book toc
</xsl:param>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">3</xsl:param>
<!--###################################################
Labels
################################################### -->
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel">1</xsl:param>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<!--###################################################
Callouts
################################################### -->
<!-- Use images for callouts instead of (1) (2) (3) -->
<xsl:param name="callout.graphics">1</xsl:param>
<!-- Place callout marks at this column in annotated areas -->
<xsl:param name="callout.defaultcolumn">90</xsl:param>
<!--###################################################
Admonitions
################################################### -->
<!-- Use nice graphics for admonitions -->
<xsl:param name="admon.graphics">1</xsl:param>
<xsl:param name="admon.graphics.path">images/admons/</xsl:param>
<!--###################################################
Misc
################################################### -->
<!-- Placement of titles -->
<xsl:param name="formal.title.placement">
figure after
example before
equation before
table before
procedure before
</xsl:param>
<xsl:template match="author" mode="titlepage.mode">
<xsl:if test="name(preceding-sibling::*[1]) = 'author'">
<xsl:text>, </xsl:text>
</xsl:if>
<span class="{name(.)}">
<xsl:call-template name="person.name"/>
<!-- (<xsl:value-of select="affiliation"/>) -->
<xsl:apply-templates mode="titlepage.mode" select="./contrib"/>
</span>
</xsl:template>
<xsl:template match="authorgroup" mode="titlepage.mode">
<div class="{name(.)}">
<h2>Authors</h2>
<p/>
<xsl:apply-templates mode="titlepage.mode"/>
</div>
</xsl:template>
<!--###################################################
Headers and Footers
################################################### -->
<!-- let's have a Spring and I21 banner across the top of each page -->
<xsl:template name="user.header.navigation">
<div style="background-color:white;border:none;height:73px;border:1px solid black;">
<a style="border:none;" href="http://www.springframework.org/osgi/"
title="The Spring Framework - Spring Data">
<img style="border:none;" src="images/xdev-spring_logo.jpg"/>
</a>
<a style="border:none;" href="http://www.SpringSource.com/" title="SpringSource - Spring from the Source">
<img style="border:none;position:absolute;padding-top:5px;right:42px;" src="images/s2-banner-rhs.png"/>
</a>
</div>
</xsl:template>
</xsl:stylesheet>

View File

@@ -1,221 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
This is the XSL HTML configuration file for the Spring Reference Documentation.
-->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:import href="urn:docbkx:stylesheet"/>
<xsl:import href="highlight.xsl"/>
<!--###################################################
HTML Settings
################################################### -->
<xsl:param name="chunk.section.depth">'5'</xsl:param>
<xsl:param name="use.id.as.filename">'1'</xsl:param>
<xsl:param name="tablecolumns.extension">0</xsl:param>
<xsl:param name="graphicsize.extension">0</xsl:param>
<xsl:param name="ignore.image.scaling">1</xsl:param>
<!--###################################################
Table Of Contents
################################################### -->
<!-- Generate the TOCs for named components only -->
<xsl:param name="generate.toc">
book toc
qandaset toc
</xsl:param>
<!-- Show only Sections up to level 3 in the TOCs -->
<xsl:param name="toc.section.depth">3</xsl:param>
<!--###################################################
Labels
################################################### -->
<!-- Label Chapters and Sections (numbering) -->
<xsl:param name="chapter.autolabel">1</xsl:param>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="section.label.includes.component.label" select="1"/>
<!--###################################################
Callouts
################################################### -->
<!-- Place callout marks at this column in annotated areas -->
<xsl:param name="callout.graphics">1</xsl:param>
<xsl:param name="callout.defaultcolumn">90</xsl:param>
<!--###################################################
Admonitions
################################################### -->
<!-- Use nice graphics for admonitions -->
<xsl:param name="admon.graphics">1</xsl:param>
<xsl:param name="admon.graphics.path">images/admons/</xsl:param>
<!--###################################################
Misc
################################################### -->
<!-- Placement of titles -->
<xsl:param name="formal.title.placement">
figure after
example before
equation before
table before
procedure before
</xsl:param>
<xsl:template match="author" mode="titlepage.mode">
<xsl:if test="name(preceding-sibling::*[1]) = 'author'">
<xsl:text>, </xsl:text>
</xsl:if>
<span class="{name(.)}">
<xsl:call-template name="person.name"/>
(<xsl:value-of select="affiliation"/>)
<xsl:apply-templates mode="titlepage.mode" select="./contrib"/>
<!--
<xsl:apply-templates mode="titlepage.mode" select="./affiliation"/>
-->
</span>
</xsl:template>
<xsl:template match="authorgroup" mode="titlepage.mode">
<div class="{name(.)}">
<h2>Authors</h2>
<p/>
<xsl:apply-templates mode="titlepage.mode"/>
</div>
</xsl:template>
<!--###################################################
Headers and Footers
################################################### -->
<!-- let's have a Spring and I21 banner across the top of each page -->
<xsl:template name="user.header.navigation">
<div style="background-color:white;border:none;height:73px;border:1px solid black;">
<a style="border:none;" href="http://www.springframework.org/osgi/"
title="The Spring Framework - Spring Data">
<img style="border:none;" src="images/xdev-spring_logo.jpg"/>
</a>
<a style="border:none;" href="http://www.SpringSource.com/" title="SpringSource - Spring from the Source">
<img style="border:none;position:absolute;padding-top:5px;right:42px;" src="images/s2-banner-rhs.png"/>
</a>
</div>
</xsl:template>
<!-- no other header navigation (prev, next, etc.) -->
<xsl:template name="header.navigation"/>
<xsl:param name="navig.showtitles">1</xsl:param>
<!-- let's have a 'Sponsored by SpringSource' strapline (or somesuch) across the bottom of each page -->
<xsl:template name="footer.navigation">
<xsl:param name="prev" select="/foo"/>
<xsl:param name="next" select="/foo"/>
<xsl:param name="nav.context"/>
<xsl:variable name="home" select="/*[1]"/>
<xsl:variable name="up" select="parent::*"/>
<xsl:variable name="row1" select="count($prev) &gt; 0
or count($up) &gt; 0
or count($next) &gt; 0"/>
<xsl:variable name="row2" select="($prev and $navig.showtitles != 0)
or (generate-id($home) != generate-id(.)
or $nav.context = 'toc')
or ($chunk.tocs.and.lots != 0
and $nav.context != 'toc')
or ($next and $navig.showtitles != 0)"/>
<xsl:if test="$suppress.navigation = '0' and $suppress.footer.navigation = '0'">
<div class="navfooter">
<xsl:if test="$footer.rule != 0">
<hr/>
</xsl:if>
<xsl:if test="$row1 or $row2">
<table width="100%" summary="Navigation footer">
<xsl:if test="$row1">
<tr>
<td width="40%" align="left">
<xsl:if test="count($prev)>0">
<a accesskey="p">
<xsl:attribute name="href">
<xsl:call-template name="href.target">
<xsl:with-param name="object" select="$prev"/>
</xsl:call-template>
</xsl:attribute>
<xsl:call-template name="navig.content">
<xsl:with-param name="direction" select="'prev'"/>
</xsl:call-template>
</a>
</xsl:if>
<xsl:text>&#160;</xsl:text>
</td>
<td width="20%" align="center">
<xsl:choose>
<xsl:when test="$home != . or $nav.context = 'toc'">
<a accesskey="h">
<xsl:attribute name="href">
<xsl:call-template name="href.target">
<xsl:with-param name="object" select="$home"/>
</xsl:call-template>
</xsl:attribute>
<xsl:call-template name="navig.content">
<xsl:with-param name="direction" select="'home'"/>
</xsl:call-template>
</a>
<xsl:if test="$chunk.tocs.and.lots != 0 and $nav.context != 'toc'">
<xsl:text>&#160;|&#160;</xsl:text>
</xsl:if>
</xsl:when>
<xsl:otherwise>&#160;</xsl:otherwise>
</xsl:choose>
<xsl:if test="$chunk.tocs.and.lots != 0 and $nav.context != 'toc'">
<a accesskey="t">
<xsl:attribute name="href">
<xsl:apply-templates select="/*[1]" mode="recursive-chunk-filename">
<xsl:with-param name="recursive" select="true()"/>
</xsl:apply-templates>
<xsl:text>-toc</xsl:text>
<xsl:value-of select="$html.ext"/>
</xsl:attribute>
<xsl:call-template name="gentext">
<xsl:with-param name="key" select="'nav-toc'"/>
</xsl:call-template>
</a>
</xsl:if>
</td>
<td width="40%" align="right">
<xsl:text>&#160;</xsl:text>
<xsl:if test="count($next)>0">
<a accesskey="n">
<xsl:attribute name="href">
<xsl:call-template name="href.target">
<xsl:with-param name="object" select="$next"/>
</xsl:call-template>
</xsl:attribute>
<xsl:call-template name="navig.content">
<xsl:with-param name="direction" select="'next'"/>
</xsl:call-template>
</a>
</xsl:if>
</td>
</tr>
</xsl:if>
<xsl:if test="$row2">
<tr>
<td width="40%" align="left" valign="top">
<xsl:if test="$navig.showtitles != 0">
<xsl:apply-templates select="$prev" mode="object.title.markup"/>
</xsl:if>
<xsl:text>&#160;</xsl:text>
</td>
<td width="20%" align="center">
<span style="color:white;font-size:90%;">
<a href="http://www.SpringSource.com/"
title="SpringSource - Spring from the Source">Sponsored by SpringSource
</a>
</span>
</td>
<td width="40%" align="right" valign="top">
<xsl:text>&#160;</xsl:text>
<xsl:if test="$navig.showtitles != 0">
<xsl:apply-templates select="$next" mode="object.title.markup"/>
</xsl:if>
</td>
</tr>
</xsl:if>
</table>
</xsl:if>
</div>
</xsl:if>
</xsl:template>
</xsl:stylesheet>