felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Felix: iPOJO in 10 minutes (page edited)
Date Mon, 21 Apr 2008 18:31:02 GMT
<html>
<head>
    <base href="http://cwiki.apache.org/confluence" />
    <style type="text/css">
    <!--
    body, p, td, table, tr, .bodytext, .stepfield {
	font-family: Verdana, arial, sans-serif;
	font-size: 11px;
	line-height: 16px;
	color: #000000;
	font-weight: normal;
}
#PageContent {
	text-align: left;
	background-color: #fff;
	padding: 0px;
	margin: 0px;
    padding-bottom:20px;
}
/*
** when this stylesheet is used for the Tiny MCE Wysiwyg editor's edit area, we can't
** use an id=PageContent or class=wiki-content, so we must
** set the body style to that used for PageContent, and p to that used for wiki-content.
*/

body {
	margin: 0px;
	padding: 0px;
	text-align: center;
    background-color: #f0f0f0;
}

@media print {

body {
    background-color: #fff;
}

}

.monospaceInput {
    font:12px monospace
}

.wiki-content p, .commentblock p {
    margin: 16px 0px 16px 0px;
    padding: 0px;
}

.wiki-content-preview {
    padding: 5px;
    border-left: 1px solid #3c78b5;
    border-right: 1px solid #3c78b5;
}

ul, ol {
    margin-top: 2px;
    margin-bottom: 2px;
    padding-top: 0px;
    padding-bottom: 0px;
}

pre {
    padding: 0px;
    margin-top: 5px;
    margin-left: 15px;
    margin-bottom: 5px;
    margin-right: 5px;
    text-align: left;
}

.helpheading {
    font-weight: bold;
    background-color: #D0D9BD;
        border-bottom: 1px solid #3c78b5;
        padding: 4px 4px 4px 4px;
        margin: 0px;
        margin-top: 10px;
}
.helpcontent {
        padding: 4px 4px 20px 4px;
    background-color: #f5f7f1;
}

.code {
 	border: 1px dashed #3c78b5;
    font-size: 11px;
	font-family: Courier;
    margin: 10px;
	line-height: 13px;
}

.focusedComment {
    background: #ffffce;
}

.commentBox, .focusedComment {
    padding: 10px;
    margin: 5px 0 5px 0;
    border: 1px #bbb solid;
}

.codeHeader {
    background-color: #f0f0f0;
 	border-bottom: 1px dashed #3c78b5;
    padding: 3px;
	text-align: center;
}

.codeContent {
    text-align: left;
    background-color: #f0f0f0;
    padding: 3px;
}

.preformatted {
 	border: 1px dashed #3c78b5;
    font-size: 11px;
	font-family: Courier;
    margin: 10px;
	line-height: 13px;
}

.preformattedHeader {
    background-color: #f0f0f0;
 	border-bottom: 1px dashed #3c78b5;
    padding: 3px;
	text-align: center;
}

.preformattedContent {
    background-color: #f0f0f0;
    padding: 3px;
}

.panel {
 	border: 1px dashed #3c78b5;
    margin: 10px;
    margin-top: 0px;
}

.panelHeader {
    background-color: #f0f0f0;
 	border-bottom: 1px dashed #3c78b5;
    padding: 3px;
	text-align: center;
}

.panelContent {
    background-color: #f0f0f0;
    padding: 5px;
}

.anonymousAlert {
    background-color: #f0f0f0;
 	border: 1px dashed red;
    font-size: 11px;
    padding: 10px 5px 10px 5px;
    margin: 4px;
	line-height: 13px;
}

.lockAlert {
    background-color: #f0f0f0;
    width: 50%;
 	border: 1px dashed red;
    font-size: 11px;
    padding: 10px 5px 10px 5px;
    margin: 4px;
	line-height: 13px;
}


.code-keyword {
  color: #000091;
  background-color: inherit;
}

.code-object {
  color: #910091;
  background-color: inherit;
}

.code-quote {
  color: #009100;
  background-color: inherit;
}

.code-comment {
  color: #808080;
  background-color: inherit;
}


.code-xml .code-keyword {
  color: inherit;
  font-weight: bold;
}

.code-tag {
  color: #000091;
  background-color: inherit;
}

.breadcrumbs {
    background-color: #f0f0f0;
 	border-color: #3c78b5;
	border-width: 1px 0px 1px 0px;
	border-style: solid;
    font-size: 11px;
    padding: 3px 0px 3px 0px;
}

.navmenu {
    border: 1px solid #ccc;
}

.menuheading {
    font-weight: bold;
    background-color: #f0f0f0;
 	border-bottom: 1px solid #3c78b5;
	padding: 4px 4px 2px 4px;
}

.menuitems {
	padding: 4px 4px 20px 4px;
}

.rightpanel {
    border-left: 1px solid #ccc;
    border-bottom: 1px solid #ccc;
}

#helpheading {
    text-align: left;
    font-weight: bold;
    background-color: #D0D9BD;
 	border-bottom: 1px solid #3c78b5;
	padding: 4px 4px 4px 4px;
	margin: 0px;
}
#helpcontent {
	padding: 4px 4px 4px 4px;
    background-color: #f5f7f1;
}
.helptab-unselected {
    font-weight: bold;
	padding: 5px;
    background-color: #f5f7f1;
}
.helptab-selected {
    font-weight: bold;
    background-color: #D0D9BD;
	padding: 5px;
}
.helptabs {
    margin: 0px;
    background-color: #f5f7f1;
	padding: 5px;
}
.infopanel-heading {
    font-weight: bold;
	padding: 4px 0px 2px 0px;
}

.pagebody {
}

.pageheader {
	padding: 5px 5px 5px 0px;
 	border-bottom: 1px solid #3c78b5;
}

.pagetitle {
	font-size: 22px;
	font-weight: bold;
	font-family: Arial, sans-serif;
	color: #003366;
}

.newpagetitle {
    color: #ccc !important;
}

.steptitle {
	font-size: 18px;
	font-weight: bold;
	font-family: Arial, sans-serif;
	color: #003366;
	margin-bottom: 7px;
}

.substeptitle {
    font-size: 12px;
    font-weight: bold;
    font-family: Arial, sans-serif;
    color: #003366;
    margin: 2px 4px 4px 4px;
    padding: 2px 4px 1px 4px;
}

.stepdesc {
    font-family: Verdana, arial, sans-serif;
	font-size: 11px;
	line-height: 16px;
	font-weight: normal;
    color: #666666;
    margin-top: 7px;
    margin-bottom: 7px;
}

.steplabel {
    font-weight: bold;
    margin-right: 4px;
    color: black;
    float: left;
    width: 15%;
    text-align: right;
}

.stepfield {
    background: #f0f0f0;
    padding: 5px;
}

.submitButtons{
    margin-top:5px;
    text-align:right;
}

.formtitle {
	font-size: 12px;
	font-weight: bold;
	font-family: Arial, sans-serif;
	color: #003366;
}

.sectionbottom {
    border-bottom: 1px solid #3c78b5;
}

.topRow {
    border-top: 2px solid #3c78b5;
}

.tabletitle {
	font-size: 14px;
	font-weight: bold;
	font-family: Arial, sans-serif;
    padding: 3px 0px 2px 0px;
    margin: 8px 4px 2px 0px;
	color: #003366;
	border-bottom: 2px solid #3c78b5;
}
.pagesubheading {
    color: #666666;
    font-size: 10px;
    padding: 0px 0px 5px 0px;
}

HR {
	color: 3c78b5;
	height: 1;
}

A:link, A:visited, A:active, A:hover {
	color: #003366;
}

h1 A:link, h1 A:visited, h1 A:active {
	text-decoration: none;
}

h1 A:hover {
    border-bottom: 1px dotted #003366;
}

.wiki-content > :first-child, .commentblock > :first-child {
    margin-top: 3px;
}

.logocell {
    padding: 10px;
}

input {
	font-family: verdana, geneva, arial, sans-serif;
	font-size: 11px;
	color: #000000;
}

textarea, textarea.editor {
	font-family: verdana, geneva, arial, sans-serif;
	font-size: 11px;
	color: #333333;
}

/* use logoSpaceLink instead.
.spacenametitle {
	font: 21px/31px Impact, Arial, Helvetica;
    font-weight: 100;
    color: #999999;
	margin: 0px;
}
.spacenametitle img {
  margin: 0 0 -4px 0;
}
.spacenametitle a {
    text-decoration: none;
    color: #999999;
}
.spacenametitle a:visited {
    text-decoration: none;
    color: #999999;
}*/

.spacenametitle-printable {
	font: 20px/25px Impact, Arial, Helvetica;
    font-weight: 100;
    color: #999999;
	margin: 0px;
}
.spacenametitle-printable a {
    text-decoration: none;
    color: #999999;
}
.spacenametitle-printable a:visited {
    text-decoration: none;
    color: #999999;
}

.blogDate {
	font-weight: bold;
	text-decoration: none;
	color: black;
}

.blogSurtitle {
    background: #f0f0f0;
 	border: 1px solid #ddd;
	padding: 3px;
	margin: 1px 1px 10px 1px;
}

.blogHeading {
    font-size: 20px;
    line-height: normal;
    font-weight: bold;
    padding: 0px;
    margin: 0px;
}

.blogHeading a {
   text-decoration: none;
   color: black;
}

.endsection {
	align: right;
	color: #666666;
	margin-top: 10px;
}
.endsectionleftnav {
	align: right;
	color: #666666;
	margin-top: 10px;
}

h1 {
	font-size: 24px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
	color: #003366;
 	border-bottom: 1px solid #3c78b5;
	padding: 2px;
	margin: 36px 0px 4px 0px;
}

h2 {
	font-size: 18px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
 	border-bottom: 1px solid #3c78b5;
	padding: 2px;
	margin: 27px 0px 4px 0px;
}

h3 {
	font-size: 14px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
	padding: 2px;
	margin: 21px 0px 4px 0px;
}

h4 {
	font-size: 12px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
	padding: 2px;
	margin: 18px 0px 4px 0px;
}

h4.search {
	font-size: 12px;
	line-height: normal;
	font-weight: normal;
	background-color: #f0f0f0;
	padding: 4px;
	margin: 18px 0px 4px 0px;
}

h5 {
	font-size: 10px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
	padding: 2px;
	margin: 14px 0px 4px 0px;
}

h6 {
	font-size: 8px;
	line-height: normal;
	font-weight: bold;
	background-color: #f0f0f0;
	padding: 2px;
	margin: 14px 0px 4px 0px;
}

.smallfont {
    font-size: 10px;
}
.descfont {
    font-size: 10px;
    color: #666666;
}
.smallerfont {
    font-size: 9px;
}
.smalltext {
    color: #666666;
    font-size: 10px;
}
.smalltext a {
    color: #666666;
}
.smalltext-blue {
    color: #3c78b5;
    font-size: 10px;
}
.surtitle {
    margin-left: 1px;
    margin-bottom: 5px;
    font-size: 14px;
    color: #666666;
}

/* css hack found here:  http://www.fo3nix.pwp.blueyonder.co.uk/tutorials/css/hacks/ */
.navItemOver { font-size: 10px; font-weight: bold; color: #ffffff; background-color: #003366; cursor: hand; voice-family: '\'}\''; voice-family:inherit; cursor: pointer;}
.navItemOver a { color: #ffffff; background-color:#003366; text-decoration: none; }
.navItemOver a:visited { color: #ffffff; background-color:#003366; text-decoration: none; }
.navItemOver a:hover { color: #ffffff; background-color:#003366; text-decoration: none; }
.navItem { font-size: 10px; font-weight: bold; color: #ffffff; background-color: #3c78b5; }
.navItem a { color: #ffffff; text-decoration: none; }
.navItem a:hover { color: #ffffff; text-decoration: none; }
.navItem a:visited { color: #ffffff; text-decoration: none; }

div.padded { padding: 4px; }
div.thickPadded { padding: 10px; }
h3.macrolibrariestitle {
    margin: 0px 0px 0px 0px;
}

div.centered { text-align: center; margin: 10px; }
div.centered table {margin: 0px auto; text-align: left; }

.tableview table {
    margin: 0;
}

.tableview th {
    text-align: left;
    color: #003366;
    font-size: 12px;
    padding: 5px 0px 0px 5px;
    border-bottom: 2px solid #3c78b5;
}
.tableview td {
    text-align: left;
    border-color: #ccc;
    border-width: 0px 0px 1px 0px;
    border-style: solid;
    margin: 0;
    padding: 4px 10px 4px 5px;
}

.grid {
    margin: 2px 0px 5px 0px;
    border-collapse: collapse;
}
.grid th  {
    border: 1px solid #ccc;
    padding: 2px 4px 2px 4px;
    background: #f0f0f0;
    text-align: center;
}
.grid td  {
    border: 1px solid #ccc;
    padding: 3px 4px 3px 4px;
}
.gridHover {
	background-color: #f9f9f9;
}

td.infocell {
    background-color: #f0f0f0;
}
.label {
	font-weight: bold;
	color: #003366;
}

label {
	font-weight: bold;
	color: #003366;
}

.error {
	background-color: #fcc;
}

.errorBox {
	background-color: #fcc;
    border: 1px solid #c00;
    padding: 5px;
    margin: 5px;
}

.errorMessage {
	color: #c00;
}

.success {
	background-color: #dfd;
}

.successBox {
	background-color: #dfd;
    border: 1px solid #090;
    padding: 5px;
    margin-top:5px;
    margin-bottom:5px;
}

blockquote {
	padding-left: 10px;
	padding-right: 10px;
	margin-left: 5px;
	margin-right: 0px;
	border-left: 1px solid #3c78b5;
}

table.confluenceTable
{
    margin: 5px;
    border-collapse: collapse;
}

/* Added as a temporary fix for CONF-4223. The table elements appear to be inheriting the border: none attribute from the sectionMacro class */
table.confluenceTable td.confluenceTd
{
    border-width: 1px;
    border-style: solid;
    border-color: #ccc;
    padding: 3px 4px 3px 4px;
}

/* Added as a temporary fix for CONF-4223. The table elements appear to be inheriting the border: none attribute from the sectionMacro class */
table.confluenceTable th.confluenceTh
{
    border-width: 1px;
    border-style: solid;
    border-color: #ccc;
    padding: 3px 4px 3px 4px;
    background-color: #f0f0f0;
    text-align: center;
}

td.confluenceTd
{
    border-width: 1px;
    border-style: solid;
    border-color: #ccc;
    padding: 3px 4px 3px 4px;
}

th.confluenceTh
{
    border-width: 1px;
    border-style: solid;
    border-color: #ccc;
    padding: 3px 4px 3px 4px;
    background-color: #f0f0f0;
    text-align: center;
}

DIV.small {
	font-size: 9px;
}

H1.pagename {
	margin-top: 0px;
}

IMG.inline  {}

.loginform {
    margin: 5px;
    border: 1px solid #ccc;
}

/* The text how the "This is a preview" comment should be shown. */
.previewnote { text-align: center;
                font-size: 11px;
                    color: red; }

/* How the preview content should be shown */
.previewcontent { background: #E0E0E0; }

/* How the system messages should be shown (DisplayMessage.jsp) */
.messagecontent { background: #E0E0E0; }

/* How the "This page has been modified..." -comment should be shown. */
.conflictnote { }

.createlink {
    color: maroon;
}
a.createlink {
    color: maroon;
}
.templateparameter {
    font-size: 9px;
    color: darkblue;
}

.diffadded {
    background: #ddffdd;
    padding: 1px 1px 1px 4px;
	border-left: 4px solid darkgreen;
}
.diffdeleted {
    color: #999;
    background: #ffdddd;
    padding: 1px 1px 1px 4px;
	border-left: 4px solid darkred;
}
.diffnochange {
    padding: 1px 1px 1px 4px;
	border-left: 4px solid lightgrey;
}
.differror {
    background: brown;
}
.diff {
    font-family: lucida console, courier new, fixed-width;
	font-size: 12px;
	line-height: 14px;
}
.diffaddedchars {
    background-color:#99ff99;
    font-weight:bolder;
}
.diffremovedchars {
    background-color:#ff9999;
    text-decoration: line-through;
    font-weight:bolder;
}

.greybackground {
    background: #f0f0f0
}

.greybox {
 	border: 1px solid #ddd;
	padding: 3px;
	margin: 1px 1px 10px 1px;
}

.borderedGreyBox {
    border: 1px solid #cccccc;
    background-color: #f0f0f0;
    padding: 10px;
}

.greyboxfilled {
 	border: 1px solid #ddd;
    background: #f0f0f0;
    padding: 3px;
	margin: 1px 1px 10px 1px;
}

.navBackgroundBox {
    padding: 5px 5px 5px 5px;
    font-size: 22px;
	font-weight: bold;
	font-family: Arial, sans-serif;
	color: white;
    background: #3c78b5;
    text-decoration: none;
}

.previewBoxTop {
	background-color: #f0f0f0;
    border-width: 1px 1px 0px 1px;
    border-style: solid;
    border-color: #3c78b5;
    padding: 5px;
    margin: 5px 0px 0px 0px;
    text-align: center;
}
.previewContent {
    background-color: #fff;
 	border-color: #3c78b5;
	border-width: 0px 1px 0px 1px;
	border-style: solid;
	padding: 10px;
	margin: 0px;
}
.previewBoxBottom {
	background-color: #f0f0f0;
    border-width: 0px 1px 1px 1px;
    border-style: solid;
    border-color: #3c78b5;
    padding: 5px;
    margin: 0px 0px 5px 0px;
    text-align: center;
}

.functionbox {
    background-color: #f0f0f0;
 	border: 1px solid #3c78b5;
	padding: 3px;
	margin: 1px 1px 10px 1px;
}

.functionbox-greyborder {
    background-color: #f0f0f0;
 	border: 1px solid #ddd;
	padding: 3px;
	margin: 1px 1px 10px 1px;
}

.search-highlight {
    background-color: #ffffcc;
}

/* normal (white) background */
.rowNormal {
    background-color: #ffffff;
 }

/* alternate (pale yellow) background */
.rowAlternate {
    background-color: #f7f7f7;
}

/* used in the list attachments table */
.rowAlternateNoBottomColor {
    background-color: #f7f7f7;
}

.rowAlternateNoBottomNoColor {
}

.rowAlternateNoBottomColor td {
    border-bottom: 0px;
}

.rowAlternateNoBottomNoColor td {
    border-bottom: 0px;
}

/* row highlight (grey) background */
.rowHighlight {
    background-color: #f0f0f0;

}

TD.greenbar {FONT-SIZE: 2px; BACKGROUND: #00df00; BORDER: 1px solid #9c9c9c; PADDING: 0px; }
TD.redbar {FONT-SIZE: 2px; BACKGROUND: #df0000; BORDER: 1px solid #9c9c9c; PADDING: 0px; }
TD.darkredbar {FONT-SIZE: 2px; BACKGROUND: #af0000; BORDER: 1px solid #9c9c9c; PADDING: 0px; }

TR.testpassed {FONT-SIZE: 2px; BACKGROUND: #ddffdd; PADDING: 0px; }
TR.testfailed {FONT-SIZE: 2px; BACKGROUND: #ffdddd; PADDING: 0px; }

.toolbar  {
    margin: 0px;
    border-collapse: collapse;
}

.toolbar td  {
    border: 1px solid #ccc;
    padding: 2px 2px 2px 2px;
    color: #ccc;
}

td.noformatting {
    border-width: 0px;
    border-style: none;
    text-align: center;
	padding: 0px;
}

.commentblock {
    margin: 12px 0 12px 0;
}

/*
 * Divs displaying the license information, if necessary.
 */
.license-eval, .license-none, .license-nonprofit {
    border-top: 1px solid #bbbbbb;
    text-align: center;
    font-size: 10px;
    font-family: Verdana, Arial, Helvetica, sans-serif;
}

.license-eval, .license-none {
    background-color: #ffcccc;
}

.license-eval b, .license-none b {
    color: #990000
}

.license-nonprofit {
    background-color: #ffffff;
}

/*
 * The shadow at the bottom of the page between the main content and the
 * "powered by" section.
 */
.bottomshadow {
    height: 12px;
    background-image: url("$req.contextPath/images/border/border_bottom.gif");
    background-repeat: repeat-x;
}

/*
 * Styling of the operations box
 */
.navmenu .operations li, .navmenu .operations ul {
    list-style: none;
    margin-left: 0;
    padding-left: 0;
}

.navmenu .operations ul {
    margin-bottom: 9px;
}

.navmenu .label {
    font-weight: inherit;
}

/*
 * Styling of ops as a toolbar
 */
.toolbar div {
    display: none;
}

.toolbar .label {
    display: none;
}

.toolbar .operations {
    display: block;
}

.toolbar .operations ul {
    display: inline;
    list-style: none;
    margin-left: 10px;
    padding-left: 0;
}

.toolbar .operations li {
    list-style: none;
    display: inline;
}

/* list page navigational tabs */
#foldertab {
padding: 3px 0px 3px 8px;
margin-left: 0;
border-bottom: 1px solid #3c78b5;
font: bold 11px Verdana, sans-serif;
}

#foldertab li {
list-style: none;
margin: 0;
display: inline;
}

#foldertab li a {
padding: 3px 0.5em;
margin-left: 3px;
border: 1px solid #3c78b5;
border-bottom: none;
background: #3c78b5;
text-decoration: none;
}

#foldertab li a:link { color: #ffffff; }
#foldertab li a:visited { color: #ffffff; }

#foldertab li a:hover {
color: #ffffff;
background: #003366;
border-color: #003366;
}

#foldertab li a.current {
background: white;
border-bottom: 1px solid white;
color: black;
}

#foldertab li a.current:link { color: black; }
#foldertab li a.current:visited { color: black; }
#foldertab li a.current:hover {
background: white;
border-bottom: 1px solid white;
color: black;
}

/* alphabet list */
ul#squaretab {
margin-left: 0;
padding-left: 0;
white-space: nowrap;
font: bold 8px Verdana, sans-serif;
}

#squaretab li {
display: inline;
list-style-type: none;
}

#squaretab a {
padding: 2px 6px;
border: 1px solid #3c78b5;
}

#squaretab a:link, #squaretab a:visited {
color: #fff;
background-color: #3c78b5;
text-decoration: none;
}

#squaretab a:hover {
color: #ffffff;
background-color: #003366;
border-color: #003366;
text-decoration: none;
}

#squaretab li a#current {
background: white;
color: black;
}

.blogcalendar * {
    font-family:verdana, arial, sans-serif;
    font-size:x-small;
    font-weight:normal;
    line-height:140%;
    padding:2px;
}


table.blogcalendar {
    border: 1px solid #3c78b5;
}

.blogcalendar th.calendarhead, a.calendarhead {
    font-size:x-small;
    font-weight:bold;
    padding:2px;
    text-transform:uppercase;
    background-color: #3c78b5;
    color: #ffffff;
    letter-spacing: .3em;
    text-transform: uppercase;
}

.calendarhead:visited {color: white;}
.calendarhead:active {color: white;}
.calendarhead:hover {color: white;}

.blogcalendar th {
    font-size:x-small;
    font-weight:bold;
    padding:2px;
    background-color:#f0f0f0;
}

.blogcalendar td {
    font-size:x-small;
    font-weight:normal;
}

.searchGroup { padding: 0 0 10px 0; background: #f0f0f0; }
.searchGroupHeading { font-size: 10px; font-weight: bold; color: #ffffff; background-color: #3c78b5; padding: 2px 4px 1px 4px; }
.searchItem { padding: 1px 4px 1px 4px; }
.searchItemSelected { padding: 1px 4px 1px 4px; font-weight: bold; background: #ddd; }

/* permissions page styles */
.permissionHeading {
    border-bottom: #bbb; border-width: 0 0 1px 0; border-style: solid; font-size: 16px; text-align: left;
}
.permissionTab {
    border-width: 0 0 0 1px; border-style: solid; background: #3c78b5; color: #ffffff; font-size: 10px;
}
.permissionSuperTab {
    border-width: 0 0 0 1px; border-style: solid; background: #003366; color: #ffffff;
}
.permissionCell {
    border-left: #bbb; border-width: 0 0 0 1px; border-style: solid;
}

/* warning panel */
.warningPanel { background: #FFFFCE; border:#F0C000 1px solid; padding: 8px; margin: 10px; }
/* alert panel */
.alertPanel { background: #FFCCCC; border:#C00 1px solid; padding: 8px; margin: 10px; }
/* info panel */
.infoPanel { background: #D8E4F1; border:#3c78b5 1px solid; padding: 8px; margin: 10px; }

/* side menu highlighting (e.g. space content screen) */
.optionPadded { padding: 2px; }
.optionSelected { background-color: #ffffcc; padding: 2px; border: 1px solid #ddd; margin: -1px; }
.optionSelected a { font-weight: bold; text-decoration: none; color: black; }

/* information macros */
.noteMacro { border-style: solid; border-width: 1px; border-color: #F0C000; background-color: #FFFFCE; text-align:left; margin-top: 5px; margin-bottom: 5px}
.warningMacro { border-style: solid; border-width: 1px; border-color: #c00; background-color: #fcc; text-align:left; margin-top: 5px; margin-bottom: 5px}
.infoMacro { border-style: solid; border-width: 1px; border-color: #3c78b5; background-color: #D8E4F1; text-align:left; margin-top: 5px; margin-bottom: 5px}
.tipMacro { border-style: solid; border-width: 1px; border-color: #090; background-color: #dfd; text-align:left; margin-top: 5px; margin-bottom: 5px}
.informationMacroPadding { padding: 5px 0 0 5px; }

table.infoMacro td, table.warningMacro td, table.tipMacro td, table.noteMacro td, table.sectionMacro td {
    border: none;
}

table.sectionMacroWithBorder td.columnMacro { border-style: dashed; border-width: 1px; border-color: #cccccc;}

.pagecontent
{
    padding: 10px;
    text-align: left;
}

/* styles for links in the top bar */
.topBarDiv a:link {color: #ffffff;}
.topBarDiv a:visited {color: #ffffff;}
.topBarDiv a:active {color: #ffffff;}
.topBarDiv a:hover {color: #ffffff;}
.topBarDiv {color: #ffffff;}

.topBar {
    background-color: #003366;
}


/* styles for extended operations */
.greyLinks a:link {color: #666666; text-decoration:underline;}
.greyLinks a:visited {color: #666666; text-decoration:underline;}
.greyLinks a:active {color: #666666; text-decoration:underline;}
.greyLinks a:hover {color: #666666; text-decoration:underline;}
.greyLinks {color: #666666; display:block; padding: 10px}

.logoSpaceLink {color: #999999; text-decoration: none}
.logoSpaceLink a:link {color: #999999; text-decoration: none}
.logoSpaceLink a:visited {color: #999999; text-decoration: none}
.logoSpaceLink a:active {color: #999999; text-decoration: none}
.logoSpaceLink a:hover {color: #003366; text-decoration: none}

/* basic panel (basicpanel.vmd) style */
.basicPanelContainer {border: 1px solid #3c78b5; margin-top: 2px; margin-bottom: 8px; width: 100%}
.basicPanelTitle {padding: 5px; margin: 0px; background-color: #f0f0f0; color: black; font-weight: bold;}
.basicPanelBody {padding: 5px; margin: 0px}

.separatorLinks a:link {color: white}
.separatorLinks a:visited {color: white}
.separatorLinks a:active {color: white}

.greynavbar {background-color: #f0f0f0; border-top: 1px solid #3c78b5; margin-top: 2px}

div.headerField {
    float: left;
    width: auto;
    height: 100%;
}

.headerFloat {
    margin-left: auto;
    width: 50%;
}

.headerFloatLeft {
    float: left;
    margin-right: 20px;
    margin-bottom: 10px;
}

#headerRow {
    padding: 10px;
}

div.license-personal {
   background-color: #003366;
   color: #ffffff;
}

div.license-personal a {
   color: #ffffff;
}

.greyFormBox {
    border: 1px solid #cccccc;
    padding: 5px;
}

/* IE automatically adds a margin before and after form tags. Use this style to remove that */
.marginlessForm {
    margin: 0px;
}

.openPageHighlight {
    background-color: #ffffcc;
    padding: 2px;
    border: 1px solid #ddd;
}

.editPageInsertLinks, .editPageInsertLinks a
{
    color: #666666;
    font-weight: bold;
    font-size: 10px;
}

/* Style for label heatmap. */
.top10 a {
    font-weight: bold;
    font-size: 2em;
    color: #003366;
}
.top25 a {
    font-weight: bold;
    font-size: 1.6em;
    color: #003366;
}
.top50 a {
    font-size: 1.4em;
    color: #003366;
}
.top100 a {
    font-size: 1.2em;
    color: #003366;
}

.heatmap {
    list-style:none;
    width: 95%;
    margin: 0px auto;
}

.heatmap a {
    text-decoration:none;
}

.heatmap a:hover {
    text-decoration:underline;
}

.heatmap li {
    display: inline;
}

.minitab {
padding: 3px 0px 3px 8px;
margin-left: 0;
margin-top: 1px;
margin-bottom: 0px;
border-bottom: 1px solid #3c78b5;
font: bold 9px Verdana, sans-serif;
text-decoration: none;
float:none;
}
.selectedminitab {
padding: 3px 0.5em;
margin-left: 3px;
margin-top: 1px;
border: 1px solid #3c78b5;
background: white;
border-bottom: 1px solid white;
color: #000000;
text-decoration: none;
}
.unselectedminitab {
padding: 3px 0.5em;
margin-left: 3px;
margin-top: 1px;
border: 1px solid #3c78b5;
border-bottom: none;
background: #3c78b5;
color: #ffffff;
text-decoration: none;
}

a.unselectedminitab:hover {
color: #ffffff;
background: #003366;
border-color: #003366;
}

a.unselectedminitab:link { color: white; }
a.unselectedminitab:visited { color: white; }

a.selectedminitab:link { color: black; }
a.selectedminitab:visited { color: black; }

.linkerror { background-color: #fcc;}

a.labelOperationLink:link {text-decoration: underline}
a.labelOperationLink:active {text-decoration: underline}
a.labelOperationLink:visited {text-decoration: underline}
a.labelOperationLink:hover {text-decoration: underline}

a.newLabel:link {background-color: #ddffdd}
a.newLabel:active {background-color: #ddffdd}
a.newLabel:visited {background-color: #ddffdd}
a.newLabel:hover {background-color: #ddffdd}

ul.square {list-style-type: square}

.inline-control-link {
    background: #ffc;
    font-size: 9px;
    color: #666;
    padding: 2px;
    text-transform: uppercase;
    text-decoration: none;
}


.inline-control-link a:link {text-decoration: none}
.inline-control-link a:active {text-decoration: none}
.inline-control-link a:visited {text-decoration: none}
.inline-control-link a:hover {text-decoration: none}

.inline-control-link {
    background: #ffc;
    font-size: 9px;
    color: #666;
    padding: 2px;
    text-transform: uppercase;
    text-decoration: none;
    cursor: pointer;
}

div.auto_complete {
    width: 350px;
    background: #fff;
}
div.auto_complete ul {
    border: 1px solid #888;
    margin: 0;
    padding: 0;
    width: 100%;
    list-style-type: none;
}
div.auto_complete ul li {
    margin: 0;
    padding: 3px;
}
div.auto_complete ul li.selected {
    background-color: #ffb;
}
div.auto_complete ul strong.highlight {
    color: #800;
    margin: 0;
    padding: 0;
}

/******* Edit Page Styles *******/
.toogleFormDiv{
    border:1px solid #A7A6AA;
    background-color:white;
    padding:5px;
    margin-top: 5px;
}

.toogleInfoDiv{
    border:1px solid #A7A6AA;
    background-color:white;
    display:none;
    padding:5px;
    margin-top: 10px;
}

.inputSection{
    margin-bottom:20px;
}

#editBox{
   border:1px solid lightgray;
   background-color:#F0F0F0;
}

/******* Left Navigation Theme Styles ********/
.leftnav li a {
    text-decoration:none;
    color:white;
    margin:0px;
    display:block;
    padding:2px;
    padding-left:5px;
    background-color: #3c78b5;
    border-top:1px solid #3c78b5;
}

.leftnav li a:active {color:white;}
.leftnav li a:visited {color:white;}
.leftnav li a:hover {background-color: #003366; color:white;}

/* Added by Shaun during i18n */
.replaced
{
    background-color: #33CC66;
}

.topPadding
{
    margin-top: 20px;
}

/* new form style */
.form-block {
    padding: 6px;
}
.form-error-block {
    padding: 6px;
    background: #fcc;
    border-top: #f0f0f0 1px solid;
    border-bottom: #f0f0f0 1px solid;
    margin-bottom: 6px;
    padding: 0 12px 0 12px;
}
.form-element-large {
    font-size: 16px;
    font-weight: bold;
    font-family: Arial, sans-serif;
    color: #003366;
}

.form-element-small {
    font-size: 12px;
    font-weight: bold;
    font-family: Arial, sans-serif;
    color: #003366;
}

.form-header {
    background: lightyellow;
    border-top: #f0f0f0 1px solid;
    border-bottom: #f0f0f0 1px solid;
    margin-bottom: 6px;
    padding: 0 12px 0 12px;
}
.form-header p, .form-block p, .form-error-block p {
    line-height: normal;
    margin: 12px 0 12px 0;
}
.form-example {
    color: #888;
    font-size: 11px;
}
.form-divider {
    border-bottom: #ccc 1px solid;
    margin-bottom: 6px;
}
.form-buttons {
    margin-top: 6px;
    border-top: #ccc 1px solid;
    border-bottom: #ccc 1px solid;
    background: #f0f0f0;
    padding: 10px;
    text-align: center;
}
.form-buttons input {
    width: 100px;
}
.form-block .error {
    padding: 6px;
    margin-bottom: 6px;
}
    -->
    </style>
</head>
<body>

<div id="PageContent">
<table class="pagecontent" border="0" cellpadding="0" cellspacing="0" width="100%"><tr>
<td valign="top" class="pagebody">

    <div class="pageheader">
        <span class="pagetitle">
            Page Edited :
            <a href="http://cwiki.apache.org/confluence/display/FELIX">FELIX</a> :
            <a href="http://cwiki.apache.org/confluence/display/FELIX/iPOJO+in+10+minutes">iPOJO in 10 minutes</a>
        </span>
    </div>

     <p>
        <a href="http://cwiki.apache.org/confluence/display/FELIX/iPOJO+in+10+minutes">iPOJO in 10 minutes</a>
        has been edited by             <a href="http://cwiki.apache.org/confluence/display/~clement.escoffier">Clement Escoffier</a>
            <span class="smallfont">(Apr 15, 2008)</span>.
     </p>
    
     <p>
                 <a href="http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=81324&originalVersion=4&revisedVersion=5">(View changes)</a>
     </p>

    <span class="label">Content:</span><br/>
    <div class="greybox wiki-content"><table class="sectionMacro" border="0" cellpadding="5" cellspacing="0" width="100%"><tbody><tr>
<td class="confluenceTd"  valign="top" width="80%">
<h1><a name="iPOJOin10minutes-iPOJOin10minutes"></a>iPOJO in 10 minutes</h1>

<p><em>This page presents how to use the</em> <em>iPOJO</em> <em>runtime and its associated service component model. The concepts of the service component model are introduced, followed by a simple example that demonstrates the features of iPOJO.</em></p>

<h2><a name="iPOJOin10minutes-Introduction"></a>Introduction</h2>

<p>iPOJO aims to simplify service-oriented programming on OSGi frameworks; the name iPOJO is an abbreviation for <em>injected POJO</em>. iPOJO provides a new way to develop OSGi service components with the main goal being to simplify service component implementation by transparently managing the dynamics of the environment as well as other non-functional requirements. The iPOJO framework allows developers to more clearly separate functional code (i.e., the POJO) from the non-functional code (i.e., dependency management, service provision, configuration, etc.). iPOJO combines the functional and non-functional aspects at run time. To achieve this, iPOJO provides a simple and extensible service component model based on POJOs.</p>

<h2><a name="iPOJOin10minutes-ThePOJOconcept"></a>The POJO concept</h2>

<p>POJO is an acronym for Plain Old Java Object, but it embodies a concept that the simpler and less intrusive the design of a given framework, the better. The name is used to emphasize that a given object is not somehow special, but is an ordinary Java Object. Martin Fowler, Rebecca Parsons and Josh Mackenzie coined the term POJO in September 2000: "We wondered why people were so against using regular objects in their systems and concluded that it was because simple objects lacked a fancy name. So we gave them one, and it's caught on very nicely." From the developer's perspective, the iPOJO framework strives to only require POJOs in as much as it is possible.</p>

<h2><a name="iPOJOin10minutes-iPOJOservicecomponentoverview"></a>iPOJO service component overview</h2>

<p>A service component is able to provide and/or require services, where a service is an object that implements a given service interface embodied as a Java interface. In addition, iPOJO introduces a callback concept to notify a component about various state changes.</p>

<p>The component is the central concept in iPOJO. In the core iPOJO model, a component describes service dependencies, provided services, and callbacks; this information is recorded in the component's metadata. Then, the second important concept in iPOJO is component instances. A component instances is a special <em>version</em> of the component. By merging component metadata and instance configuration, the iPOJO runtime is able to manage the component, i.e., manage its life cycle, inject required services, publish provided services, discover needed services.</p>

<h2><a name="iPOJOin10minutes-Asimpleexample"></a>A simple example</h2>

<p>In this tutorial we will present how to:</p>
<ul>
	<li>Publish an OSGi service</li>
	<li>Require an OSGi service</li>
	<li>Use lifecycle callbacks to activate and deactivate components</li>
</ul>


<h3><a name="iPOJOin10minutes-PresentationoftheSpellapplication"></a>Presentation of the <em>Spell</em> application</h3>

<p>To illustrate iPOJO features, we will implement a very simple application. This application is composed by three components:</p>
<ul>
	<li>A component implementing a dictionary service</li>
	<li>A component requiring the dictionary service and providing a spellchecker service</li>
	<li>A component requiring the spellchecker and providing an user interface</li>
</ul>


<p><img src="/confluence/download/attachments/81324/spell.png" align="absmiddle" border="0" /></p>

<h3><a name="iPOJOin10minutes-Preparingthetutorial"></a>Preparing the tutorial</h3>

<p>This tutorial is based on Ant. So, you need to have the Ant program accessible in your path (see <span class="nobr"><a href="http://ant.apache.org/" title="Visit page outside Confluence" rel="nofollow">here<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> to download and install Ant). Download the tutorial archive available <span class="nobr"><a href="/confluence/download/attachments/81324/tutorial.zip?version=2" title="tutorial.zip attached to iPOJO in 10 minutes">here<sup><img class="rendericon" src="/confluence/images/icons/link_attachment_7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> and then unzip it. The archive is composed by seven directories:</p>
<ul>
	<li>spell.services contains service interfaces used by the applications</li>
	<li>spell.english contains an implementation of the Dictionary service (containing English words)</li>
	<li>spell.checker contains an implementation of a Spell Checker. The spell checker requires a dictionary service and check if an input passage is correct (according to the words contained in the dictionary).</li>
	<li>spell.gui contains a very simple user interface. This component uses a spell checker service. Then the user can interact with the spell checker with this user interface.</li>
	<li>The task directory contains Ant tasks used to build the project</li>
	<li>The solution directory contains an already developed version of the application.</li>
	<li>Finally, the felix-1.0.3 contains a configured version of the Felix runtime</li>
</ul>


<h3><a name="iPOJOin10minutes-Thespell.servicesproject"></a>The spell.services project</h3>

<p>The spell.services project contains only service interfaces. It is not an iPOJO powered bundle.</p>

<p>Go inside the Spell.services directory and create the file "src/spell/services/DictionaryService.java" for the following <em>Dictionary</em> service interface:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">package</span> spell.services;
/**
 * A simple service <span class="code-keyword">interface</span> that defines a dictionary service.
 * A dictionary service simply verifies the existence of a word.
**/
<span class="code-keyword">public</span> <span class="code-keyword">interface</span> DictionaryService {
    /**
     * Check <span class="code-keyword">for</span> the existence of a word.
     * @param word the word to be checked.
     * @<span class="code-keyword">return</span> <span class="code-keyword">true</span> <span class="code-keyword">if</span> the word is in the dictionary,
     *         <span class="code-keyword">false</span> otherwise.
     **/
    <span class="code-keyword">public</span> <span class="code-object">boolean</span> checkWord(<span class="code-object">String</span> word);
}</pre>
</div></div>
<p>Then, create the file "src/spell/services/SpellChecker.java" for the following <em>Spell Checker</em> service interface:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">package</span> spell.services;
/**
 * A simple service <span class="code-keyword">interface</span> that defines a spell checker service.
 * A spell checker service checks the spelling of all words in a
 * given passage. A passage is any number of words separated by
 * a space character and the following punctuation marks: comma,
 * period, exclamation mark, question mark, semi-colon, and colon.
**/
<span class="code-keyword">public</span> <span class="code-keyword">interface</span> SpellChecker {
    /**
     * Checks a given passage <span class="code-keyword">for</span> spelling errors. A passage is any
     * number of words separated by a space and any of the following
     * punctuation marks: comma (,), period (.), exclamation mark (!),
     * question mark (?), semi-colon (;), and colon(:).
     * @param passage the passage to spell check.
     * @<span class="code-keyword">return</span> An array of misspelled words or <span class="code-keyword">null</span> <span class="code-keyword">if</span> no
     *         words are misspelled.
    **/
    <span class="code-keyword">public</span> <span class="code-object">String</span>[] check(<span class="code-object">String</span> passage);
}</pre>
</div></div>
<p>Once created, you can build the project by launching Ant from the project directory.</p>
<div class="code"><div class="codeContent">
<pre class="code-java">$ ant
Buildfile: build.xml
clean:
compile:
    [mkdir] Created dir: d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.services\output
    [mkdir] Created dir: d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.services\output\classes
    [javac] Compiling 2 source files to d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.services\output\classes
<span class="code-keyword">package</span>:
      [bnd] spell.services 2
BUILD SUCCESSFUL
Total time: 0 seconds</pre>
</div></div>
<p>The created bundle is inside the output directory (spell.services.jar). The build process use <span class="nobr"><a href="http://www.aqute.biz/Code/Bnd" title="Visit page outside Confluence" rel="nofollow">BND<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>. The bundle manifest is described in the spell.services.bnd file.<br/>
Once this project is done, we are able to implement a Dictionary service.</p>

<h3><a name="iPOJOin10minutes-Thespell.englishproject%3AProvidinganOSGiservice"></a>The spell.english project: Providing an OSGi service</h3>

<p>The spell.english project is a simple dictionary implementation of the Dictionary service. It contains few English words. This implementation is an iPOJO component.<br/>
The first step is to implement the service. Create the "src/spell.english/EnglishDictionary.java" file for the following <em>Dictionary service</em> implementation:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">package</span> spell.english;
<span class="code-keyword">import</span> spell.services.DictionaryService;
/**
 * An implementation of the Dictionary service containing English words
 * see DictionaryService <span class="code-keyword">for</span> details of the service.
 **/
<span class="code-keyword">public</span> class EnglishDictionary <span class="code-keyword">implements</span> DictionaryService {
    <span class="code-comment">// The set of words contained in the dictionary.
</span>    <span class="code-object">String</span>[] m_dictionary = { <span class="code-quote">"welcome"</span>, <span class="code-quote">"to"</span>, <span class="code-quote">"the"</span>, <span class="code-quote">"ipojo"</span>, <span class="code-quote">"tutorial"</span> };
    /**
     * Implements DictionaryService.checkWord(). Determines
     * <span class="code-keyword">if</span> the passed in word is contained in the dictionary.
     * @param word the word to be checked.
     * @<span class="code-keyword">return</span> <span class="code-keyword">true</span> <span class="code-keyword">if</span> the word is in the dictionary,
     *         <span class="code-keyword">false</span> otherwise.
     **/
    <span class="code-keyword">public</span> <span class="code-object">boolean</span> checkWord(<span class="code-object">String</span> word) {
        word = word.toLowerCase();
        <span class="code-comment">// This is very inefficient
</span>        <span class="code-keyword">for</span> (<span class="code-object">int</span> i = 0; i &lt; m_dictionary.length; i++) {
            <span class="code-keyword">if</span> (m_dictionary[i].equals(word)) {
                <span class="code-keyword">return</span> <span class="code-keyword">true</span>;
            }
        }
        <span class="code-keyword">return</span> <span class="code-keyword">false</span>;
    }
}</pre>
</div></div>
<p>Notice that this class does not contains neither OSGi nor iPOJO specific code. It is just an implementation of the Dictionary Service interface.<br/>
Once created, we need to describe this component to ask iPOJO to manage it. To achieve this create the "metadata.xml_"&#95; file in the spell.english directory:</p>
<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;ipojo&gt;</span>
<span class="code-tag">&lt;component classname=<span class="code-quote">"spell.english.EnglishDictionary"</span>&gt;</span>
	<span class="code-tag">&lt;provides/&gt;</span>
<span class="code-tag">&lt;/component&gt;</span>
<span class="code-tag">&lt;instance component=<span class="code-quote">"spell.english.EnglishDictionary"</span>/&gt;</span>
<span class="code-tag">&lt;/ipojo&gt;</span></pre>
</div></div>
<p>This file describes the Dictionary service implementation. First it creates a <em>component</em>. This component has a <em>classname</em>attribute containing the implementation class name. The <em>'provides'</em> element indicates that the component provide a service. Provided service interfaces are computed by iPOJO, so it is not necessary to indicate them. The <em>instance</em> element asks iPOJO to create an instance of the described component when the bundle starts. The relation between components and instances is the same than between classes and objects in the object oriented programming. The <em>component</em> attribute indicates which component needs to be instantiated. By default, component type name is the implementation class (i.e. the classname attribute).</p>

<p>Then, we are able to create the bundle. In the spell.english directory launch the ant command:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">$ ant
Buildfile: build.xml
clean:
   [delete] Deleting directory d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.english\output\classes
   [delete] Deleting directory d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.english\output
buildclasspath:
compile:
    [mkdir] Created dir: d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.english\output
    [mkdir] Created dir: d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.english\output\classes
    [javac] Compiling 1 source file to d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.english\output\classes
<span class="code-keyword">package</span>:
      [bnd] spell.english 1
    [ipojo] Input Bundle File : d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.english\output\spell.english.jar
    [ipojo] Metadata File : d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.english\metadata.xml
    [ipojo] Start bundle manipulation
    [ipojo] Bundle manipulation - SUCCESS
    [ipojo] Output File : d:\clement\workspaces\sandbox\ipojo\examples\tutorial-ant\spell.english\output\spell.english.jar
BUILD SUCCESSFUL
Total time: 1 second</pre>
</div></div>
<p>The created bundle is inside the output directory (spell.english.jar). The build process is based on BND and on the iPOJO Ant task. The manifest of the bundle is described in the spell.english.bnd file.</p>

<h3><a name="iPOJOin10minutes-Thespell.checkerproject%3ARequiringanOSGiservice"></a>The spell.checker project: Requiring an OSGi service</h3>

<p>The spell.checker project aims to provide a<em>spell checker</em> service. However, to serve this service, this implementation requires a <em>dictionary</em> service. During this step, we will create an iPOJO component requiring a Dictionary service and providing the Spell Checker service.</p>

<p>First create the file "src/spell/checker/SpellCheck.java" in the spell.checker directory for the following <em>Check Speller service</em>implementation:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">package</span> spell.check;
<span class="code-keyword">import</span> java.util.ArrayList;
<span class="code-keyword">import</span> java.util.List;
<span class="code-keyword">import</span> java.util.StringTokenizer;
<span class="code-keyword">import</span> spell.services.DictionaryService;
<span class="code-keyword">import</span> spell.services.SpellChecker;
<span class="code-keyword">public</span> class SpellCheck <span class="code-keyword">implements</span> SpellChecker {
    <span class="code-keyword">private</span> DictionaryService m_dictionary;
    /**
     * Implements SpellChecker.check(). Checks the given passage <span class="code-keyword">for</span> misspelled words.
     * @param passage the passage to spell check.
     * @<span class="code-keyword">return</span> An array of misspelled words or <span class="code-keyword">null</span> <span class="code-keyword">if</span> no words are misspelled.
     */
    <span class="code-keyword">public</span> <span class="code-object">String</span>[] check(<span class="code-object">String</span> passage) {
        <span class="code-comment">// No misspelled words <span class="code-keyword">for</span> an empty string.
</span>        <span class="code-keyword">if</span> ((passage == <span class="code-keyword">null</span>) || (passage.length() == 0)) { <span class="code-keyword">return</span> <span class="code-keyword">null</span>; }
        List errorList = <span class="code-keyword">new</span> ArrayList();
        <span class="code-comment">// Tokenize the passage using spaces and punctuation.
</span>        StringTokenizer st = <span class="code-keyword">new</span> StringTokenizer(passage, <span class="code-quote">" ,.!?;:"</span>);
        <span class="code-comment">// Loop through each word in the passage.
</span>        <span class="code-keyword">while</span> (st.hasMoreTokens()) {
            <span class="code-object">String</span> word = st.nextToken();
            <span class="code-comment">// Check the current word.
</span>            <span class="code-keyword">if</span> (! m_dictionary.checkWord(word)) {
                <span class="code-comment">// If the word is not correct, then add it
</span>                <span class="code-comment">// to the incorrect word list.
</span>                errorList.add(word);
            }
        }
        <span class="code-comment">// Return <span class="code-keyword">null</span> <span class="code-keyword">if</span> no words are incorrect.
</span>        <span class="code-keyword">if</span> (errorList.size() == 0) { <span class="code-keyword">return</span> <span class="code-keyword">null</span>; }
        <span class="code-comment">// Return the array of incorrect words.
</span>        <span class="code-keyword">return</span> (<span class="code-object">String</span>[]) errorList.toArray(<span class="code-keyword">new</span> <span class="code-object">String</span>[errorList.size()]);
    }
}</pre>
</div></div>
<p>This class implements the SpellChecker service interface as it will provide it. Moreover, it has a <em>special</em> field "_m_dictionary_". This field represents the required service. iPOJO will inject a Dictionary service when needed. So, the class can use it directly. Notice that this class as no OSGi specific code, both the service providing and the requiring are managed by iPOJO. If the used dictionary service leaves, iPOJO will try to find another provider. If no more providers are available, the instance is invalidated, and the provided service is withdrawn from the service registry.</p>

<p>Once implemented, we need to describe this component. Create the "metadata.xml" file in the spell.checker directory for the following component descriptor:</p>
<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;ipojo&gt;</span>
<span class="code-tag">&lt;component classname=<span class="code-quote">"spell.check.SpellCheck"</span>&gt;</span>
	<span class="code-tag">&lt;requires field=<span class="code-quote">"m_dictionary"</span>/&gt;</span>
	<span class="code-tag">&lt;provides/&gt;</span>
<span class="code-tag">&lt;/component&gt;</span>
<span class="code-tag">&lt;instance component=<span class="code-quote">"spell.check.SpellCheck"</span>/&gt;</span>
<span class="code-tag">&lt;/ipojo&gt;</span></pre>
</div></div>
<p>This description contains a '<em>requires'</em> element. This element indicates to iPOJO to manage the service dependency. The <em>field</em> attributes describe in which member of the class the service need to be injected. It is not necessary to write the required service as it is computed by iPOJO. Notice that iPOJO can inject required service by invoking methods too.</p>

<p>Finally, we are able to build the bundle. As for previous projects, launch Ant from the project directory.</p>

<h3><a name="iPOJOin10minutes-Thespell.check.guiproject"></a>The spell.check.gui project</h3>

<p>The spell.check.gui project contains a very simple user interface (in Swing) allowing a user to interact with a <em>spell checker</em> service.</p>

<p>Create the "src\spell\gui\SpellCheckerGui.java" for the following implementation:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">package</span> spell.gui;
<span class="code-keyword">import</span> javax.swing.JButton;
<span class="code-keyword">import</span> javax.swing.JFrame;
<span class="code-keyword">import</span> javax.swing.JLabel;
<span class="code-keyword">import</span> javax.swing.JTextField;
<span class="code-keyword">import</span> spell.services.SpellChecker;
/**
 * A very simple Gui interacting with the CheckSpeller service
 */
<span class="code-keyword">public</span> class SpellCheckerGui <span class="code-keyword">extends</span> JFrame {
    /**
     * Swing component where the user write the passage to check.
     */
    <span class="code-keyword">private</span> JTextField m_passage = <span class="code-keyword">null</span>;

    /**
     * Check button
     */
    <span class="code-keyword">private</span> JButton m_checkButton = <span class="code-keyword">null</span>;

    /**
     * Area where the result is displayed.
     */
    <span class="code-keyword">private</span> JLabel m_result = <span class="code-keyword">null</span>;
    /**
     * Service dependency on the SpellChecker.
     */
    <span class="code-keyword">private</span> SpellChecker m_checker;

    /**
     * Constructor.
     * Initialize the GUI.
     */
    <span class="code-keyword">public</span> SpellCheckerGui() {
        <span class="code-keyword">super</span>();
        initComponents();
        <span class="code-keyword">this</span>.setTitle(<span class="code-quote">"Spellchecker Gui"</span>);
    }
    /**
     * Initialize the Swing Gui.
     */
    <span class="code-keyword">private</span> void initComponents() {
        java.awt.GridBagConstraints gridBagConstraints;
        m_checkButton = <span class="code-keyword">new</span> javax.swing.JButton();
        m_result = <span class="code-keyword">new</span> javax.swing.JLabel();
        m_passage = <span class="code-keyword">new</span> javax.swing.JTextField();
        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        getContentPane().setLayout(<span class="code-keyword">new</span> java.awt.GridBagLayout());
        m_checkButton.setText(<span class="code-quote">"Check"</span>);
        m_checkButton.addActionListener(<span class="code-keyword">new</span> java.awt.event.ActionListener() {
            <span class="code-keyword">public</span> void actionPerformed(java.awt.event.ActionEvent e) {
                check();
            }
        });
        gridBagConstraints = <span class="code-keyword">new</span> java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 1;
        gridBagConstraints.insets = <span class="code-keyword">new</span> java.awt.Insets(2, 2, 2, 2);
        getContentPane().add(m_checkButton, gridBagConstraints);
        m_result.setPreferredSize(<span class="code-keyword">new</span> java.awt.Dimension(175, 20));
        gridBagConstraints = <span class="code-keyword">new</span> java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 2;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = <span class="code-keyword">new</span> java.awt.Insets(2, 2, 2, 2);
        getContentPane().add(m_result, gridBagConstraints);
        m_passage.setPreferredSize(<span class="code-keyword">new</span> java.awt.Dimension(175, 20));
        gridBagConstraints = <span class="code-keyword">new</span> java.awt.GridBagConstraints();
        gridBagConstraints.gridx = 0;
        gridBagConstraints.gridy = 0;
        gridBagConstraints.fill = java.awt.GridBagConstraints.HORIZONTAL;
        gridBagConstraints.insets = <span class="code-keyword">new</span> java.awt.Insets(2, 2, 2, 2);
        getContentPane().add(m_passage, gridBagConstraints);
        pack();
    }
    /**
     * Check Button action.
     * Collects the user input and checks it.
     */
    <span class="code-keyword">private</span> void check() {
        <span class="code-object">String</span>[] result = m_checker.check(m_passage.getText());
        <span class="code-keyword">if</span> (result != <span class="code-keyword">null</span>) {
            m_result.setText(result.length + <span class="code-quote">" word(s) are mispelled"</span>);
        } <span class="code-keyword">else</span> {
            m_result.setText(<span class="code-quote">"All words are correct"</span>);
        }
    }
    /**
     * Start callback.
     * This method will be called when the instance becomes valid.
     * It set the Gui visibility to <span class="code-keyword">true</span>.
     */
    <span class="code-keyword">public</span> void start() {
        <span class="code-keyword">this</span>.setVisible(<span class="code-keyword">true</span>);
    }
    /**
     * Stop callback.
     *  This method will be called when the instance becomes invalid or stops.
     *  It deletes the Gui.
     */
    <span class="code-keyword">public</span> void stop() {
        <span class="code-keyword">this</span>.dispose();
    }
}</pre>
</div></div>
<p>Look at the three last methods. The <em>check</em> methods collect the user input and use a <em>Check speller</em> service to check this input. This method is called when the button is pressed by the user. The <em>start</em> and <em>stop</em> methods are lifecycle callbacks. As we need to display the user interface when the instance is created and to delete it when the instance stops, we need a way to be notified when we need to execute these actions. iPOJO provide an easy way to do this. The component provides two callback methods for its activation and deactivation, start and stop, respectively. Callbacks are used when the component needs to be informed about a component state change. In iPOJO, the component state is either <b>INVALID</b> (i.e., not all of the component's constraints are satisfied) or <b>VALID</b> (i.e., all of the component's constraints are satisfied). In this example, the start callback method set the GUI visibility to true; the stop callback method deletes the GUI. The component metadata will instruct iPOJO to invoke these methods when the component's state changes to <b>VALID</b> or <b>INVALID</b> respectively.</p>

<p>Create the <em>metadata.xml</em> file in the spell.chercker.gui directory with the following content:</p>
<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;ipojo&gt;</span>
<span class="code-tag">&lt;component classname=<span class="code-quote">"spell.gui.SpellCheckerGui"</span>&gt;</span>
	<span class="code-tag">&lt;requires field=<span class="code-quote">"m_checker"</span>/&gt;</span>
	<span class="code-tag">&lt;callback transition=<span class="code-quote">"validate"</span> method=<span class="code-quote">"start"</span>/&gt;</span>
	<span class="code-tag">&lt;callback transition=<span class="code-quote">"invalidate"</span> method=<span class="code-quote">"stop"</span>/&gt;</span>
<span class="code-tag">&lt;/component&gt;</span>
<span class="code-tag">&lt;instance component=<span class="code-quote">"spell.gui.SpellCheckerGui"</span>/&gt;</span>
<span class="code-tag">&lt;/ipojo&gt;</span></pre>
</div></div>
<p>The component element again has the '<em>classname'</em> attribute that refers to the component implementation class. The '<em>requires</em>' element describes the <em>Check Speller</em> service dependency by simply specifying its associated component field. The '<em>callback'</em> elements describe which method to invoke when the component's state changes. Then the <em>'instance'</em> element asks iPOJO to create an instance of the component.</p>

<p>Once this file is created, you can compile the project by launching <em>ant</em> in the spell.checker.gui directory.</p>

<h2><a name="iPOJOin10minutes-Runningtheapplication"></a>Running the application</h2>

<p>To run the example, start Felix. A distribution of Felix is provided in the felix-1.0.3 directory. This version is configured to launch iPOJO automatically. From the Felix directory, launch the following command to start the framework. Then enter a profile name.</p>
<div class="code"><div class="codeContent">
<pre class="code-java">java -jar bin/felix.jar</pre>
</div></div>
<p>You can check installed bundles by using the '_ps'_command:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">-&gt; ps
START LEVEL 1
   ID   State        Level  Name
[   0] [Active     ] [   0] <span class="code-object">System</span> Bundle (1.0.3)
[   1] [Active     ] [   1] Apache Felix Shell Service (1.0.0)
[   2] [Active     ] [   1] Apache Felix Shell TUI (1.0.0)
[   3] [Active     ] [   1] Apache Felix Bundle Repository (1.0.2)
[   4] [Active     ] [   1] iPOJO (0.7.6.SNAPSHOT)
-&gt;</pre>
</div></div>
<p>iPOJO runtime is the bundle 4. Once started, install the four created bundles as above:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">start file:../spell.services/output/spell.services.jar
start file:../spell.english/output/spell.english.jar
start file:../spell.checker/output/spell.checker.jar
start file:../spell.checker.gui/output/spell.checker.gui.jar</pre>
</div></div>
<p>When starting the GUI bundle, the user interface appears. Indeed, the <em>Check Speller</em> service is provided. You can interact with this service by entering a passage and clicking on the check button:<br/>
<img src="/confluence/download/attachments/81324/ss.png" align="absmiddle" border="0" /><br/>
Then, stop the <em>Dictionary</em>service provider (with the <em>stop 6</em>) command. The GUI disappears. Indeed, Spell Checker service cannot be provided as it depends on the Dictionary service.<br/>
<img src="/confluence/download/attachments/81324/spell2.png" align="absmiddle" border="0" /><br/>
Then, restart the Dictionary service provider with the <em>start 6</em> command. The GUI reappears immediately. You can try to stop the <em>check speller</em> service provider without stopping the <em>dictionary</em> service provider with the <em>stop 7</em> command. As for the last manipulation, the GUI disappears.<br/>
<img src="/confluence/download/attachments/81324/spell3.png" align="absmiddle" border="0" /></p>

<h2><a name="iPOJOin10minutes-Conclusion"></a>Conclusion</h2>

<p>We saw how to use easily iPOJO to build service-oriented component. In this tutorial, we have demonstrated how to:</p>
<ul>
	<li>Publish OSGi services</li>
	<li>Require OSGi services</li>
	<li>Use lifecycle callbacks to activate and deactivate components</li>
</ul>


<p>iPOJO provides a lot of others features that you can try in the others available tutorials. Subscribe to the Felix users mailing list by sending a message to users-subscribe@felix.apache.org; after subscribing, email questions or feedback to users@felix.apache.org.</p>
</td>
<td class="confluenceTd"  valign="top" width="20%">
<form method="get" class="confluence-searchbox marginlessForm " action="/confluence/dosearchsite.action">
    <input type="hidden" name="searchQuery.spaceKey" value="FELIX" />
    <input type="text" name="searchQuery.queryString" />
    <input type="submit" value="Search" />
</form>
<hr />
<h6><a name="iPOJOin10minutes-Overview"></a><b>Overview</b></h6>
<ul>
	<li><a href="/confluence/display/FELIX/Apache+Felix+iPOJO-2" title="Apache Felix iPOJO-2">Home Page</a></li>
	<li><a href="/confluence/display/FELIX/Apache+Felix+iPOJO+Feature+Overview" title="Apache Felix iPOJO Feature Overview">iPOJO Feature Overview</a></li>
	<li><a href="/confluence/display/FELIX/Download" title="Download">Download &amp; Install </a></li>
</ul>


<h6><a name="iPOJOin10minutes-GettingStarted"></a><b>Getting Started</b></h6>
<ul>
	<li><a href="/confluence/display/FELIX/iPOJO+in+10+minutes" title="iPOJO in 10 minutes">iPOJO in 10 minutes</a></li>
	<li><a href="/confluence/display/FELIX/iPOJO+Hello+Word+%28Maven-Based%29+tutorial" title="iPOJO Hello Word (Maven-Based) tutorial">iPOJO Hello Word &#40;Maven&#45;Based&#41; tutorial</a></li>
	<li><a href="/confluence/display/FELIX/iPOJO+Advanced+Tutorial" title="iPOJO Advanced Tutorial">iPOJO Advanced Tutorial</a></li>
</ul>


<h6><a name="iPOJOin10minutes-UserGuide"></a><b>User Guide</b></h6>
<ul>
	<li><a href="/confluence/display/FELIX/Describing+components" title="Describing components">Describing components</a></li>
	<li><a href="/confluence/display/FELIX/How+to+use+iPOJO+Annotations" title="How to use iPOJO Annotations">How to use iPOJO Annotations</a></li>
	<li><a href="/confluence/display/FELIX/iPOJO+Advanced+Topics" title="iPOJO Advanced Topics">Advanced Topics</a></li>
	<li><a href="/confluence/display/FELIX/iPOJO+FAQ" title="iPOJO FAQ">FAQ</a></li>
</ul>


<h6><a name="iPOJOin10minutes-Tools"></a><b>Tools</b></h6>
<ul>
	<li><a href="/confluence/display/FELIX/iPOJO+Eclipse+Plug-in" title="iPOJO Eclipse Plug-in">iPOJO Eclipse Plug&#45;in</a></li>
	<li><a href="/confluence/display/FELIX/iPOJO+Ant+Task" title="iPOJO Ant Task">iPOJO Ant Task</a></li>
	<li><a href="/confluence/display/FELIX/iPOJO+Maven+Plug-in" title="iPOJO Maven Plug-in">iPOJO Maven Plug&#45;in</a></li>
	<li><a href="/confluence/display/FELIX/iPOJO+Concepts+Overview" title="iPOJO Concepts Overview">iPOJO concepts overview</a></li>
</ul>


<h6><a name="iPOJOin10minutes-DeveloperGuide"></a><b>Developer Guide</b></h6>
<ul>
	<li><a href="/confluence/display/FELIX/How+to+write+your+own+handler" title="How to write your own handler">How to write your own handler</a></li>
	<li><a href="/confluence/display/FELIX/How+to+use+iPOJO+Manipulation+Metadata" title="How to use iPOJO Manipulation Metadata">How to use iPOJO Manipulation Metadata</a></li>
</ul>


<h6><a name="iPOJOin10minutes-Misc%26Contact"></a><b>Misc &amp; Contact</b></h6>
<ul>
	<li><a href="/confluence/display/FELIX/apache-felix-ipojo-issuestracker" title="apache-felix-ipojo-issuestracker">Issues Tracker</a></li>
	<li><span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=Supported+JVMs&amp;linkCreation=true&amp;fromPageId=82824" title="Create Page: Supported JVMs" class="createlink">Supported JVMs<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></li>
	<li><span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=Supported+OSGi+Implementations&amp;linkCreation=true&amp;fromPageId=82824" title="Create Page: Supported OSGi Implementations" class="createlink">Supported OSGi Implementations<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></li>
	<li><a href="/confluence/display/FELIX/Future+Ideas" title="Future Ideas">Future Ideas</a></li>
	<li><span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=Contact&amp;linkCreation=true&amp;fromPageId=82824" title="Create Page: Contact" class="createlink">Contact<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></li>
	<li><a href="/confluence/display/FELIX/Related+Works" title="Related Works">Related Works</a></li>
	<li><a href="/confluence/pages/viewpage.action?pageId=54954" title="Article &amp; Presentations">Article &amp; Presentations</a></li>
</ul>


<hr />
<div class="" align="center">
<p><span class="nobr"><a href="http://cwiki.apache.org/confluence/createrssfeed.action?types=blogpost&amp;statuses=created&amp;statuses=modified&amp;spaces=FELIX&amp;labelString=iPOJO&amp;rssType=atom&amp;maxResults=10&amp;timeSpan=5&amp;publicFeed=true&amp;title=iPOJO+Atom+Feed" title="Stay tuned!" rel="nofollow"><img src="http://cwiki.apache.org/confluence/images/icons/feed-icon-32x32.png" align="absmiddle" border="0" /><sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></p></div></td></tr></tbody></table></div>


</td></tr></table></div>
<p>
<table border="0" cellpadding="0" cellspacing="0" width="100%">
    <tr>
        <td height="12" background="http://cwiki.apache.org/confluence/images/border/border_bottom.gif"><img src="http://cwiki.apache.org/confluence/images/border/spacer.gif" width="1" height="1" border="0"/></td>
    </tr>
</table>

<div class="smalltext">
    Powered by
    <a href="http://www.atlassian.com/software/confluence/default.jsp?clicked=footer" class="smalltext">Atlassian Confluence</a>
    (Version: 2.2.9 Build:#527 Sep 07, 2006)
    -
    <a href="http://jira.atlassian.com/secure/BrowseProject.jspa?id=10470" class="smalltext">Bug/feature request</a><br/>
    <br>
    <a href="http://cwiki.apache.org/confluence/users/viewnotifications.action">Unsubscribe or edit your notifications preferences</a>

</div>

</body>
</html>


Mime
View raw message