felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Felix: How to write your own handler (page edited)
Date Mon, 21 Apr 2008 18:32:01 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/How+to+write+your+own+handler">How to write your own handler</a>
        </span>
    </div>

     <p>
        <a href="http://cwiki.apache.org/confluence/display/FELIX/How+to+write+your+own+handler">How to write your own handler</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=35380&originalVersion=9&revisedVersion=10">(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="Howtowriteyourownhandler-HowtowriteyouriPOJOHandler"></a>How to write your iPOJO Handler</h1>

<p>This document explains how developers can use iPOJO extensibility mechanism to extends the (primitive) component container. This tutorial shows two small examples: a Log Handler logging messages inside the OSGi log service and a Property Handler injecting properties values inside fields.<br/>
This document is organized as follow. First, iPOJO concepts are briefly explained. The next section explains the first step to create a handler. The two last sections describe the implementation and the usage of two example handlers.</p>

<h2><a name="Howtowriteyourownhandler-iPOJOConcepts"></a>iPOJO Concepts</h2>

<p>iPOJO is a service component model aiming to simplify OSGiâ„¢ applications development. iPOJO is based on the POJO concepts. A POJO is a simple Java class without any dependency on its runtime environment.  In iPOJO, POJO are encapsulated in a container managing the relation between the POJO and the external world. This container keeps separate the POJO from the external world. Moreover, this container is flexible and extensible.<br/>
Basically, iPOJO contains two main concepts: Component Type and Component Instance. A component type is a type of component. A component type defines its implementation class, its creation policy, and its container. A component instance is a configured instance of a component type. This instance is created with the component type factory. A component instance inherits of all component type characteristics but has a unique name, and owns a configuration (set of &lt;key, value&gt;).</p>

<p>Above these concepts, iPOJO runtime will manage component type factories and component instances. Each component instance is managed separately. (but the factory can delete them).</p>

<p>A component type declares its container configuration. Each component instance owns its container conform to the component type container configuration. An iPOJO container is composed by an "InstanceManager", encapsulating the POJO, on which are plugged Handlers. A handler manages one non functional concern. Handlers participate to the component instance lifecycle; can interact with the POJO; can manage relations with external entity like database, or other POJOs ...</p>

<p>iPOJO is an extensible model allowing developer to manage other non functional concerns. Indeed, handlers can be developed singly, without modifying the iPOJO core. At runtime, iPOJO will look for each handler needed by a component instance and plug an instance of each (needed) handler on the container. So iPOJO containers are flexible, light and adaptable to each component. When a needed handler cannot be found, the component instance management failed.</p>

<p>An external handler is identified by a Namespace. This namespace matches with the class name (qualified name) implementing the handler behavior. This namespace will be used by developers to refer to the external handler (when he configures its component type) and by iPOJO to instantiate the handler object.</p>

<p><em>Note:</em> iPOJO core contains 5 "core" handlers managing service providing, service dependencies, lifecycle callbacks, instance dynamic configuration and component instance architecture. Theses handlers follow the same rules than external handlers, except that they don't have a namespace.</p>

<h2><a name="Howtowriteyourownhandler-Handlerdevelopmentfirststeps"></a>Handler development first steps</h2>


<h3><a name="Howtowriteyourownhandler-GoGoGo%5C%21"></a>Go Go Go&#33;</h3>

<p>To create a handler, you need to create a Bundle. To know how to create bundles see: <span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=BND&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: BND" class="createlink">http://cwiki.apache.org/confluence/display/FELIX/Bundle+Plugin+for+Maven+%28BND%29<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></p>

<p>Your bundle will contain a class extending the "org.apache.felix.ipojo.Handler" class. All handler need to extends this class. This class defines three abstracts methods: configure, start and stop. This method refers to the component instance lifecycle:</p>
<ul>
	<li>The Configure method is called when the component instance is created. The configure method have three parameters: the instance manager representing the component instance, the component type metadata and the component instance configuration. Inside the Configure method, the handler needs to look for its metadata, and register itself on the component instance.</li>
	<li>The Start method is called when the component instance starts. Then the component instance is started. A started component instance is either VALID or INVALID. A component instance is valid if and only if all plugged handler are valid. In the Start, method a handler needs to start its management (service publication, listener registration...)</li>
	<li>The Stop method is called when the component instance stops. In the Stop, method a handler needs to release all references on services ...</li>
</ul>


<p>Before, implementing the handler, you need to answer to some questions:</p>
<ul>
	<li>How configuring your handler?  : Which metadata need to write a developer in its component type configuration to configure your handler?</li>
	<li>Does your handler participate to the component instance lifecycle? : Does your handler invalid the component instance?</li>
	<li>Does your handler interact with POJO fields?</li>
</ul>


<p>According to theses answers, your handler class needs to parse the component type metadata, and select which method it needs to override from the Handler class.</p>

<p>Your resulting bundle needs to export the package containing your handler class.</p>

<h3><a name="Howtowriteyourownhandler-Handlersclassmethods"></a>Handlers class methods</h3>

<p>This section will explain the handler class. According to this description, you can select which method you want to override.</p>
<ul>
	<li>void configure(InstanceManager im, Element metadata, Dictionary configuration) : this method is mandatory. Your handler will receive the instance manager on which it need to registers, the component type metadata (to parse to find your handler metadata) and the component instance configuration.</li>
	<li>void start() : this method is called when the component instance management starts. Your handler needs to begin its management.</li>
	<li>void stop() : this method is called when the component instance management stops. Your handler needs to end its management, and release all used services.</li>
	<li>boolean isValid() : this method is called by the instance manager, when it needs to check the component instance state (VALID or INVALID). If your handler does not participate to the component instance lifecycle, you don't need to override this method. Else, you need to return if your handler is valid.</li>
	<li>void stateChanged(int state) : this method is called by the instance manager each time that the instance state changes. The parameter describe the new instance state (-1 : Disposed, 0 : Stopped, 1 : Invalid, 2 : Valid).</li>
	<li>void setterCallback (String fieldName, Object value) : this method is called by the instance manager, when a POJO field value changes. To be called, your handler needs to register to the field. The first argument of the method is the field name. The second argument is the new value of the field. If the field type is a primitive type, the method sends the boxing object.</li>
	<li>Object getterCallback (String fieldName, Object value) : this method is called by the instance manager, when a POJO field asks for a value. To be called, your handler needs to register to the field. The first argument of the method is the field name. The second argument is the actual value of the field. This method returns the value that your handler wants to inject in the field.</li>
	<li>void createInstance (Object inst) : this method is called by the instance manager, when a POJO object is created but before that anyone can use it. The argument is the created object.</li>
	<li>void reconfigure(Dictionary configuration) : this method is called when the instance manager recevie a new instance configuration. This configugration can be applied whithout restarting the instance. The parameter contains the new configuration. Each handler managing the dynamic reconfiguration can, by overriden this method, apply the new configuration.</li>
	<li>HandlerDescription getDescription(): this method allow an handler to participate to the instance introspection. When called, the handler needs to describe its state and returns a HandlerDescription object.</li>
</ul>


<h2><a name="Howtowriteyourownhandler-LogHandlerexample"></a>Log Handler example</h2>

<p>This section describes how to create a simple handler. This handler logs a message in the OSGiâ„¢ log service when the component instance state changes. It participates to the component instance lifecycle (the handler in not valid when there is no log service available).</p>

<h3><a name="Howtowriteyourownhandler-Handlermetadata"></a>Handler metadata</h3>

<p>The handler namespace is "org.apache.felix.ipojo.log.handler.LogHandler". It is the handler implementation class too. A developer who wants to use the handler will configure its component type with the following metadata:</p>
<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;iPOJO <span class="code-keyword">xmlns:log</span>= org.apache.felix.ipojo.log.handler.LogHandler&gt;</span>
<span class="code-tag">&lt;component className=<span class="code-quote">"..."</span>&gt;</span>
<span class="code-tag">&lt;log:Log level=<span class="code-quote">"error"</span>/&gt;</span><span class="code-tag">&lt;!- - error, warning or info accepted - -&gt;</span>
<span class="code-tag">&lt;/component&gt;</span>
<span class="code-tag">&lt;instance component=<span class="code-quote">"..."</span> name=<span class="code-quote">"LogHandlerTest-1"</span>/&gt;</span>
<span class="code-tag">&lt;/iPOJO&gt;</span></pre>
</div></div>

<h3><a name="Howtowriteyourownhandler-Handlerimplementation"></a>Handler implementation</h3>

<p>The handler needs to override following methods:</p>
<ul>
	<li>Configure : to parse the metadata and get the logging level</li>
	<li>Start and Stop : to track Log Service</li>
	<li>stateChanged : to log the message</li>
	<li>isValid : to be invalid when the Log Service is not available</li>
</ul>


<h4><a name="Howtowriteyourownhandler-LogHandlerclass"></a>Log Handler class</h4>

<p>The handler is implemented inside the "org.apache.felix.ipojo.log.handler.LogHandler" class. This class extends the "org.apache.felix.ipojo.Handler" class. This class has the final static string field "NAMESPACE", with the "org.apache.felix.ipojo.log.handler.LogHandler" value.</p>

<p>The handler needs the Log Service. So it will implement the "org.osgi.framework.ServiceListener" interface too.</p>

<p>The class has several other fields:</p>
<ul>
	<li>The bundle context (context)</li>
	<li>The instance manager (manage)</li>
	<li>The service reference of the actual used Log Service (ref)</li>
	<li>The used log service (log)</li>
	<li>The level of the log (level)</li>
</ul>


<p><em>Note:</em> Handler code is OSGiâ„¢ standard code. A handler cannot be a POJO.</p>

<h4><a name="Howtowriteyourownhandler-ConfigureMethod"></a>Configure Method</h4>

<p>This method begins by parsing the component type metadata. The handler needs a log element from its namespace. According to the result, the configure method can return immediately or parse the level attribute (to get the logging level). Then, the handler stores some value inside field as the instance manager and the bundle context (note how your handler can access to the bundle context). To finish, the handler must register itself to the instance manager to become a part of the instance container.</p>
<div class="code"><div class="codeHeader"><b>LogHandler.java:Configure Method</b></div><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void configure(InstanceManager im, Element metadata, Dictionary config) {
 <span class="code-comment">// First parse the metadata to check <span class="code-keyword">if</span> the log handler level
</span>
 <span class="code-comment">// Get all Namespace:log element from the metadata
</span> Element[] log_elements = metadata.getElements(<span class="code-quote">"log"</span>, NAMESPACE);

 <span class="code-comment">// <span class="code-keyword">if</span> no element found, <span class="code-keyword">return</span>
</span> <span class="code-keyword">if</span>(log_elements.length == 0) { <span class="code-keyword">return</span>; }
 <span class="code-keyword">else</span> {
	<span class="code-comment">// If an element match, parse the level attribute of the first element
</span>	<span class="code-keyword">if</span>(log_elements[0].containsAttribute(<span class="code-quote">"level"</span>)) {
		<span class="code-object">String</span> l = log_elements[0].getAttribute(<span class="code-quote">"level"</span>);
		<span class="code-keyword">if</span>(l.equalsIgnoreCase(<span class="code-quote">"info"</span>)){level=LogService.LOG_INFO; }
		<span class="code-keyword">else</span> <span class="code-keyword">if</span>(l.equalsIgnoreCase(<span class="code-quote">"error"</span>)){level=LogService.LOG_ERROR; }
       	<span class="code-keyword">else</span> {level=LogService.LOG_WARNING;}
	}

<span class="code-comment">// Register on the instance manager, to be a part of the component                  // instance container
</span>	manager = im;
	context = manager.getContext();  <span class="code-comment">// Store the bundle context
</span>	manager.register(<span class="code-keyword">this</span>);
   }
}</pre>
</div></div>

<h4><a name="Howtowriteyourownhandler-Thestartandstopmethods"></a>The start and stop methods</h4>

<p>The start method needs to look for a Log Service, and register a service listener to track it. If a log service is available, it logs a message.</p>
<div class="code"><div class="codeHeader"><b>LogHandler.java:Start Method</b></div><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void start() {
 <span class="code-comment">// When starting, look <span class="code-keyword">for</span> an LogService
</span> ref = context.getServiceReference(LogService.class.getName());
 <span class="code-keyword">if</span>(ref != <span class="code-keyword">null</span>) {
   log = (LogService) context.getService(ref);
   <span class="code-comment">// Log a starting message
</span>   log.log(level,<span class="code-quote">"The component instance "</span> + manager.getInstanceName() + <span class="code-quote">" is starting"</span>);
 }
<span class="code-comment">// Registered a service listenner
</span><span class="code-keyword">try</span> {
  context.addServiceListener(<span class="code-keyword">this</span>,<span class="code-quote">"(OBJECTCLASS="</span>+LogService.class.getName()+<span class="code-quote">")"</span>);
} <span class="code-keyword">catch</span> (InvalidSyntaxException e) { e.printStackTrace(); }
}</pre>
</div></div>
<p>The stop method logs a message if the Log Service is available. Then it releases the used Log Service.</p>
<div class="code"><div class="codeHeader"><b>LogHandler.java:Stop Method</b></div><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void stop() {
 <span class="code-comment">// Log the event, unget the service
</span> <span class="code-keyword">if</span>(log != <span class="code-keyword">null</span>) { log.log(level, <span class="code-quote">"The component instance "</span> +
				manager.getInstanceName() + <span class="code-quote">" is stopping"</span>); }
 <span class="code-keyword">if</span>(ref != <span class="code-keyword">null</span>) { log = <span class="code-keyword">null</span>; context.ungetService(ref); }
}</pre>
</div></div>
<p><em>Note:</em> do not forget to unget all used services and to release all service objects.</p>

<h4><a name="Howtowriteyourownhandler-TheisValidandstateChangedmethods"></a>The isValid and stateChanged methods</h4>

<p>The isValid method returns the handler validity. In our case, the handler is valid if a log service is available.</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> <span class="code-object">boolean</span> isValid() {
 <span class="code-comment">// The handler is valid &lt;=&gt; a log service is available
</span> <span class="code-keyword">return</span> (ref != <span class="code-keyword">null</span>);
}</pre>
</div></div>
<p>The stateChanged method is called by the instance manager to notify that the component instance state changes. The handler needs to log a message (if the log service is available) containing the new state.</p>
<div class="code"><div class="codeHeader"><b>LogHandler.java:stateChanged method</b></div><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void stateChanged(<span class="code-object">int</span> state) {
 <span class="code-comment">// log the state changed events
</span> <span class="code-keyword">if</span>(log != <span class="code-keyword">null</span>) {
   <span class="code-keyword">if</span>(state == InstanceManager.VALID) { log.log(level, "The component
instance <span class="code-quote">" + manager.getInstanceName() + "</span> becomes valid"); }
   <span class="code-keyword">if</span>(state == InstanceManager.INVALID) { log.log(level, "The component
		instance <span class="code-quote">" + manager.getInstanceName() + "</span> becomes invalid"); }
 }
}</pre>
</div></div>

<h4><a name="Howtowriteyourownhandler-ImplementationoftheServiceListenerinterface"></a>Implementation of the Service Listener interface</h4>

<p>To track the availability of the Log Service, the start method has registered the handler as a service listener. So, the handler class needs to implement the Service Listener interface. This interface contains a method called when a service appears, disappears or is modified. The start method has registered a service listener with a filter. So the handler will received only service events matching the filter. (In our case, only service events referring to a Log Service).</p>
<div class="code"><div class="codeHeader"><b>LogHandler.java:serviceChanged method</b></div><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void serviceChanged(ServiceEvent event) {
  <span class="code-comment">// Check <span class="code-keyword">if</span> the service event does not infers with the log service
</span>  <span class="code-keyword">if</span>(ref == <span class="code-keyword">null</span> &amp;&amp; event.getType() == ServiceEvent.REGISTERED) {
    ref = event.getServiceReference();
    log = (LogService) context.getService(ref);
    <span class="code-comment">// ask the component manager to check the component instance state
</span>    manager.checkInstanceState();
 }
 <span class="code-keyword">if</span>(ref != <span class="code-keyword">null</span> &amp;&amp; event.getType() == ServiceEvent.UNREGISTERING
&amp;&amp; ref == event.getServiceReference()) {
  <span class="code-comment">//The log service goes away
</span>  log = <span class="code-keyword">null</span>;
  context.ungetService(ref);
  ref = context.getServiceReference(LogService.class.getName());
  <span class="code-keyword">if</span>(ref != <span class="code-keyword">null</span>) { log = (LogService) context.getService(ref); }
  <span class="code-keyword">else</span> { manager.checkInstanceState(); }
 }
}</pre>
</div></div>
<p>According to the event type, the method gets or releases a Log Service. If a Log Service appears, the method checks if the handler has already a Log Service. If not, it gets the service object, and asks the component instance to check the instance state because the handler state changes. If a Log Service disappears, the method checks if it used this Log Service. Then, it releases the service and look for another Log Service. If no other Log Service is available, the handler becomes invalid. It asks the instance manager to check the instance state.<br/>
Note: another event type exists. The MODIFED event type describes a property change in a service reference. In the example, we don't manage this event type.</p>

<h3><a name="Howtowriteyourownhandler-Handlerpackaging"></a>Handler packaging</h3>

<p>This handler needs to be packaged inside a bundle exporting the package "org.apache.felix.ipojo.log.handler". The bundle will import "org.apache.felix.ipojo", "org.osgi.framework" and "org.osgi.service.log" packages.</p>

<h3><a name="Howtowriteyourownhandler-Handlerusage"></a>Handler usage</h3>

<p>To use this handler, a component needs to declare an org.apache.felix.ipojo.log.handler.LogHandler :Log XML element, with a level attribute. This level attribute can be "error", "warning" or "info".</p>

<h3><a name="Howtowriteyourownhandler-Download"></a>Download</h3>

<p>This handler is available here : <span class="nobr"><a href="http://cwiki.apache.org/confluence/download/attachments/35380/log_handler.zip" title="Visit page outside Confluence" rel="nofollow">http://cwiki.apache.org/confluence/download/attachments/35380/log_handler.zip<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>.<br/>
The archive file contains the log handler implementation and a simple component using this handler. To work, you need to deploy an implementation of the Log Service. An implementation is available inside the Felix trunk.</p>

<h2><a name="Howtowriteyourownhandler-PropertiesHandlerexample"></a>Properties Handler example</h2>

<p>This section presents a second handler. This handler loads a property file containing field name and initial value. Then it injects and maintains these values inside POJO fields. In this example, only String values are managed.<br/>
This handler is always valid, so do not participate to the component instance lifecycle. Moreover, the handler does not need to be notified when the component instance state changed. But, it need to be notified when POJO fields need a value or change their value.</p>

<h3><a name="Howtowriteyourownhandler-Handlerimplementation"></a>Handler implementation</h3>

<p>The handler needs to override following methods:</p>
<ul>
	<li>Configure : to parse the metadata and load the properties file</li>
	<li>Stop : to store the properties</li>
	<li>getterCallback : to inject a values inside a field</li>
	<li>setterCallback : to obtain the new field value</li>
</ul>


<h4><a name="Howtowriteyourownhandler-PropertiesHandlerclass"></a>Properties Handler class</h4>

<p>The handler is implemented inside the "org.apache.felix.ipojo. properties.handler.PropertiesHandler" class. This class extends the "org.apache.felix.ipojo.Handler" class.<br/>
The class has several fields:</p>
<ul>
	<li>The instance manager (manage)</li>
	<li>The properties to maintain (props)</li>
	<li>The properties file name (file_name)</li>
</ul>


<p><em>Note:</em> the file name is the absolute path on the local machine of the file.</p>

<h4><a name="Howtowriteyourownhandler-ConfigureMethod"></a>Configure Method</h4>

<p>This method begins by parsing the component type metadata. The handler needs a properties element from its namespace. According to the result, the configure method can return immediately or parse the file attribute (to get the properties file path). Then, it builds a field list (String array) to register to field notification. By registering with a field array, the handler will be a part of the component instance container and will be notified of field access.</p>
<div class="code"><div class="codeHeader"><b>PropertiesHandler.java:Configure Method</b></div><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void configure(InstanceManager inst, Element meta, Dictionary conf) {
  manager = inst;
  Element[] prop_element = meta.getElements(<span class="code-quote">"Properties"</span>, NAMESPACE);
  <span class="code-keyword">if</span>(prop_element.length == 0) { <span class="code-keyword">return</span>; }
  <span class="code-keyword">else</span> {
	<span class="code-keyword">if</span>(prop_element[0].containsElement(<span class="code-quote">"file"</span>)) {
        file_name = prop_element[0].getAttribute(<span class="code-quote">"file"</span>);
       }
	<span class="code-keyword">else</span> { <span class="code-keyword">return</span>; }
	<span class="code-comment">// Load the file and register the field
</span>	File file = <span class="code-keyword">new</span> File(file_name);
	<span class="code-keyword">try</span> {
	  InputStream is = <span class="code-keyword">new</span> FileInputStream(file);
	  props.load(is);
	} <span class="code-keyword">catch</span> (FileNotFoundException e) { e.printStackTrace(); <span class="code-keyword">return</span>; }
	  <span class="code-keyword">catch</span> (IOException e) { e.printStackTrace(); <span class="code-keyword">return</span> ; }
	<span class="code-comment">// Register to field notification
</span>	Enumeration e = props.propertyNames();
	<span class="code-object">String</span>[] fields = <span class="code-keyword">new</span> <span class="code-object">String</span>[props.size()];
	<span class="code-keyword">for</span>(<span class="code-object">int</span> i=0; i &lt; fields.length; i++) {fields[i]=(<span class="code-object">String</span>)e.nextElement();}
	manager.register(<span class="code-keyword">this</span>, fields);
  }
}</pre>
</div></div>

<h4><a name="Howtowriteyourownhandler-Thestartandstopmethods"></a>The start and stop methods</h4>

<p>The start method does nothing, but need to be implemented.</p>
<div class="code"><div class="codeHeader"><b>PropertiesHandler.java:Start Method</b></div><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void start() { }</pre>
</div></div>
<p>The stop method stores properties inside the properties file.</p>
<div class="code"><div class="codeHeader"><b>PropertiesHandler.java:Stop Method</b></div><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void stop() {
 File file = <span class="code-keyword">new</span> File(file_name);
 <span class="code-keyword">try</span> {
   OutputStream os = <span class="code-keyword">new</span> FileOutputStream(file);
   props.store(os, <span class="code-quote">"written by "</span> + NAMESPACE);
 } <span class="code-keyword">catch</span> (FileNotFoundException e) { e.printStackTrace(); }
   <span class="code-keyword">catch</span> (IOException e) { e.printStackTrace(); }
}</pre>
</div></div>

<h4><a name="Howtowriteyourownhandler-GetterCallbackandSetterCallbackmethods"></a>GetterCallback and SetterCallback methods</h4>

<p>The getterCallback method is called when the POJO need a field value. When called, the method needs to return the stored value.<br/>
The setterCallback method is called when the POJO modifies a field value. If the new value if null, the handler will remove this properties from the property list.</p>
<div class="code"><div class="codeHeader"><b>PropertiesHandler.java: GetterCallback and SetterCallback methods</b></div><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void setterCallback(<span class="code-object">String</span> fieldName, <span class="code-object">Object</span> value) {
 <span class="code-comment">// Store the <span class="code-keyword">new</span> value in props (<span class="code-keyword">if</span> not <span class="code-keyword">null</span>) <span class="code-keyword">else</span> remove the property
</span> <span class="code-keyword">if</span>(value != <span class="code-keyword">null</span>) { props.put(fieldName, value); }
 <span class="code-keyword">else</span> { props.remove(fieldName); }
}

<span class="code-keyword">public</span> <span class="code-object">Object</span> getterCallback(<span class="code-object">String</span> fieldName, <span class="code-object">Object</span> value) {
  <span class="code-keyword">if</span>(props.containsKey(fieldName)) { <span class="code-keyword">return</span> props.get(fieldName); }
  <span class="code-keyword">else</span> { <span class="code-keyword">return</span> value; }
}</pre>
</div></div>

<h3><a name="Howtowriteyourownhandler-Handlerpackaging"></a>Handler packaging</h3>

<p>This handler needs to be packaged inside a bundle exporting the package "org.apache.felix.ipojo.properties.handler". The bundle will import the "org.apache.felix.ipojo" packages.</p>

<h3><a name="Howtowriteyourownhandler-Handlerusage"></a>Handler usage</h3>

<p>To used this handler, a component need to declare an org.apache.felix.ipojo.properties.handler :Properties XML element, with a file attribute indicating the absolute file path.</p>

<p><em>Note:</em> the file path need to used two '\' instead of one '\'</p>

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

<p>In this document, we present how-to develop handler for your components. We describe two small examples : a log handler and a properties handler. These handlers are plugged on (primitive) instance. However, it is posible to extends Composite Handler too. See the handler proposition section of the iPOJO documentation to see available handlers or to propose your own handler. </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="Howtowriteyourownhandler-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="Howtowriteyourownhandler-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="Howtowriteyourownhandler-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="Howtowriteyourownhandler-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="Howtowriteyourownhandler-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="Howtowriteyourownhandler-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