felix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From conflue...@apache.org
Subject [CONF] Apache Felix: Dependency Handler (page edited)
Date Mon, 14 May 2007 16:08: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/Dependency+Handler">Dependency Handler</a>
        </span>
    </div>

     <p>
        <a href="http://cwiki.apache.org/confluence/display/FELIX/Dependency+Handler">Dependency Handler</a>
        has been edited by             <a href="http://cwiki.apache.org/confluence/display/~clement.escoffier">Clement Escoffier</a>
            <span class="smallfont">(May 14, 2007)</span>.
     </p>
    
     <p>
                 <a href="http://cwiki.apache.org/confluence/pages/diffpagesbyversion.action?pageId=27610&originalVersion=2&revisedVersion=3">(View changes)</a>
     </p>

    <span class="label">Content:</span><br/>
    <div class="greybox wiki-content"><p><b>Dependency Handler</b></p>

<p>The dependency handler manages <em>OSGi service</em> <em>dependencies</em>. It allows a component to consume service without managing service discovery, tracking and binding. The handler manages all this interaction and injects required service in the component.</p>

<h1><a name="DependencyHandler-Dependency"></a>Dependency</h1>


<h2><a name="DependencyHandler-What%27sadependency%3F"></a>What's a dependency?</h2>

<p>A dependency represents a required service. Therefore, it manages the service lookup and the service binding. When an instance requires a service, the handler injects directly a service object inside a field, or invokes a method when a consistent service appears (or disappears). Dependencies have several attribute. A dependency can be:</p>
<ul>
	<li>Simple / Aggregate : the component can require one or several service providers</li>
	<li>Mandatory / Optional : a component can declare an optional dependency</li>
	<li>Filtered : a component can filter available providers</li>
</ul>


<h2><a name="DependencyHandler-Dynamism%26InstanceLifecycle"></a>Dynamism &amp; Instance Lifecycle</h2>

<p>In OSGi™, services can appear and disappear dynamically. This implies dependencies can target a service that can appear or disappear dynamically.&nbsp; So, dependencies need to manage this dynamism by tracking every time available service. At any moment, a dependency can be unresolved.&nbsp; In the case of a mandatory dependency, the instance becomes invalid (an invalid instance is no more accessible externally, for example provided service are unpublished). If a service, resolving the unfilled dependency appears, the instance becomes valid. In consequence, dependencies affect directly the instance state, and must manage correctly the dynamics of OSGi to allow a complete unloading when a service goes away. As soon a mandatory dependency cannot be fulfilled, the instance is invalidated.</p>

<h1><a name="DependencyHandler-DependencyInjectionMechanisms"></a>Dependency Injection Mechanisms</h1>

<p>The handler manages two types of injections:</p>
<ul>
	<li>Field injection: a field contains the service object. As soon as the field is used, a consistent service object is injected. This injection type fully hides the dynamism</li>
	<li>Method invocation: when a service appears, or disappears a method in the component is invoked. For each dependency, bind and unbind methods are used to allow the developer to manage the dynamism.</li>
</ul>


<p>Moreover, the two injections type can be merged. A field will contain the value and 'binding' methods will be invoked.</p>

<h2><a name="DependencyHandler-Fieldinjection"></a>Field injection</h2>

<p>Imagine a Hello service with one method 'getMessage' returning a "Hello Message". The following component implementation can use this service by attaching this service to a field and by using the field:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer {
                <span class="code-keyword">private</span> Hello m_hello;
                <span class="code-keyword">public</span> doSomething() {
                               <span class="code-object">System</span>.out.println(m_hello.getMesage());
                }
}</pre>
</div></div>
<p>For this component, metadata could be:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;component classname=<span class="code-quote">"...HelloConsumer"</span>&gt;
&lt;dependency field=<span class="code-quote">"m_hello"</span>/&gt;
...
&lt;/component&gt;</pre>
</div></div>
<p>The metadata contains a dependency (representing the service dependency). This element has a field attribute. This attribute is the name of the field representing the service dependency in the implementation class. The implementation uses the field as a normal field without managing service interactions.</p>

<h2><a name="DependencyHandler-Methodinvocation"></a>Method invocation</h2>

<p>The second injection mechanism uses methods in the implementation class. By this way, the dynamics can be managed directly by the developer. Each dependency declares two methods:</p>
<ul>
	<li>A bind method called when a service appears</li>
	<li>An unbind method called when a service disappears</li>
</ul>


<p>These methods can have three signatures:</p>
<ul>
	<li>Without any argument: the method is just a notification</li>
	<li>With an object of the required service: the object is the implicated service object</li>
	<li>With an OSGi service reference: the service reference appearing or disappearing</li>
</ul>


<p>The following component shows an example of implementation using this mechanism:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer {
  <span class="code-keyword">private</span> Hello m_hello;

  <span class="code-keyword">public</span> void bindHello(Hello h) { m_hello = h; }
  <span class="code-keyword">public</span> void unbindHello() { m_hello = <span class="code-keyword">null</span>; }
  <span class="code-keyword">public</span> doSomething() { <span class="code-object">System</span>.out.println(m_hello.getMesage()); }
}</pre>
</div></div>
<p>For this component, metadata could be:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;component classname=<span class="code-quote">"...HelloConsumer"</span>&gt;
&lt;dependency &gt;
    &lt;callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>&gt;
    &lt;callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>&gt;
&lt;/dependency&gt;
...
&lt;/component&gt;</pre>
</div></div>
<p>Note, that the bind the unbind method can be have different signature. By using this mechanism, you need to be sure to manage the dynamism correctly.</p>

<p>(see note on type discovery)</p>

<h2><a name="DependencyHandler-FieldinjectionsandMethodinvocations"></a>Field injections and Method invocations</h2>

<p>The two mechanisms can be merged together. In this case, the field receives the value before the bind method invocation.</p>

<p>The following component shows an example of implementation using this mechanism:</p>
<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer {
     <span class="code-keyword">private</span> Hello m_hello;

     <span class="code-keyword">public</span> void bindHello() { <span class="code-object">System</span>.out.println(<span class="code-quote">"Hello appears"</span>); }
     <span class="code-keyword">public</span> void unbindHello() { <span class="code-object">System</span>.out.println(<span class="code-quote">"Hello disapears"</span>); }
     <span class="code-keyword">public</span> doSomething() { <span class="code-object">System</span>.out.println(m_hello.getMesage()); }
}</pre>
</div></div>
<p>For this component, metadata could be:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;component classname=<span class="code-quote">"...HelloConsumer"</span>&gt;
&lt;dependency  field=<span class="code-quote">"m_hello"</span>&gt;
    &lt;callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>&gt;
    &lt;callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>&gt;
&lt;/dependency&gt;
...
&lt;/component&gt;</pre>
</div></div>

<h2><a name="DependencyHandler-Injectionmechanisms%26lazzyobjectcreation"></a>Injection mechanisms &amp; lazzy object creation</h2>

<p>IPOJO creates objects only when required. When needed, iPOJO invokes the constructor of the implementation class. The implementation class can use field dependency because values are already injected. However, method dependencies are called just after the constructor. If the service already presents, the invocation of the methods are delayed after the constructor invocation.</p>

<h1><a name="DependencyHandler-SomeExamples"></a>Some Examples</h1>


<h2><a name="DependencyHandler-SimpleDependency"></a>Simple Dependency</h2>

<p>By default, a dependency is mandatory, non-filtered and simple (non-aggregate). The two previous examples illustrate this kind of dependency. When services goes away and appears, the service substitution is hidden.</p>

<p>Field attached to simple dependency points always a consistent service object.  For a simple dependency, the bind method is called once time at the beginning. If the service disappear the unbind method is called. The bind method is re-invoked as soon as another service provider is available. If another service provider is presents when the used one disappears, the instance is not invalidated.</p>

<h2><a name="DependencyHandler-AggregateDependency"></a>Aggregate Dependency</h2>

<p>When a component requires several providers of the same service, it declares an aggregate dependency.</p>

<h3><a name="DependencyHandler-AggregateDependencywithfieldinjection"></a>Aggregate Dependency with field injection</h3>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer {
     <span class="code-keyword">private</span> Hello m_hellos[];
     <span class="code-keyword">public</span> doSomething() {
            <span class="code-keyword">synchronized</span>(m_hellos) {
                     <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I &lt; m_hellos.length; i++) { <span class="code-object">System</span>.out.println(m_hellos[i].getMessage());}
            }
       }
}</pre>
</div></div>
<p>For this component, metadata could be:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;component classname=<span class="code-quote">"...HelloConsumer"</span>&gt;
&lt;dependency field=<span class="code-quote">"m_hellos"</span>/&gt;
...
&lt;/component&gt;</pre>
</div></div>
<p>To declare an aggregate field for field dependency, you only need to declare an array (instead of a simple type). IPOJO will create and inject the service object array.</p>

<p><ins>Note:</ins> To avoid array modification during the loop, you need synchronized the block.</p>

<h3><a name="DependencyHandler-AggregateDependencywithmethodinvocation"></a>Aggregate Dependency with method invocation</h3>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer {
      <span class="code-keyword">private</span> List m_hellos= <span class="code-keyword">new</span> ArrayList();
      <span class="code-keyword">private</span> void bindHello(Hello h) { m_hellos.add(h); }
      <span class="code-keyword">private</span> void unbindHello(Hello h) { m_hellos.remove(h); }
      <span class="code-keyword">public</span> doSomething() {
               <span class="code-keyword">synchronized</span>(m_hellos) {
                     <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I &lt; m_hellos.size(); i++) { <span class="code-object">System</span>.out.println(m_hellos.get(i).getMessage());}
                }
        }
}</pre>
</div></div>
<p>For this component, metadata could be:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;dependency  aggregate=<span class="code-quote">"<span class="code-keyword">true</span>"</span>&gt;
    &lt;callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>&gt;
    &lt;callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>&gt;
&lt;/dependency&gt;</pre>
</div></div>
<p>In this case, iPOJO cannot detect if the dependency is aggregate or not. So, you need to add the 'aggregate' attribute. The bindHello and unbindHello will be called each time a Hello service appears or disappears.</p>

<p><ins>Note:</ins> To avoid the list modification during the loop, you need synchronized the block.</p>

<h2><a name="DependencyHandler-OptionalDependency%28nonaggregate%29"></a>Optional Dependency (non-aggregate)</h2>

<p>An optional dependency does not invalidate the instance if it is not resolved.</p>

<h3><a name="DependencyHandler-OptionalDependencywithfieldinjection"></a>Optional Dependency with field injection</h3>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer {
         <span class="code-keyword">private</span> Hello m_hello;
         <span class="code-keyword">public</span> doSomething() {  <span class="code-object">System</span>.out.println(m_hello.getMesage());  }
}</pre>
</div></div>
<p>For this component, metadata could be:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;component classname=<span class="code-quote">"...HelloConsumer"</span>&gt;
&lt;dependency field=<span class="code-quote">"m_hello"</span> optional=<span class="code-quote">"<span class="code-keyword">true</span>"</span>/&gt;
...
&lt;/component&gt;</pre>
</div></div>
<p>To declare an optional dependency, you need to add the 'optional' attribute. To avoid null pointer exception, iPOJO injects a <em>Nullable</em>object in the field when no service provider is available. The nullable object implements the service interface, but does nothing. For further information see the note about nullable object.</p>

<h3><a name="DependencyHandler-OptionalDependencywithmethodinvocation"></a>Optional Dependency with method invocation</h3>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer {
     <span class="code-keyword">private</span> Hello m_hello;
     <span class="code-keyword">public</span> void bindHello(Hello h) { m_hello = h; }
     <span class="code-keyword">public</span> void unbindHello() { m_hello = <span class="code-keyword">null</span>; }
     <span class="code-keyword">public</span> doSomething() { <span class="code-keyword">if</span>(m_hello != <span class="code-keyword">null</span>) { <span class="code-object">System</span>.out.println(m_hello.getMesage()); } }
}</pre>
</div></div>
<p>For this component, metadata should be:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;component classname=<span class="code-quote">"...HelloConsumer"</span>&gt;
&lt;dependency optional=<span class="code-quote">"<span class="code-keyword">true</span>"</span>&gt;
    &lt;callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>&gt;
    &lt;callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>&gt;
&lt;/dependency&gt;
...
&lt;/component&gt;</pre>
</div></div>
<p>As for field dependency, the dependency metadata needs to contain the optional attribute. IPOJO invokes the method only when a 'real' service is available, so you need to test if m_hello is null before to use it.</p>

<h2><a name="DependencyHandler-Aggregate%26OptionalDependency"></a>Aggregate &amp; Optional Dependency</h2>

<p>A dependency can be both aggregate and optional.</p>

<h3><a name="DependencyHandler-Aggregate%26OptionalDependencywithfieldinjection"></a>Aggregate &amp; Optional Dependency with field injection</h3>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer {
     <span class="code-keyword">private</span> Hello m_hellos[];
     <span class="code-keyword">public</span> doSomething() {
        <span class="code-keyword">synchronized</span>(m_hellos) {
           <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I &lt; m_hellos.length; i++) { <span class="code-object">System</span>.out.println(m_hellos[i].getMessage());}
        }
     }
}</pre>
</div></div>
<p>For this component, metadata could be:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;component classname=<span class="code-quote">"...HelloConsumer"</span>&gt;
&lt;dependency field=<span class="code-quote">"m_hellos"</span> optional=<span class="code-quote">"<span class="code-keyword">true</span>"</span>/&gt;
...
&lt;/component&gt;</pre>
</div></div>
<p>To declare an optional &amp; aggregate field dependency you need to write the optional attrbiute in the dependency metadata and to point on a field array. If no service available, iPOJO injects an empty array.</p>

<p><ins>Note:</ins> To avoid array modification during the loop, you need synchronized the block.</p>

<h3><a name="DependencyHandler-Aggregate%26OptionalDependencywithmethodinvocation"></a>Aggregate &amp; Optional Dependency with method invocation</h3>

<div class="code"><div class="codeContent">
<pre class="code-java"><span class="code-keyword">public</span> class HelloConsumer {
     <span class="code-keyword">private</span> List m_hellos&lt;Hello&gt; = <span class="code-keyword">new</span> ArrayList&lt;Hello&gt;();
     <span class="code-keyword">private</span> void bindHello(Hello h) { m_hellos.add(h); }
     <span class="code-keyword">private</span> void unbindHello(Hello h) { m_hellos.remove(h); }
     <span class="code-keyword">public</span> doSomething() {
        <span class="code-keyword">synchronized</span>(m_hellos) {
               <span class="code-keyword">for</span>(<span class="code-object">int</span> I = 0; I &lt; m_hellos.size(); i++) { <span class="code-object">System</span>.out.println(m_hellos.get(i).getMessage());}
        }
     }
}</pre>
</div></div>
<p>For this component, metadata could be:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;dependency aggregate=<span class="code-quote">"<span class="code-keyword">true</span>"</span> optional=<span class="code-quote">"<span class="code-keyword">true</span>"</span>&gt;
     &lt;callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>&gt;
     &lt;callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>&gt;
&lt;/dependency&gt;</pre>
</div></div>
<p>In this case, you need to add the 'aggregate' attribute and the 'optional' attribute. The bindHello and unbindHello will be called each time a Hello service appears or disappears.</p>

<p><ins>Note:</ins> To avoid the list modification during the loop, you need synchronized the block.</p>

<h2><a name="DependencyHandler-FilteredDependency"></a>Filtered Dependency</h2>

<p>A filtered dependency applies an LDAP filter on service provider. IPOJO reuses OSGi LDAP filter ability. The following metadata illustrates how to use filters:</p>
<div class="code"><div class="codeContent">
<pre class="code-java">&lt;component classname=<span class="code-quote">"...HelloConsumer"</span>&gt;
&lt;dependency filter=<span class="code-quote">"(language=fr)"</span>&gt;
     &lt;callback type=<span class="code-quote">"bind"</span> method=<span class="code-quote">"bindHello"</span>&gt;
     &lt;callback type=<span class="code-quote">"unbind"</span> method=<span class="code-quote">"unbindHello"</span>&gt;
&lt;/dependency&gt;
...
&lt;/component&gt;</pre>
</div></div>

<p>To add a filter, just add a 'filter' attribute in your dependency containing the LDAP filter. IPOJO will select only provider matching with this filter.</p>

<p><ins>Note:</ins> to use the &amp; operator in your filter, you need to use '&amp;'.</p>

<h1><a name="DependencyHandler-DependencyMetadata"></a>Dependency Metadata</h1>

<p>A dependency metadata:</p>
<ul>
	<li>Field : name of the field representing the dependency in the component class</li>
	<li>Interface : type of the Field</li>
	<li>Optional: is the dependency an optional dependency?</li>
	<li>Aggregate: is the dependency an aggregate dependency?</li>
	<li>Filter : filter selecting service provider</li>
	<li>Callback : allow to call a method on the component instances when a service provider (matching with the dependency) appears or disappears</li>
</ul>


<p>Some of these attributes are optional. Indeed, either the component implementation contains the information; either iPOJO uses default behavior.</p>

<p>The field attribute is optional if callbacks are specified. The field attribute contains the name of the field of the component attached with this dependency.</p>

<p>The interface attribute describes the required service. This element is optional because the component implementation contains the same information (the type of the field). If the interface attribute has a value, the consistency of the information is checked. However, sometimes this attribute is mandatory if iPOJO cannot discover the type of the dependency.</p>

<p>The optional attribute describes if the dependency is optional or not. An optional dependency is always valid, and does not interact with the instance state. On the other hand, when a mandatory is no more valid the component state becomes INVALID.</p>

<p>The aggregate attribute determines if the dependency needs to inject several providers on just one. This attribute is optional if the dependency point on a field array.</p>

<p>The filter attribute contains the LDAP request on the service provider. By default, iPOJO use no filter, but you can specify a filter. For further information, see the OSGi specification.</p>

<p>The callback elements contain the name of method to call when a service provider matching with the dependency appears or disappears. This allows the component to be notified when a service provider arrives or goes away.</p>

<h1><a name="DependencyHandler-Technicaldetailsonservicediscoveryandserviceinvocation"></a>Technical details on service discovery and service invocation</h1>

<p>The handler of the registers an OSGi service event listener and listens for interesting events. When an interesting service arrives, it stores the service reference. When the service is used, it obtains the service object and injects the object in the instance. If it is an aggregate dependencies, it returns an array of service object or/and call the bind method for each provider.<br/>
When a service goes away, the handler removes the reference from its list (and call the <em>unget</em> method): the manager does not keep any reference on the old service. This allows a complete unloading of the service.<br/>
Two calls to a service can use two different service providers if the used provider has gone. IPOJO tries to return always the same service object if possible, since the service goes away.</p>

<h1><a name="DependencyHandler-Noteaboutnullableobject"></a>Note about nullable object</h1>

<p>The instance implementation can use an optional dependency without any checking. Indeed, when an instance declares an optional dependency using field injection, iPOJO create on the fly a Nullable class implementing the service specification but doing nothing (mock object). Therefore, iPOJO cannot return a service to the instance, for an optional dependency, it returns a nullable object.</p>

<p>A nullable object returns:</p>
<ul>
	<li>Null when the method returns an object</li>
	<li>0 when the method returns an int, log, byte, short, char, float or a double</li>
	<li>False when the method return a boolean</li>
</ul>


<p>You can check if the returned object is a nullable object with the test: &#95;m_myservice instanceof Nullable.&#95;</p>

<h1><a name="DependencyHandler-Noteaboutsynchronization"></a>Note about synchronization</h1>

<p>When you want to be sure to have always the same service objects, you can use a synchronized block. It is useful for multiple dependencies. Indeed when you want to be sure that a service does not go away during the iteration on your array, you can put your loop inside a synchronized blocks.</p>

<h1><a name="DependencyHandler-NoteaboutCallbacks"></a>Note about Callbacks</h1>

<p>Dependency manages two type of callback: bind and unbind. A callback with a type "bind" is called each type that a service provider arrives and the binding is necessary. According to the cardinality of the dependency it means:</p>
<ul>
	<li>Simple dependency : at the firs binding and at each rebinding to another service provider</li>
	<li>Aggregate dependencies: each time that a service provider arrives</li>
</ul>


<p>An unbind callback is called each time that a <b>used</b> service provider goes away. For a simple dependency this method is called each time that the used service provider goes away. For a multiple dependency this method is called each time that a service provider goes away.</p>

<p>The method can receive in argument the service object or the service reference (in order to obtain service properties). The bind methods are delayed since a component instance is created.</p>

<h1><a name="DependencyHandler-Noteonservicetypediscovery"></a>Note on service type discovery</h1>

<p>The 'interface' attribute is generally optional except when iPOJO cannot discover the type of the service. IPOJO cannot infer the type when the dependency has no field and no callbacks receive the service object in parameter. In this case, you need to declare the service interface.</p></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