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 Sat, 04 Oct 2008 16:19:00 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">(Oct 04, 2008)</span>.
     </p>
    
     <p>
                 <a href="http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=35380&originalVersion=10&revisedVersion=11">(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 extend the (primitive) component instance container.</p>

<p>First, iPOJO concepts are briefly explained. The second section explains the steps to create a handler. The two last sections describes the implementation and the usage of two small example handlers : a Log Handler, logging messages inside the OSGi log service, and a Property Handler, injecting properties values inside fields.</p>

<h2><a name="Howtowriteyourownhandler-iPOJOConcepts"></a>iPOJO Concepts </h2>
<p>iPOJO is a service oriented 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 separated the POJO from the external "wild" world. Moreover, this container can be extended, using handlers.<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 its own configuration (set of &lt;key, value&gt;).<br/>
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 <tt>InstanceManager</tt>, 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... For example, a persistence handler may interact with a database to store and inject POJO state, while an administration handler may use JMX to allow remote configuration of instance properties.</p>

<p><span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=Image.&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: Image." class="createlink">Image.<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></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 looks for each handler needed by a component instance and plugs an instance of each (required) 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 cannot be created.<br/>
An external handler is identified by a namespace. 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 6 "core" handlers managing service providing, service dependencies, lifecycle callbacks, lifecycle controller, instance dynamic configuration, and component instance architecture. Theses handlers follow the same rules than external handlers, except that they use the iPOJO default namespace (i.e. org.apache.felix.ipojo).</p>

<h2><a name="Howtowriteyourownhandler-Handlerdevelopmentbasis"></a>Handler development basis </h2>
<h3><a name="Howtowriteyourownhandler-Fundamentals"></a>Fundamentals </h3>
<p>As explain above, the handler interacts with the POJO, with the component's container and with the external world (e.g. : other components, services, bundles, the OSGi framework, ...). The skeleton of such an agent is defined in iPOJO is defined by the <tt>PrimitiveHandler</tt> (abstract) class that can be found in the <tt>org.apache.felix.ipojo</tt> package.</p>

<p>You need to implement the three basic lifecycle methods of this class, but you can extends this model by redefining some other methods (e.g. : to intercept POJO method calls, field accesses, ...).</p>

<h3><a name="Howtowriteyourownhandler-Declaringyourhandler"></a>Declaring your handler </h3>
<p>You first need to declare your handler, so iPOJO will be able to initialize, configure and use it when needed. First, you must give a name and an XML namespace to your handler. By doing that, iPOJO can recognize that a certain component uses your handler, so it can initialize it. You need to declare, in the <tt>metadata.xml</tt> of the bundle containing your handler, the class name of your handler and its name and XML namespace. You can, of course, declare several handlers, and even declare components using these handlers, in the same bundle.<br/>
Then, you must know that a handler is a component (almost) like standard iPOJO components : it can use other handlers (like core handlers : service requirements, provided services, ...). You can consequently describe your handler's required services, provided services, etc. in its metadata.xml, as for classic iPOJO components.</p>
<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;ipojo&gt;</span>
 ... 
    <span class="code-tag">&lt;handler className=<span class="code-quote">"your.handler.class"</span> name=<span class="code-quote">"HandlerName"</span> namespace=<span class="code-quote">"the.namespace.of.your.handler"</span>&gt;</span>
        ...
        <span class="code-tag">&lt;provides interface=<span class="code-quote">"a.provided.Service"</span>&gt;</span>        
            <span class="code-tag">&lt;property field=<span class="code-quote">"a_field"</span> name=<span class="code-quote">"a.property"</span> value=<span class="code-quote">"a.value"</span>/&gt;</span>
        <span class="code-tag">&lt;/provides&gt;</span>
        ...
    <span class="code-tag">&lt;/handler&gt;</span>
<span class="code-tag">&lt;/ipojo&gt;</span></pre>
</div></div>

<p><em>Note :</em> In order to use iPOJO annotations processing, the namespace must be a valid package name and the name must be a valid annotation name (without the '@'). Refer to the <span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=Handler%27s+annotations&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: Handler's annotations" class="createlink">Handler's annotations<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> section in the <span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=Advanced+Topics&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: Advanced Topics" class="createlink">Advanced Topics<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> chapter.</p>

<p><em>Hint :</em> It is a good idea to provide a documented XML schema description (XSD) with your handler to help users to configure your handler and to validate their configurations. Refer to the <span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=Handler%27s+XSD&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: Handler's XSD" class="createlink">Handler's XSD<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> section in the <span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=Advanced+Topics&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: Advanced Topics" class="createlink">Advanced Topics<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> chapter.</p>

<h2><a name="Howtowriteyourownhandler-Handlerlifecycle"></a>Handler lifecycle </h2>
<p>A handler lifecycle is composed of four different states.</p>

<p><span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=Image.&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: Image." class="createlink">Image.<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></p>

<ul>
	<li>First, when iPOJO parses the <tt>metadata.xml</tt> of a bundle, it detects that a certain component type use your handler (using XML qualified names, see the following ìUsing your handlerî section). When it finds such a reference, it initializes the handler by calling the <tt>initializeComponentFactory()</tt> method. This method should be static but actually can't be so for some technical reasons. Consequently, a ìmockî instance of the handler is created, the <tt>initializeComponentFactory()</tt> method is called, and this instance is destroyed. This method aims to check the validity of the component type description, avoiding starting invalid factories.If you override this method, you should here set up the component description (e.g. : common properties, exported services, ...) and check the handler configuration. The parameters passed to this method are the <tt>ComponentTypeDescription</tt> and the component's <tt>Metadata</tt> (i.e. : the structure of the component type declaration).</li>
	<li>Once your handler has been initialized, iPOJO configures it for each created instance of the using components. The <tt>ComponentTypeDescription</tt> and the instance specific properties are passed to the <tt>configure()</tt> method of your handler.This method is mandatory so you have to implement it. Here you should check the handler configuration (if not already done in the <tt>initializeComponentFactory()</tt> method) and configure the handler with given instance specific properties.</li>
	<li>Then, iPOJO starts the handler, following the component instance lifecycle, by calling the <tt>start()</tt> method. You have to put in this method the activation code of your handler. A freshly started handler is by default in an active state (if all its used handlers, like required services, are in an active state).</li>
	<li>Once started, the handler state can be either in a valid or in an invalid state, depending on its used handlers (a handler is an iPOJO component, so it can depend on other handlers, like service dependencies, provided services, ... See the ìHandler extends Componentî section). The validity of your handler depends on used handlers status, but it also can be changed in your handler code by using the <tt>setValidity()</tt> method.</li>
	<li>Finally, when the component instance is stopped (generally just before being destroyed), the stop method of the handler is called. Place here the inactivation code of your handler.</li>
</ul>


<p><em>Note :</em> Keep in mind that the <tt>stop()</tt> method of your handler is called when the component instance is stopped (not necessarily destroyed). This instance can be restarted later, so the same instance of your handler must have to ability to restart too.</p>

<h1><a name="Howtowriteyourownhandler-Readinghandlerandinstanceconfigurations"></a>Reading handler and instance configurations </h1>
<p>Your handler need to read how it is configured in the using component type description. The configuration is written in the <tt>metadata.xml</tt> of the using bundle, but is passed to the <tt>initializeComponentFactory()</tt> and <tt>configure()</tt> methods as an <tt>Element</tt> object.</p>

<p>The <tt>Element</tt> type (placed in the <tt>org.apache.felix.ipojo.metadata package</tt>), coupled with the <tt>Attribute</tt> type, is used to retrieve the structure and the content of the component configuration. The <tt>Element</tt> parameter, passed to the initialization and configuration methods, represents the root of the component type description (i.e. the root of the tree is the <tt>component</tt> XML tag).</p>

<p>Several methods allows to browse the entire configuration from the root <tt>Element</tt> :</p>

<ul>
	<li>The <tt><b>getElement()</b></tt> methods let you access the content of an <tt>Element</tt> (i.e. the children elements)</li>
	<li>The <tt><b>getAttribute()</b></tt> methods allows you to access the attributes of an <tt>Element</tt>.</li>
	<li>The <tt><b>containsElement()</b></tt> and <tt><b>containsAttribute()</b></tt> methods test the presence of a child-element or an attribute in an <tt>Element</tt>.</li>
</ul>


<p><em>Note :</em> As described in the <span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=Declaring+your+handler&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: Declaring your handler" class="createlink">Declaring your handler<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span> section, a name and a namespace are associated to each handler. To safely retrieve the configuration of this handler from the component metadata, you can take inspiration from the following snippet (the <tt>componentMetadata</tt> variable is the component root <tt>Element</tt> passed to the <tt>initializeComponentFactory()</tt> and <tt>configure()</tt> methods) :</p>

<div class="code"><div class="codeContent">
<pre class="code-java">Element[] handlerConfig = componentMetadata.getElements(<span class="code-quote">"HandlerName"</span>,
                                          <span class="code-quote">"the.namespace.of.your.handler"</span>);</pre>
</div></div>

<p>You will also need to read specific instance configuration (properties defined in the <tt>instance</tt> XML tag). The instance properties are directly passed, as a <tt>Dictionary,</tt> to the <tt>configure()</tt> method. With these properties, you can easily allow instances to override some component fixed configuration.</p>

<h2><a name="Howtowriteyourownhandler-InteractingwiththePOJO"></a>Interacting with the POJO </h2>
<p>One of the most interesting features of an handler is the ability to interact with the component's POJO. Indeed, you can intercept method calls and returns, inject values in the POJO's fields...</p>

<p>The <tt>getPojoMetadata()</tt> method of the PrimitiveHandler class lets you access the structure of the POJO (represented by the <tt>PojoMetadata</tt> type) without having to use (slow) reflection. It allows you to list all fields and methods of the POJO, and get informations about implemented interfaces and the super-class. The <tt>PojoMetadata</tt> class implements the following operations :</p>

<ul>
	<li>The <tt><b>getInterfaces()</b></tt> method returns the list of implemented interfaces, while the <tt><b>isInterfaceImplemented()</b></tt> methods test if a given interface is implemented by the POJO.</li>
	<li>The <tt><b>getSuperClass()</b></tt> method returns the name of the class extended by the POJO (or <tt>null</tt> instead of <tt>java.lang.Object</tt>).</li>
	<li>The <tt><b>getField()</b></tt> methods lets you access the fields of the POJO. The returned object is a <tt>FieldMetadata</tt> that provides informations about a particular field inside the POJO.</li>
	<li>The <tt><b>getMethod()</b></tt> methods lets you access the methods of the POJO. The returned object is a <tt>MethodMetadata</tt> that provides informations about a particular method in the POJO.</li>
</ul>


<p>Once you've retrieved informations about the POJO structure, you can interact with it, via the <tt>InstanceManager</tt>, accessible in your handler by the <tt>getInstanceManager()</tt> method. It allows you to register interceptors, that are called before and after POJO method calls or field accesses.</p>

<p><em>Note :</em> The InstanceManager manages the component instance attached to your handler instance. Thus, it can't be available in the <tt>initializeComponentFactory()</tt> because this method is run before the creation of any component instance.</p>

<p>You need to implement some of the following methods to intercept fields accesses :</p>

<ul>
	<li>The <tt>void <b>onSet</b>(Object pojo, String fieldName, Object value)</tt> method: This method is called each time a field of the POJO is assigned. The first parameter is the instance of the concerned POJO, the second is the name of the accessed field and the third is the value assigned to the POJO's field. If the field type is a primitive type, this method receives the boxed object.</li>
	<li>The <tt>Object <b>onGet</b>(Object pojo, String fieldName, Object value)</tt> method : This method is called each time a field of the POJO is read. The first parameter is the instance of the concerned POJO, the second is the name of the accessed field and the third is the actual value of the POJO's field. If the field type is a primitive type, this method receives the boxed object. The returned object is the value the intercepted read process will return. It's the standard way to inject a value in the field : returning a specific object whatever the field really contains.</li>
</ul>


<p>You need to implements some of the following methods to intercept methods accesses. When these methods are called, the first parameter is the POJO's instance on which the intercepted method is called and the second parameter contains the descriptor of the called method.</p>

<ul>
	<li>The <tt>void <b>onEntry</b>(Object pojo, Method method, Object[] args)</tt> method: This method is called before the execution of an intercepted method. The third parameter is the list of parameters with which the method have been called. The method is executed just after the execution of the <tt>onEntry()</tt> callback.</li>
	<li>The <tt>void <b>onExit</b>(Object pojo, Method method, Object returnedObj)</tt> method: This method is called right after the successful execution of an intercepted method. The third parameter is the value returned by the method (or <tt>null</tt> if the method return type is <tt>void</tt>). This value must not be modified.</li>
	<li>The <tt>void <b>onError</b>(Object pojo, Method method, Throwable throwable)</tt> method: This method is called right after the unexpected return of an intercepted method (i.e. when an uncaught exception occurred). The third parameter is the thrown object that caused the method termination.</li>
	<li>The <tt>void <b>onFinally</b>(Object pojo, Method method)</tt> method: This method is called after the termination of an intercepted method (expected or not), after the call of the <tt>onExit()</tt> or <tt>onError()</tt> callback.</li>
</ul>


<p><em>Warning :</em> The <tt>InstanceManager</tt> has to know your handler wants to intercept fields or methods access, otherwise the implemented callbacks won't be called. Thus you need to register each field and method you want to intercept, so the <tt>InstanceManager</tt> will call the appropriated callbacks when the specified field or method is accessed :</p>

<div class="code"><div class="codeContent">
<pre class="code-java">getInstanceManager().register(anInterestingFieldMetadata, <span class="code-keyword">this</span>);
 ...
 getInstanceManager().register(anInterestingMethodMetadata, <span class="code-keyword">this</span>);
 ...</pre>
</div></div>

<p><em>Note :</em> The <tt>PrimitiveHandler</tt> abstract class implements the <tt>FieldInterceptor</tt> and <tt>MethodInterceptor</tt> interfaces, which declares the methods described just above. You can create your own interceptor class (implementing one or both of these interfaces) and give it to the <tt>InstanceManager</tt> register method instead of the handler object itself.</p>

<h2><a name="Howtowriteyourownhandler-Usingyourhandler"></a>Using your handler </h2>
<p>Once your handler has been declared, you can use it in iPOJO components. To do so, you first have to be bound to your handler's namespace (using standard XML namespace declaration). Then you can configure the handler in your components type description. An example of bundle's <tt>metadata.xml</tt> declaring components using the handler is shown hereafter :</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;ipojo xmlns:your-shortcut=<span class="code-quote">"the.namespace.of.your.handler"</span>&gt;
    ...
    &lt;component className=<span class="code-quote">"your.component.class"</span>&gt;
        ...
        &lt;your-shortcut:HandlerName param1=<span class="code-quote">"value1"</span> ...&gt;
            &lt;!-- Configuration of your handler <span class="code-keyword">for</span> <span class="code-keyword">this</span> component type --&gt;
        &lt;/your-shortcut{noformat}:HandlerName&gt;
        ...
    &lt;/component&gt;
    ...
&lt;/ipojo&gt;</pre>
</div></div>

<p>The remainder of this document describes two examples of handlers:</p>
<ul>
	<li>A log handler logging messages in the OSGi Log Service</li>
	<li>A properties handler reading a property files to configure POJO field</li>
</ul>


<h1><a name="Howtowriteyourownhandler-LogHandlerexample"></a>Log Handler example</h1>
<p>This section describes how to create a simple handler. This handler logs a message in the <em>OSGi Log Service</em> (if present) when the component instance state changes. The code source of this handler is downloadable <span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=here&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: here" class="createlink">here<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>.</p>

<h2><a name="Howtowriteyourownhandler-Handlermetadata"></a>Handler metadata</h2>
<p>The handler namespace is <tt>"org.apache.felix.ipojo.log.handler.LogHandler"</tt>. It is also the name of the handler implementation class. You can note that the handler has an optional dependency on a OSGi log service. If no log services are found, a default implementation is used instead.</p>
<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;ipojo&gt;</span>
    <span class="code-tag"><span class="code-comment">&lt;!-- Declare the handler --&gt;</span></span>
    <span class="code-tag">&lt;handler classname=<span class="code-quote">"org.apache.felix.ipojo.handler.log.LogHandler"</span>  name=<span class="code-quote">"log"</span>  namespace=<span class="code-quote">"org.apache.felix.ipojo.log.handler.LogHandler"</span> &gt;</span>
        <span class="code-tag"><span class="code-comment">&lt;!-- The log service dependency --&gt;</span></span>
        <span class="code-tag">&lt;requires field=<span class="code-quote">"m_log"</span>  optional=<span class="code-quote">"true"</span>  default-implementation=<span class="code-quote">"org.apache.felix.ipojo.handler.log.PrimitiveLogService"</span>/&gt;</span>
    <span class="code-tag">&lt;/handler&gt;</span>
<span class="code-tag">&lt;/ipojo&gt;</span></pre>
</div></div>

<h2><a name="Howtowriteyourownhandler-Handlerimplementation"></a>Handler implementation </h2>
<p>The handler needs to override following methods:</p>
<ul>
	<li><tt>configure</tt> : to parse the metadata and load the properties file</li>
	<li><tt>stateChanged</tt> : to log messages when the instance state changes.</li>
</ul>


<h3><a name="Howtowriteyourownhandler-LogHandlerclass"></a>LogHandler class </h3>
<p>The handler is implemented inside the <tt>LogHandler</tt> class in the <tt>org.apache.felix.ipojo.handler.log</tt> package. This class extends the <tt>org.apache.felix.ipojo.PrimitiveHandler</tt> class.<br/>
The handler needs to be notified when component instances becomes valid or invalid, thus it implements the <tt>InstanceStateListener</tt> interface.</p>

<h3><a name="Howtowriteyourownhandler-InitializeComponentFactoryMethod"></a>InitializeComponentFactory Method </h3>
<p>This method parses and checks the component type metadata. The handler needs a log element from its namespace. According to the result, the configure method can throw an exception or parse the level attribute (to get the logging level).</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void initializeComponentFactory(ComponentTypeDescription typeDesc, Element metadata) <span class="code-keyword">throws</span> ConfigurationException { 
    <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">// There must be exactly one configuration element. 
</span>    <span class="code-keyword">if</span> (log elements.length == 1) { 
        Element log_element = log_elements[0]; <span class="code-comment">// There must be a level attribute in the configuration element 
</span>        <span class="code-keyword">if</span>(log_element.containsAttribute(<span class="code-quote">"level"</span>)) { 
            <span class="code-object">String</span> level = log_element.getAttribute(<span class="code-quote">"level"</span>); <span class="code-comment">// Check the value of the level attribute
</span>            <span class="code-keyword">if</span> (level == <span class="code-keyword">null</span>) {
                <span class="code-keyword">throw</span> <span class="code-keyword">new</span> ConfigurationException(<span class="code-quote">"No level attribute found in the configuration"</span>);
            }
            <span class="code-keyword">if</span> (!level.equalsIgnoreCase(<span class="code-quote">"info"</span>) &amp;&amp; !level.equalsIgnoreCase(<span class="code-quote">"warning"</span>) &amp;&amp; !level.equalsIgnoreCase(<span class="code-quote">"error"</span>)) {
                <span class="code-keyword">throw</span>* <span class="code-keyword">new</span> ConfigurationException(<span class="code-quote">"Bad log level specified, accepted values are : info, warning, error"</span>);
            }
        }
    }
}</pre>
</div></div>

<h3><a name="Howtowriteyourownhandler-ConfigureMethod"></a>Configure Method </h3>
<p>This method reads the component description and configures the handler. Then, the handler registers itself to the instance manager to be informed of the component's validity changes.</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void configure(Element metadata, Dictionary config)
                                <span class="code-keyword">throws</span> ConfigurationException {
   
   <span class="code-comment">// Get the configuration element
</span>   Element log_element = metadata.getElements(<span class="code-quote">"log"</span>, _NAMESPACE_{noformat})[0];{noformat}
   
   <span class="code-comment">// Get the level attribute's value
</span>   <span class="code-object">String</span> level = log_element.getAttribute(<span class="code-quote">"level"</span>);
   
   <span class="code-comment">// Extract the log level
</span>   <span class="code-keyword">if</span>(level.equalsIgnoreCase(<span class="code-quote">"info"</span>)) { 
       m_level = LogService.LOG_INFO;
    } <span class="code-keyword">else</span> <span class="code-keyword">if</span> (level.equalsIgnoreCase(<span class="code-quote">"warning"</span>)) { 
       m_level = LogService.LOG_WARNING;
    } <span class="code-keyword">else</span> <span class="code-keyword">if</span> (level.equalsIgnoreCase(<span class="code-quote">"error"</span>)) { 
       m_level = LogService.LOG_ERROR;
    }
    
    m_manager = getInstanceManager(); 
    m_context = m_manager.getContext();
}</pre>
</div></div>

<h3><a name="Howtowriteyourownhandler-StateChangedMethod"></a>StateChanged Method </h3>
<p>This method is called by the instance manager to notify that the component instance state changes. The handler needs to log a message containing the new state.</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void stateChanged(ComponentInstance instance, <span class="code-object">int</span> state) {
    <span class="code-comment">// Log the state changed events
</span>    <span class="code-keyword">if</span> (state == InstanceManager.VALID) { 
        m_log.log(m_level, <span class="code-quote">"The component instance "</span> + m_manager.getInstanceName() + <span class="code-quote">" becomes VALID"</span>); 
    } <span class="code-keyword">else</span> <span class="code-keyword">if</span> (state == InstanceManager.INVALID) { 
        m_log.log(m_level, <span class="code-quote">"The component instance "</span> + }}m_manager{{.getInstanceName() + <span class="code-quote">" becomes INVALID"</span>); 
    }
}</pre>
</div></div>

<h2><a name="Howtowriteyourownhandler-Handlerpackaging"></a>Handler packaging </h2>
<p>This handler needs to be packaged inside an iPOJO bundle. The bundle will import the <tt>org.apache.felix.ipojo</tt>, <tt>org.osgi.framework</tt> and <tt>org.osgi.service.log</tt> packages.</p>

<h2><a name="Howtowriteyourownhandler-Handlerusage"></a>Handler usage </h2>
<p>To use this handler, a component needs to declare an <tt>org.apache.felix.ipojo.log.handler.LogHandler:log</tt> XML element, with a level attribute. This level attribute's value can be <tt>"error"</tt>, <tt>"warning"</tt> or <tt>"info"</tt>. Here is an usage example:</p>
<div class="code"><div class="codeContent">
<pre class="code-xml"><span class="code-tag">&lt;ipojo <span class="code-keyword">xmlns:log</span>=<span class="code-quote">"org.apache.felix.ipojo.log.handler.LogHandler"</span>&gt;</span>
     
    <span class="code-tag"><span class="code-comment">&lt;!-- Declare a component using the LogHandler --&gt;</span></span>
    <span class="code-tag">&lt;component_classname=_<span class="code-quote">"..."</span>_&gt;</span>
        ...
        &lt;!-- Configuration of the LogHandler ?
        <span class="code-tag">&lt;log:log level=_<span class="code-quote">"WARNING"</span>_ /&gt;</span>
     <span class="code-tag">&lt;/component&gt;</span>
     ...
<span class="code-tag">&lt;/ipojo&gt;</span></pre>
</div></div>

<h2><a name="Howtowriteyourownhandler-Download"></a>Download </h2>
<p>The LogHandler is available here : <span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=INSERT+URL+HERE&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: INSERT URL HERE" class="createlink">INSERT URL HERE<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>. The archive file contains the handler implementation and a simple component using this handler.</p>

<h1><a name="Howtowriteyourownhandler-PropertiesHandlerexample"></a>Properties Handler example </h1>
<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.</p>

<p>You can find the sources of this example handler in the <tt>example/handler/property</tt> directory of the iPOJO sources.</p>

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

<h2><a name="Howtowriteyourownhandler-Handlerimplementation"></a>Handler implementation </h2>
<p>The handler needs to override following methods:</p>

<ul>
	<li><tt>configure</tt> : to parse the metadata and load the properties file</li>
	<li><tt>stop</tt> : to store the properties</li>
	<li><tt>onGet</tt> : to inject a values inside a field</li>
	<li><tt>onSet</tt> : to obtain the new field value</li>
</ul>


<h3><a name="Howtowriteyourownhandler-PropertiesHandlerclass"></a>PropertiesHandler class </h3>
<p>The handler is implemented by the <tt>PropertiesHandler</tt> class present in the <tt>org.apache.felix.ipojo.properties.handler</tt> package. The class has several fields:</p>

<ul>
	<li>The properties to maintain (<tt>m_properties</tt>)</li>
	<li>The properties file name (<tt>m_file</tt>)</li>
</ul>


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

<h3><a name="Howtowriteyourownhandler-ConfigureMethod"></a>Configure Method </h3>
<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="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void configure(Element metadata, Dictionary configuration) <span class="code-keyword">throws</span> ConfigurationException {
    <span class="code-comment">// Parse metadata to get &lt;properties file=<span class="code-quote">"$file"</span>/&gt;
</span>    Element[] elem = metadata.getElements(<span class="code-quote">"properties"</span>, NAMESPACE).  <span class="code-comment">// Get all example.handler.properties:properties element 
</span>    <span class="code-keyword">switch</span> (elem.length) {
        <span class="code-keyword">case</span> 0: <span class="code-comment">// No matching element in metadata, <span class="code-keyword">throw</span> a configuration error. 
</span>            <span class="code-keyword">throw</span> <span class="code-keyword">new</span> ConfigurationException(<span class="code-quote">"No properties found"</span>);
        <span class="code-keyword">case</span> 1: <span class="code-comment">// One 'properties' found, get attributes
</span>            m_file = elem[0].getAttribute(<span class="code-quote">"file"</span>); 
            <span class="code-keyword">if</span> (m_file == <span class="code-keyword">null</span>) { <span class="code-comment">// <span class="code-keyword">if</span> file is <span class="code-keyword">null</span>, <span class="code-keyword">throw</span> a configuration error. 
</span>                <span class="code-keyword">throw</span> <span class="code-keyword">new</span> ConfigurationException(<span class="code-quote">"Malformed properties element : file attribute must be set"</span>);
             } 
             <span class="code-keyword">break</span>;
         <span class="code-keyword">default</span>: <span class="code-comment">// To simplify we handle only one properties element. 
</span>             <span class="code-keyword">throw</span> <span class="code-keyword">new</span> ConfigurationException(<span class="code-quote">"Only one properties element is supported"</span>); 
     }  
     <span class="code-comment">// Look <span class="code-keyword">if</span> the instance configuration overrides file location : 
</span>     <span class="code-object">String</span> instanceFile = (<span class="code-object">String</span>) configuration.get(<span class="code-quote">"properties.file"</span>); 
     <span class="code-keyword">if</span> (instanceFile != <span class="code-keyword">null</span>) {
         m_file = instanceFile; 
      }
      <span class="code-comment">// Load properties
</span>      <span class="code-keyword">try</span>{
          loadProperties();
      } <span class="code-keyword">catch</span>(IOException e) {
          <span class="code-keyword">throw</span> <span class="code-keyword">new</span> ConfigurationException(<span class="code-quote">"Error when reading the "</span> +  m_file + <span class="code-quote">" file : "</span> + e.getMessage()); 
      }
      <span class="code-comment">// Register fields 
</span>      <span class="code-comment">// By convention, properties file entries are field name, so look <span class="code-keyword">for</span> each property to get field list.
</span>      <span class="code-comment">//First get the Pojo Metadata metadata:
</span>      PojoMetadata pojoMeta = getPojoMetadata();
      Enumeration e = m_properties.keys();
      <span class="code-keyword">while</span>(e.hasMoreElements()) { 
          <span class="code-object">String</span> field = (<span class="code-object">String</span>) e.nextElement();
          FieldMetadata fm = pojoMeta.getField(field);
          <span class="code-keyword">if</span>(fm==<span class="code-keyword">null</span>){
              <span class="code-comment">//The field does not exist
</span>              <span class="code-keyword">throw</span> <span class="code-keyword">new</span> ConfigurationException(<span class="code-quote">"The field "</span> + field + <span class="code-quote">" is declared in the properties file but does not exist in the pojo"</span>);
          }
          <span class="code-comment">// Then check that the field is a <span class="code-object">String</span> field 
</span>          <span class="code-keyword">if</span> (!fm.getFieldType().equals(<span class="code-object">String</span>.class.getName())) { 
              <span class="code-keyword">throw</span> <span class="code-keyword">new</span> ConfigurationException(<span class="code-quote">"The field "</span> + field + <span class="code-quote">" exists in the pojo, but is not a <span class="code-object">String</span>"</span>); 
          } 
          <span class="code-comment">// All checks are ok, register the interceptor. 
</span>          getInstanceManager().register(fm, <span class="code-keyword">this</span>);
      }
  }
}</pre>
</div></div>

<h3><a name="Howtowriteyourownhandler-Thestartandstopmethods"></a>The start and stop methods </h3>
<p>The start method does nothing, but needs to be implemented.</p>
<div class="code"><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="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> void stop() { 
    <span class="code-keyword">try</span> { 
        saveProperties();
    } <span class="code-keyword">catch</span> (IOException e) { 
        <span class="code-comment">// Log an error message by using the iPOJO logger 
</span>        error(<span class="code-quote">"Cannot read the file : "</span> + m_file, e); 
    } 
    m_properties = <span class="code-keyword">null</span>;
}</pre>
</div></div>

<h3><a name="Howtowriteyourownhandler-onGetandonSetmethods"></a>onGet and onSet methods </h3>
<p>The onGet method is called when the POJO need a field value. When called, the method needs to return the stored value.The onSet 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="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> <span class="code-object">Object</span> onGet(<span class="code-object">Object</span> pojo, <span class="code-object">String</span> field, <span class="code-object">Object</span> o) { 
    <span class="code-comment">// When the pojo requires a value <span class="code-keyword">for</span> a managed field, <span class="code-keyword">this</span> method is invoked. 
</span>    <span class="code-comment">// So, we have just to <span class="code-keyword">return</span> the stored value. 
</span>    <span class="code-keyword">return</span> m_properties.get(field);
}

<span class="code-keyword">public</span> void onSet(<span class="code-object">Object</span> pojo, <span class="code-object">String</span> field, <span class="code-object">Object</span> newvalue) { 
    <span class="code-comment">// When the pojo set a value to a managed field, <span class="code-keyword">this</span> method is invoked. 
</span>    <span class="code-comment">// So, we update the stored value. 
</span>    m_properties.put(field, newvalue);
}</pre>
</div></div>

<h2><a name="Howtowriteyourownhandler-Handlerpackaging"></a>Handler packaging </h2>
<p>This handler needs to be inside a bundle importing the <tt>org.apache.felix.ipojo</tt> packages and exporting the <tt>org.apache.felix.ipojo.properties.handler</tt> package.</p>

<h2><a name="Howtowriteyourownhandler-Handlerusage"></a>Handler usage </h2>
<p>To use this handler, a component need to declare an <tt>Properties</tt> XML element in the <tt>org.apache.felix.ipojo.properties.handler</tt> namespace, with a <tt>file</tt> attribute indicating the absolute file path of the properties file.</p>

<p><em>Note :</em> you need to escape '\' (anti-slash characters) in the file path name.</p>

<h2><a name="Howtowriteyourownhandler-Download"></a>Download </h2>
<p>The PropertiesHandler is available here : <span class="nobr"><a href="/confluence/pages/createpage.action?spaceKey=FELIX&amp;title=INSERT+URL+HERE&amp;linkCreation=true&amp;fromPageId=35380" title="Create Page: INSERT URL HERE" class="createlink">INSERT URL HERE<sup><img class="rendericon" src="/confluence/images/icons/plus.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span>. The archive file contains the handler implementation and a simple component using this handler.</p>

<h1><a name="Howtowriteyourownhandler-Advancedtopics"></a>Advanced topics </h1>
<h2><a name="Howtowriteyourownhandler-Handlerreconfiguration"></a>Handler reconfiguration </h2>
<p>iPOJO has the ability to reconfigure component instances while they are running. When instances are reconfigured, their used handler need to update their configuration (if they support such an operation). <br/>
To do so, reconfigurable handlers must override the <tt>reconfigure()</tt> method, which notify the concerned handlers of the new instance configuration (represented as a <tt>Dictionary</tt>).</p>

<h2><a name="Howtowriteyourownhandler-Describingyourhandler"></a>Describing your handler </h2>
<p>Handlers have the possibility to describe their state, overriding the <tt>getDescription()</tt> method and the <tt>HandlerDescription</tt> class. <br/>
By default, only the handler's name and validity are displayed in component instance's description (informations displayed by the (<tt>arch -instance an.instance.name</tt> command). The standard way to add description to your handler is shown hereafter :</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class YourHandler <span class="code-keyword">extends</span> PrimitiveHandler {  
    ... 
    <span class="code-comment">// Method returning the handler description. 
</span>    <span class="code-keyword">public</span> HandlerDescription getDescription() { 
        <span class="code-keyword">return</span> <span class="code-keyword">new</span> YourHandlerDescription(<span class="code-keyword">this</span>);
    }
    
    ...
    
    <span class="code-keyword">private</span> class YourHandlerDescription <span class="code-keyword">extends</span> HandlerDescription {  
        <span class="code-keyword">public</span> Description(PrimitiveHandler h) { <span class="code-keyword">super</span>(h); }  
        
        <span class="code-comment">// Method returning the custom description of <span class="code-keyword">this</span> handler. 
</span>        <span class="code-keyword">public</span> Element getHandlerInfo() { 
             <span class="code-comment">// Needed to get the root description element. 
</span>             Element elem = <span class="code-keyword">super</span>.getHandlerInfo();  
             <span class="code-comment">// Add here attributes and sub-elements 
</span>             <span class="code-comment">// into the root description element. 
</span>             <span class="code-comment">// Example : elem.addAttribute(<span class="code-keyword">new</span> Attribute(<span class="code-quote">"param"</span>, <span class="code-quote">"value"</span>)); 
</span>             Element subElement = <span class="code-keyword">new</span> Element(<span class="code-quote">"subElement"</span>, ""); 
             subElement.addAttribute(<span class="code-keyword">new</span> Attribute(<span class="code-quote">"subParam"</span>, <span class="code-quote">"subValue"</span>)); 
             elem.addElement(subElement);
             ...
             <span class="code-keyword">return</span> elem; 
       }
   }
}</pre>
</div></div>

<h1><a name="Howtowriteyourownhandler-Handler%27sannotations"></a>Handler's annotations </h1>
<p>Coming soon...</p>

<h1><a name="Howtowriteyourownhandler-Handler%27sXSD"></a>Handler's XSD </h1>
<p>Coming soon...</p>

<h1><a name="Howtowriteyourownhandler-Conclusion"></a>Conclusion </h1>
<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 possible to extends <tt>CompositeHandler</tt> 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%">
<h6><a name="Howtowriteyourownhandler-Overview"></a><b>Overview</b></h6>
<ul>
	<li><a href="/confluence/display/FELIX/Apache+Felix+iPOJO" title="Apache Felix iPOJO">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 (handler list) </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/Using+XML+Schemas" title="Using XML Schemas">Using XML Schemas</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>API: <span class="nobr"><a href="http://people.apache.org/~clement/ipojo/api/0.8/" title="Visit page outside Confluence" rel="nofollow">0.8<sup><img class="rendericon" src="/confluence/images/icons/linkext7.gif" height="7" width="7" align="absmiddle" alt="" border="0"/></sup></a></span></li>
	<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><a href="/confluence/display/FELIX/apache-felix-ipojo-supportedVMs" title="apache-felix-ipojo-supportedVMs">Supported JVMs</a></li>
	<li><a href="/confluence/display/FELIX/apache-felix-ipojo-supportedOSGi" title="apache-felix-ipojo-supportedOSGi">Supported OSGi Implementations</a></li>
	<li><a href="/confluence/display/FELIX/Future+Ideas" title="Future Ideas">Future Ideas</a></li>
	<li><a href="/confluence/display/FELIX/Contact" title="Contact">Contact</a></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