blob: d26264da625424bb1fa941b1f805ec5bc8f303ff [file] [log] [blame]
\documentclass[a4paper,12pt]{article}
\usepackage{zed-cm}
\usepackage{graphicx}
\markboth{Unclassified, v0.1}{Unclassified, v0.1}
\pagestyle{myheadings}
\begin{document}
\parskip 2 pt
\parindent 10 pt
\title{A Formal Model of the OSGi Web Container (0.1)}
\author{Rob Harrop}
\maketitle
% The following three commands ensure the title page is stamped as
% confidential without a page number. Page numbering is started at the
% table of contents.
\thispagestyle{myheadings}
\pagenumbering{roman}
\setcounter{page}{0}
%=============================================================================
We model aspects of OSGi Web Container (RFC66).
%\clearpage
%\pagenumbering{roman}
%\tableofcontents
% Type checking hacks
\newcommand{\true}{true}
\newcommand{\false}{false}
%\renewcommand{\empty}{\emptyset}
\newcommand{\ModuleDefZero}{ModuleDef_0}
\newcommand{\ModuleDefOne}{ModuleDef_1}
\newcommand{\ModuleDefTwo}{ModuleDef_2}
\newcommand{\ModuleDefThree}{ModuleDef_3}
\newcommand{\ModuleDefFour}{ModuleDef_4}
\newcommand{\defaultsTo}{\mathbin{\sf defaultsTo}}
%=============================================================================
\clearpage
\tableofcontents
\clearpage
\pagenumbering{arabic}
\section{Introduction}
This specification describes the OSGi Web Container service. The Web Container service extends an OSGi service platform to support the installation of WAR files adhering to the Servlet 2.5 specification.
The Web Container provides no new installation artefacts for the OSGi service platform. Instead, WAR files are installed into the service platform as standard OSGi bundles.
The Web Container provides an \emph{extender} that recognises bundles that are also valid WAR files. We refer to these bundles as \emph{WAR bundles}. The extender reacts to {\tt STARTED} and {\tt STOPPED} events on these WAR bundles and starts and stops the corresponding web application appropriately.
The Web Container provides two main installation modes. The first mode allows a WAR bundle to be installed directly into the Web Container. In this mode, the Web Container performs no transformations to the bundle during or after installation.
The second mode allows for WAR files to be transformed during installation, with the container ensuring that result is a valid WAR bundle. The transformation process is complex and considers input from three sources. It should be noted that the WAR file going through the transformation may already be a valid WAR bundle. This specification aims to capture the exact semantics of the transformations being performed.
\begin{thebibliography}{99}
\bibitem{OSGi} OSGi Service Platform Core Specification v4.1, April 2007 {\tt http://www.OSGi.org}
\bibitem{Servlet 2.5} Servlet 2.5 Specification \\
{\tt http://jcp.org/aboutJava/communityprocess/mrel/jsr154/index2.html}
\bibitem{Extender Model} The OSGi Extender Model \\
{\tt http://www.osgi.org/blog/2007/02/osgi-extender-model.html}
\end{thebibliography}
%=============================================================================
\clearpage
\section{Basic Types}
\label{cha:basictypes}
We are interested in various identifiers, names, versions and attributes of both bundles and WARs.
\subsection{Identifying Bundles}
Bundles are uniquely identified by their symbolic name and version
\begin{zed}
[SymbolicName, Version]
\end{zed}
We are interested in the ordering of Versions. There is an earliest version number which we can name here. All other versions are later than this one.
\begin{axdef}
EARLIEST\_VERSION : Version
\end{axdef}
We define a relation between all Versions and the Versions that are greater than or equal to those Versions
\begin{axdef}
vgeq : Version \rel Version
\where
\forall v : \dom vgeq @ v \mapsto v \in vgeq \\
\forall v1, v2 : \dom vgeq | v1 \neq v2 @ v1 \mapsto v2 \in vgeq \implies v2 \mapsto v1 \notin vgeq \\
\lnot (\exists v : \dom vgeq | v \neq EARLIEST\_VERSION \\
\t1 @ v \mapsto EARLIEST\_VERSION \in vgeq) \\
\end{axdef}
\subsection{Bundle Manifest Versions}
Bundles have a {\tt Bundle-ManifestVersion} that controls the behaviour applied to the bundle by the OSGi Service Platform. {\tt Bundle-ManifestVersions} are simply numbers:
\begin{zed}
BundleManifestVersion == \nat
\end{zed}
\subsection{Bundle Class Path}
Each bundle has a private class path. The class path is made up of class path entries:
\begin{zed}
[BundleClassPathEntry]
\end{zed}
\subsection{Imports and Exports}
Bundles may import and export zero or more packages. An imported package is quite different from an exported package
\begin{zed}
[PackageName]
\end{zed}
\begin{schema}{ImportedPackage}
name: PackageName \\
version: Version
\end{schema}
\begin{zed}
[ExportedPackage]
\end{zed}
All WAR files and bundles have a file name associated with them
\begin{zed}
[FileName]
\end{zed}
%=============================================================================
\clearpage
\section{Transformation}
\label{cha:transformation}
The transformation process takes a WAR file and generates a valid bundle.
Transformations to a given property in the WAR generally operate on the value of the property in the WAR, an optional user value for this property and a default value for this property.
\subsection{Bundle Symbolic Name Transformation}
For the purpose of this specification we only allow bundles that comply with OSGi R4.1 or above. Therefore, all bundles must have a symbolic name
\begin{schema}{BundleSN}
bsn: SymbolicName
\end{schema}
WAR files optionally have a symbolic name
\begin{schema}{WarSN}
wsn: Opt~SymbolicName
\end{schema}
A mechanism exists for translating the file name of the WAR into a suitable symbolic name.
\begin{axdef}
defaultSymbolicName: FileName \fun SymbolicName
\end{axdef}
WAR symbolic name are transformed into Bundle symbolic names according to the following rules:
\begin{itemize}
\item if the user supplies a symbolic name it is used; otherwise
\item if the WAR already has a symbolic name it is used; otherwise
\item a symbolic name is generated from the file name
\end{itemize}
\begin{schema}{TransformSN}
WarSN \\
BundleSN' \\
usn? : Opt~SymbolicName \\
fn? : FileName \\
\where
bsn' = usn? \defaultsTo (wsn \defaultsTo (defaultSymbolicName ~ fn? ) )
\end{schema}
\subsection{Bundle Version Transformation}
Bundles must have a version
\begin{schema}{BundleVersion}
bv: Version
\end{schema}
WARs may optionally have a version
\begin{schema}{WarVersion}
wv: Opt ~ Version
\end{schema}
WAR versions are transformed into Bundle versions according to the following rules:
\begin{itemize}
\item if the user supplies a version it is used; otherwise
\item if the WAR already has a version it is used; otherwise
\item the default {\tt EARLIEST\_VERSION} is used
\end{itemize}
\begin{schema}{TransformVersion}
WarVersion \\
BundleVersion' \\
uv?: Opt ~ Version
\where
bv' = uv? \defaultsTo (wv \defaultsTo EARLIEST\_VERSION)
\end{schema}
\subsection{Bundle Manifest Version Transformation}
Bundles must have a bundle manifest version of at least 2
\begin{schema}{BundleMV}
bmv : BundleManifestVersion \\
\where
bmv \geq 2 \\
\end{schema}
WARs may optionally have a manifest version. There is no restriction on the value of a WARs bundle manifest version
\begin{schema}{WarMV}
wmv : Opt ~ BundleManifestVersion \\
\end{schema}
WAR bundle manifest versions are transformed into bundle manifest versions according to the following rules
\begin{itemize}
\item if the user supplies a bundle manifest version greater than 2 it will be used; otherwise
\item if the WAR contains a bundle manifest version greater than 2 it will be used; otherwise
\item the bundle manifest version is set to 2
\end{itemize}
You should note that the bundle manifest version must always be at least 2.
\begin{schema}{TransformMV}
WarMV \\
BundleMV' \\
umv? : Opt ~ BundleManifestVersion \\
\where
\LET mv == umv? \defaultsTo (wmv \defaultsTo 2) @ \\
\t1 mv \geq 2 \implies bmv' = mv \land mv < 2 \implies bmv' = 2
\end{schema}
\subsection{Bundle Class Path Transformation}
All bundles have a class path with at least one entry. The bundle class path cannot have duplicate entries.
\begin{schema}{BundleClassPath}
bcp: \iseq BundleClassPathEntry
\where
\# bcp > 0 \\
\end{schema}
WARs need not have bundle class path entries already, and they may have duplicates entries.
\begin{schema}{WarClassPath}
wcp: \seq BundleClassPathEntry
\end{schema}
The transformation process of the WAR class path must transform the bundle class path to meet the following constraints:
\begin{itemize}
\item all unique entries in the class path of the WAR must be present in the transformed class path
\item {\tt WEB-INF/classes} must be the first entry in the transformed class path
\item all library JARs in {\tt WEB-INF/lib} must have a corresponding in the transformed class path
\end{itemize}
We need a way to represent the {\tt WEB-INF/classes} bundle class path entry
\begin{axdef}
WEB\_INF\_CLASSES : BundleClassPathEntry \\
\end{axdef}
We also need a way to represent library JARs
\begin{zed}
[Lib]
\end{zed}
A library JAR can be converted into a class path entry
\begin{axdef}
libToClassPath : Lib \fun BundleClassPathEntry \\
\end{axdef}
Thus the bundle class path transformation is defined as
\begin{schema}{TransformBundleClassPath}
WarClassPath \\
BundleClassPath' \\
libs? : \power Lib \\
\where
\ran wcp \subseteq \ran bcp' \\
libToClassPath \limg libs? \rimg \subseteq \ran bcp' \\
head ~ bcp' = WEB\_INF\_CLASSES \\
\end{schema}
\subsection{Import Package Transformation}
A bundle can import any number of packages. It may only import a package with a given name once
\begin{schema}{BundleImports}
bi: \power ImportedPackage \\
\where
\forall p1, p2 : bi | p1.name = p2.name @ p1 = p2 \\
\end{schema}
A WAR may import any number of packages. There are no restrictions on the packages imported
\begin{schema}{WarImports}
wi : \power ImportedPackage \\
\end{schema}
\begin{schema}{TransformImports}
WarImports \\
BundleImports' \\
ui? : \power ImportedPackage \\
\end{schema}
\subsection{Full Transformation}
\begin{zed}
Bundle \defs BundleSN \land BundleVersion \land BundleMV \land BundleClassPath
\end{zed}
\begin{zed}
War \defs WarSN \land WarVersion \land WarMV \land WarClassPath
\end{zed}
\begin{zed}
TransformWarToBundle \defs TransformSN \land TransformVersion \\
\t1 \land TransformMV \land TransformBundleClassPath
\end{zed}
\end{document}