PK HAoa,mimetypeapplication/epub+zipPK HA META-INF/PK HAOEBPS/PK HA OEBPS/images/PK HAOEBPS/imagesdb/PK HAhhMETA-INF/container.xml PK HAeh\\%OEBPS/BestPractices-BuildBundles.html Building OSGi Bundles

Building OSGi Bundles

The following best practices are recommended when building OSGi bundles using Maven:

Use your application's package prefix as the bundle symbolic name. For example, if all of your Java source code is located in sub-packages of org.fusesource.fooProject, use org.fusesource.fooProject as the bundle symbolic name.

It makes sense to identify a Maven artifact with an OSGi bundle. To show this relationship as clearly as possible, you should use base the artifact ID on the bundle symbolic name. Two conventions are commonly used:

[Tip]Tip

Properties of the form project.* can be used to reference the value of any element in the current POM. To construct the name of a POM property, take the XPath name of any POM element (for example, project/artifactId) and replace occurrences of / with the . character. Hence, ${project.artifactId} references the artifactId element from the current POM.

One of the key advantages of the OSGi framework is its ability to manage bundle versions and the possibility of deploying multiple versions of a bundle in the same container. In order to take advantage of this capability, however, it is essential that you associate a version with any packages that you export.

For example, you can configure the maven-bundle-plugin plug-in to export packages with the current artifact version (given by the project.version property) as follows:

<Export-Package>
  ${project.artifactId}*;version=${project.version}
</Export-Package>

Notice how this example exploits the convention that packages use the artifact ID, project.artifactId, as their package prefix. The combination of package prefix and wildcard, ${project.artifactId}*, enables you to reference all of the source code in your bundle.

If you define any private packages in your bundle (packages that you do not want to export), it is recommended that you identify these packages using a strict naming convention. For example, if your bundle includes implementation classes that you do not want to export, you should place these classes in packages prefixed by ${project.artifactId}.impl or ${project.artifactId}.internal.

[Note]Note

If you do not specify any Export-Package instruction, the default behavior of the Maven bundle plug-in is to exclude any packages that contain a path segment equal to impl or internal.

To ensure that the private packages are not exported, you can add an entry of the form !PackagePattern to the Maven bundle plug-in's export instructions. The effect of this entry is to exclude any matching packages. For example, to exclude any packages prefixed by ${project.artifactId}.impl, you could add the following instruction to the Maven bundle plug-in configuration:

<Export-Package>
  !${project.artifactId}.impl.*,
  ${project.artifactId}*;version=${project.version}
</Export-Package>
[Note]Note

The order of entries in the Export-Package element is significant. The first match in the list determines whether a package is included or excluded. Hence, in order for exclusions to be effective, they should appear at the start of the list.

In order to benefit from OSGi version management capabilities, it is important to restrict the range of acceptable versions for imported packages. You can use either of the following approaches:

[Tip]Tip

In practice, you are likely to find that the majority of imported packages can be automatically versioned by Maven. It is, typically, only occasionally necessary to specify a version manually.

Normally, it is not good practice to import the packages that you export (though there are exceptions to this rule). Here are some guidelines to follow:

Assuming you want to avoid importing the packages that you export, there are two alternative approaches you can take, as follows:

When an imported package is specified with optional resolution, this allows the bundle to be resolved without resolving the optional package. This affects the resolution order of the bundles which, in turn, can affect the runtime behavior. You should therefore be careful with optional imports, in case they have some unintended side effects.

A package is optional when it appears in the Import-Package manifest header with the resolution:="optional" setting appended to it. For example, the following example shows an Import-Package instruction for the Maven bundle plug-in that specifies an optional import:

<Import-Package>
  org.springframework.*;version="[2.5,4)",
  org.apache.commons.logging.*;version="[1.1,2)";resolution:="optional",
  *
</Import-Package>

Avoid using the Require-Bundle header, if possible. The trouble with using the Require-Bundle header is that it forces the OSGi resolver to use packages from the specified bundle. Importing at the granularity of packages, on the other hand, allows the resolver to be more flexible, because there are fewer constraints: if a package is already available and resolved from another bundle, the resolver could use that package instead.

PK HA۱c0G G "OEBPS/BestPractices-SamplePOM.html Sample POM File

Sample POM File

Example B.1 shows a sample POM that illustrates the best practices for building an OSGi bundle using Maven.

PK HA; OEBPS/BestPractices-Tooling.html OSGi Tooling

OSGi Tooling

The following best practices are recommended for OSGi related tools and utilities:

Even for a moderately sized bundle project, it is usually impractical to create and maintain a bundle Manifest by hand. The Maven bundle plug-in is the most effective tool for automating the generation of bundle Manifests in a Maven project. See Building OSGi Bundles.

Avoid using the OSGi Java API directly. Prefer a higher level technology, for example: Blueprint (from the OSGi Compendium Specification), Spring-DM, Declarative Services (DS), iPojo, and so on.

The Blueprint container is now the preferred framework for instantiating, registering, and referencing OSGi services, because this container has now been adopted as an OSGi standard. This ensures greater portability for your OSGi service definitions in the future.

Spring Dynamic Modules (Spring-DM) provided much of the original impetus for the definition of the Blueprint standard, but should now be regarded as obsolescent. Using the Blueprint container does not prevent you from using the Spring framework: the latest version of Spring is compatible with Blueprint.

When an application is composed of a large number of bundles, it becomes essential to group bundles together in order to deploy them efficiently. Apache Karaf features is a mechanism that is designed just for this purpose. It is easy to use and supported by a variety of different tools. See Deploying Features for details.

The OSGi Configuration Admin service is the preferred mechanism for providing configuration properties to your application. This configuration mechanism enjoys better tooling support than other approaches. For example, in Fuse ESB Enterprise the OSGi Configuration Admin service is supported in the following ways:

In order for testing to be really effective, you should run at least some of your tests in an OSGi container. This requires you to start an OSGi container, configure its environment, install prerequisite bundles, and install the actual test. Performing these steps manually for every test would make testing prohibitively difficult and time-consuming. Pax-Exam solves this problem by providing a testing framework that is capable of automatically initializing an OSGi container before running tests in the container.

See Appendix C for more details.

PK HA}eOEBPS/BestPractices.html Appendix B. OSGi Best Practices

Appendix B. OSGi Best Practices

OSGi Tooling
Building OSGi Bundles
Sample POM File
PK HAgAAOEBPS/Build-GenerateMaven.html Preparing to use Maven

Preparing to use Maven

This section gives a brief overview of how to prepare Maven for building Fuse ESB Enterprise projects and introduces the concept of Maven coordinates, which are used to locate Maven artifacts.

In order to build a project using Maven, you must have the following prerequisites:

In order to access artifacts from the FuseSource Maven repository, you need to add it to Maven's settings.xml file. Maven looks for your settings.xml file in the .m2 directory of the user's home directory. If there is not a user specified settings.xml file, Maven will use the system-level settings.xml file at M2_HOME/conf/settings.xml.

To add the FuseSource repository to Maven's list of repositories, you can either create a new .m2/settings.xml file or modify the system-level settings. In the settings.xml file, add the repository element for the FuseSource repository as shown in bold text in Example 3.2.

The preceding example also shows repository element for the following repositories:

The basic building block in the Maven build system is an artifact. The output of an artifact, after performing a Maven build, is typically an archive, such as a JAR or a WAR.

A key aspect of Maven functionality is the ability to locate artifacts and manage the dependencies between them. Maven defines the location of an artifact using the system of Maven coordinates, which uniquely define the location of a particular artifact. A basic coordinate tuple has the form, {groupId, artifactId, version}. Sometimes Maven augments the basic set of coordinates with the additional coordinates, packaging and classifier. A tuple can be written with the basic coordinates, or with the additional packaging coordinate, or with the addition of both the packaging and classifier coordinates, as follows:

groupdId:artifactId:version
groupdId:artifactId:packaging:version
groupdId:artifactId:packaging:classifier:version

Each coordinate can be explained as follows:

The group ID, artifact ID, packaging, and version are defined by the corresponding elements in an artifact's POM file. For example:

<project ... >
  ...
  <groupId>org.fusesource.example</groupId>
  <artifactId>bundle-demo</artifactId>
  <packaging>bundle</packaging>
  <version>1.0-SNAPSHOT</version>
  ...
</project>

For example, to define a dependency on the preceding artifact, you could add the following dependency element to a POM:

<project ... >
  ...
  <dependencies>
    <dependency>
      <groupId>org.fusesource.example</groupId>
      <artifactId>bundle-demo</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
  </dependencies>
  ...
</project>
[Note]Note

It is not necessary to specify the bundle package type in the preceding dependency, because a bundle is just a particular kind of JAR file and jar is the default Maven package type. If you do need to specify the packaging type explicitly in a dependency, however, you can use the type element.

PK HA9K(K(OEBPS/Build-MavenDir.html Maven Directory Structure

Maven Directory Structure

One of the most important principles of the Maven build system is that there are standard locations for all of the files in the Maven project. There are several advantages to this principle. One advantage is that Maven projects normally have an identical directory layout, making it easy to find files in a project. Another advantage is that the various tools integrated with Maven need almost no initial configuration. For example, the Java compiler knows that it should compile all of the source files under src/main/java and put the results into target/classes.

Example 3.1 shows the elements of the standard Maven directory layout that are relevant to building OSGi bundle projects. In addition, the standard locations for Spring-DM and Blueprint configuration files (which are not defined by Maven) are also shown.

[Note]Note

It is possible to override the standard directory layout, but this is not a recommended practice in Maven.

The pom.xml file is the Project Object Model (POM) for the current project, which contains a complete description of how to build the current project. A pom.xml file can be completely self-contained, but frequently (particular for more complex Maven projects) it can import settings from a parent POM file.

After building the project, a copy of the pom.xml file is automatically embedded at the following location in the generated JAR file:

META-INF/maven/groupId/artifactId/pom.xml

The src/ directory contains all of the code and resource files that you will work on while developing the project.

The target/ directory contains the result of the build (typically a JAR file), as well as all all of the intermediate files generated during the build. For example, after performing a build, the target/classes/ directory will contain a copy of the resource files and the compiled Java classes.

The src/main/ directory contains all of the code and resources needed for building the artifact.

The src/test/ directory contains all of the code and resources for running unit tests against the compiled artifact.

Each java/ sub-directory contains Java source code (*.java files) with the standard Java directory layout (that is, where the directory pathnames mirror the Java package names, with / in place of the . character). The src/main/java/ directory contains the bundle source code and the src/test/java/ directory contains the unit test source code.

If you have any configuration files, data files, or Java properties to include in the bundle, these should be placed under the src/main/resources/ directory. The files and directories under src/main/resources/ will be copied into the root of the JAR file that is generated by the Maven build process.

The files under src/test/resources/ are used only during the testing phase and will not be copied into the generated JAR file.

By default, Fuse ESB Enterprise installs and activates support for Spring Dynamic Modules (Spring DM), which integrates Spring with the OSGi container. This means that it is possible for you to include Spring configuration files, META-INF/spring/*.xml, in your bundle. One of the key consequences of having Spring DM enabled in the OSGi container is that the lifecycle of the Spring application context is automatically synchronized with the OSGi bundle lifecycle:

  • Activation—when a bundle is activated, Spring DM automatically scans the bundle to look for Spring configuration files in the standard location (any .xml files found under the META-INF/spring/ directory). If any Spring files are found, Spring DM creates an application context for the bundle and creates the beans defined in the Spring configuration files.

  • Stopping—when a bundle is stopped, Spring DM automatically shuts down the bundle's Spring application context, causing any Spring beans to be deleted.

In practice, this means that you can treat your Spring-enabled bundle as if it is being deployed in a Spring container. Using Spring DM, the features of the OSGi container and a Spring container are effectively merged. In addition, Spring DM provides additional features to support the OSGi container environment—some of these features are discussed in OSGi Services.

OSGi R4.2 defines a blueprint container, which is effectively a standardized version of Spring DM. Fuse ESB Enterprise has built-in support for the blueprint container, which you can enable simply by including blueprint configuration files, OSGI-INF/blueprint/*.xml, in your project. For more details about the blueprint container, see OSGi Services.

PK HAhoOEBPS/Build-ModifyMaven.html Generating a Bundle Project

Generating a Bundle Project

To help you get started quickly, you can invoke a Maven archetype to generate the initial outline of a Maven project (a Maven archetype is analogous to a project wizard). The following Maven archetypes can generate projects for building OSGi bundles:

The Apache CXF code-first archetype creates a project for building a service from Java. To generate a Maven project with the coordinates, GroupId:ArtifactId:Version, enter the following command:

[Note]Note

The arguments to the mvn command are shown on separate lines purely for the sake of readability. When you are entering the command at a command prompt, you must ensure that all of the parameters are on the same line.

The Apache CXF WSDL-first archetype creates a project for building a service from WSDL. To generate a Maven project with the coordinates, GroupId:ArtifactId:Version, enter the following command:

The Apache Camel OSGi archetype creates a project for building a route that can be deployed into the OSGi container. To generate a Maven project with the coordinates, GroupId:ArtifactId:Version, enter the following command:

By default, the preceding archetypes create a project in a new directory, whose names is the same as the specified artifact ID, ArtifactId. To build the bundle defined by the new project, open a command prompt, go to the project directory (that is, the directory containing the pom.xml file), and enter the following Maven command:

mvn install

The effect of this command is to compile all of the Java source files, to generate a bundle JAR under the ArtifactId/target directory, and then to install the generated JAR in the local Maven repository.

PK HA͍OEBPS/Build.html Chapter 3. Building with Maven

Chapter 3. Building with Maven

Maven is an open source build system which is available from the Apache Maven project. This chapter explains some of the basic Maven concepts and describes how to set up Maven to work with Fuse ESB Enterprise. In principle, you could use any build system to build an OSGi bundle. But Maven is strongly recommended, because it is well supported by Fuse ESB Enterprise. Moreover, Maven is a requirement for building FABs.

Maven Directory Structure
Preparing to use Maven
PK HA1ĊOEBPS/BuildBundle-Modify.html Modifying an Existing Maven Project

Modifying an Existing Maven Project

If you already have a Maven project and you want to modify it so that it generates an OSGi bundle, perform the following steps:

Configure Maven to generate an OSGi bundle by changing the package type to bundle in your project's pom.xml file. Change the contents of the packaging element to bundle, as shown in the following example:

<project ... >
  ...
  <packaging>bundle</packaging>
  ...
</project>

The effect of this setting is to select the Maven bundle plug-in, maven-bundle-plugin, to perform packaging for this project. This setting on its own, however, has no effect until you explicitly add the bundle plug-in to your POM.

To add the Maven bundle plug-in, copy and paste the following sample plugin element into the project/build/plugins section of your project's pom.xml file:

Where the bundle plug-in is configured by the settings in the instructions element.

For some specific recommendations on configuring the bundle plug-in for Apache CXF and Apache Camel, see Packaging a Web Service in a Bundle and Spring example.

For an in-depth discussion of bundle plug-in configuration, in the context of the OSGi framework and versioning policy, see Managing OSGi Dependencies.

It is almost always necessary to specify the JDK version in your POM file. If your code uses any modern features of the Java language—such as generics, static imports, and so on—and you have not customized the JDK version in the POM, Maven will fail to compile your source code. It is not sufficient to set the JAVA_HOME and the PATH environment variables to the correct values for your JDK, you must also modify the POM file.

To configure your POM file, so that it accepts the Java language features introduced in JDK 1.6, add the following maven-compiler-plugin plug-in settings to your POM (if they are not already present):

PK HA N OEBPS/BuildBundle.html Chapter 11. Building an OSGi Bundle

Chapter 11. Building an OSGi Bundle

Generating a Bundle Project
Modifying an Existing Maven Project
Packaging a Web Service in a Bundle
Configuring the Bundle Plug-In
PK HAnaRROEBPS/BuildFab-Archetypes.html Generating a FAB Project

Generating a FAB Project

To help you get started quickly, you can invoke a Maven archetype to generate the initial outline of a Maven project (a Maven archetype is analogous to a project wizard). Because FABs do not require any special configuration (apart from the presence of a pom.xml file, which is always present in a Maven-generated JAR), you can use almost any Maven archetype, as long as the generated Maven project has the jar packaging type.

The following Maven archetypes are useful for generating Apache Camel projects:

For example, consider an archetype for building an Apache Camel project. The camel-archetype-blueprint archetype creates a project that demonstrates a simple Apache Camel route written in the XML DSL using the Blueprint injection framework. To generate a Maven project with the coordinates, GroupId:ArtifactId:Version, enter the following command:

[Note]Note

The arguments to the mvn command are shown on separate lines purely for the sake of readability. When you are entering the command at a command prompt, you must ensure that all of the parameters are on the same line.

The archetype creates a project in a new directory whose name is that of the specified artifact ID, ArtifactId. To build the FAB defined by the new project, open a command prompt, go to the project directory (that is, the directory containing the pom.xml file), and enter the following Maven command:

mvn install

The effect of this command is to compile all of the Java source files, to generate a FAB JAR under the ArtifactId/target directory, and then to install the generated JAR in the local Maven repository.

PK HAG OEBPS/BuildFab-ClassSharing.html Class Sharing

Class Sharing

By default, a FAB adds each Maven dependency to its private class space at run time (except for dependencies having Maven group ID org.apache.camel, org.apache.activemq, or org.apache.cxf, which are shared by default). This is a safe approach to deploying dependencies, because it reduces the risk of version inconsistencies. But it is also an expensive approach, in terms of resources, because it forces the JVM to maintain a dedicated copy of each dependency in memory, just for this FAB.

You can make a FAB more economical by opting to share some of its dependencies with other applications in the container. There are two approaches you can use:

To share a dependency (and its transitive dependencies), declare a dependency with the provided scope in your project's pom.xml file. For example:

<dependency>
  <groupId>org.acme.foo</groupId>
  <artifactId>foo-core</artifactId>
  <version>${foo-version}</version>
  <scope>provided</scope>
</dependency>

This is analogous to the approach you would use when building a WAR with Maven, in order to avoid including libraries like the servlet API or the JSP API.

You can also configure class sharing by setting the FAB-Provided-Dependency: manifest header. For example, to share all artifacts with the org.acme.foo Maven group ID:

FAB-Provided-Dependency: org.acme.foo:* org.apache.camel:* org.apache.cxf:* org.apache.activemq:* 

For full details of how to use this approach, see Sharing dependencies and How to set JAR manifest headers.

PK HA+eppOEBPS/BuildFab-Configure.html Configuring a FAB

Configuring a FAB

Typically, it is not necessary to specify any additional configuration for a FAB. But you might be interested in setting some of the optional FAB manifest headers, in order to optimize the performance of your FAB at run time. In particular, it is often a good idea to share some of the bigger dependencies, so that the FAB does not consume too much system memory in the JVM at run time.

Many of the FAB manifest headers take a value, which is a space-separated list of patterns that match Maven artifacts. Each artifact pattern has the following syntax:

groupId[:artifactId]

If the artifact ID, artifactId, is omitted, the pattern matches all of the artifacts in the specified group, groupId. You can also use the wildcard character, *, to match an arbitrary sequence of characters in either the group ID or the artifact ID.

For example, to match specific artifacts, you could specify a list like the following:

org.apache.camel:camel-core org.apache.cxf:cxf-core

To match all of the Apache Camel, Apache ActiveMQ, and Apache CXF artifacts, you could specify a list like the following:

org.apache.camel org.apache.activemq org.apache.cxf

To match all Apache artifacts and all Spring framework artifacts, you could specify a list like the following:

org.apache.* org.springframework.*

To configure a FAB, you can optionally specify any of the following FAB manifest headers:

FAB-Version-Range-Digits

See Specifying version ranges.

FAB-Provided-Dependency

See Sharing dependencies.

FAB-Include-Optional-Dependency

See Including optional dependencies.

FAB-Dependency-Require-Bundle

See Specifying OSGi Require-Bundle.

FAB-Exclude-Dependency

See Excluding dependencies.

Import-Package

See Customising import packages.

FAB-Skip-Matching-Feature-Detection

See Automatic feature detection.

FAB-Require-Feature-URL, FAB-Require-Feature

See Requiring features.

FAB-Install-Provided-Bundle-Dependencies

See Respecting pre-installed features and bundles.

Maven dependencies typically specify the exact version of each required artifact. At deployment time, however, a little bit of flexibility is usually required. For example, you would normally prefer the FAB to be capable of accepting a patch update to one of its dependencies. For this reason, when the FAB is converted to a bundle at deploy time, each dependency version is normally converted into a range.

For example, given the following Maven dependency:

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-core</artifactId>
  <version>2.8.1-fuse-00-02</version>
  <scope>provided</scope>
</dependency>

When the FAB is converted to a bundle, the preceding exact version is converted to a range in the generated OSGi Import-Package header, as follows:

Import-Package: org.apache.camel;version="[2.8.1-fuse-00-02,2.9)"

This reflects the default range policy, where later patch versions (2.8.2, 2.8.3, 2.8.4, and so on) are accepted, but minor and major upgrades are rejected.

It is possible to modify the range policy—either to be more strict or to be more lax—by setting the FAB-Version-Range-Digits: manifest header to one of the following policy values:

ValueSampleDescription
0[2.5.6.qual,2.5.6.qual]Exact only.
1[2.5.6.qual,2.5.7)Allow arbitrary qualifers (order not guaranteed).
2[2.5.6.qual,2.6)Allow patch releases (default).
3[2.5.6.qual,3)Allow patch and minor releases.
4[2.5.6.qual,)Any version from 2.5.6 onwards.

This manifest header gives you an alternative way to configure class sharing. Instead of adding <scope>provided</scope> to dependencies in the pom.xml file, you can list the shared artifacts in this manifest header. The shared artifacts are specified as a space-separated list of artifact patterns, for example:

FAB-Provided-Dependency: groupId1:artifactId1 groupId2:artifactId2 ...

You can also use a wildcard, *, for the groupId or the artifactId. For example, to share all Apache Camel and Spring dependencies (transitively) in your FAB, add the following header to your manifest:

FAB-Provided-Dependency: org.apache.camel:* org.springframework:*

If you do not explicitly configure the FAB-Provided-Dependency manifest header, the FAB runtime implicitly adds the following default header:

FAB-Provided-Dependency: org.apache.camel:* org.apache.cxf:* org.apache.activemq:*
[Important]Important

If you specify the FAB-Provided-Dependency manifest header explicitly, you override the default header value, which would make the org.apache.camel, org.apache.cxf, and org.apache.activemq dependencies unshared again. Since you normally want these dependencies to remain shared, it is good practice to include the entries, org.apache.camel:* org.apache.cxf:* org.apache.activemq:*, in your custom FAB-Provided-Dependency manifest header.

Optional dependencies In a pom.xml file are marked by the presence of <optional>true</optional> in the dependency.

By default, optional dependencies are excluded from a FAB. To force their inclusion, list them in the FAB-Include-Optional-Dependency: manifest header.

The header value is specified as a space-separated list of artifact patterns, with support for the wildcard, * . For example, to force the inclusion of all optional dependencies, add the following manifest header:

FAB-Include-Optional-Dependency: *:*

Specifies a list of artifacts which should not use the regular OSGi mechanism of importing packages, but instead should use the OSGi Require-Bundle directive.

By default, packages are imported from shared dependencies using the OSGi Import-Package directive for all artifacts not selected by the FAB-Dependency-Require-Bundle header.

The header value is specified as a space-separated list of artifacts, with support for the wildcard, * —for example:

FAB-Dependency-Require-Bundle: groupId1:artifactId1 groupId2:artifactId2 ...

To exclude specific dependencies, you can list them in the FAB-Exclude-Dependency: manifest header, as a space-separated list of artifact patterns, for example:

FAB-Exclude-Dependency: log4j logkit

Specifying Java packages to import from the classpath, using the Import-Package manifest header, is the standard OSGi mechanism for specifying dependencies. Normally, you do not have to worry about imported packages when using FABs, because the FAB runtime automatically generates the Import-Package manifest header with the requisite entries.

In exceptional cases, however, you might find that you need to import specific Java packages that FAB is unable to figure out by itself. For these cases, it is possible to add an Import-Package manifest header to your FAB package. At run time, FAB merges your customized import package list with the automatically generated list of import packages.

The Import-Package header is specified using the standard OSGi format. For example, to import the package, com.acme.special, where the version is allowed to lie in the range [1.0, 1.1), you could add the following header:

Import-Package: com.acme.special;version="[1.0,1.1)"

Fuse ESB Enterprise comes with a collection of features that have been carefully crafted and manually adjusted so that they install exactly the right set of dependencies for a particular piece of functionality. For example, to install all of the required dependencies for the Apache Camel Jetty component, you can install the camel-jetty feature by entering the following console command:

karaf@root> features:install camel-jetty

If you want to use the Jetty component in a FAB, you would add the following Maven dependency to the FAB's POM:

<dependency>
  <groupId>org.apache.camel</groupId>
  <artifactId>camel-jetty</artifactId>
  <version>2.9.0.fuse-70-097</version>
  <scope>provided</scope>
</dependency>

If the camel-jetty feature is not already installed in the runtime, however, it is unlikely that the FAB mechanism would be able to install all of the required transitive dependencies successfully (after all, the camel-jetty feature was created in the first place precisely because it has third-party dependencies that are not well integrated with OSGi or FAB).

This is where automatic feature detection comes in. By default, whenever FAB encounters a Maven dependency that matches a known feature, it automatically maps the dependency to the corresponding feature and installs the feature instead. For example, when the FAB runtime encounters the org.apache.camel/camel-jetty Maven dependency, it automatically maps the dependency to the camel-jetty feature and installs the camel-jetty feature.

[Note]Note

Automatic feature detection is not yet available for all standard features. At the time of writing, auto-detection is supported for Apache Camel component features, camel-ComponentName, and some Apache CXF features, cxf, cxf-sts, and cxf-wsn.

Automatic feature detection is enabled by default. If you want to explicitly disable feature detection, you can set the FAB-Skip-Matching-Feature-Detection, specifying a space-separated list of artifact patterns. For example, to disable automatic feature detection for the Apache Camel components, add the following entry to the manifest:

FAB-Skip-Matching-Feature-Detection: org.apache.camel

You can configure a FAB explicitly to require one or more features, so that the features are automatically installed when you deploy the FAB into the container. To identify a feature, you must specify both the location of the features repository (normally provided in a Maven repository) and the name of the feature.

For example, to require the cxf-sts feature, add the following entries to the Manifest (noting that the Maven URL is continued on a second line, because it does not fit within the 72 byte line limit):

FAB-Require-Feature-URL: mvn:org.apache.cxf.karaf/apache-cxf/
 2.5.0.fuse-70-097/xml/features
FAB-Require-Feature: cxf-sts

The FAB-Require-Feature-URL header is specified as a space-separated list of URLs that give the locations of the features repositories.

The FAB-Require-Feature header is specified as a space-separated list of features, in the format, FeatureName, or in the format, FeatureName/Version. For example:

FAB-Require-Feature: cxf-sts/2.5.0.fuse-70-097 cxf-wsn/2.5.0.fuse-70-097

There would not be much point in using features (which are manually adjusted to install exactly the right dependencies, for special cases that an automated tool could not copy with), if the FAB runtime simply forged ahead and installed all of the dependencies it thinks it needs, ignoring the dependencies that were already installed by the feature. For this reason, the FAB runtime adopts a respectful attitude towards previously installed bundles: by default, FAB does not try to install dependencies for a provided bundle, if that bundle is already installed.

The assumption is that a pre-installed bundle already has all of its transitive dependencies installed. For example, this is normally true, if the bundle was installed as part of a feature.

FAB respects pre-installed features and bundles by default. If you want to override this behavior, forcing the FAB runtime to scan the POM files in provided bundles and to install all of the transitive dependencies it finds, set the following Manifest header flag:

FAB-Install-Provided-Bundle-Dependencies: true

The Maven JAR plug-in supports the following alternative approaches to setting manifest headers in your Maven project:

You can specify manifest headers in pom.xml, by configuring the Maven JAR plug-in. In the JAR plug-in's configuration/archive/manifestEntries element, specify manifest header settings using the following syntax:

<ManifestHeaderName>HeaderValue</ManifestHeaderName>

For example, to set the FAB-Version-Range-Digits manifiest header and the FAB-Provided-Dependency manifest header in your pom.xml file, configure the JAR plug-in as shown in Example 5.1.

Alternatively, you can create a MANIFEST.MF file directly and instruct the Maven JAR plug-in to include the provided manifest in the generated JAR (the JAR plug-in does not include the manifest by default). Configure the JAR plug-in to include the manifest file as follows:

In your Maven project directory tree, create a MANIFEST.MF file at the following location:

ProjectDir/src/main/resources/META-INF/MANIFEST.MF

The following example shows a correctly formatted META-INF/MANIFEST.MF file:

Note the following peculiarities of the manifest file syntax:

[Tip]Tip

Given the awkward constraints on the manifest file syntax, it is recommended that you edit the manifest using a dedicated editor, such as the Eclipse Manifest Editor Plug-In.

PK HAg f33OEBPS/BuildFab-Modify.html Modifying an Existing Maven Project

Modifying an Existing Maven Project

If you already have a Maven project and you want to customize it to generate a FAB, perform the following steps:

A FAB is packaged as a regular JAR file, which is the default package type in Maven. Ensure that the packaging element in your project's pom.xml file contains the value, jar, as shown in the following example:

<project ... >
  ...
  <packaging>jar</packaging>
  ...
</project>

It is almost always necessary to specify the JDK version in your POM file. If your code uses any modern features of the Java language—such as generics, static imports, and so on—and you have not customized the JDK version in the POM, Maven will fail to compile your source code. It is not sufficient to set the JAVA_HOME and the PATH environment variables to the correct values for your JDK, you must also modify the POM file.

To configure your POM file, so that it accepts the Java language features introduced in JDK 1.6, add the following maven-compiler-plugin plug-in settings to your POM (if they are not already present):

Any dependencies on standard artifacts already provided by the container should be declared as provided, to prevent the FAB runtime from unnecessarily installing those dependencies again. This typically includes artifacts whose names match the patterns, camel-*, cxf-*, activemq-*, and fabric-*.

For example, if you have an existing dependency on the camel-http artifact, you should modify the dependency by adding the scope element as follows:

[Note]Note

Since Fuse ESB Enterprise 7.0.1, all dependencies with Maven group ID org.apache.camel, org.apache.cxf, or org.apache.activemq are shared by default (equivalent to provided scope), so that the value of the scope element is ignored by default. This behavior changes, however, if the FAB-Provided-Dependency manifest header is specified explicitly—see Sharing dependencies for details.

If you have a large number of dependencies to manage, it might be easier to share the standard container artifacts by adding a FAB manifest header. For details, see Example 5.1.

Any artifacts needed only for testing must be marked with the test scope, as in the following example:

Of course, this is the standard convention in POM files. But it is particularly important to observe this convention with FAB projects. For any test artifacts that are not marked as such, the FAB runtime will attempt to download and install the test artifact into the container at run time.

[Important]Important

Because the test-only artifacts are not intended to be installed in the container, it is quite likely that a FAB will fail to deploy properly if test artifacts are not marked with the test scope.

If you are building a Web service application based on Apache CXF, you should add a dependency on the cxf-bundle artifact—for example, by adding the following dependency element as a child of the dependencies element in your POM file:

Note the following points about this dependency:

If your project uses dependency injection or XML configuration, you should prefer the Blueprint framework over the Spring framework.

Because Blueprint is more tightly integrated with OSGi, it is usually able to find whatever dependencies it needs dynamically at deploy time. By contrast, dependencies introduced by a Spring XML file are more likely to lead to ClassNotFound exceptions at deploy time (FAB is not capable of parsing a Spring XML file to discover the dependencies it introduces).

Although the FAB runtime obtains most of its deployment metadata by scanning the pom.xml file embedded in the JAR, you can also specify FAB-specific configuration settings by adding headers to the JAR's manifest. For example:

For detailed explanations of all the FAB manifest headers, see Configuring a FAB.

PK HAEo OEBPS/BuildFab.html Chapter 5. Building a FAB

Chapter 5. Building a FAB

Generating a FAB Project
Class Sharing
Modifying an Existing Maven Project
Configuring a FAB
PK HAP,sgOEBPS/BuildWar-CxfServlet.html Bootstrapping a CXF Servlet in a WAR

Bootstrapping a CXF Servlet in a WAR

A simple way to bootstrap Apache CXF in a WAR is to configure web.xml to use the standard CXF servlet, org.apache.cxf.transport.servlet.CXFServlet.

For example, the following web.xml file shows how to configure the CXF servlet, where all Web service addresses accessed through this servlet would be prefixed by /services/ (as specified by the value of servlet-mapping/url-pattern):

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC 
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
  <display-name>cxf</display-name>
  <description>cxf</description>

  <servlet>
    <servlet-name>cxf</servlet-name>
    <display-name>cxf</display-name>
    <description>Apache CXF Endpoint</description>
    <servlet-class>org.apache.cxf.transport.servlet.CXFServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
  </servlet>

  <servlet-mapping>
    <servlet-name>cxf</servlet-name>
    <url-pattern>/services/*</url-pattern>
  </servlet-mapping>

  <session-config>
    <session-timeout>60</session-timeout>
  </session-config>

</web-app>

In addition to configuring the web.xml file, it is also necessary to configure your Web services by defining a cxf-servlet.xml file, which must be copied into the root of the generated WAR.

Alternatively, if you do not want to put cxf-servlet.xml in the default location, you can customize its name and location, by setting the contextConfigLocation context parameter in the web.xml file. For example, to specify that Apache CXF configuration is located in WEB-INF/cxf-servlet.xml, set the following context parameter in web.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE web-app PUBLIC 
  "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN"
  "http://java.sun.com/dtd/web-app_2_3.dtd">

<web-app>
    ...
	<context-param>
		<param-name>contextConfigLocation</param-name>
		<param-value>WEB-INF/cxf-servlet.xml</param-value>
	</context-param>
    ...
</web-app>

For full details of how to configure the CXF servlet, see .

PK HA1|g--OEBPS/BuildWar-Modify.html Modifying an Existing Maven Project

Modifying an Existing Maven Project

If you already have a Maven project and you want to modify it so that it generates a WAR, perform the following steps:

Configure Maven to generate a WAR by changing the package type to war in your project's pom.xml file. Change the contents of the packaging element to war, as shown in the following example:

<project ... >
  ...
  <packaging>war</packaging>
  ...
</project>

The effect of this setting is to select the Maven WAR plug-in, maven-war-plugin, to perform packaging for this project.

It is almost always necessary to specify the JDK version in your POM file. If your code uses any modern features of the Java language—such as generics, static imports, and so on—and you have not customized the JDK version in the POM, Maven will fail to compile your source code. It is not sufficient to set the JAVA_HOME and the PATH environment variables to the correct values for your JDK, you must also modify the POM file.

To configure your POM file, so that it accepts the Java language features introduced in JDK 1.6, add the following maven-compiler-plugin plug-in settings to your POM (if they are not already present):

Resource files for the Web application are stored under the /WEB-INF directory in the standard WAR directory layout. In order to ensure that these resources are copied into the root of the generated WAR package, store the WEB-INF directory under ProjectDir/src/main/webapp in the Maven directory tree, as follows:

ProjectDir/
    pom.xml
    src/
        main/
            webapp/
                WEB-INF/
                    web.xml
                    classes/
                    lib/

In particular, note that the web.xml file is stored at ProjectDir/src/main/webapp/WEB-INF/web.xml.

It is possible to customize the Maven WAR plug-in by adding an entry to the plugins section of the pom.xml file. Most of the configuration options are concerned with adding additonal resources to the WAR package. For example, to include all of the resources under the src/main/resources directory (specified relative to the location of pom.xml) in the WAR package, you could add the following WAR plug-in configuration to your POM:

<project ...>
  ...
  <build>
    ...
    <plugins>
      <plugin>
        <artifactId>maven-war-plugin</artifactId>
    	<version>2.1.1</version>
        <configuration>
          <!-- Optionally specify where the web.xml file comes from -->
          <webXml>src/main/webapp/WEB-INF/web.xml</webXml>
          <!-- Optionally specify extra resources to include -->
          <webResources>
            <resource>
              <directory>src/main/resources</directory>
              <targetPath>WEB-INF</targetPath>
              <includes>
                <include>**/*</include>
              </includes>
            </resource>
          </webResources>
        </configuration>
      </plugin>
      ...
    </plugins>
  </build>
</project>

The preceding plug-in configuration customizes the following settings:

For complete details of how to configure the Maven WAR plug-in, see http://maven.apache.org/plugins/maven-war-plugin/index.html.

[Note]Note

Do not use version 2.1 of the maven-war-plugin plug-in, which has a bug that causes two copies of the web.xml file to be inserted into the generated .war file.

To build the WAR defined by the Maven project, open a command prompt, go to the project directory (that is, the directory containing the pom.xml file), and enter the following Maven command:

mvn install

The effect of this command is to compile all of the Java source files, to generate a WAR under the ProjectDir/target directory, and then to install the generated WAR in the local Maven repository.

PK HA, , OEBPS/BuildWar-Spring.html Bootstrapping a Spring Context in a WAR

Bootstrapping a Spring Context in a WAR

You can bootstrap a Spring context in a WAR using Spring's ContextLoaderListener class.

For example, the following web.xml file shows how to boot up a Spring application context that is initialized by the XML file, /WEB-INF/applicationContext.xml (which is the location of the context file in the generated WAR package):

<?xml version="1.0" encoding="ISO-8859-1"?>
<web-app version="2.4" xmlns="http://java.sun.com/xml/ns/j2ee"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://java.sun.com/xml/ns/j2ee http://java.sun.com/xml/ns/j2ee/web-app_2_4.xsd">

    <display-name>Camel Routes</display-name>

    <!-- location of spring xml files -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/applicationContext.xml</param-value>
    </context-param>

    <!-- the listener that kick-starts Spring -->
    <listener>
        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
    </listener>

</web-app>
PK HA ROEBPS/BuildWar.html Chapter 8. Building a WAR

Chapter 8. Building a WAR

This chapter describes how to build and package a WAR using Maven.

Note: Consider using FABs instead of WARs as your unit of deployment, because FABs are smaller (dependent JARs do not have to be packaged inside the FAB) and more flexible (you can optionally share specific dependencies as OSGi bundles).

Modifying an Existing Maven Project
Bootstrapping a CXF Servlet in a WAR
Bootstrapping a Spring Context in a WAR
PK HAXotOEBPS/BundleTutorial.html Chapter 15. OSGi Bundle Tutorials

Chapter 15. OSGi Bundle Tutorials

Generating and Running an EIP Bundle
Generating and Running a Web Services Bundle
PK HAI99!OEBPS/DeployActiveMQ-Example.html JMS Endpoints in a Router Application

JMS Endpoints in a Router Application

The following example shows how you can integrate a JMS broker into a router application. The example generates messages using a timer; sends the messages through the camel.timer queue in the JMS broker; and then writes the messages to a specific directory in the file system.

In order to run the sample router application, you need to have the camel-activemq feature installed in the OSGi container. The camel-activemq component is needed for defining Apache ActiveMQ-based JMS endpoints in Apache Camel. This feature is not installed by default, so you must install it using the following console command:

karaf@root> features:install camel-activemq

You also need the activemq feature, but this feature is normally available, because Fuse ESB Enterprise installs it by default.

[Tip]Tip

Most of the Apache Camel components are not installed by default. Whenever you are about to define an endpoint in a Apache Camel route, remember to check whether the corresponding component feature is installed. Apache Camel component features generally have the same name as the corresponding Apache Camel component artifact ID, camel-ComponentName.

Example 17.3 gives an example of a Apache Camel route defined using the Spring XML DSL. Messages generated by the timer endpoint are propagated through the JMS broker and then written out to the file system.

In general, it is necessary to create a custom instance of the Apache Camel activemq component, because you need to specify the connection details for connecting to the broker. The preceding example uses Spring syntax to instantiate the activemq bean which connects to the broker URL, tcp://localhost:61616. The broker URL must correspond to one of the transport connectors defined in the broker configuration file, deploy/test-broker.xml.

Example 17.3 defines two routes, as follows:

  1. The first route uses a timer endpoint to generate messages at four-second intervals. The setBody element places a dummy string in the body of the message (which would otherwise be null). The messages are then sent to the camel.timer queue on the broker (the activemq:camel.timer endpoint).

    [Note]Note

    The activemq scheme in activemq:camel.timer is resolved by looking up activemq in the bean registry, which resolves to the locally instantiated bean with ID, activemq.

  2. The second route pulls messages off the camel.timer queue and then writes the messages to the specified directory, C:\temp\sandpit\timer, in the file system.

To run the sample router application, perform the following steps:

  1. Using your favorite text editor, copy and paste the router configuration from Example 17.3 into a file called camel-timer.xml.

    Edit the file endpoint in the second route, in order to change the target directory to a suitable location on your file system:

        <route>
          <from uri="activemq:camel.timer"/>
          <to uri="file:YourDirectoryHere!"/>
        </route>
  2. Start up a local instance of the Fuse ESB Enterprise runtime by entering the following at a command prompt:

    servicemix
  3. Make sure the requisite features are installed in the OSGi container. To install the camel-activemq feature, enter the following command at the console:

    karaf@root> features:install camel-activemq

    To ensure that the activemq-broker feature is not installed, enter the following command at the console:

    karaf@root> features:uninstall activemq-broker
  4. Use one of the following alternatives to obtain a broker instance for this demonstration:

    • Use the default broker—assuming you have not disabled the default broker, you can use it for this demonstration, because it is listening on the correct port, 61616.

    • Create a new broker instance using the console—if you prefer not to use the default broker, you can disable it (as described in Working with the Default Broker) and then create a new JMS broker instance by entering the following command at the console:

      karaf@root> activemq:create-broker --name test

      After executing this command, you should see the broker configuration file, test-broker.xml, in the InstallDir/deploy directory.

  5. Hot deploy the router configuration you created in step 1. Copy the camel-timer.xml file into the InstallDir/deploy directory.

  6. Within a few seconds, you should start to see files appearing in the target directory (which is C:\temp\sandpit\timer, by default). The file component automatically generates a unique filename for each message that it writes.

    It is also possible to monitor activity in the JMS broker by connecting to the Fuse ESB Enterprise runtime's JMX port. To monitor the broker using JMX, perform the following steps:

    1. To monitor the Fuse ESB Enterprise runtime, start a JConsole instance (a standard Java utility) by entering the following command:

      jconsole
    2. Initially, a JConsole: Connect to Agent dialog prompts you to connect to a JMX port. From the Local tab, select the org.apache.felix.karaf.main.Bootstrap entry and click Connect.

    3. In the main JConsole window, click on the MBeans tab and then drill down to org.apache.activemq|test|Queue in the MBean tree (assuming that test is the name of your broker).

    4. Under the Queue folder, you should see the camel.timer queue. Click on the camel.timer queue to view statistics on the message throughput of this queue.

  7. To shut down the router application, delete the camel-timer.xml file from the InstallDir/deploy directory.

PK HA aaOEBPS/DeployBundle-Hot.html Hot Deployment

Hot Deployment

Fuse ESB monitors JAR files in the InstallDir/deploy directory and hot deploys everything in this directory. Each time a JAR file is copied to this directory, it is installed in the runtime and also started. You can subsequently update or delete the JARs, and the changes are handled automatically.

For example, if you have just built the bundle, ProjectDir/target/foo-1.0-SNAPSHOT.jar, you can deploy this bundle by copying it to the InstallDir/deploy directory as follows (assuming you are working on a UNIX platform):

% cp ProjectDir/target/foo-1.0-SNAPSHOT.jar InstallDir/deploy
PK HAf''!OEBPS/DeployBundle-Lifecycle.html Lifecycle Management

Lifecycle Management

Applications in an OSGi environment are subject to the lifecycle of its bundles. Bundles have six lifecycle states:

  1. Installed — All bundles start in the installed state. Bundles in the installed state are waiting for all of their dependencies to be resolved, and once they are resolved, bundles move to the resolved state.

  2. Resolved — Bundles are moved to the resolved state when the following conditions are met:

    • The runtime environment meets or exceeds the environment specified by the bundle.

    • All of the packages imported by the bundle are exposed by bundles that are either in the resolved state or that can be moved into the resolved state at the same time as the current bundle.

    • All of the required bundles are either in the resolved state or they can be resolved at the same time as the current bundle.

    [Important]Important

    All of an application's bundles must be in the resolved state before the application can be started.

    If any of the above conditions ceases to be satisfied, the bundle is moved back into the installed state. For example, this can happen when a bundle that contains an imported package is removed from the container.

  3. Starting — The starting state is a transitory state between the resolved state and the active state. When a bundle is started, the container must create the resources for the bundle. The container also calls the start() method of the bundle's bundle activator when one is provided.

  4. Active — Bundles in the active state are available to do work. What a bundle does in the active state depends on the contents of the bundle. For example, a bundle containing a JAX-WS service provider indicates that the service is available to accept requests.

  5. Stopping — The stopping state is a transitory state between the active state and the resolved state. When a bundle is stopped, the container must clean up the resources for the bundle. The container also calls the stop() method of the bundle's bundle activator when one is provided.

  6. Uninstalled — When a bundle is uninstalled it is moved from the resolved state to the uninstalled state. A bundle in this state cannot be transitioned back into the resolved state or any other state. It must be explicitly re-installed.

The most important lifecycle states for application developers are the starting state and the stopping state. The endpoints exposed by an application are published during the starting state. The published endpoints are stopped during the stopping state.

When you install a bundle using the osgi:install command (without the -s flag), the kernel installs the specified bundle and attempts to put it into the resolved state. If the resolution of the bundle fails for some reason (for example, if one of its dependencies is unsatisfied), the kernel leaves the bundle in the installed state.

At a later time (for example, after you have installed missing dependencies) you can attempt to move the bundle into the resolved state by invoking the osgi:resolve command, as follows:

osgi:resolve 181

Where the argument (181, in this example) is the ID of the bundle you want to resolve.

You can start one or more bundles (from either the installed or the resolved state) using the osgi:start command. For example, to start the bundles with IDs, 181, 185, and 186, enter the following console command:

osgi:start 181 185 186

You can stop one or more bundles using the osgi:stop command. For example, to stop the bundles with IDs, 181, 185, and 186, enter the following console command:

osgi:stop 181 185 186

You can restart one or more bundles (that is, moving from the started state to the resolved state, and then back again to the started state) using the osgi:restart command. For example, to restart the bundles with IDs, 181, 185, and 186, enter the following console command:

osgi:restart 181 185 186

A start level is associated with every bundle. The start level is a positive integer value that controls the order in which bundles are activated/started. Bundles with a low start level are started before bundles with a high start level. Hence, bundles with the start level, 1, are started first and bundles belonging to the kernel tend to have lower start levels, because they provide the prerequisites for running most other bundles.

Typically, the start level of user bundles is 60 or higher.

Use the osgi:bundle-level command to set the start level of a particular bundle. For example, to configure the bundle with ID, 181, to have a start level of 70, enter the following console command:

osgi:bundle-level 181 70

The OSGi container itself has a start level associated with it and this system start level determines which bundles can be active and which cannot: only those bundles whose start level is less than or equal to the system start level can be active.

To discover the current system start level, enter osgi:start-level in the console, as follows:

karaf@root> osgi:start-level
Level 100

If you want to change the system start level, provide the new start level as an argument to the osgi:start-level command, as follows:

osgi:start-level 200
PK HA?BH  OEBPS/DeployBundle-Manual.html Manual Deployment

Manual Deployment

You can manually deploy and undeploy bundles by issuing commands at the Fuse ESB Enterprise console.

Use the osgi:install command to install one or more bundles in the OSGi container. This command has the following syntax:

osgi:install [-s] [--start] [--help] UrlList

Where UrlList is a whitespace-separated list of URLs that specify the location of each bundle to deploy. The following command arguments are supported:

For example, to install and start the bundle, ProjectDir/target/foo-1.0-SNAPSHOT.jar, enter the following command at the Karaf console prompt:

osgi:install -s file:ProjectDir/target/foo-1.0-SNAPSHOT.jar
[Note]Note

On Windows platforms, you must be careful to use the correct syntax for the file URL in this command. See File URL Handler for details.

To uninstall a bundle, you must first obtain its bundle ID using the osgi:list command. You can then uninstall the bundle using the osgi:uninstall command (which takes the bundle ID as its argument).

For example, if you have already installed the bundle named A Camel OSGi Service Unit, entering osgi:list at the console prompt might produce output like the following:

...
[ 175] [Active     ] [            ] [Started] [   60] ServiceMix :: FTP (2009.02.0.psc-01-00RC1)
[ 181] [Resolved   ] [            ] [       ] [   60] A Camel OSGi Service Unit (1.0.0.SNAPSHOT)

You can now uninstall the bundle with the ID, 181, by entering the following console command:

osgi:uninstall 181

When specifying the location URL to the osgi:install command, you can use any of the URL schemes supported by Fuse ESB Enterprise, which includes the following scheme types:

PK HAOEBPS/DeployBundle.html Chapter 12. Deploying an OSGi Bundle

Chapter 12. Deploying an OSGi Bundle

Hot Deployment
Manual Deployment
Lifecycle Management
Troubleshooting Dependencies
PK HA٬T#T#!OEBPS/DeployCamel-Frameworks.html Spring and Blueprint Frameworks

Spring and Blueprint Frameworks

The OSGi framework allows third-party frameworks to be piggybacked on top of it. In particular, Fuse ESB Enterprise enables the Spring framework and the blueprint framework, by default. In the case of the Spring framework, OSGi automatically activates any Spring XML files under the META-INF/spring/ directory in a JAR, and Spring XML files can also be hot-deployed to the ESBInstallDir/deploy directory. In the case of the blueprint framework, OSGi automatically activates any blueprint XML files under the OSGI-INF/blueprint/ directory in a JAR, and blueprint XML files can also be hot-deployed to the ESBInstallDir/deploy directory.

There are two kinds of file that you can use to configure your project:

If you decide to use the blueprint configuration, you can embed camelContext elements in the blueprint file, as described in Blueprint configuration file.

If you decide to configure your Apache Camel application using blueprint, you must ensure that the camel-blueprint feature is installed. If necessary, install it by entering the following console command:

karaf@root> features:install camel-blueprint

You can deploy a camelContext using a Spring configuration file, where the root element is a Spring beans element and the camelContext element is a child of the beans element. In this case, the camelContext namespace must be http://camel.apache.org/schema/spring.

For example, the following Spring configuration defines a route that generates timer messages every two seconds, sending the messages to the ExampleRouter log (which get incorporated into the console log file, InstallDir/data/log/servicemix.log):

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       >

  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
      <from uri="timer://myTimer?fixedRate=true&amp;period=2000"/>
      <to uri="log:ExampleRouter"/>
    </route>
  </camelContext>

</beans>

It is not necessary to specify schema locations in the configuration. But if you are editing the configuration file with an XML editor, you might want to add the schema locations in order to support schema validation and content completion in the editor. For the preceding example, you could specify the schema locations as follows:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
    ...

Before deploying routes in a blueprint configuration file, check that the camel-blueprint feature is already installed.

You can deploy a camelContext using a blueprint configuration file, where the root element is blueprint and the camelContext element is a child of the blueprint element. In this case, the camelContext namespace must be http://camel.apache.org/schema/blueprint.

For example, the following blueprint configuration defines a route that generates timer messages every two seconds, sending the messages to the ExampleRouter log (which get incorporated into the console log file, InstallDir/data/log/servicemix.log):

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    >

  <camelContext xmlns="http://camel.apache.org/schema/blueprint">
    <route>
      <from uri="timer://myTimer?fixedRate=true&amp;period=2000"/>
      <to uri="log:ExampleRouter"/>
    </route>
  </camelContext>

</blueprint>
[Note]Note

Blueprint is a dependency injection framework, defined by the OSGi standard, which is similar to Spring in many respects. For more details about blueprint, see The Blueprint Container.

PK HAfc OEBPS/DeployCamel-HotDeploy.html Hot Deployment

Hot Deployment

You can hot deploy the following types of configuration file:

If you have an existing Spring XML or blueprint XML configuration file, you can deploy the configuration file directly by copying it into the following hot deploy directory:

InstallDir/deploy

After deploying, the configuration file is activated immediately.

If you want to deploy Apache Camel routes in a blueprint configuration file, the camel-blueprint feature must be installed (which it is by default). If the camel-blueprint feature has been disabled, however, you can re-install it by entering the following console command:

karaf@root> features:install camel-blueprint

When a Spring XML file or a Blueprint XML file is hot deployed, the XML file is automatically wrapped in an OSGi bundle and deployed as a bundle in the OSGi container. By default, the generated bundle has the version, 0.0.0.

If you prefer to customize the bundle version, use the manifest element in the XML file. The manifest element enables you to override any of the headers in the generated bundle's META-INF/MANIFEST.MF file. In particular, you can use it to specify the bundle version.

To specify the bundle version in a hot-deployed Spring XML file, define a manifest element as follows:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       >

  <manifest xmlns="http://karaf.apache.org/xmlns/deployer/spring/v1.0.0">
      Bundle-Version = 1.2.3.4
  </manifest>

  <camelContext xmlns="http://camel.apache.org/schema/spring">
    <route>
      <from uri="timer://myTimer?fixedRate=true&amp;period=2000"/>
      <to uri="log:ExampleRouter"/>
    </route>
  </camelContext>

</beans>

The manifest element for Spring XML files belongs to the following schema namespace:

http://karaf.apache.org/xmlns/deployer/spring/v1.0.0

The contents of the manifest element are specified using the syntax of a Java properties file.

To specify the bundle version in a hot-deployed Blueprint XML file, define a manifest element as follows:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    >

  <manifest xmlns="http://karaf.apache.org/xmlns/deployer/blueprint/v1.0.0">
      Bundle-Version = 1.2.3.4
  </manifest>

  <camelContext xmlns="http://camel.apache.org/schema/blueprint">
    <route>
      <from uri="timer://myTimer?fixedRate=true&amp;period=2000"/>
      <to uri="log:ExampleRouter"/>
    </route>
  </camelContext>

</blueprint>

The manifest element for Blueprint XML files belongs to the following schema namespace:

http://karaf.apache.org/xmlns/deployer/blueprint/v1.0.0

The contents of the manifest element are specified using the syntax of a Java properties file.

PK HAM,,&OEBPS/DeployCamel-OsgiConfigProps.html Using OSGi Configuration Properties

Using OSGi Configuration Properties

The OSGi Configuration Admin service defines a mechanism for passing configuration settings to an OSGi bundle. You do not have to use this service for configuration, but it is typically the most convenient way of configuring applications deployed in Fuse ESB Enterprise (including FABs and OSGi bundles).

In the OSGi Configuration Admin service, a persistent ID is a name that identifies a group of related configuration properties. In Fuse ESB Enterprise, every persistent ID, PersistentID, is implicitly associated with a file named PersistentID.cfg in the ESBInstallDir/etc/ directory. If the corresponding file exists, it can be used to initialize the values of properties belonging to the PersistentID property group.

For example, the etc/org.ops4j.pax.url.mvn.cfg file is used to set the properties associated with the org.ops4j.pax.url.mvn persistent ID (for the PAX Mvn URL handler).

Spring DM provides support for OSGi configuration, enabling you to substitute variables in a Spring XML file using values obtained from the OSGi Configuration Admin service.

Example 2.1 shows how to pass the value of the prefix variable to the constructor of the myTransform bean in Spring XML, where the value of prefix is set by the OSGi Configuration Admin service.

The syntax, ${prefix}, substitutes the value of the prefix variable into the Spring XML file. The OSGi properties are set up using the following XML elements:

osgix:cm-properties

To integrate Spring properties with the properties from the OSGi Configuration Admin service, insert an osgix:cm-properties element into the Spring XML file. This element creates a bean that gets injected with all of the properties from the OSGi ManagedService instance that is identified by the persistent-id attribute. The minimal configuration consists of an empty osgix:cm-properties element that sets the persistent-id attribute and the id attribute—for example:

<osgix:cm-properties id="preProps" persistent-id="org.fusesource.example"/>

For an example of how the persistent ID relates to OSGi configuration settings, see the example in Add OSGi configurations to the feature.

If you want to define defaults for some of the properties in the Spring XML file, add prop elements as children of the osgix:cm-properties element, as shown in Example 2.1.

ctx:property-placeholder

Property placeholder is a Spring mechanism that enables you to use the syntax, ${PropName}, to substitute variables in a Spring XML file. By defining a ctx:property-placeholder element with a reference to the preProps bean (as in Example 2.1), you enable the property placeholder mechanism to substitute any of the variables from the preProps bean (which encapsulates the OSGi configuration properties) into the Spring XML file.

Example 2.2 shows how to pass the value of the prefix variable to the constructor of the myTransform bean in blueprint XML, where the value of prefix is set by the OSGi Configuration Admin service.

The syntax, {{prefix}}, substitutes the value of the prefix variable into the blueprint XML file. The OSGi properties are set up using the following XML elements:

PK HAE:%%OEBPS/DeployCamel-Running.html Generating and Running an EIP Bundle

Generating and Running an EIP Bundle

This section explains how to generate, build, and run a complete Apache Camel example as an OSGi bundle, where the starting point code is generated with the help of a Maven archetype.

In order to generate a project using an Fuse ESB Enterprise Maven archetype, you must have the following prerequisites:

The servicemix-camel-osgi-bundle archetype creates a router project, which is configured to deploy as a bundle. To generate a Maven project with the coordinates, org.fusesource.example:camel-bundle, enter the following command:

The result of this command is a directory, ProjectDir/camel-bundle, containing the files for the generated bundle project.

To install and run the generated camel-bundle project, perform the following steps:

  1. Build the project—open a command prompt and change directory to ProjectDir/camel-bundle. Use Maven to build the demonstration by entering the following command:

    mvn install

    If this command runs successfully, the ProjectDir/camel-bundle/target directory should contain the bundle file, camel-bundle-1.0-SNAPSHOT.jar and the bundle will also be installed in the local Maven repository.

  2. Install prerequisite features (optional)—by default, the camel-core feature and some related features are pre-installed in the OSGi container. But many of the Apache Camel components are not installed by default. To check which features are available and whether or not they are installed, enter the following console command:

    karaf@root> features:list

    Apache Camel features are identifiable by the camel- prefix. For example, if one of your routes requires the HTTP component, you can make sure that it is installed in the OSGi container by issuing the following console command:

    karaf@root> features:install camel-http
  3. Install and start the camel-bundle bundle—at the Fuse ESB Enterprise console, enter the following command:

    karaf@root> osgi:install -s file:ProjectDir/camel-bundle/target/camel-bundle-1.0-SNAPSHOT.jar

    Where ProjectDir is the directory containing your Maven projects and the -s flag directs the container to start the bundle right away. For example, if your project directory is C:\Projects on a Windows machine, you would enter the following command:

    karaf@root> osgi:install -s file:C:/Projects/camel-bundle/target/camel-bundle-1.0-SNAPSHOT.jar

    Alternatively, you could install the bundle from the local Maven repository using an Mvn URL (see Mvn URL Handler) as follows:

    karaf@root> osgi:install -s mvn:org.fusesource.example/camel-bundle

    After entering this command, you should soon see output like the following being logged to the console screen:

    >>>> MyTransform set body:  Mon Sep 22 11:43:42 BST 2008
    >>>> MyTransform set body:  Mon Sep 22 11:43:44 BST 2008
    >>>> MyTransform set body:  Mon Sep 22 11:43:46 BST 2008
    [Note]Note

    On Windows machines, be careful how you format the file URL—for details of the syntax understood by the file URL handler, see File URL Handler.

  4. Stop the camel-bundle bundle—to stop the camel-bundle bundle, you first need to discover the relevant bundle number. To find the bundle number, enter the following console command (this might look a bit confusing, because the text you are typing will intermingle with the output that is being logged to the screen):

    karaf@root> osgi:list

    At the end of the listing, you should see an entry like the following:

    [ 189] [Active     ] [            ] [       ] [   60] A Camel OSGi Service Unit (1.0.0.SNAPSHOT)

    Where, in this example, the bundle number is 189. To stop this bundle, enter the following console command:

    karaf@root> osgi:stop 189
PK HA}Q  !OEBPS/DeployCamel-RunningFab.html Generating and Running an EIP FAB

Generating and Running an EIP FAB

This section explains how to generate, build, and run a complete Apache Camel example as a FAB, where the starting point code is generated with the help of a Maven archetype.

In order to generate a project using an Fuse ESB Enterprise Maven archetype, you must have the following prerequisites:

The camel-archetype-blueprint archetype creates a sample Maven project that can be deployed as a FAB. To generate a Maven project with the coordinates, org.fusesource.example:camel-fab, enter the following command:

The result of this command is a directory, ProjectDir/camel-fab, containing the files for the generated FAB project.

To install and run the generated camel-fab project, perform the following steps:

PK HAy$$OEBPS/DeployCxf-Packaging.html Packaging a Web Service in a Bundle

Packaging a Web Service in a Bundle

This section explains how to modify an existing Maven project for a Apache CXF application, so that the project generates an OSGi bundle suitable for deployment in the Fuse ESB Enterprise OSGi container. To convert the Maven project, you need to modify the project's POM file and the project's Spring XML file(s) (located in META-INF/spring).

To configure a Maven POM file to generate a bundle, there are essentially two changes you need to make: change the POM's package type to bundle; and add the Maven bundle plug-in to your POM. For details, see Generating a Bundle Project.

The Apache CXF runtime components are included in Fuse ESB Enterprise as an OSGi bundle called org.apache.cxf.bundle. The dependency on this bundle can conveniently be expressed by adding the Require-Bundle element to the Maven bundle plug-in's instructions, as highlighted in the following sample POM:

<project ... >
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <extensions>true</extensions>
                <configuration>
                    <instructions>
                        ...
                        <Require-Bundle>org.apache.cxf.bundle</Require-Bundle>
                        ...
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>
    ...
</project>

In order for your application to use the Apache CXF components, you need to import their packages into the application's bundle. Because of the complex nature of the dependencies in Apache CXF, you cannot rely on the Maven bundle plug-in, or the bnd tool, to automatically determine the needed imports. You will need to explicitly declare them.

You need to import the following packages into your bundle:

javax.jws
javax.wsdl
javax.xml.bind
javax.xml.bind.annotation
javax.xml.namespace
javax.xml.ws
META-INF.cxf
META-INF.cxf.osgi
org.apache.cxf.bus
org.apache.cxf.bus.spring
org.apache.cxf.bus.resource
org.apache.cxf.configuration.spring
org.apache.cxf.resource
org.apache.cxf.jaxws
org.springframework.beans.factory.config

Example 11.1 shows how to configure the Maven bundle plug-in in your POM to import the mandatory packages. The mandatory import packages appear as a comma-separated list inside the Import-Package element. Note the appearance of the wildcard, *, as the last element of the list. The wildcard ensures that the Java source files from the current bundle are scanned to discover what additional packages need to be imported.

A Web services project typically requires code to be generated. Apache CXF provides two Maven plug-ins for the JAX-WS front-end, which enable tyou to integrate the code generation step into your build. The choice of plug-in depends on whether you develop your service using the Java-first approach or the WSDL-first approach, as follows:

The OSGi Configuration Admin service defines a mechanism for passing configuration settings to an OSGi bundle. You do not have to use this service for configuration, but it is typically the most convenient way of configuring bundle applications. Both Spring DM and Blueprint provide support for OSGi configuration, enabling you to substitute variables in a Spring XML file or a Blueprint file using values obtained from the OSGi Configuration Admin service.

For details of how to use OSGi configuration properties, see Configuring the Bundle Plug-In and Add OSGi configurations to the feature.

PK HA/,,OEBPS/DeployCxf-Running.html Generating and Running a Web Services Bundle

Generating and Running a Web Services Bundle

This section explains how to generate, build, and run a complete Apache CXF example as a bundle in the OSGi container, where the starting point code is generated with the help of a Maven archetype.

In order to generate a project using a Fuse ESB Enterprise Maven archetype, you must have the following prerequisites:

The servicemix-cxf-code-first-osgi-bundle archetype creates a project for building a Java-first JAX-WS application that can be deployed into the OSGi container. To generate a Maven project with the coordinates, org.fusesource.example:cxf-code-first-bundle, enter the following command:

The result of this command is a directory, ProjectDir/cxf-code-first-bundle, containing the files for the generated bundle project.

Typically, you will need to modify the instructions for the Maven bundle plug-in in the POM file. In particular, the default Import-Package element generated by the servicemix-cxf-code-first-osgi-bundle archetype is not configured to scan the project's Java source files. In most cases, however, you would want the Maven bundle plug-in to perform this automatic scanning in order to ensure that the bundle imports all of the packages needed by your code.

To enable the Import-Package scanning feature, simply add the wildcard, *, as the last item in the comma-separated list inside the Import-Package element, as shown in the following example:

To install and run the generated cxf-code-first-bundle project, perform the following steps:

  1. Build the project—open a command prompt and change directory to ProjectDir/cxf-code-first-bundle. Use Maven to build the demonstration by entering the following command:

    mvn install

    If this command runs successfully, the ProjectDir/cxf-code-first-bundle/target directory should contain the bundle file, cxf-code-first-bundle-1.0-SNAPSHOT.jar.

  2. Install and start the cxf-code-first-bundle bundle—at the Fuse ESB Enterprise console, enter the following command:

    karaf@root> osgi:install -s file:ProjectDir/cxf-code-first-bundle/target/cxf-code-first-bundle-1.0-SNAPSHOT.jar

    Where ProjectDir is the directory containing your Maven projects and the -s flag directs the container to start the bundle right away. For example, if your project directory is C:\Projects on a Windows machine, you would enter the following command:

    karaf@root> osgi:install -s file:C:/Projects/cxf-code-first-bundle/target/cxf-code-first-bundle-1.0-SNAPSHOT.jar
    [Note]Note

    On Windows machines, be careful how you format the file URL—for details of the syntax understood by the file URL handler, see File URL Handler.

    Alternatively, you could install the bundle from your local Maven repository, using the following PAX mvn URL:

    karaf@root> osgi:install -s mvn:org.fusesource.example/cxf-code-first-bundle/1.0-SNAPSHOT
  3. Test the Web serivce—to test the Web service deployed in the previous step, you can use a web browser to query the service's WSDL. Open your favorite web browser and navigate to the following URL:

    http://localhost:8181/cxf/PersonServiceCF?wsdl

    When the web service receives the query, ?wsdl, it returns a WSDL description of the running service.

  4. Stop the cxf-code-first-bundle bundle—to stop the cxf-code-first-bundle bundle, you first need to discover the relevant bundle number. To find the bundle number, enter the following console command:

    karaf@root> osgi:list

    At the end of the listing, you should see an entry like the following:

    [ 191] [Active     ] [            ] [       ] [   60] A CXF Code First OSGi Project (1.0.0.SNAPSHOT)

    Where, in this example, the bundle number is 191. To stop this bundle, enter the following console command:

    karaf@root> osgi:stop 191
PK HAӹƴ$OEBPS/DeployFab-FabsAndFeatures.html FABs and Features

FABs and Features

FABs have been designed to integrate smoothly with Apache Karaf features. Although there is some overlap in the capabilities of FABs and features, FABs cannot replace features completely. There are some cases, involving third-party dependencies, where figuring out the correct set of dependencies is inherently difficult and unavoidably it remains a manual process. Features remain the ideal mechanism for encapsulating these kinds of hand-crafted dependencies.

A FAB can be configured to require specific features, so that the required features are automatically installed at deploy time. For details of how to configure this, see Requiring features.

Automatic feature detection is a special case of requiring features. When the FAB runtime scans an embedded pom.xml file, it automatically maps certain Maven dependencies to features and installs the corresponding feature instead of the Maven dependency.

For example, if the FAB runtime finds a Maven dependency on the the org.apache.camel/camel-jetty artifact, it will automatically install the camel-jetty feature.

The basic FAB model of deployment is rather aggressive: the FAB runtime walks the tree of Maven transitive dependencies, installing (and if necessary, also downloading) all of the dependencies that it finds along the way. This deployment model must be softened, however, if FABs are to integrate properly with features.

Features are manually constructed deployment units and, in many cases, they include combinations of bundles that an automated tool would never be able to figure out. For this reason, it is better if the FAB runtime respects the judgement of the developer who constructed the feature and does not try to install dependencies for bundles belonging to a feature. To avoid clobbering feature dependencies, the FAB runtime applies the following rule: by default, FAB does not try to install dependencies for a provided bundle, if that bundle is already installed.

This rule ensures that the FAB runtime does not try to second-guess the dependencies installed by a feature.

PK HAd d OEBPS/DeployFab-Hot.html Hot Deployment

Hot Deployment

If you save a FAB as a file ending in .fab, you can deploy it simply by copying it into the InstallDir/deploy directory.

Fuse ESB monitors files in the InstallDir/deploy directory and hot deploys any files that have a recognized suffix. Each time a FAB file is copied to this directory, it is installed in the runtime and also started. You can subsequently update or delete the FABs, and the changes are handled automatically.

For example, if you have just built the FAB, ProjectDir/target/fabulous-1.0.fab, you can deploy this FAB by copying it to the InstallDir/deploy directory as follows (assuming you are working on a UNIX platform):

% cp ProjectDir/target/fabulous-1.0.fab InstallDir/deploy
PK HAǓvX X OEBPS/DeployFab-Manual.html Manual Deployment

Manual Deployment

You can manually deploy and undeploy FABs by issuing commands at the Fuse ESB Enterprise console.

FABs can be deployed using the fab: URL scheme, which is useful for installing FABs in a general context, such as a FAB URL embedded in an Apache Karaf features file. For example, to install a FAB using the osgi:install command, prefix the FAB's URL with the fab: scheme, as follows:

osgi:install fab:mvn:groupId/artifactId/version

To start a FAB, you must first obtain its bundle ID using the osgi:list command. You can then start the FAB using the fab:start command (which takes the bundle ID as its argument).

For example, if you have already installed the FAB named A Camel FAB, entering osgi:list at the console prompt might produce output like the following:

...
[ 175] [Active     ] [            ] [Started] [   60] ServiceMix :: FTP (2009.02.0.psc-01-00RC1)
[ 180] [Installed  ] [            ] [       ] [   60] A Camel FAB (1.0.0.SNAPSHOT)

You can now start the bundle with the ID, 180, by entering the following console command:

fab:start 180

The fab:start command recursively starts all of the FAB's dependent bundles, which ensures that services required by the FAB are available when the FAB starts up.

To stop a FAB, invoke the fab:stop console command (which takes the FAB's bundle ID as its argument).

For example, to stop the FAB with the bundle ID, 180, enter the following console command:

fab:stop 180

The fab:stop command recursively stops all of the FAB's dependent bundles. If you would prefer to perform a shallow stop (that is, to stop only the bundle corresponding to the FAB), use the osgi:stop command instead.

To uninstall a FAB, invoke the fab:uninstall console command (which takes the FAB's bundle ID as its argument).

For example, to uninstall the FAB with the bundle ID, 180, enter the following console command:

fab:uninstall 180

The fab:uninstall command also uninstalls the FAB's unused transitive dependencies. Hence, fab:uninstall can potentially uninstall multiple bundles from the OSGi container. If you would prefer to perform a shallow uninstall (that is, to uninstall only the bundle corresponding to the FAB), use the osgi:uninstall command instead.

Seeing as how a FAB is ultimately transformed into a bundle (after it is deployed into the OSGi container), some of the standard bundle lifecycle commands are also of interest to FAB users. For details, see Lifecycle Management.

When specifying the FAB's URL to the osgi:install command, you can combine fab: with any of the URL schemes supported by Fuse ESB Enterprise, which includes the following scheme types:

PK HA5>>OEBPS/DeployFab-Model.html The FAB Deployment Model

The FAB Deployment Model

FABs have a fundamentally different deployment model from standard OSGi bundles. When a FAB is installed, the FAB runtime automatically figures out what dependencies are required, by scanning the Maven metadata, and these dependencies are then installed dynamically. This makes FABs easier to use than standard OSGi bundles.

A Fuse Application Bundle (FAB) is any JAR created using Apache Maven, or similar build tools, so that inside the JAR there is a pom.xml file at the following location (where groupId and artifactId are the Maven coordinates of the JAR):

META-INF/maven/groupId/artifactId/pom.xml

Which contains the transitive dependency information for the JAR.

[Important]Important

A FAB is not an OSGi bundle. At installation time, however, a FAB results in the creation of one or more bundles, which are constructed dynamically.

It is possible to add some additional (optional) configuration to a FAB by including FAB-specific headers in the JAR's Manifest.mf file. For example, the FAB-Provided-Dependency header can be used to specify whether some or all of the FAB's dependencies are to be shared.

For full details about FAB manifest headers, see Configuring a FAB.

Depending on how a FAB is configured, there are two basic alternatives for deploying a FAB:

Figure 6.1 shows how a FAB is installed when all of its dependencies are configured to be private.

The figure shows the installation of the FAB, Fab, and its private dependencies, which proceeds as follows:

When a FAB is configured to have all of its dependencies private, as in this example, what you end up with is very similar to a WAR deployment (which also tends to keep its dependencies private, by default). An advantage that the FAB has over the WAR, however, is that the FAB does not need to be packaged together with its dependencies. Thus a FAB can be much smaller than a typical WAR package.

At the other extreme, Figure 6.2 shows how a FAB is installed when all of its dependencies are configured to be shared.

The figure shows the installation of the FAB, Fab, and its shared dependencies, which proceeds as follows:

When a FAB is configured to share all of its dependencies, as in this example, what you end up with is very similar to the conventional approach using OSGi bundles and features. The advantage of the FAB approach, however, is that you do not need to write a custom features file to make sure that all of the dependencies are installed at the same time.

A FAB can have all private dependencies, some shared dependencies, or all shared dependencies. In other words, you can configure a FAB's dependencies anywhere on the spectrum from all-shared to all-private.

By default, a FAB keeps its dependencies private (except for the dependencies with Maven group ID org.apache.camel, org.apache.cxf, or org.apache.activemq). This deployment approach is relatively safe, because it minimizes the risk of version conflicts and so on. But it is also an expensive option, because it uses up a lot of system memory and resources. If you would like to experiment with sharing some of the FAB's dependencies, you can specify which artifacts to share using the FAB-Provided-Dependency: header in the FAB's manifest, Manifest.mf. For example:

FAB-Provided-Dependency: org.apache.camel:* org.apache.cxf:* org.apache.activemq:*
  org.springframework:*

In this way, you can easily optimize the performance of the FAB, while balancing the risk of version conflicts occurring.

Figure 6.3 shows an outline of what happens when you start a FAB, in the case where the FAB shares its dependencies.

When you start a FAB using the fab:start console command, the FAB runtime iterates over the FAB's transitive dependencies and starts every single bundle in the tree of dependencies (starting with the leaves). This contrasts with the conventional osgi:start console command, which starts only the specified bundle.

The default install behavior of a FAB is actually more complex than suggested by the all-private dependencies model (as shown in Figure 6.1). In reality, the FAB runtime distinguishes between the following types of dependency:

  • Plain FAB dependency (has pom.xml file, but no bundle headers)—by default, the plain FAB dependencies are added to the deployed FAB's private classpath and bundled together with the deployed FAB.

  • OSGi bundle dependency (has pom.xml file and bundle headers)—by default, the OSGi bundle dependencies are deployed as separate bundles (shared dependencies).

Figure 6.4 shows how a FAB is installed, by default, when some its dependencies are plain FABs (DepA and DepA1) and some of its dependencies are OSGi bundles (Bnd1, Bnd2, and Bnd3):

The FAB runtime works on the assumption that whoever built an artifact as an OSGi bundle presumably intended for the artifact to be deployed as a bundle. Another good reason for deploying OSGi bundles separately is that this guarantees that the bundles will be properly activated when you invoke fab:start. If the dependent bundles (Bnd1, Bnd2, and Bnd3) were merely added to the private classpath of the Fab bundle, they would not be activated when fab:start is invoked (in other words, any Spring configuration files or blueprint configuration files would fail to be activated).

PK HAZ9OEBPS/DeployFab.html Chapter 6. Deploying a FAB

Chapter 6. Deploying a FAB

The FAB Deployment Model
FABs and Features
Hot Deployment
Manual Deployment
Configuring Maven for FAB
PK HA[sj;j; OEBPS/DeployFeatures-Create.html Creating a Feature

Creating a Feature

Essentially, a feature is created by adding a new feature element to a special kind of XML file, known as a feature repository. To create a feature, perform the following steps:

If you have not already defined a custom feature repository, you can create one as follows. Choose a convenient location for the feature repository on your file system—for example, C:\Projects\features.xml—and use your favorite text editor to add the following lines to it:

<?xml version="1.0" encoding="UTF-8"?>
<features name="CustomRepository">
</features>

Where you must specify a name for the repository, CustomRepository, by setting the name attribute.

[Note]Note

In contrast to a Maven repository or an OBR, a feature repository does not provide a storage location for bundles. A feature repository merely stores an aggregate of references to bundles. The bundles themselves are stored elsewhere (for example, in the file system or in a Maven repository).

To add a feature to the custom feature repository, insert a new feature element as a child of the root features element. You must give the feature a name and you can list any number of bundles belonging to the feature, by inserting bundle child elements. For example, to add a feature named example-camel-bundle containing the single bundle, C:\Projects\camel-bundle\target\camel-bundle-1.0-SNAPSHOT.jar, add a feature element as follows:

<?xml version="1.0" encoding="UTF-8"?>
<features name="MyFeaturesRepo">
  <feature name="example-camel-bundle">
    <bundle>file:C:/Projects/camel-bundle/target/camel-bundle-1.0-SNAPSHOT.jar</bundle>
  </feature>
</features>

The contents of the bundle element can be any valid URL, giving the location of a bundle (see Appendix A). You can optionally specify a version attribute on the feature element, to assign a non-zero version to the feature (you can then specify the version as an optional argument to the features:install command).

To check whether the features service successfully parses the new feature entry, enter the following pair of console commands:

karaf@root> features:refreshUrl
karaf@root> features:list
...
[uninstalled] [0.0.0                 ] example-camel-bundle                 MyFeaturesRepo
...

The features:list command typically produces a rather long listing of features, but you should be able to find the entry for your new feature (in this case, example-camel-bundle) by scrolling back through the listing. The features:refreshUrl command forces the kernel to reread all the feature repositories: if you did not issue this command, the kernel would not be aware of any recent changes that you made to any of the repositories (in particular, the new feature would not appear in the listing).

To avoid scrolling through the long list of features, you can grep for the example-camel-bundle feature as follows:

karaf@root> features:list | grep example-camel-bundle
[uninstalled] [0.0.0                 ] example-camel-bundle                 MyFeaturesRepo

Where the grep command (a standard UNIX pattern matching utility) is built into the shell, so this command also works on Windows platforms.

In order to make the new feature repository available to Apache Karaf, you must add the feature repository using the features:addUrl console command. For example, to make the contents of the repository, C:\Projects\features.xml, available to the kernel, you would enter the following console command:

features:addUrl file:C:/Projects/features.xml

Where the argument to features:addUrl can be specified using any of the supported URL formats (see Appendix A).

You can check that the repository's URL is registered correctly by entering the features:listUrl console command, to get a complete listing of all registered feature repository URLs, as follows:

karaf@root> features:listUrl
mvn:org.apache.servicemix.nmr/apache-servicemix-nmr/1.1.0-fuse-01-00/xml/features
mvn:org.apache.servicemix.camel/features/7.0.2.fuse-097/xml/features
file:C:/Projects/features.xml
mvn:org.apache.ode/ode-jbi-karaf/1.3.3-fuse-01-00/xml/features
mvn:org.apache.felix.karaf/apache-felix-karaf/1.2.0-fuse-01-00/xml/features
mvn:org.apache.servicemix/apache-servicemix/7.0.2.fuse-097/xml/features

If your feature depends on other features, you can specify these dependencies by adding feature elements as children of the original feature element. Each child feature element contains the name of a feature on which the current feature depends. When you deploy a feature with dependent features, the dependency mechanism checks whether or not the dependent features are installed in the container. If not, the dependency mechanism automatically installs the missing dependencies (and any recursive dependencies).

For example, for the custom Apache Camel feature, example-camel-bundle, you can specify explicitly which standard Apache Camel features it depends on. This has the advantage that the application could now be successfully deployed and run, even if the OSGi container does not have the required features pre-deployed. For example, you can define the example-camel-bundle feature with Apache Camel dependencies as follows:

<?xml version="1.0" encoding="UTF-8"?>
<features name="MyFeaturesRepo">
  <feature name="example-camel-bundle">
    <bundle>file:C:/Projects/camel-bundle/target/camel-bundle-1.0-SNAPSHOT.jar</bundle>
    <feature version="7.0.2.fuse-097">camel-core</feature>
    <feature version="7.0.2.fuse-097">camel-spring-osgi</feature>
    <feature version="7.0.2.fuse-097">servicemix-camel</feature>
  </feature>
</features>

Specifying the version attribute is optional. When present, it enables you to select the specified version of the feature.

If your application uses the OSGi Configuration Admin service, you can specify configuration settings for this service using the config child element of your feature definition. For example, to specify that the prefix property has the value, MyTransform, add the following config child element to your feature's configuration:

<?xml version="1.0" encoding="UTF-8"?>
<features name="MyFeaturesRepo">
  <feature name="example-camel-bundle">
    <config name="org.fusesource.fuseesb.example">
      prefix=MyTransform
    </config>
  </feature>
</features>

Where the name attribute of the config element specifies the persistent ID of the property settings (where the persistent ID acts effectively as a name scope for the property names). The content of the config element is parsed in the same way as a Java properties file.

The settings in the config element can optionally be overriden by the settings in the Java properties file located in the InstallDir/etc directory, which is named after the persistent ID, as follows:

InstallDir/etc/org.fusesource.fuseesb.example.cfg

As an example of how the preceding configuration properties can be used in practice, consider the following Spring XML file that accesses the OSGi configuration properties using Spring DM:

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:ctx="http://www.springframework.org/schema/context"
       xmlns:osgi="http://camel.apache.org/schema/osgi"
       xmlns:osgix="http://www.springframework.org/schema/osgi-compendium" ...>
    ...
    <bean id="myTransform" class="org.fusesource.fuseesb.example.MyTransform">
      <property name="prefix" value="${prefix}"/>
    </bean>
   
    <osgix:cm-properties id="preProps" persistent-id="org.fusesource.fuseesb.example">
        <prop key="prefix">DefaultValue</prop>
    </osgix:cm-properties>

    <ctx:property-placeholder properties-ref="preProps" />

</beans>

When this Spring XML file is deployed in the example-camel-bundle bundle, the property reference, ${prefix}, is replaced by the value, MyTransform, which is specified by the config element in the feature repository.

PK HAP%% OEBPS/DeployFeatures-Deploy.html Deploying a Feature

Deploying a Feature

You can deploy a feature in one of the following ways:

After you have created a feature (by adding an entry for it in a feature repository and registering the feature repository), it is relatively easy to deploy the feature using the features:install console command. For example, to deploy the example-camel-bundle feature, enter the following pair of console commands:

karaf@root> features:refreshUrl
karaf@root> features:install example-camel-bundle

It is recommended that you invoke the features:refreshUrl command before calling features:install, in case any recent changes were made to the features in the feature repository which the kernel has not picked up yet. The features:install command takes the feature name as its argument (and, optionally, the feature version as its second argument).

[Note]Note

Features use a flat namespace. So when naming your features, be careful to avoid name clashes with existing features.

To uninstall a feature, invoke the features:uninstall command as follows:

karaf@root> features:uninstall example-camel-bundle
[Note]Note

After uninstalling, the feature will still be visible when you invoke features:list, but its status will now be flagged as [uninstalled].

You can hot deploy all of the features in a feature repository simply by copying the feature repository file into the InstallDir/deploy directory.

As it is unlikely that you would want to hot deploy an entire feature repository at once, it is often more convenient to define a reduced feature repository or feature descriptor, which references only those features you want to deploy. The feature descriptor has exactly the same syntax as a feature repository, but it is written in a different style. The difference is that a feature descriptor consists only of references to existing features from a feature repository.

For example, you could define a feature descriptor to load the example-camel-bundle feature as follows:

<?xml version="1.0" encoding="UTF-8"?>
<features name="CustomDescriptor">
  <repository>RepositoryURL</repository>
  <feature name="hot-example-camel-bundle">
    <feature>example-camel-bundle</feature>
  </feature>
</features>

The repository element specifies the location of the custom feature repository, RepositoryURL (where you can use any of the URL formats described in Appendix A). The feature, hot-example-camel-bundle, is just a reference to the existing feature, example-camel-bundle.

If you want to provision copies of the Apache Karaf for deployment on multiple hosts, you might be interested in adding a feature to the boot configuration, which determines the collection of features that are installed when Apache Karaf boots up for the very first time.

The configuration file, /etc/org.apache.felix.karaf.features.cfg, in your install directory contains the following settings:

This configuration file has two properties:

You can modify the configuration to customize the features that are installed as Fuse ESB starts up. You can also modify this configuration file, if you plan to distribute Fuse ESB with pre-installed features.

[Important]Important

This method of adding a feature is only effective the first time a particular Apache Karaf instance boots up. Any changes made subsequently to the featuresRepositories setting and the featuresBoot setting are ignored, even if you restart the Apache Karaf.

You could force the Apache Karaf instance to revert back to its initial state, however, by deleting the complete contents of the InstallDir/data/cache (thereby losing all of the Apache Karaf instance's custom settings).

PK HA\HP}  OEBPS/DeployFeatures.html Chapter 13. Deploying Features

Chapter 13. Deploying Features

Creating a Feature
Deploying a Feature
PK HAOEBPS/DeployJar-Bnd.html Bundle Tool (Bnd)

Bundle Tool (Bnd)

The Bnd tool is a an open source utility for creating and diagnosing OSGi bundles. It has been developed by Peter Kriens and is freely downloadable from the aQute Web site (subject to an Apache version 2.0 open source license). The key feature of the Bnd tool is that it automatically generates Manifest headers for the OSGi bundle, thus relieving you of this tedious task. The main tasks that Bnd can perform are:

  • Print the manifiest and show the package dependencies of a JAR file or bundle file.

  • Wrap a vanilla JAR file, converting it into a bundle.

  • Build a bundle from the class path, based on specifications in a .bnd file.

  • Validate manifest entries.

You have the option of invoking Bnd in any of the following ways: from the command line; as an Ant task; or through the Maven bundle plug-in, maven-bundle-plugin. In fact, the approach to building bundles described in Building with Maven is based on the Maven bundle plug-in and therefore, implicitly, is also based on the Bnd tool.

You can download Bnd from the aQute Web site at the following location:

http://www.aqute.biz/Code/Download#bnd

Download the Bnd JAR file, bnd-Version.jar, to a convenient location. There is no installation involved: the JAR file is all that you need to use the Bnd tool. For convenience, however, it is advisable to rename the JAR file to bnd.jar, so you won't have to do so much typing when you invoke it from the command line (for example, as in java -jar bnd.jar Cmd Options)

To learn more about the Bnd tool, consult the following references:

PK HAk6LO4O4OEBPS/DeployJar-Convert.html Converting a JAR Using Bnd

Converting a JAR Using Bnd

This section describes how to convert a vanilla JAR file into an OSGi bundle using the Bnd tool's wrap command. You can choose either to perform the conversion with default settings (which works in most cases) or to perform a custom conversion with the help of a Bnd properties file.

To demonstrate how to convert a plain JAR into a bundle, we will consider the example of the commons-logging-Version.jar, which is available from the Apache Commons project and can be downloaded from the following location:

http://commons.apache.org/downloads/download_logging.cgi
[Note]Note

Actually, this is a rather artificial example, because the Apache Commons logging API is not intended to be deployed as an OSGi bundle (which is why it does not have the requisite Manifest headers in the first place). Most of the other JARs from Apache Commons are already provided as bundles.

The Bnd print command is a useful diagnostic tool that displays most of the information about a JAR that is relevant to bundle creation. For example, to print the Manifest headers and package dependencies of the commons logging JAR, you can invoke the Bnd print command as follows:

java -jar bnd.jar print commons-logging-1.1.1.jar

The preceding command produces the following output:

From this output, you can see that the JAR does not define any bundle manifest headers. The output consists of the following sections:

To convert the plain commons logging JAR into an OSGi bundle, invoke the Bnd wrap command as follows:

java -jar bnd.jar wrap commons-logging-1.1.1.jar

The result of running this command is a bundle file, commons-logging-1.1.1.bar, which consists of the original JAR augmented by the Manifest headers required by a bundle.

To display the Manifest headers and package dependencies of the newly created bundle JAR, enter the following Bnd print command:

java -jar bnd.jar print commons-logging-1.1.1.bar

The preceding command should produce output like the following:

[MANIFEST commons-logging-1.1.1-bnd.jar]
Archiver-Version                        Plexus Archiver
Bnd-LastModified                        1263987809524
Build-Jdk                               1.4.2_16
Built-By                                dlg01
Bundle-ManifestVersion                  2
Bundle-Name                             commons-logging-1.1.1
Bundle-SymbolicName                     commons-logging-1.1.1
Bundle-Version                          0
Created-By                              1.5.0_08 (Sun Microsystems Inc.)
Export-Package                          org.apache.commons.logging;uses:="org.ap
ache.commons.logging.impl",org.apache.commons.logging.impl;uses:="org.apache.ava
lon.framework.logger,org.apache.commons.logging,org.apache.log4j,org.apache.log,
javax.servlet"
Extension-Name                          org.apache.commons.logging
Implementation-Title                    Commons Logging
Implementation-Vendor                   Apache Software Foundation
Implementation-Vendor-Id                org.apache
Implementation-Version                  1.1.1
Import-Package                          javax.servlet;resolution:=optional,org.a
pache.avalon.framework.logger;resolution:=optional,org.apache.commons.logging;re
solution:=optional,org.apache.commons.logging.impl;resolution:=optional,org.apac
he.log;resolution:=optional,org.apache.log4j;resolution:=optional
Manifest-Version                        1.0
Originally-Created-By                   Apache Maven
Specification-Title                     Commons Logging
Specification-Vendor                    Apache Software Foundation
Specification-Version                   1.0
Tool                                    Bnd-0.0.384
X-Compile-Source-JDK                    1.2
X-Compile-Target-JDK                    1.1


[IMPEXP]
Import-Package
  javax.servlet                         {resolution:=optional}
  org.apache.avalon.framework.logger    {resolution:=optional}
  org.apache.log                        {resolution:=optional}
  org.apache.log4j                      {resolution:=optional}
Export-Package
  org.apache.commons.logging
  org.apache.commons.logging.impl

[USES]
org.apache.commons.logging              org.apache.commons.logging.impl
org.apache.commons.logging.impl         javax.servlet
                                        org.apache.avalon.framework.logger
                                        org.apache.commons.logging
                                        org.apache.log
                                        org.apache.log4j

By default, the Bnd wrap command behaves as if it was configured to use the following Bnd property file:

Export-Package: * 
Import-Package: AllReferencedPackages

The result of this configuration is that the new bundle imports all of the packages referenced by the JAR (which is almost always what you need) and all of the packages defined in the JAR are exported. Sometimes you might want to hide some of the packages in the JAR, however, in which case you would need to define a custom property file.

If you want to have more control over the way the Bnd wrap command generates a bundle, you can define a Bnd properties file to control the conversion process. For a detailed description of the syntax and capabilities of the Bnd properties file, see the Bnd tool documentation.

For example, in the case of the commons logging JAR, you might decide to hide the org.apache.commons.logging.impl package, while exporting the org.apache.commons.logging package. You could do this by creating a Bnd properties file called commons-logging-1.1.1.bnd and inserting the following lines using a text editor:

version=1.1.1
Export-Package: org.apache.commons.logging;version=${version}
Private-Package: org.apache.commons.logging.impl
Bundle-Version: ${version}

Notice how a version number is assigned to the exported package by substituting the version variable (any properties starting with a lowercase letter are interpreted as variables).

To wrap a JAR file using the custom property file, specify the Bnd properties file using the -properties option of the wrap command. For example, to wrap the vanilla commons logging JAR using the instructions contained in the commons-logging-1.1.1.bnd properties file, enter the following command:

java -jar bnd.jar wrap -properties commons-logging-1.1.1.bnd commons-logging-1.1.1.jar
PK HAUOEBPS/DeployJar-Wrap.html Converting a JAR Using the wrap Scheme

Converting a JAR Using the wrap Scheme

You also have the option of converting a JAR into a bundle using the wrap scheme, which can be prefixed to any existing URL format. The wrap scheme is also based on the Bnd utility.

The wrap scheme has the following basic syntax:

wrap:LocationURL

The wrap scheme can prefix any URL that locates a JAR. The locating part of the URL, LocationURL, is used to obtain the (non-bundlized) JAR and the URL handler for the wrap scheme then converts the JAR automatically into a bundle.

[Note]Note

The wrap scheme also supports a more elaborate syntax, which enables you to customize the conversion by specifying a Bnd properties file or by specifying individual Bnd properties in the URL. Typically, however, the wrap scheme is used just with its default settings.

Because the wrap scheme is based on the Bnd utility, it uses exactly the same default properties to generate the bundle as Bnd does—see Default property file.

The following example shows how you can use a single console command to download the plain commons-logging JAR from a remote Maven repository, convert it into an OSGi bundle on the fly, and then install it and start it in the OSGi container:

karaf@root> osgi:install -s wrap:mvn:commons-logging/commons-logging/1.1.1

Example 14.1 shows how the example-jpa-osgi feature combines the mvn scheme and the wrap scheme in order to download the plain HyperSQL JAR file and convert it to an OSGi bundle on the fly.

The wrap scheme is provided by the Pax project, which is the umbrella project for a variety of open source OSGi utilities. For full documentation on the wrap scheme, see the Wrap Protocol reference page.

PK HA9] ] OEBPS/DeployJar.html Chapter 14. Deploying a Plain JAR

Chapter 14. Deploying a Plain JAR

Bundle Tool (Bnd)
Converting a JAR Using Bnd
Converting a JAR Using the wrap Scheme
PK HAɧh9h9OEBPS/DeploySimple-Access.html Accessing an OSGi Service

Accessing an OSGi Service

This section explains how to generate, build, and deploy a simple OSGi client in the OSGi container. The client finds the simple Hello World service in the OSGi registry and invokes the sayHello() method on it.

In order to generate a project using the Maven Quickstart archetype, you must have the following prerequisites:

The maven-archetype-quickstart archetype creates a generic Maven project, which you can then customize for whatever purpose you like. To generate a Maven project with the coordinates, org.fusesource.example:osgi-client, enter the following command:

mvn archetype:create
-DarchetypeArtifactId=maven-archetype-quickstart
-DgroupId=org.fusesource.example
-DartifactId=osgi-client

The result of this command is a directory, ProjectDir/osgi-client, containing the files for the generated project.

[Note]Note

Be careful not to choose a group ID for your artifact that clashes with the group ID of an existing product! This could lead to clashes between your project's packages and the packages from the existing product (because the group ID is typically used as the root of a project's Java package names).

You must customize the POM file in order to generate an OSGi bundle, as follows:

  1. Follow the POM customization steps described in Generating a Bundle Project.

  2. Because the client uses the HelloWorldSvc Java interface, which is defined in the osgi-service bundle, it is necessary to add a Maven dependency on the osgi-service bundle. Assuming that the Maven coordinates of the osgi-service bundle are org.fusesource.example:osgi-service:1.0-SNAPSHOT, you should add the following dependency to the client's POM file:

    <project ... >
      ...
      <dependencies>
        ...
        <dependency>
            <groupId>org.fusesource.example</groupId>
            <artifactId>osgi-service</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
      </dependencies>
      ...
    </project>

To add a blueprint file to your client project, first create the following sub-directories:

ProjectDir/osgi-client/src/main/resources
ProjectDir/osgi-client/src/main/resources/OSGI-INF
ProjectDir/osgi-client/src/main/resources/OSGI-INF/blueprint

Under the ProjectDir/osgi-client/src/main/resources/OSGI-INF/blueprint directory, use your favorite text editor to create the file, config.xml, and add the XML code from Example 16.6.

Where the reference element creates a reference manager that finds a service of HelloWorldSvc type in the OSGi registry. The bean element creates an instance of the Client class and injects the service reference as the bean property, helloWorldSvc. In addition, the init-method attribute specifies that the Client.init() method is called during the bean initialization phase (that is, after the service reference has been injected into the client bean).

Under the ProjectDir/osgi-client/src/main/java/org/fusesource/example/client directory, use your favorite text editor to create the file, Client.java, and add the Java code from Example 16.7.

The Client class defines a getter and a setter method for the helloWorldSvc bean property, which enables it to receive the reference to the Hello World service by injection. The init() method is called during the bean initialization phase, after property injection, which means that it is normally possible to invoke the Hello World service within the scope of this method.

To install and run the osgi-client project, perform the following steps:

PK HA`w(OEBPS/DeploySimple-Blueprint-Config.html Blueprint Configuration

Blueprint Configuration

Relative to the root of the bundle JAR file, the standard location for blueprint configuration files is the following directory:

OSGI-INF/blueprint

Any files with the suffix, .xml, under this directory are interpreted as blueprint configuration files; in other words, any files that match the pattern, OSGI-INF/blueprint/*.xml.

In the context of a Maven project, ProjectDir, the standard location for blueprint configuration files is the following directory:

ProjectDir/src/main/resources/OSGI-INF/blueprint

Blueprint configuration elements are associated with the following XML namespace:

http://www.osgi.org/xmlns/blueprint/v1.0.0

The root element for blueprint configuration is blueprint, so a blueprint XML configuration file normally has the following outline form:

<?xml version="1.0" encoding="UTF-8"?>
<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  ...
</blueprint>
[Note]Note

In the blueprint root element, there is no need to specify the location of the blueprint schema using an xsi:schemaLocation attribute, because the schema location is already known to the blueprint framework.

There are a few aspects of blueprint configuration that are controlled by headers in the JAR's manifest file, META-INF/MANIFEST.MF, as follows:

If you need to place your blueprint configuration files in a non-standard location (that is, somewhere other than OSGI-INF/blueprint/*.xml), you can specify a comma-separated list of alternative locations in the Bundle-Blueprint header in the manifest file—for example:

Bundle-Blueprint: lib/account.xml, security.bp, cnf/*.xml

Dependencies on an OSGi service are mandatory by default (although this can be changed by setting the availability attribute to optional on a reference element or a reference-list element). Declaring a dependency to be mandatory means that the bundle cannot function properly without that dependency and the dependency must be available at all times.

Normally, while a blueprint container is initializing, it passes through a grace period, during which time it attempts to resolve all mandatory dependencies. If the mandatory dependencies cannot be resolved in this time (the default timeout is 5 minutes), container initialization is aborted and the bundle is not started. The following settings can be appended to the Bundle-SymbolicName manifest header to configure the grace period:

For example, to enable a grace period of 10 seconds, you could define the following Bundle-SymbolicName header in the manifest file:

Bundle-SymbolicName: org.fusesource.example.osgi-client;
 blueprint.graceperiod:=true;
 blueprint.timeout:= 10000

The value of the Bundle-SymbolicName header is a semi-colon separated list, where the first item is the actual bundle symbolic name, the second item, blueprint.graceperiod:=true, enables the grace period and the third item, blueprint.timeout:= 10000, specifies a 10 second timeout.

PK HA ҡ!!)OEBPS/DeploySimple-Blueprint-DefBean.html Defining a Service Bean

Defining a Service Bean

Similarly to the Spring container, the blueprint container enables you to instantiate Java classes using a bean element. You can create all of your main application objects this way. In particular, you can use the bean element to create a Java object that represents an OSGi service instance.

The blueprint bean element is defined in the blueprint schema namespace, http://www.osgi.org/xmlns/blueprint/v1.0.0. The blueprint {http://www.osgi.org/xmlns/blueprint/v1.0.0}bean element should not be confused with the Spring {http://www.springframework.org/schema/beans}bean selement, which has a similar syntax but is defined in a different namespace.

[Note]Note

The Spring DM specification version 2.0 or later, allows you to mix both kinds of bean element under the beans root element, (as long as you define each bean elements using the appropriate namespace prefix).

The blueprint bean element enables you to create objects using a similar syntax to the conventional Spring bean element. One significant difference, however, is that blueprint constructor arguments are specified using the argument child element, in contrast to Spring's constructor-arg child element. The following example shows how to create a few different types of bean using blueprint's bean element:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">

  <bean id="label" class="java.lang.String">
    <argument value="LABEL_VALUE"/>
  </bean>

  <bean id="myList" class="java.util.ArrayList">
    <argument type="int" value="10"/>
  </bean>

  <bean id="account" class="org.fusesource.example.Account">
    <property name="accountName" value="john.doe"/>
    <property name="balance" value="10000"/>
  </bean>
  
</blueprint>

Where the Account class referenced by the last bean example could be defined as follows:

// Java
package org.fusesource.example;

public class Account
{
    private String accountName;
    private int balance;

    public Account () { }

    public void setAccountName(String name) {
        this.accountName = name;
    }

    public void setBalance(int bal) {
        this.balance = bal;
    }
    ...
}

Althought the syntax of the blueprint bean element and the Spring bean element are similar, there are a few differences, as you can see from Table 16.1. In this table, the XML tags (identifiers enclosed in angle brackets) refer to child elements of bean and the plain identifiers refer to attributes.

Where the default value of the blueprint scope attribute is singleton and the default value of the blueprint activation attribute is eager.

For more details on defining blueprint beans, consult the following references:

PK HAx !{C{C+OEBPS/DeploySimple-Blueprint-Exporting.html Exporting a Service

Exporting a Service

This section describes how to export a Java object to the OSGi service registry, thus making it accessible as a service to other bundles in the OSGi container.

To export a service to the OSGi service registry under a single interface name, define a service element that references the relevant service bean, using the ref attribute, and specifies the published interface, using the interface attribute.

For example, you could export an instance of the SavingsAccountImpl class under the org.fusesource.example.Account interface name using the blueprint configuration code shown in Example 16.1.

Where the ref attribute specifies the ID of the corresponding bean instance and the interface attribute specifies the name of the public Java interface under which the service is registered in the OSGi service registry. The classes and interfaces used in this example are shown in Example 16.2

To export a service to the OSGi service registry under multiple interface names, define a service element that references the relevant service bean, using the ref attribute, and specifies the published interfaces, using the interfaces child element.

For example, you could export an instance of the SavingsAccountImpl class under the list of public Java interfaces, org.fusesource.example.Account and org.fusesource.example.SavingsAccount, using the following blueprint configuration code:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/>
  <service ref="savings">
    <interfaces>
      <value>org.fusesource.example.Account</value>
      <value>org.fusesource.example.SavingsAccount</value>
    </interfaces>
  </service>
  ...
</blueprint>
[Note]Note

The interface attribute and the interfaces element cannot be used simultaneously in the same service element. You must use either one or the other.

If you want to export a service to the OSGi service registry under all of its implemented public Java interfaces, there is an easy way of accomplishing this using the auto-export attribute.

For example, to export an instance of the SavingsAccountImpl class under all of its implemented public interfaces, use the following blueprint configuration code:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  <bean id="savings" class="org.fusesource.example.SavingsAccountImpl"/>
  <service ref="savings" auto-export="interfaces"/>
  ...
</blueprint>

Where the interfaces value of the auto-export attribute indicates that blueprint should register all of the public interfaces implemented by SavingsAccountImpl. The auto-export attribute can have the following valid values:

The OSGi service registry also allows you to associate service properties with a registered service. Clients of the service can then use the service properties to search for or filter services. To associate service properties with an exported service, add a service-properties child element that contains one or more beans:entry elements (one beans:entry element for each service property).

For example, to associate the bank.name string property with a savings account service, you could use the following blueprint configuration:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
           xmlns:beans="http://www.springframework.org/schema/beans"
           ...>
  ...
  <service ref="savings" auto-export="interfaces">
    <service-properties>
      <beans:entry key="bank.name" value="HighStreetBank"/>
    </service-properties>
  </service>
  ...
</blueprint>

Where the bank.name string property has the value, HighStreetBank. It is possible to define service properties of type other than string: that is, primitive types, arrays, and collections are also supported. For details of how to define these types, see Controlling the Set of Advertised Properties. in the Spring Reference Guide.

[Note]Note

Strictly speaking, the entry element ought to belong to the blueprint namespace. The use of the beans:entry element in Spring's implementation of blueprint is non-standard.

There are two service properties that might be set automatically when you export a service using the service element, as follows:

If a bundle looks up a service in the service registry and finds more than one matching service, you can use ranking to determine which of the services is returned. The rule is that, whenever a lookup matches multiple services, the service with the highest rank is returned. The service rank can be any non-negative integer, with 0 being the default. You can specify the service ranking by setting the ranking attribute on the service element—for example:

<service ref="savings" interface="org.fusesource.example.Account" ranking="10"/>

If you want to keep track of service registration and unregistration events, you can define a registration listener callback bean that receives registration and unregistration event notifications. To define a registration listener, add a registration-listener child element to a service element.

For example, the following blueprint configuration defines a listener bean, listenerBean, which is referenced by a registration-listener element, so that the listener bean receives callbacks whenever an Account service is registered or unregistered:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" ...>
  ...
  <bean id="listenerBean" class="org.fusesource.example.Listener"/>

  <service ref="savings" auto-export="interfaces">
    <registration-listener
        ref="listenerBean"
        registration-method="register"
        unregistration-method="unregister"/>
  </service>
  ...
</blueprint>

Where the registration-listener element's ref attribute references the id of the listener bean, the registration-method attribute specifies the name of the listener method that receives the registration callback, and unregistration-method attribute specifies the name of the listener method that receives the unregistration callback.

The following Java code shows a sample definition of the Listener class that receives notifications of registration and unregistration events:

// Java
package org.fusesource.example;

public class Listener
{
    public void register(Account service, java.util.Map serviceProperties) {
        ...
    }

    public void unregister(Account service, java.util.Map serviceProperties) {
        ...
    }
}

The method names, register and unregister, are specified by the registration-method and unregistration-method attributes respectively. The signatures of these methods must conform to the following syntax:

PK HAԌ\\+OEBPS/DeploySimple-Blueprint-Importing.html Importing a Service

Importing a Service

This section describes how to obtain and use references to OSGi services that have been exported to the OSGi service registry. Essentially, you can use either the reference element or the reference-list element to import an OSGi service. The key difference between these elements is not (as you might at first be tempted to think) that reference returns a single service reference, while reference-list returns a list of service references. Rather, the real difference is that the reference element is suitable for accessing stateless services, while the reference-list element is suitable for accessing stateful services.

The following models for obtaining OSGi services references are supported:

A reference manager instance is created by the blueprint reference element. This element returns a single service reference and is the preferred approach for accessing stateless services. Figure 16.1 shows an overview of the model for accessing a stateless service using the reference manager.

Beans in the client blueprint container get injected with a proxy object (the provided object), which is backed by a service object (the backing service) from the OSGi service registry. This model explicitly takes advantage of the fact that stateless services are interchangeable, in the following ways:

The contract between the client and the backing service is thus stateless, and the client must not assume that it is always talking to the same service instance. If no matching service instances are available, the proxy will wait for a certain length of time before throwing the ServiceUnavailable exception. The length of the timeout is configurable by setting the timeout attribute on the reference element.

A reference list manager instance is created by the blueprint reference-list element. This element returns a list of service references and is the preferred approach for accessing stateful services. Figure 16.2 shows an overview of the model for accessing a stateful service using the reference list manager.

Beans in the client blueprint container get injected with a java.util.List object (the provided object), which contains a list of proxy objects. Each proxy is backed by a unique service instance in the OSGi service registry. Unlike the stateless model, backing services are not considered to be interchangeable here. In fact, the lifecycle of each proxy in the list is tightly linked to the lifecycle of the corresponding backing service: when a service gets registered in the OSGi registry, a corresponding proxy is synchronously created and added to the proxy list; and when a service gets unregistered from the OSGi registry, the corresponding proxy is synchronously removed from the proxy list.

The contract between a proxy and its backing service is thus stateful, and the client may assume when it invokes methods on a particular proxy, that it is always communicating with the same backing service. It could happen, however, that the backing service becomes unavailable, in which case the proxy becomes stale. Any attempt to invoke a method on a stale proxy will generate the ServiceUnavailable exception.

The simplest way to obtain a stateles service reference is by specifying the interface to match, using the interface attribute on the reference element. The service is deemed to match, if the interface attribute value is a super-type of the service or if the attribute value is a Java interface implemented by the service (the interface attribute can specify either a Java class or a Java interface).

For example, to reference a stateless SavingsAccount service (see Example 16.1), define a reference element as follows:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  
  <reference id="savingsRef"
             interface="org.fusesource.example.SavingsAccount"/>

  <bean id="client" class="org.fusesource.example.client.Client">
    <property name="savingsAccount" ref="savingsRef"/>
  </bean>

</blueprint>

Where the reference element creates a reference manager bean with the ID, savingsRef. To use the referenced service, inject the savingsRef bean into one of your client classes, as shown.

The bean property injected into the client class can be any type that is assignable from SavingsAccount. For example, you could define the Client class as follows:

package org.fusesource.example.client;

import org.fusesource.example.SavingsAccount;

public class Client {
    SavingsAccount savingsAccount;
    
    // Bean properties
    public SavingsAccount getSavingsAccount() {
        return savingsAccount;
    }

    public void setSavingsAccount(SavingsAccount savingsAccount) {
        this.savingsAccount = savingsAccount;
    }
    ...
}

The simplest way to obtain a stateful service reference is by specifying the interface to match, using the interface attribute on the reference-list element. The reference list manager then obtains a list of all the services, whose interface attribute value is either a super-type of the service or a Java interface implemented by the service (the interface attribute can specify either a Java class or a Java interface).

For example, to reference a stateful SavingsAccount service (see Example 16.1), define a reference-list element as follows:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  
  <reference-list id="savingsListRef"
                  interface="org.fusesource.example.SavingsAccount"/>

  <bean id="client" class="org.fusesource.example.client.Client">
    <property name="savingsAccountList" ref="savingsListRef"/>
  </bean>

</blueprint>

Where the reference-list element creates a reference list manager bean with the ID, savingsListRef. To use the referenced service list, inject the savingsListRef bean reference into one of your client classes, as shown.

By default, the savingsAccountList bean property is a list of service objects (for example, java.util.List<SavingsAccount>). You could define the client class as follows:

package org.fusesource.example.client;

import org.fusesource.example.SavingsAccount;

public class Client {
    java.util.List<SavingsAccount> accountList;
    
    // Bean properties
    public java.util.List<SavingsAccount> getSavingsAccountList() {
        return accountList;
    }

    public void setSavingsAccountList(
                    java.util.List<SavingsAccount> accountList
    ) {
        this.accountList = accountList;
    }
    ...
}

To match both the interface and the component name (bean ID) of a stateless service, specify both the interface attribute and the component-name attribute on the reference element, as follows:

<reference id="savingsRef"
           interface="org.fusesource.example.SavingsAccount"
           component-name="savings"/>

To match both the interface and the component name (bean ID) of a stateful service, specify both the interface attribute and the component-name attribute on the reference-list element, as follows:

<reference-list id="savingsRef"
           interface="org.fusesource.example.SavingsAccount"
           component-name="savings"/>

You can select services by matching service properties against a filter. The filter is specified using the filter attribute on the reference element or on the reference-list element. The value of the filter attribute must be an LDAP filter expression. For example, to define a filter that matches when the bank.name service property equals HighStreetBank, you could use the following LDAP filter expression:

(bank.name=HighStreetBank)

To match two service property values, you can use & conjunction, which combines expressions with a logical and.For example, to require that the foo property is equal to FooValue and the bar property is equal to BarValue, you could use the following LDAP filter expression:

(&(foo=FooValue)(bar=BarValue))

For the complete syntax of LDAP filter expressions, see section 3.2.7 of the OSGi Core Specification.

Filters can also be combined with the interface and component-name settings, in which case all of the specified conditions are required to match.

For example, to match a stateless service of SavingsAccount type, with a bank.name service property equal to HighStreetBank, you could define a reference element as follows:

<reference id="savingsRef"
           interface="org.fusesource.example.SavingsAccount"
           filter="(bank.name=HighStreetBank)"/>

To match a stateful service of SavingsAccount type, with a bank.name service property equal to HighStreetBank, you could define a reference-list element as follows:

<reference-list id="savingsRef"
           interface="org.fusesource.example.SavingsAccount"
           filter="(bank.name=HighStreetBank)"/>

By default, a reference to an OSGi service is assumed to be mandatory (see Mandatory dependencies). It is possible, however, to customize the dependency behavior of a reference element or a reference-list element by setting the availability attribute on the element. There are two possible values of the availability attribute: mandatory (the default), means that the dependency must be resolved during a normal blueprint container initialization; and optional, means that the dependency need not be resolved during initialization.

The following example of a reference element shows how to declare explicitly that the reference is a mandatory dependency:

<reference id="savingsRef"
           interface="org.fusesource.example.SavingsAccount"
           availability="mandatory"/>

To cope with the dynamic nature of the OSGi environment—for example, if you have declared some of your service references to have optional availability—it is often useful to track when a backing service gets bound to the registry and when it gets unbound from the registry. To receive notifications of service binding and unbinding events, you can define a reference-listener element as the child of either the reference element or the reference-list element.

For example, the following blueprint configuration shows how to define a reference listener as a child of the reference manager with the ID, savingsRef:

<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0">
  
  <reference id="savingsRef"
             interface="org.fusesource.example.SavingsAccount"
             >
    <reference-listener bind-method="onBind" unbind-method="onUnbind">
      <bean class="org.fusesource.example.client.Listener"/>
    </reference-listener>
  </reference>

  <bean id="client" class="org.fusesource.example.client.Client">
    <property name="savingsAcc" ref="savingsRef"/>
  </bean>

</blueprint>

The preceding configuration registers an instance of org.fusesource.example.client.Listener type as a callback that listens for bind and unbind events. Events are generated whenever the savingsRef reference manager's backing service binds or unbinds.

The following example shows a sample implementation of the Listener class:

package org.fusesource.example.client;

import org.osgi.framework.ServiceReference;

public class Listener {
    
    public void onBind(ServiceReference ref) {
        System.out.println("Bound service: " + ref);
    }
    
    public void onUnbind(ServiceReference ref) {
        System.out.println("Unbound service: " + ref);
    }
    
}

The method names, onBind and onUnbind, are specified by the bind-method and unbind-method attributes respectively. Both of these callback methods take an org.osgi.framework.ServiceReference argument.

PK HA\)^!OEBPS/DeploySimple-Blueprint.html The Blueprint Container

The Blueprint Container

Blueprint Configuration
Defining a Service Bean
Exporting a Service
Importing a Service
PK HA؞%OEBPS/DeploySimple-CamelRegistry.html Integration with Apache Camel

Integration with Apache Camel

Apache Camel provides a simple way to invoke OSGi services using the Bean language. This feature is automatically available whenever a Apache Camel application is deployed into an OSGi container and requires no special configuration.

When a Apache Camel route is deployed into the OSGi container, the CamelContext automatically sets up a registry chain for resolving bean instances: the registry chain consists of the OSGi registry, followed by the blueprint (or Spring) registry. Now, if you try to reference a particular bean class or bean instance, the registry resolves the bean as follows:

Consider the OSGi service defined by the following Java interface, which defines the single method, getGreeting():

// Java
package org.fusesource.example.hello.boston;

public interface HelloBoston {
    public String getGreeting();
}

When defining the bundle that implements the HelloBoston OSGi service, you could use the following blueprint configuration to export the service:

Where it is assumed that the HelloBoston interface is implemented by the HelloBostonImpl class (not shown).

After you have deployed the bundle containing the HelloBoston OSGi service, you can invoke the service from a Apache Camel application using the Java DSL. In the Java DSL, you invoke the OSGi service through the Bean language, as follows:

In the bean command, the first argument is the OSGi interface or class, which must match the interface exported from the OSGi service bundle. The second argument is the name of the bean method you want to invoke. For full details of the bean command syntax, see Bean Integration in Implementing Enterprise Integration Patterns.

[Note]Note

When you use this approach, the OSGi service is implicitly imported. It is not necessary to import the OSGi service explicitly in this case.

In the XML DSL, you can also use the Bean language to invoke the HelloBoston OSGi service, but the syntax is slightly different. In the XML DSL, you invoke the OSGi service through the Bean language, using the method element, as follows:

[Note]Note

When you use this approach, the OSGi service is implicitly imported. It is not necessary to import the OSGi service explicitly in this case.

PK HAӏ==OEBPS/DeploySimple-Publish.html Publishing an OSGi Service

Publishing an OSGi Service

This section explains how to generate, build, and deploy a simple OSGi service in the OSGi container. The service is a simple Hello World Java class and the OSGi configuration is defined using a blueprint configuration file.

In order to generate a project using the Maven Quickstart archetype, you must have the following prerequisites:

The maven-archetype-quickstart archetype creates a generic Maven project, which you can then customize for whatever purpose you like. To generate a Maven project with the coordinates, org.fusesource.example:osgi-service, enter the following command:

mvn archetype:create
-DarchetypeArtifactId=maven-archetype-quickstart
-DgroupId=org.fusesource.example
-DartifactId=osgi-service

The result of this command is a directory, ProjectDir/osgi-service, containing the files for the generated project.

[Note]Note

Be careful not to choose a group ID for your artifact that clashes with the group ID of an existing product! This could lead to clashes between your project's packages and the packages from the existing product (because the group ID is typically used as the root of a project's Java package names).

You must customize the POM file in order to generate an OSGi bundle, as follows:

  1. Follow the POM customization steps described in Generating a Bundle Project.

  2. In the configuration of the Maven bundle plug-in, modify the bundle instructions to export the org.fusesource.example.service package, as follows:

    <project ... >
      ...
      <build>
        ...
        <plugins>
          ...
          <plugin>
            <groupId>org.apache.felix</groupId>
            <artifactId>maven-bundle-plugin</artifactId>
            <extensions>true</extensions>
            <configuration>
              <instructions>
                <Bundle-SymbolicName>${pom.groupId}.${pom.artifactId}</Bundle-SymbolicName>
            	    <Export-Package>org.fusesource.example.service</Export-Package>
              </instructions>
            </configuration>
          </plugin>
        </plugins>
      </build>
      ...
    </project>

Create the ProjectDir/osgi-service/src/main/java/org/fusesource/example/service sub-directory. In this directory, use your favorite text editor to create the file, HelloWorldSvc.java, and add the code from Example 16.3 to it.

Create the ProjectDir/osgi-service/src/main/java/org/fusesource/example/service/impl sub-directory. In this directory, use your favorite text editor to create the file, HelloWorldSvcImpl.java, and add the code from Example 16.4 to it.

The blueprint configuration file is an XML file stored under the OSGI-INF/blueprint directory on the class path. To add a blueprint file to your project, first create the following sub-directories:

ProjectDir/osgi-service/src/main/resources
ProjectDir/osgi-service/src/main/resources/OSGI-INF
ProjectDir/osgi-service/src/main/resources/OSGI-INF/blueprint

Where the src/main/resources is the standard Maven location for all JAR resources. Resource files under this directory will automatically be packaged in the root scope of the generated bundle JAR.

Example 16.5 shows a sample blueprint file that creates a HelloWorldSvc bean, using the bean element, and then exports the bean as an OSGi service, using the service element.

Under the ProjectDir/osgi-service/src/main/resources/OSGI-INF/blueprint directory, use your favorite text editor to create the file, config.xml, and add the XML code from Example 16.5.

To install and run the osgi-service project, perform the following steps:

  1. Build the project—open a command prompt and change directory to ProjectDir/osgi-service. Use Maven to build the demonstration by entering the following command:

    mvn install

    If this command runs successfully, the ProjectDir/osgi-service/target directory should contain the bundle file, osgi-service-1.0-SNAPSHOT.jar.

  2. Install and start the osgi-service bundle—at the Fuse ESB Enterprise console, enter the following command:

    karaf@root> osgi:install -s file:ProjectDir/osgi-service/target/osgi-service-1.0-SNAPSHOT.jar

    Where ProjectDir is the directory containing your Maven projects and the -s flag directs the container to start the bundle right away. For example, if your project directory is C:\Projects on a Windows machine, you would enter the following command:

    karaf@root> osgi:install -s file:C:/Projects/osgi-service/target/osgi-service-1.0-SNAPSHOT.jar
    [Note]Note

    On Windows machines, be careful how you format the file URL—for details of the syntax understood by the file URL handler, see File URL Handler.

  3. Check that the service has been created—to check that the bundle has started successfully, enter the following Fuse ESB Enterprise console command:

    karaf@root> osgi:list

    Somewhere in this listing, you should see a line for the osgi-service bundle, for example:

    [ 236] [Active     ] [Created     ] [       ] [   60] osgi-service (1.0.0.SNAPSHOT)

    To check that the service is registered in the OSGi service registry, enter a console command like the following:

    karaf@root> osgi:ls 236

    Where the argument to the preceding command is the osgi-service bundle ID. You should see some output like the following at the console:

    osgi-service (236) provides:
    ----------------------------
    osgi.service.blueprint.compname = hello
    objectClass = org.fusesource.example.service.HelloWorldSvc
    service.id = 272
    ----
    osgi.blueprint.container.version = 1.0.0.SNAPSHOT
    osgi.blueprint.container.symbolicname = org.fusesource.example.osgi-service
    objectClass = org.osgi.service.blueprint.container.BlueprintContainer
    service.id = 273
PK HAoa a OEBPS/DeploySimple.html Chapter 16. OSGi Services

Chapter 16. OSGi Services

The Blueprint Container
Blueprint Configuration
Defining a Service Bean
Exporting a Service
Importing a Service
Publishing an OSGi Service
Accessing an OSGi Service
Integration with Apache Camel
PK HA"vCC OEBPS/DeployWar-Configuring.html Configuring the Web Container

Configuring the Web Container

Fuse ESB Enterprise automatically deploys WAR files into a Web container, which is implemented by the PAX Web library. You can configure the Web container through the OSGi Configuration Admin service.

The Web container uses the following configuration file:

EsbInstallDir/etc/org.ops4j.pax.web.cfg 

You must create this file, if it does not already exist in the EsbInstallDir/etc/ directory.

By default, the Web container listens on the IP port, 8181. You can change this value by editing the etc/org.ops4j.pax.web.cfg file and setting the value of the org.osgi.service.http.port property, as follows:

# Configure the Web container
org.osgi.service.http.port=8181

The Web container is also used for deploying the Fuse ESB Enterprise Web console. The instructions for securing the Web container with SSL/TLS are identical to the instructions for securing the Web console with SSL/TLS. See Securing the Web Console in Security Guide for details.

The properties that you can set in the Web container's configuration file are defined by the PAX Web library. You can set the following kinds of property:

PK HAz:44OEBPS/DeployWar-Convert.html Converting the WAR Using the war Scheme

Converting the WAR Using the war Scheme

To convert a WAR file into a bundle suitable for deployment in the OSGi container, add the war: prefix to the WAR URL. The PAX War URL handler acts as a wrapper, which adds the requisite manifest headers to the WAR file.

The war scheme has the following basic syntax:

war:LocationURL[?Options]

The location URL, LocationURL, can be any of the location URLs described in Appendix A (for example, an mvn: or a file: URL). Options can be appended to the URL in the following format:

?Option=Value&Option=Value&...

Or if the war URL appears in an XML file:

?Option=Value&amp;Option=Value&amp;...

If the WAR file is stored in a Maven repository, you can deploy it into the OSGi container using the osgi:install command, taking a war:mvn: URL as its argument. For example, to deploy the wicket-example WAR file from a Maven repository, where the application should be accessible from the wicket Web application context, enter the following console command:

karaf@root> install war:mvn:org.apache.wicket/wicket-examples/1.4.7/war?Web-ContextPath=wicket

Alternatively, if the WAR file is stored on the filesystem, you can deploy it into the OSGi container by specifying a war:file: URL. For example, to deploy the WAR file, wicket-example-1.4.6.war, enter the following console command:

karaf@root> install war:file://wicket-examples-1.4.7.war?Web-ContextPath=wicket

The WAR file is automatically installed into a Web container, which listens on the IP port 8181 by default, and the Web container uses the Web application context specified by the Web-ContextPath option. For example, the wicket-example WAR deployed in the preceding examples, would be accessible from the following URL:

http://localhost:8181/wicket

The PAX War URL handler converts a WAR file to a special kind of OSGi bundle, which includes additional Manifest headers to support WAR deployment (for example, the Web-ContextPath Manifest header). By default, the deployed WAR is configured as an isolated bundle (neither importing nor exporting any packages). This mimics the deployment model of a WAR inside a J2EE container, where the WAR is completely self-contained, including all of the JAR files it needs.

For details of the default conversion parameters, see Table A.2.

The PAX War URL handler is layered over Bnd. If you want to customize the bundle headers in the Manifest file, you can either add a Bnd instruction as a URL option or you can specify a Bnd instructions file for the War URL handler to use—for details, see War URL Handler.

In particular, you might sometimes find it necessary to customize the entry for the Bundle-ClassPath, because the default value of Bundle-ClassPath does not include all of the resources in the WAR file (see Table A.2).

Support for running WARs in the OSGi container is provided by the PAX WAR Extender, which monitors each bundle as it starts and, if the bundle contains a web.xml file, automatically deploys the WAR in a Web container. The War Protocol page has the original reference documentation for the War URL handler.

PK HA*/H)OEBPS/DeployWar.html Chapter 9. Deploying a WAR

Chapter 9. Deploying a WAR

Converting the WAR Using the war Scheme
Configuring the Web Container
PK HA5E]FFOEBPS/ESBDeployFabMaven.html Configuring Maven for FAB

Configuring Maven for FAB

FAB requires access to Maven repositories to download dependencies. The Maven configuration of FAB leverages the property settings of the Maven URL handler. This means that any changes to the Maven URL handler will have a ripple effect to other functions of the container. It also means that once a container is moved to a fabric, FAB uses the fabric's Maven proxy to resolve dependencies.

The properties used to configure a Standalone container's Maven URL handler are in the org.ops4j.pax.url.mvn PID. See Mvn URL Handler.

A fabric container will also have a profile assigned to it that contains the org.ops4j.pax.url.mvn PID. This PID should not be modified for purposes of configuring FAB dependency resolution. Instead, you should modify the fabric's Maven proxy as described in Configuring a Fabric's Maven Proxy in Configuring and Running Fuse ESB Enterprise.

If your local Maven repository is in a non-default location, you might find it necessary to configure it explicitly in order to access Maven artifacts that you have built locally. You can change the location of the local repository for a standalone container by setting the org.ops4j.pax.url.mvn PID's org.ops4j.pax.url.mvn.localRepository property to the location of your local Maven repository. Example 6.1 shows the commands.

To customize the list of remote Maven repositories used by a standalone container, add or remove entries appearing in the comma-separated list in the org.ops4j.pax.url.mvn.repositories property value in the org.ops4j.pax.url.mvn.cfg PID.

PK HA'  OEBPS/ESBDeployLocate.html Chapter 4. Locating Dependencies

Chapter 4. Locating Dependencies

Revision History
Understanding Where Fuse ESB Enterprise Bundles are Stored
Locating Maven Artifacts at Build Time
Locating Maven Artifacts at Run Time
Locating Artifacts in a Fabric
Generating a Custom Offline Repository
PK HA=g%OEBPS/ESBDeployLocateOnOrOffline.html Understanding Where Fuse ESB Enterprise Bundles are Stored

Understanding Where Fuse ESB Enterprise Bundles are Stored

Revision History

Fuse ESB Enterprise uses Maven as the primary mechanism for locating features, bundles, and their dependencies. Maven is an inherently online tool and will automatically search remote repositories if it cannot locate a dependency in a local repository. Most of the repositories Maven uses by default are accessed through the Internet. A few of them are also public repositories.

It is important to understand where the bundles for the Fuse ESB Enterprise features are stored to make sure you understand the connectivity requirements for using Fuse ESB Enterprise. It is also useful to know this information so that you understand the potential risks involved. If your systems are not able to connect to the public Internet, you can create either request a copy of the Fuse ESB Enterprise off-line repository or build a repository to be hosted on your local network.

If you start up a Fuse ESB Enterprise console and enter the features:list command you will see a complete list of the available features. The first column of the listing indicates whether each feature is installed or uninstalled. If you run this command immediately after installing Fuse ESB Enterprise, the installed features are the core Fuse ESB Enterprise features. These core features and all of their dependencies are provided in the Fuse ESB Enterprise installation under the EsbInstallDir/system directory.

All of the core features are contained locally to the installation. Maven will not need to access a network to search for anything.

If you run features:list immediately after installing Fuse ESB Enterprise, the features listed as uninstalled are the optional Fuse ESB Enterprise features. The optional features are not provided in the system repository and must be downloaded over a network connection.

The default configuration for a standalone container will look for these in the FuseSource repositories first. If it cannot find some artifacts, it will then begin looking in other repositories such as Maven central and SpringSource's repositories.

If you are working in an environment that does not allow access to the Internet, you need to make sure that all of the Fuse ESB Enterprise features you require are available from internal repositories. One way to achieve this is to create a smaller custom offline repository, which contains just the features and artifacts you need to run your application. For more details, see Generating a Custom Offline Repository.

PK HA,,!OEBPS/ESBDeployLocateRunTime.html Locating Maven Artifacts at Run Time

Locating Maven Artifacts at Run Time

At run time the container strikes a balance between accessing artifacts locally and downloading artifacts from remote repositories. The container will first search all systems local to the container. If it cannot locate the artifacts in a local repository, it will then search remote repositories.

For default features, the artifacts are always stored in the container's system repository. For non-default features, third party bundles, or customer developed bundles, it is likely that Maven will need to search remote repositories to locate the artifacts.

Figure 4.2 shows an overview of the procedure that Fuse ESB Enterprise follows when a feature or bundle is installed at run time.

The steps followed to locate the required Maven artifacts are:

  1. The container searches for artifacts in the system repository.

    This repository contains all of the artifacts provided with the Fuse ESB Enterprise installation. The system repository is located at EsbInstallDir/system.

  2. If an artifact is not available in the system repository, the container searches any other configured default repositories.

    Fuse ESB Enterprise allows you to specify one or more repositories into which you can place artifacts. For example, you could use a shared folder as a default repository that provides an easy way to distribute bundles to remote machines. See Default repositories for details on configuring the default repositories.

  3. If the artifact is not available in the default repositories, the container searches the Maven local repository.

    The default location of the local repository is the .m2/repository/ directory under the user's home directory. See Local repository for details on configuring the local repository.

  4. If the artifact is not available in any of the local repositories, the container searches the remote repositories specified in the Fuse ESB Enterprise configuration.

    The remote repositories are specified by the org.ops4j.pax.url.mvn.repositories property in the org.ops4j.pax.url.mvn. PID. See Remote repositories for details on configuring the remote repositories that the container will check.

    [Note]Note

    If an artifact is found in a remote repository, it is automatically downloaded and installed into the local repository.

The default repositories are a list of repositories that the container always checks first. The list is specified by the org.ops4j.pax.url.mvn.defaultRepositories in the org.ops4j.pax.url.mvn PID. The property's initial setting is a single entry for the container's system repository as shown in Example 4.1.

The org.ops4j.pax.url.mvn.defaultRepositories property is a comma-separated list, so you can specify multiple default repositories. You can specify the repository location using a URL with a file:, http:, or https: scheme. You can optionally add the following suffixes to the URL:

[Tip]Tip

It is recommended that you leave the container's system repository as the first entry in the list.

The container resolves the location of the local repository in the following manner:

  1. Use the location specified by the org.ops4j.pax.url.mvn.localRepository.localRepository property in the org.ops4j.pax.url.mvn PID.

  2. Otherwise, use the location specified by the localRepository element in the settings.xml file specified by the org.ops4j.pax.url.mvn.localRepository.settings property in the org.ops4j.pax.url.mvn PID.

  3. Otherwise, use the location specified by the localRepository element in the .m2/settings.xml file located under the user's home directory.

  4. Otherwise, use the location specified by the localRepository element in the M2_HOME/conf/settings.xml file.

  5. Otherwise, the default location is .m2/repository/ under the user's home directory.

The remote repositories checked by the container are specified by the org.ops4j.pax.url.mvn.repositories property in the org.ops4j.pax.url.mvn PID. The repositories are specified as a comma-separated list as shown in Example 4.2.

You can optionally add the following suffixes to the URsL:

PK HA̖fHHOEBPS/ESBMavenOSGiConfig.html Configuring the Bundle Plug-In

Configuring the Bundle Plug-In

A bundle plug-in requires very little information to function. All of the required properties use default settings to generate a valid OSGi bundle.

While you can create a valid bundle using just the default values, you will probably want to modify some of the values. You can specify most of the properties inside the plug-in's instructions element.

Some of the commonly used configuration properties are:

By default, the bundle plug-in sets the value for the Bundle-SymbolicName property to groupId + "." + artifactId, with the following exceptions:

  • If groupId has only one section (no dots), the first package name with classes is returned.

    For example, if the group Id is commons-logging:commons-logging, the bundle's symbolic name is org.apache.commons.logging.

  • If artifactId is equal to the last section of groupId, then groupId is used.

    For example, if the POM specifies the group ID and artifact ID as org.apache.maven:maven, the bundle's symbolic name is org.apache.maven.

  • If artifactId starts with the last section of groupId, that portion is removed.

    For example, if the POM specifies the group ID and artifact ID as org.apache.maven:maven-core, the bundle's symbolic name is org.apache.maven.core.

To specify your own value for the bundle's symbolic name, add a Bundle-SymbolicName child in the plug-in's instructions element, as shown in Example 11.2.

By default, a bundle's name is set to ${project.name}.

To specify your own value for the bundle's name, add a Bundle-Name child to the plug-in's instructions element, as shown in Example 11.3.

By default, a bundle's version is set to ${project.version}. Any dashes (-) are replaced with dots (.) and the number is padded up to four digits. For example, 4.2-SNAPSHOT becomes 4.2.0.SNAPSHOT.

To specify your own value for the bundle's version, add a Bundle-Version child to the plug-in's instructions element, as shown in Example 11.4.

By default, the OSGi manifest's Export-Package list is populated by all of the packages in your local Java source code (under src/main/java), except for the deault package, ., and any packages containing .impl or .internal.

[Important]Important

If you use a Private-Package element in your plug-in configuration and you do not specify a list of packages to export, the default behavior includes only the packages listed in the Private-Package element in the bundle. No packages are exported.

The default behavior can result in very large packages and in exporting packages that should be kept private. To change the list of exported packages you can add an Export-Package child to the plug-in's instructions element.

The Export-Package element specifies a list of packages that are to be included in the bundle and that are to be exported. The package names can be specified using the * wildcard symbol. For example, the entry com.fuse.demo.* includes all packages on the project's classpath that start with com.fuse.demo.

You can specify packages to be excluded be prefixing the entry with !. For example, the entry !com.fuse.demo.private excludes the package com.fuse.demo.private.

When excluding packages, the order of entries in the list is important. The list is processed in order from the beginning and any subsequent contradicting entries are ignored.

For example, to include all packages starting with com.fuse.demo except the package com.fuse.demo.private, list the packages using:

!com.fuse.demo.private,com.fuse.demo.*

However, if you list the packages using com.fuse.demo.*,!com.fuse.demo.private, then com.fuse.demo.private is included in the bundle because it matches the first pattern.

If you want to specify a list of packages to include in a bundle without exporting them, you can add a Private-Package instruction to the bundle plug-in configuration. By default, if you do not specify a Private-Package instruction, all packages in your local Java source are included in the bundle.

[Important]Important

If a package matches an entry in both the Private-Package element and the Export-Package element, the Export-Package element takes precedence. The package is added to the bundle and exported.

The Private-Package element works similarly to the Export-Package element in that you specify a list of packages to be included in the bundle. The bundle plug-in uses the list to find all classes on the project's classpath that are to be included in the bundle. These packages are packaged in the bundle, but not exported (unless they are also selected by the Export-Package instruction).

Example 11.5 shows the configuration for including a private package in a bundle

By default, the bundle plug-in populates the OSGi manifest's Import-Package property with a list of all the packages referred to by the contents of the bundle.

While the default behavior is typically sufficient for most projects, you might find instances where you want to import packages that are not automatically added to the list. The default behavior can also result in unwanted packages being imported.

To specify a list of packages to be imported by the bundle, add an Import-Package child to the plug-in's instructions element. The syntax for the package list is the same as for the Export-Package element and the Private-Package element.

[Important]Important

When you use the Import-Package element, the plug-in does not automatically scan the bundle's contents to determine if there are any required imports. To ensure that the contents of the bundle are scanned, you must place an * as the last entry in the package list.

Example 11.6 shows the configuration for specifying the packages imported by a bundle

For more information on configuring a bundle plug-in, see:

PK HA8""OEBPS/ESBOSGiIntro-Esb.html Fuse ESB Enterprise

Fuse ESB Enterprise

Fuse ESB Enterprisehas the following layered architecture:

Figure 10.1 shows the architecture of Fuse ESB.

Fuse ESB is based on Apache Karaf, a powerful, lightweight, OSGi-based runtime container for deploying and managing bundles to facilitate componentization of applications. Fuse ESB also provides native OS integration and can be integrated into the operating system as a service so that the lifecycle is bound to the operating system.

As shown in Figure 10.1, Fuse ESB extends the OSGi layers with:

PK HAj[OEBPS/ESBOSGiIntro.html Chapter 10. Introduction to OSGi

Chapter 10. Introduction to OSGi

Fuse ESB Enterprise
OSGi Framework
OSGi Services
OSGi Bundles
PK HANOEBPS/ESBOSGiIntroEsbArch.html Fuse ESB Enterprise Container Architecture

Fuse ESB Enterprise Container Architecture

Revision History

Figure 1.1 shows a high-level overview of the Fuse ESB Enterprise container architecture, showing the variety of deployment models that are supported.

Fuse ESB Enterprise is a multi-faceted container that supports a variety of deployment models. You can deploy any of the following kinds of deployment unit:

OSGi bundle

An OSGi bundle is a JAR file augmented with metadata in the JAR's META-INF/MANIFEST.MF file. Because the Fuse ESB Enterprise container is fundamentally an OSGi container, the OSGi bundle is also the native format for the container. Ultimately, after deployment, all of the other deployment unit types are converted into OSGi bundles.

Fuse Application Bundle, FAB

A Fuse Application Bundle (FAB) is a Fuse-specific deployment unit optimised for the Fuse ESB Enterprise container. FABs are a plain JAR built using the Apache Maven. FABs address some of the issues when using OSGi such as dependency resolution and class-loader conflicts. The FAB deployer in Fuse ESB Enterprise scans the metadata in the POM and automatically downloads any dependencies needed by the bundle.

WAR

A Web application ARchive (WAR) is the standard archive format for applications that run inside a Web server. As originally conceived by the Java servlet specification, a WAR packages Web pages, JSP pages, Java classes, servlet code, and so on, as required for a typical Web application. More generally, however, a WAR can be any deployment unit that obeys the basic WAR packaging rules (which, in particular, require the presence of a Web application deployment descriptor, web.xml).

JBI service assembly

A Java Business Integration (JBI) service assembly is the basic unit of deployment for JBI applications. A discussion of the JBI container lies outside the scope of this document. For details, see Using Java Business Integration.

The Spring framework is a popular dependency injection framework, which is fully integrated into the Fuse ESB Enterprise container. In other words, Spring enables you to create instances of Java objects and wire them together by defining a file in XML format. In addition, you can also access a wide variety of utilities and services (such as security, persistence, and transactions) through the Spring framework.

The blueprint framework is a dependency injection framework defined by the OSGi Alliance. It is similar to Spring (in fact, it was originally sponsored by SpringSource), but is a more lightweight framework that is optimized for the OSGi environment.

At its heart, Fuse ESB Enterprise is an OSGi container, based on Apache Karaf, whose architecture is defined by the OSGi Service Platform Core Specification (available from http://www.osgi.org/Release4/Download). OSGi is a flexible and dynamic container, whose particular strengths include: sophisticated management of version dependencies; sharing libraries between applications; and support for dynamically updating libraries at run time (hot fixes).

For more details about the OSGi framework, see Introduction to OSGi.

The Fuse ESB Enterprise kernel extends the core framework of OSGi, adding features such as the runtime console, administration, logging, deployment, provisioning, management, and so on. For more details, see Fuse ESB Enterprise.

PK HAQl1yyOEBPS/FESBDeployActiveMQ.html Chapter 17. JMS Broker

Chapter 17. JMS Broker

Revision History
Working with the Default Broker
JMS Endpoints in a Router Application
PK HA(V"OEBPS/FESBDeployDefaultBroker.html Working with the Default Broker

Working with the Default Broker

Revision History

When you deploy an Fuse ESB Enterprise instance, whether as a standalone container or as a part of a fabric, the default behavior is for a Apache ActiveMQ instance to be started in the container. The default broker creates an Openwire port that listens on port 61616. The broker remains installed in the container and activates whenever you restart the container.

The default broker's configuration is controlled by two files:

  • etc/activemq.xml—a standard Apache ActiveMQ configuration file that serves as a template for the default broker's configuration. It contains property place holders, specified using the syntax ${propName}, that allow you to set the values of the actual property using the OSGi Admin service.

  • etc/org.fusesource.mq.fabric.server-default.cfg—the OSGi configuration file that specifies the values for the properties in the broker's template configuration file.

For details on how to edit the default broker's configuration see Editing a Broker's Configuration in Managing and Monitoring a Broker.

The default broker's data is stored in data/activemq. You can change this location using the config command to change the broker's data property as shown in Example 17.1.

If you decide that you don't want to use the default broker, you can disable it by removing it's OSGi configuration file:

It is important to do both steps. Step 1 removes the broker from the running container and its cached deployment information. Step 2 removes the broker's configuration from the file system and ensures that it will not be automatically reloaded if the container is restarted.

For more information about working with the included Apache ActiveMQ distribution, see Managing and Monitoring a Broker.

PK HA7X5!!OEBPS/FESBIntroFabric.html Fuse Fabric

Fuse Fabric

Fuse Fabric is a technology layer that allows a group of containers to form a cluster that shares a common set of configuration information and a common set of repositories from which to access runtime artifacts. Fabric containers are managed by a Fabric Agent that installs a set of bundles that are specified in the profiles assigned to the container. The agent requests artifacts from the Fabric Ensemble. The ensemble has a list of repositories that it can access. These repositories are managed using a Maven proxy and include a repository that is local to the ensemble.

The added layer imposed on fabric containers does not change the basic deployment models, but it does impact how you specify what needs to be deployed. It also impacts how dependencies are located.

In a fabric container, you cannot directly deploy bundles to a container. A container's configuration is managed by a Fabric Agent that updates its contents and configuration based on one or more profiles. So to add a bundle to a container, you must either add the bundle to an existing profile or create a new profile containing the bundle. When the profile is applied to a container the Fuse Agent will install the bundle.

The installation process will download the bundle from a Maven repository and use the appropriate install command to load it into the container. Once the bundle is installed, the dependency resolution process proceeds as it would in a standalone container.

While installing bundles to a fabric container is not radically different from installing bundles in a standalone container, there are a number of things to consider when thinking about creating profiles to deploy your applications:

PK HA{K!!OEBPS/FESBLocateFabric.html Locating Artifacts in a Fabric

Locating Artifacts in a Fabric

Fabric containers also use Maven to locate artifacts, however they do so in a more constrained manner than a standalone container. Fabric containers use Maven through the fabric's Maven proxy and never search the local repository of the system on which it is running.

The Maven proxy attempts to strike a similar balance between accessing artifacts locally and accessing artifacts from remote repositories, however it changes the scope of local and remote. For default features, the artifacts are always stored in the fabric's system repository which is maintained by the fabric's ensemble servers. For non-default features, third party bundles, or customer developed bundles, it is likely that Maven will need to search remote repositories that are outside of the fabric to locate the artifacts.

Figure 4.3 shows an overview of the procedure that a fabric container follows when a feature or bundle is installed.

The steps followed to locate the required Maven artifacts are:

Because fabric containers generally do not check a repository local to the machine on which it is running, you must load all of an application's artifacts into a repository that the fabric's Maven proxy knows about. There are two ways to do this:

PK HA9OEBPS/FabTutorial.html Chapter 7. FAB Tutorial

Chapter 7. FAB Tutorial

Generating and Running an EIP FAB
PK HA XXOEBPS/Injection.html Chapter 2. Dependency Injection Frameworks

Chapter 2. Dependency Injection Frameworks

Spring and Blueprint Frameworks
Hot Deployment
Using OSGi Configuration Properties
PK HAOEBPS/IntroEsb-Async.html Asynchronous Communication

Asynchronous Communication

Fuse ESB Enterprise supports two alternative mechanisms of asynchronous communication within the container: the JMS broker and the NMR bus.

You can optionally install a broker instance, typically Apache ActiveMQ, into the Fuse ESB Enterprise container, to provide support for asynchronous communication between bundles in the container. Apache ActiveMQ is a sophisticated implementation of a JMS broker, which supports asynchronous communication using either queues or topics (publish-subscribe model). Some of the basic features of this JMS broker are as follows:

For details of how to set up a JMS broker in Fuse ESB Enterprise, see JMS Broker.

The Normalized Message Router (NMR) bus is an asynchronous messaging system that was originally developed in the context of the JBI standard. In the original specification of the NMR, the message was required to be in XML format and the destination addresses were required to conform to specific URI formats.

The NMR in Fuse ESB Enterprise, however, has been modified from the original JBI specification. Although you can still use the NMR in the standard way in the context of the JBI container, there are some important differences when you use the NMR in the context of the OSGi container. In the context of OSGi, the NMR bus is much less restrictive, in particular:

PK HAnOEBPS/IntroEsb-Deployment.html Deployment Models

Deployment Models

Revision History

Although Fuse ESB Enterprise is an OSGi container at heart, it supports a variety of different deployment models. You can think of these as virtual containers, which hide the details of the OSGi framework. In this section we compare the deployment models to give you some idea of the weaknesses and strengths of each model.

Table 1.1 shows an overview of the package types associated with each deployment model.

Figure 1.2 gives an overview of what happens when you install an OSGi bundle into the Fuse ESB Enterprise container, where the bundle depends on several other bundles.

Implicitly, a bundle shares all of its dependencies. This is a flexible approach to deployment, which minimizes resource consumption. But it also introduces a degree of complexity when working with large applications. A bundle does not automatically load all of its requisite dependencies, so a bundle might fail to resolve, due to missing dependencies. The recommended way to remedy this is to use features to deploy the bundle together with its dependencies (see Deploying Features).

Figure 1.3 gives an overview of what happens when you install a typical FAB into the Fuse ESB Enterprise container (where it is assumed that all of the FAB's dependencies are either FABs or plain JARs).

After you install the FAB into the Fuse ESB Enterprise container, the runtime analyzes the metadata embedded in the FAB and automatically installs the requisite dependencies by pulling them from your local Maven repository (or, if necessary, by downloading them from a remote repository).

Figure 1.4 gives an overview of what happens when you install a WAR into the Fuse ESB Enterprise container.

The WAR has a relatively simple deployment model, because the WAR is typically packaged together with all of its dependencies. Hence, the container usually does not have to do any work to resolve the WAR's dependencies. The drawback of this approach, however, is that the WAR is typically large and it duplicates libraries already available in the container (thus consuming more resources).

PK HAhmWWOEBPS/IntroEsb-IOC.html Dependency Injection Frameworks

Dependency Injection Frameworks

Revision History

Dependency injection or inversion of control (IOC) is a design paradigm for initializing and configuring applications. Instead of writing Java code that explicitly finds and sets the properties and attributes required by an object, you declare setter methods for all of the properties and objects that this object depends on. The framework takes responsibility for injecting dependencies and properties into the object, using the declared setter methods. This approach reduces dependencies between components and reduces the amount of code that must be devoted to retrieving configuration properties.

There are many popular dependency injection frameworks in current use. In particular, the Spring framework and the blueprint framework are fully integrated with Fuse ESB Enterprise.

One of the important characteristics of the OSGi framework is that it is extensible. OSGi provides a framework extension API, which makes it possible to implement OSGi plug-ins that are tightly integrated with the OSGi core. An OSGi extension can be deployed into the OSGi container as an extension bundle, which is a special kind of bundle that enjoys privileged access to the OSGi core framework.

Fuse ESB Enterprise defines extension bundles to integrate the following dependency injection frameworks with OSGi:

The framework extension mechanism enables both the Spring extensor and the blueprint extensor to be integrated with the bundle lifecycle. In particular, the extenders receive notifications whenever a bundle is activated (using the command, osgi:start) or de-activated (using the command, osgi:stop). This gives the extenders a chance to scan the bundle, look for configuration files of the appropriate type and, if necessary, activate the dependency injection framework for that bundle.

For example, when you activate a bundle that is configured using Spring, the blueprint extensor scans the bundle package, looking for any blueprint XML files in the standard location and, if it finds one or more such files, activates the blueprint framework for this bundle.

The blueprint extensor searches a bundle for blueprint XML files whose location matches the following pattern:

OSGI-INF/blueprint/*.xml
[Note]Note

A blueprint XML file can also be placed in a non-standard location, by specifying the location in a bundle header (see Custom Blueprint file locations).

The Spring extensor searches a bundle for Spring XML files whose location matches the following pattern:

META-INF/spring/*.xml
[Note]Note

A WAR package uses a different mechanism to specify the location of Spring XML files (see Bootstrapping a Spring Context in a WAR).

PK HApOEBPS/IntroEsb-Sync.html Synchronous Communication

Synchronous Communication

Synchronous communication between bundles in the OSGi container is realized by publishing a Java object as an OSGi service. Clients of the OSGi service can then invoke the methods of the published object.

An OSGi service is a plain Java object, which is published to make it accessible to other bundles deployed in the OSGi container. Other bundles then bind to the Java object and invoke its methods synchronously, using the normal Java syntax. OSGi services thus support a model of synchronous communication between bundles.

One of the strengths of this model is that the OSGi service is a perfectly ordinary Java object. The object is not required to inherit from specific interfaces nor is it required to have any annotations. In other words, your application code is not polluted by the OSGi deployment model.

To publish an OSGi service, you must register it in the OSGi registry. The OSGi specification defines a Java API for registering services, but the simplest way to publish an OSGi service is to exploit the special syntax provided by the blueprint framework. Use the blueprint service element to register a Java object in the OSGi registry. For example, to create a SavingsAccountImpl object and export it as an OSGi service (exposing it through the org.fusesource.example.Account Java interface)

Another bundle in the container can then bind to the published OSGi service, by defining a blueprint reference element that searches the OSGi registry for a service that supports the org.fusesource.example.Account interface.

For more details, see Defining a Service Bean.

[Note]Note

Spring XML also supports the publication and binding of OSGi services.

Another important feature of OSGi services is that they are tightly integrated with the bundle lifecycle. When a bundle is activated (for example, using the console command, osgi:start), its OSGi services are published to the OSGi registry. And when a bundle is de-activated (for example, using the console command, osgi:stop), its OSGi services are removed from the OSGi registry. Clients of a service can elect to receive notifications whenever a service is published to or removed from the OSGi registry.

Consequently, the presence or absence of an OSGi service in the registry can serve as a flag that signals to other bundles whether or not a particular bundle is available (active). With appropriate programming, clients can thus be implemented to respond flexibly as other bundles are uninstalled and re-installed in the container. For example, a client could be programmed to suspend certain kinds of processing until a bundle is re-activated, thus facilitating dynamic reconfiguration or updating of that dependent bundle.

PK HAOE;OEBPS/IntroEsb.html Chapter 1. Fuse ESB Enterprise Overview

Chapter 1. Fuse ESB Enterprise Overview

Revision History
Fuse ESB Enterprise Container Architecture
Deployment Models
Dependency Injection Frameworks
Synchronous Communication
Asynchronous Communication
Fuse Fabric
PK HA/OEBPS/Locate-BuildTime.html Locating Maven Artifacts at Build Time

Locating Maven Artifacts at Build Time

This section explains how Maven locates artifacts at build time. Essentially, Maven implements a simple caching scheme: artifacts are downloaded from remote repositories on the Internet and then cached in the local repository. Figure 4.1 shows an overview of the procedure that Maven follows when locating artifacts at build time.

While building a project, Maven locates required artifacts (dependencies, required plug-ins, and so on) as follows:

You can configure the following kinds of repository for locating Maven artifacts at build time:

Maven resolves the location of the local repository, by checking the following settings:

Maven enables you to specify the location of internal repositories either in your settings.xml file (which applies to all projects) or in a pom.xml (which applies to that project only). Typically, the location of an internal repository is specified using either a file:// URL or a http:// URL (assuming you have set up a local Web server to serve up the artifacts) and you should generally ensure that internal repositories are listed before remote repositories. Otherwise, there is nothing special about an internal repository: it is just a repository that happens to be located in your internal network.

For an example of how to specify a repository in your settings.xml file, see Adding the FuseSource repository.

Remote repositories are configured in the same way as internal repositories, except that they should be listed after any internal repositories.

PK HA+Y+YOEBPS/Locate-CustomRepo.html Generating a Custom Offline Repository

Generating a Custom Offline Repository

When you move from the development phase of a project to the deployment phase, it is typically more convenient to pre-install all of the artifacts required by your application, rather than downloading them from the Internet on demand. In this case, the ideal solution is to create a custom offline repository, which contains the artifacts needed for your deployment. Creating a custom offline repository by hand, however, would be difficult, because it would need to include all of the transitive dependencies associated with your application bundles and features.

The ideal way to create a custom offline repository is to generate it, with the help of the Apache Karaf features-maven-plugin plug-in.

The features-maven-plugin plug-in from Apache Karaf is a utility that is used internally by the Apache Karaf developer community and the Fuse ESB Enterprise development team to create distributions of the Apache Karaf OSGi container. Some of the goals of this plug-in are also useful for application developers, however, and this section explains how you can use the add-features-to-repo goal to generate your own custom offline repository.

[Important]Important

At present, only the add-features-to-repo goal of the features-maven-plugin plug-in is supported.

To generate and install a custom offline repository for specific Apache Karaf features, perform the following steps:

In a convenient location—for example, ProjectDir—create a new directory, ProjectDir/custom-repo to hold the Maven project. Using a text editor, create the project's POM file, pom.xml, in the custom-repo directory and add the following contents to the file:

This is the bare bones of a Maven POM, which will be added to in the following steps. There is no need to specify a Maven package type here (it defaults to jar), because no package will be generated for this project.

Continue editing the pom.xml and add the features-maven-plugin as shown (where the build element is inserted as a child of the project element):

Subsequent steps will explain how to specify the descriptor list (of features repositories) and the features list.

In this example scenario, it is assumed that you want to make the camel-jms feature and the camel-quartz feature available in offline mode. List all of the features you want to download and store in the offline repository in the features element, which is a child of the configuration element of the features-maven-plugin.

To make the camel-jms and camel-quartz features available offline, add the following features element as a child of the feature-maven-plugin's configuration element:

A feature repository is a location that stores feature descriptor files. Generally, because features can depend recursively on other features and because of the complexity of the dependency chains, the project normally requires access to all of the standard Fuse ESB Enterprise feature repositories.

To see the full list of standard feature repositories used by your installation of Fuse ESB Enterprise, open the etc/org.apache.karaf.features.cfg configuration file and look at the featuresRepository setting, which is a comma-separated list of feature repositories, like the following:

Now, add the listed feature repositories to the configuration of the features-maven-plugin in your POM file. Open the project's pom.xml file and add a descriptor element (as a child of the descriptors element) for each of the standard feature repositories. For example, given the preceding value of the featuresRepositories list, you would define the features-maven-plugin descriptors list in pom.xml as follows:

Add the Fuse ESB Enterprise system repository, EsbInstallDir/system, to the list of repositories in the pom.xml file. This is necessary for two reasons: first of all, it saves you from downloading Maven artificats that are already locally available from your Fuse ESB Enterprise installation; and secondly, some of the artifacts in the system repository might not be available from any of the other repositories.

Using a text editor, open pom.xml and add the following repositories element as a child of the project element, customizing the file URL to point at your local system repository:

Generally, the project requires access to all of the standard Fuse ESB Enterprise remote repositories. To see the full list of standard remote repositories, open the etc/org.ops4j.pax.url.mvn.cfg configuration file and look at the org.ops4j.pax.url.mvn.repositories setting, which is a comma-separated list of URLs like the following:

Each entry in this list must be converted into a repository element, which is then inserted as a child element of the respositories element in the project's pom.xml file. The preceding repository URLs have slightly different formats and must be converted as follows:

RepoURL

The value of the repository URL, RepoURL, is inserted directly into the url child element of the repository element. For example, the http://repo1.maven.org/maven2 repository URL translates to the following repository element:

<repository>
  <!-- 'id' can be whatever you like -->
  <id>repo1.maven.org</id>
  <!-- 'name' can be whatever you like -->
  <name>Maven central</name>
  <url>http://repo1.maven.org/maven2</url>
  <snapshots>
    <enabled>false</enabled>
  </snapshots>
  <releases>
    <enabled>true</enabled>
  </releases>
</repository>
RepoURL@snapshots

The @snapshots suffix indicates that downloading snapshots should be enabled for this repository. When specifying the value of the url element, remove the @snapshots suffix from the URL. Change the snapshots/enabled flag to true, as shown in the following example:

<repository>
  <id>IdOfRepo</id>
  <name>LongNameOfRepo</name>
  <url>RepoURL</url>
  <snapshots>
    <enabled>true</enabled>
  </snapshots>
  <releases>
    <enabled>true</enabled>
  </releases>
</repository>
RepoURL@snapshots@noreleases

The combination of the @snapshots suffix and the @noreleases suffix indicates that downloading snapshots should be enabled and downloading releases should be disabled for this repository. When specifying the value of the url element, remove both suffixes from the URL. Change the snapshots/enabled flag to true and change the releases/enabled flag to false, as shown in the following example:

<repository>
  <id>IdOfRepo</id>
  <name>LongNameOfRepo</name>
  <url>RepoURL</url>
  <snapshots>
    <enabled>true</enabled>
  </snapshots>
  <releases>
    <enabled>false</enabled>
  </releases>
</repository>

To generate the custom offline repository, open a new command prompt, change directory to ProjectDir/custom-repo, and enter the following Maven command:

mvn generate-resources

Assuming that the Maven build completes successfully, the custom offline repository should now be available in the following location:

ProjectDir/custom-repo/target/features-repo

To install the custom offline repository in the Fuse ESB Enterprise container, edit the etc/org.ops4j.pax.url.mvn.cfg file and append the offline repository directory to the list of default repositories, as follows:

org.ops4j.pax.url.mvn.defaultRepositories=file:${karaf.home}/${karaf.default.repository}@snapshots,ProjectDir/custom-repo/target/features-repo@snapshots

The @snapshots suffix can be added to the offline repository URL, if there is a possibility that some of the artifacts in it are snapshot versions.

PK HA!!OEBPS/Nmr-Architecture.html Architecture of the NMR

Architecture of the NMR

Figure 18.1 shows a general overview of the NMR architecture, which spans both the OSGi container and the JBI container.

In Figure 18.1, the NMR is represented as a horizontal graphical element in order to emphasize its role linking together various application bundles. In practice, however, the NMR is deployed as a collection of bundles, just like any other application in the OSGi container.

The Fuse ESB Enterprise NMR is a general-purpose message bus used for transmitting messages between bundles in the OSGi container. It is modelled on the Normalized Message Router (NMR) defined in the Java Business Integration (JBI) specification. Hence, the Fuse ESB Enterprise NMR can be used to transmit XML messages, optionally augmented with properties and attachments.

Unlike the standard NMR, however, the Fuse ESB Enterprise NMR is not restricted to the JBI container. You can use the NMR to transmit messages inside the OSGi container or, if the JBI container is also deployed, to transmit messages between the two containers.

A key feature of the NMR message bus is that messages are transmitted in a standard, normalized form. The JBI standard defines a normalized message, which is based on the Web Services Description Language (WSDL) message format (both WSDL 1.1 and WSDL 2.0 formats are supported). A complete normalized message has the following aspects:

In the OSGi container, normalized messages have a standard layout, as follows:

[Note]Note

When transmitting messages solely within the OSGi container, normalization of message content is not enforced. That is, the OSGi container does not impose any restrictions on the format of the message content. If messages are transmitted to an endpoint in the JBI container, however, message normalization must be observed.

Fuse ESB Enterprise provides a simple Java API for accessing the NMR. You can use this API to define endpoints that process messages received from the NMR and you can write clients that send messages to NMR endpoints. To see how to use this API in practice, take a look at the examples/nmr demonstration code.

To enable integration with the NMR, Apache Camel provides an NMR component, which lets you define NMR endpoints either at the beginning (for example, as in from("nmr:ExampleEndpoint")) or at the end (for example, to("nmr:ExampleEndpoint")) of a route. For full details of how to use the NMR component, see The Apache Camel NMR Component.

[Note]Note

The NMR component is designed specifically for integrating Apache Camel with the NMR within the OSGi container. If you deploy a Apache Camel application in the JBI container, however, NMR integration is provided by the JBI component. The NMR component (for use in an OSGi context) is conventionally identified by the nmr URI scheme, whereas the JBI component (for use in a JBI context) is conventionally identified by the jbi URI scheme.

PK HAW>>OEBPS/Nmr-Component.html The Apache Camel NMR Component

The Apache Camel NMR Component

The NMR component is an adapter to the NMR, enabling Apache Camel applications to send messages to other bundles within the OSGi container or to components within the JBI container.

Normally, the NMR feature is pre-installed in the OSGi container. If you need to install the NMR feature, however, you can do so by entering the following console command:

karaf@root> features:install nmr

To make NMR endpoints available to your Apache Camel application, you need to create an instance of the NMR component. Add the code shown in Example 18.1 to your bundle's Spring configuration file (located in META-INF/spring/*.xml) in order to instantiate the NMR component.

The bean element creates an instance of the NMR component with the bean ID, nmr, where this bean ID can then be used as the scheme prefix to create or reference NMR endpoints in your Apache Camel routes. The bean definition references two external Java packages—org.apache.servicemix.camel.nmr and org.apache.servicemix.nmr.api—which must therefore be imported by this bundle. Because the packages do not occur in Java source code, you must add them explicitly to the list of imported packages in the bundle instructions in the POM—see Configuring the bundle instructions for details.

The NMR component enables you to create endpoints with the following URI format:

nmr:EndpointId

Where EndpointId is a string that identifies the endpoint uniquely. In particular, when used within the OSGi container, the endpoint ID string is not restricted to have any particular format. The scheme prefix, nmr, is actually determined by the ID of the bean that instantiates the NMR component—for example, see Example 18.1.

If you want to use the NMR component to send messages between the OSGi container and the JBI container, you need to be aware that NMR endpoints inside the JBI container requires a special syntax for the endpoint IDs. You can address an NMR endpoint inside the JBI container using the following URI format:

nmr:JBIAddressingURI

Where JBIAddressingURI conforms to the URI format described in ServiceMix URIs.

An NMR consumer endpoint automatically determines the message exchange pattern (for example, In or InOut) from the incoming message and sets the message exchange pattern in the current exchange accordingly.

The camel-nmr demonstration is located in the following directory:

InstallDir/examples/camel-nmr

The demonstration defines two routes in XML, where the routes are joined together using an NMR endpoint, as follows:

The route is deployed into the Fuse ESB Enterprise container as an OSGi bundle.

Example 18.2 shows the routes for the camel-nmr demonstration, taken from the Spring XML configuration file, META-INF/spring/beans.xml.

Example 18.2. Spring XML Defining a Route with an NMR Endpoint

<?xml version="1.0" encoding="UTF-8"?>

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:osgi="http://www.springframework.org/schema/osgi"
       xmlns:camel-osgi="http://camel.apache.org/schema/osgi"
       xsi:schemaLocation="
       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.0.xsd
       http://www.springframework.org/schema/osgi  http://www.springframework.org/schema/osgi/spring-osgi.xsd
       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
       http://camel.apache.org/schema/osgi http://camel.apache.org/schema/osgi/camel-osgi.xsd">

  <import resource="classpath:org/apache/servicemix/camel/nmr/camel-nmr.xml" /> 1

  <camel-osgi:camelContext xmlns="http://camel.apache.org/schema/spring">
    <!-- Route periodically sent events into the NMR -->
    <route>
      <from uri="timer://myTimer?fixedRate=true&amp;period=2000"/>
      <to uri="nmr:ExampleRouter"/> 2
    </route>
    <!-- Route exchange from the NMR endpoint to a log endpoint -->
    <route>
      <from uri="nmr:ExampleRouter"/> 3
      <bean ref="myTransform" method="transform"/>
      <to uri="log:ExampleRouter"/>
    </route>
  </camel-osgi:camelContext>

  <bean id="myTransform" class="org.apache.servicemix.examples.camel.MyTransform">
    <property name="prefix" value="MyTransform"/>
  </bean>

</beans>

1

This Spring import element imports a snippet of XML that instantiates and initializes the NMR component. In fact, the content of this snippet is identical to the XML code shown in Example 18.1.

2

At the end of the first route, messages are sent to the NMR endpoint, nmr:ExampleRouter.

3

When you specify an NMR endpoint in the uri attribute of the <from> tag, a new NMR endpoint is created by the NMR component. In this example, the <from> tag implicitly creates the NMR endpoint, nmr:ExampleRouter, which is then capable of receiving the messages sent by the first route.

Not all of the packages required by the NMR component can be automatically detected by the Maven bundle plug-in. Some of the package dependencies arise from settings in the Spring configuration file (see Example 18.1), which are not automatically taken into account by the bundle plug-in. In particular, you must ensure that the following additional packages are imported by the bundle:

  • org.apache.servicemix.camel.nmr

  • org.apache.servicemix.nmr.api

For example, the following sample configuration of the Maven bundle plug-in shows how to add an Import-Package element that contains a list of the packages required for the NMR component:

<project ...>
    ...
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.felix</groupId>
                <artifactId>maven-bundle-plugin</artifactId>
                <configuration>
                    <instructions>
                        <Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
                        <Import-Package>org.apache.servicemix.camel.nmr,org.apache.servicemix.nmr.api,*</Import-Package>
                    </instructions>
                </configuration>
            </plugin>
        </plugins>
    </build>

</project>

The Import-Package list also includes the wildcard, *, which instructs the bundle plug-in to scan the Java source code in order to discover further package dependencies.

PK HA~c/F F OEBPS/Nmr.html Chapter 18. Inter-Bundle Communication with the NMR

Chapter 18. Inter-Bundle Communication with the NMR

Architecture of the NMR
The Apache Camel NMR Component
PK HACOEBPS/PartAsync.html Part VI. Asynchronous Communication

Asynchronous Communication

Table of Contents

17. JMS Broker
Working with the Default Broker
JMS Endpoints in a Router Application
18. Inter-Bundle Communication with the NMR
Architecture of the NMR
The Apache Camel NMR Component
PK HAOEBPS/PartEsbContainer.html Part I. The Fuse ESB Enterprise Container

The Fuse ESB Enterprise Container

Table of Contents

1. Fuse ESB Enterprise Overview
Fuse ESB Enterprise Container Architecture
Deployment Models
Dependency Injection Frameworks
Synchronous Communication
Asynchronous Communication
Fuse Fabric
2. Dependency Injection Frameworks
Spring and Blueprint Frameworks
Hot Deployment
Using OSGi Configuration Properties
3. Building with Maven
Maven Directory Structure
Preparing to use Maven
4. Locating Dependencies
Understanding Where Fuse ESB Enterprise Bundles are Stored
Locating Maven Artifacts at Build Time
Locating Maven Artifacts at Run Time
Locating Artifacts in a Fabric
Generating a Custom Offline Repository
PK HA\< OEBPS/PartFab.html Part II. The Fuse Application Bundle Deployment Model

The Fuse Application Bundle Deployment Model

Table of Contents

5. Building a FAB
Generating a FAB Project
Class Sharing
Modifying an Existing Maven Project
Configuring a FAB
6. Deploying a FAB
The FAB Deployment Model
FABs and Features
Hot Deployment
Manual Deployment
Configuring Maven for FAB
7. FAB Tutorial
Generating and Running an EIP FAB
PK HAS((OEBPS/PartOsgi.html Part IV. OSGi Bundle Deployment Model

OSGi Bundle Deployment Model

Table of Contents

10. Introduction to OSGi
Fuse ESB Enterprise
OSGi Framework
OSGi Services
OSGi Bundles
11. Building an OSGi Bundle
Generating a Bundle Project
Modifying an Existing Maven Project
Packaging a Web Service in a Bundle
Configuring the Bundle Plug-In
12. Deploying an OSGi Bundle
Hot Deployment
Manual Deployment
Lifecycle Management
Troubleshooting Dependencies
13. Deploying Features
Creating a Feature
Deploying a Feature
14. Deploying a Plain JAR
Bundle Tool (Bnd)
Converting a JAR Using Bnd
Converting a JAR Using the wrap Scheme
15. OSGi Bundle Tutorials
Generating and Running an EIP Bundle
Generating and Running a Web Services Bundle
PK HA- OEBPS/PartSync.html Part V. OSGi Service Layer

OSGi Service Layer

Table of Contents

16. OSGi Services
The Blueprint Container
Blueprint Configuration
Defining a Service Bean
Exporting a Service
Importing a Service
Publishing an OSGi Service
Accessing an OSGi Service
Integration with Apache Camel
PK HAP4OEBPS/PartWar.html Part III. WAR Deployment Model

WAR Deployment Model

Table of Contents

8. Building a WAR
Modifying an Existing Maven Project
Bootstrapping a CXF Servlet in a WAR
Bootstrapping a Spring Context in a WAR
9. Deploying a WAR
Converting the WAR Using the war Scheme
Configuring the Web Container
PK HAO11OEBPS/PaxExam-Introduction.html Introduction to Pax-Exam

Introduction to Pax-Exam

Pax-Exam is an automated testing framework for running tests in an OSGi container. Consider the manual steps that would be needed to run tests in an OSGi container:

Using Pax-Exam you can automate and simplify this testing procedure. Initialization options and provisioning options are performed by a configuration method in the test class. The Pax-Exam framework takes care of starting the OSGi container and before running the test class bundle.

This section gives a brief introduction to the Pax-Exam testing framework and explains how to write a basic example using Apache Karaf.

JUnit 4 is the latest version of the JUnit Java testing suite. What distinguishes JUnit 4 from earlier versions is that JUnit 4 defines a test by applying Java annotations (in contrast to earlier versions of JUnit, which used inherited classes and naming conventions).

The simplest JUnit tests require just two steps:

  1. Specify which methods are the test methods by annotating them with the @org.junit.Test annotation.

  2. At any point in the test method, define an assertion by calling assertTrue() with a boolean argument (you also need to include a static import of org.junit.Assert.assertTrue() in the file). The test succeeds, if the specified assertions all evaluate to true.

To integrate JUnit 4 with Pax-Exam, perform the following steps:

  1. Customize JUnit to run the test in the Pax-Exam test runner class—JUnit allows you to delegate control over a test run to a custom runner class (by defining a runner class that inherits from org.junit.runner.Runner). In order to integrate JUnit with Pax-Exam, add a @RunWith annotation to the test class as follows:

    import org.junit.runner.RunWith;
    import org.ops4j.pax.exam.junit.JUnit4TestRunner;
    ...
    @RunWith(JUnit4TestRunner.class) 
    public class MyTest { 
        ...
    }
  2. Add a Pax-Exam configuration method to the test class—in order to run a test in an OSGi framework, you need to initialize the OSGi container properly and install any prerequisite bundles. These essential steps are performed by returning the appropriate options from the Pax-Exam configuration method. This method is identified by the @Configuration annotation as follows:

    import org.ops4j.pax.exam.junit.Configuration;
    ...
    @Configuration
    public static Option[] configuration() throws Exception {
        ...
    }
  3. Use the Pax-Exam fluent API to configure the OSGi framework—there are a fairly large number of settings and options that you can return from the Pax-Exam configuration method. In order to define these options efficiently, Pax-Exam provides a fluent API, which is defined mainly by the following classes:

Theoretically, Pax-Exam provides all of the features that are needed to run an OSGi framework embedded in Apache Karaf. In practice, however, there are a lot of Java system properties and configuration options that need to be set in order to initialize Apache Karaf. It would be a nuisance, if all of these properties and options needed to be specified explicitly in the Pax-Exam configuration method.

In order to simplify running Pax-Exam in Apache Karaf, helper classes are provided, which automatically take care of initializing the OSGi framework for you. The following classes are provided:

Example C.1 shows the Maven dependencies you need in order to run the Pax-Exam testing framework. You must specify dependencies on JUnit 4, Pax-Exam, and Apache Karaf tooling.

This example uses custom properties to specify the versions of the various Maven artifacts.

To learn more about using the Pax-Exam testing framework, consult the following references:

PK HAZ955OEBPS/PaxExam-Sample.html Sample Pax-Exam Test Class

Sample Pax-Exam Test Class

Example C.2 shows an example of how to write a test class for Apache Karaf in the Pax-Exam testing framework. The FeaturesText class configures the Apache Karaf environment, installs the obr and wrapper features, and then runs a test against the two features (where the obr and wrapper features implement particular sets of commands in the Apache Karaf command console).

Example C.2. FeaturesText Class

// Java
/*
 * Licensed to the Apache Software Foundation (ASF)
 * ...
 */
package org.apache.karaf.shell.itests;

import org.apache.karaf.testing.AbstractIntegrationTest;
import org.apache.karaf.testing.Helper;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.ops4j.pax.exam.Option;
import org.ops4j.pax.exam.junit.Configuration;
import org.ops4j.pax.exam.junit.JUnit4TestRunner;
import org.osgi.service.blueprint.container.BlueprintContainer;
import org.osgi.service.command.CommandProcessor;
import org.osgi.service.command.CommandSession;

import static org.junit.Assert.assertNotNull;
import static org.ops4j.pax.exam.CoreOptions.equinox;
import static org.ops4j.pax.exam.CoreOptions.felix;
import static org.ops4j.pax.exam.CoreOptions.maven;
import static org.ops4j.pax.exam.CoreOptions.systemProperty;
import static org.ops4j.pax.exam.CoreOptions.waitForFrameworkStartup;
import static org.ops4j.pax.exam.OptionUtils.combine;
import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.scanFeatures;

import static org.ops4j.pax.exam.container.def.PaxRunnerOptions.workingDirectory;

@RunWith(JUnit4TestRunner.class) 1
public class FeaturesTest extends AbstractIntegrationTest { 2

    @Test 3
    public void testFeatures() throws Exception {
        // Make sure the command services are available
        assertNotNull(getOsgiService(BlueprintContainer.class, "osgi.blueprint.container.symbolicname=org.apache.karaf.shell.obr", 20000));
        assertNotNull(getOsgiService(BlueprintContainer.class, "osgi.blueprint.container.symbolicname=org.apache.karaf.shell.wrapper", 20000));
        // Run some commands to make sure they are installed properly
        CommandProcessor cp = getOsgiService(CommandProcessor.class); 4
        CommandSession cs = cp.createSession(System.in, System.out, System.err);
        cs.execute("obr:listUrl");
        cs.execute("wrapper:install --help");
        cs.close();
    }

    @Configuration 5
    public static Option[] configuration() throws Exception{
        return combine( 6
            // Default karaf environment
            Helper.getDefaultOptions( 7
                // this is how you set the default log level when using pax logging (logProfile)
                systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("DEBUG")),

            // add two features
            scanFeatures( 8
                    maven().groupId("org.apache.karaf").artifactId("apache-felix-karaf").type("xml").classifier("features").versionAsInProject(),
                    "obr", "wrapper"
            ),

            workingDirectory("target/paxrunner/features/"), 9

            waitForFrameworkStartup(), 10
            
            // Test on both equinox and felix
            equinox(), felix() 11
        );
    }

}

1

The @RunWith annotation instructs JUnit 4 to run the following test with the Pax-Exam test runner class, JUnit4TestRunner. This is the key step to integrate JUnit 4 with the Pax-Exam testing framework.

2

In order to integrate this JUnit test properly with Apache Karaf, you are required to derive this test class from org.apache.karaf.testing.AbstractIntegrationTest.

The AbstractIntegrationTest base class also provides some helper methods that access the bundle context: getOsgiService() methods, for obtaining a reference to an OSGi service, and the getInstalledBundle() method, for obtaining a reference to an org.osgi.framework.bundle object.

3

The @Test annotation is a standard JUnit 4 annotation that identifies the following method as a test method that is to be executed in the testing framework.

4

This line gives an example of how to use the getOsgiService() helper method to obtain an OSGi service from the OSGi container. In this example, the service is identified by specifying its Java type, org.osgi.service.command.CommandProcessor. The CommandProcessor service is the Apache Karaf service that has the capability to process console commands.

5

The @Configuration annotation is a Pax-Exam-specific annotation that marks the following the method as the configuration method that sets Pax-Exam testing options. The configuration method must be declared as public static and must have a return value of type, org.ops4j.pax.exam.Option[].

6

The OptionUtils.combine() method combines a given options array (of Option[] type) in the first argument with the options in the remaining arguments, returning an options array that contains all of the options.

7

The getDefaultOptions() method from the org.apache.karaf.testing.Helper class returns an options array containing all of the system property settings and option settings required to initialize Apache Karaf for the Pax-Exam testing framework.

If there are any Java system properties in the Apache Karaf environment that you would like to customize, you can pass the properties as optional arguments to the getDefaultOptions() method. In the example shown here, the system property for the Pax logging level is set to DEBUG.

8

The Pax-Exam framework supports the concept of Apache Karaf features (see Deploying Features). You can use the PaxRunnerOptions.scanFeatures() method to install specific features in the OSGi container before the test is run.

The location of the relevant features repository is specified by passing a Pax URL as the first argument to scanFeatures(). In this example, the URL is constructed by creating a Pax Mvn URL (see Mvn URL Handler) with the fluent API from the CoreOptions class. Subsequent arguments specify which features to install—in this example, the obr and wrapper features.

9

The workingDirectory() option specifies the directory where the Pax Runner provisioning module looks for OSGi bundles.

10

The waitForFrameworkStartup() specifies that the testing framework should wait for a default length of time (five minutes) for the OSGi framework to start up before timing out. To specify the timeout explicitly, you could use the waitForFrameworkStartupFor(long millis) method instead, where the timeout is specified in milliseconds.

11

The options, equinox() and felix(), are used to specify that the test should be run twice: once in the Equinox OSGI framework and once in the Felix OSGi framework. Recall that Apache Karaf is a thin wrapper layer that currently supports both the Equinox framework and the Felix framework.

PK HAhvOEBPS/PaxExam.html Appendix C. Pax-Exam Testing Framework

Appendix C. Pax-Exam Testing Framework

Introduction to Pax-Exam
Sample Pax-Exam Test Class
PK HAj܂ OEBPS/UrlHandlers-File.html File URL Handler

File URL Handler

A file URL has the syntax, file:PathName, where PathName is the relative or absolute pathname of a file that is available on the Classpath. The provided PathName is parsed by Java's built-in file URL handler. Hence, the PathName syntax is subject to the usual conventions of a Java pathname: in particular, on Windows, each backslash must either be escaped by another backslash or replaced by a forward slash.

For example, consider the pathname, C:\Projects\camel-bundle\target\foo-1.0-SNAPSHOT.jar, on Windows. The following example shows the correct alternatives for the file URL on Windows:

file:C:/Projects/camel-bundle/target/foo-1.0-SNAPSHOT.jar
file:C:\\Projects\\camel-bundle\\target\\foo-1.0-SNAPSHOT.jar

The following example shows some incorrect alternatives for the file URL on Windows:

file:C:\Projects\camel-bundle\target\foo-1.0-SNAPSHOT.jar        // WRONG!
file://C:/Projects/camel-bundle/target/foo-1.0-SNAPSHOT.jar      // WRONG!
file://C:\\Projects\\camel-bundle\\target\\foo-1.0-SNAPSHOT.jar  // WRONG!
PK HA6 kOEBPS/UrlHandlers-Http.html HTTP URL Handler

HTTP URL Handler

A HTTP URL has the standard syntax, http:Host[:Port]/[Path][#AnchorName][?Query]. You can also specify a secure HTTP URL using the https scheme. The provided HTTP URL is parsed by Java's built-in HTTP URL handler, so the HTTP URL behaves in the normal way for a Java application.

PK HA8?00OEBPS/UrlHandlers-Maven.html Mvn URL Handler

Mvn URL Handler

If you use Maven to build your bundles or if you know that a particular bundle is available from a Maven repository, you can use the Mvn handler scheme to locate the bundle.

[Tip]Tip

To ensure that the Mvn URL handler can find local and remote Maven artifacts, you might find it necessary to customize the Mvn URL handler configuration. For details, see Configuring the Mvn URL handler.

An Mvn URL has the following syntax:

mvn:[repositoryUrl!]groupId/artifactId[/[version][/[packaging][/[classifier]]]]

Where repositoryUrl optionally specifies the URL of a Maven repository. The groupId, artifactId, version, packaging, and classifier are the standard Maven coordinates for locating Maven artifacts (see Maven coordinates).

When specifying an Mvn URL, only the groupId and the artifactId coordinates are required. The following examples reference a Maven bundle with the groupId, org.fusesource.example, and with the artifactId, bundle-demo:

mvn:org.fusesource.example/bundle-demo
mvn:org.fusesource.example/bundle-demo/1.1

When the version is omitted, as in the first example, it defaults to LATEST, which resolves to the latest version based on the available Maven metadata.

In order to specify a classifier value without specifying a packaging or a version value, it is permissible to leave gaps in the Mvn URL. Likewise, if you want to specify a packaging value without a version value. For example:

mvn:groupId/artifactId///classifier
mvn:groupId/artifactId/version//classifier
mvn:groupId/artifactId//packaging/classifier
mvn:groupId/artifactId//packaging

When specifying the version value in an Mvn URL, you can specify a version range (using standard Maven version range syntax) in place of a simple version number. You use square brackets—[ and ]—to denote inclusive ranges and parentheses—( and )—to denote exclusive ranges. For example, the range, [1.0.4,2.0), matches any version, v, that satisfies 1.0.4 <= v < 2.0. You can use this version range in an Mvn URL as follows:

mvn:org.fusesource.example/bundle-demo/[1.0.4,2.0)

Before using Mvn URLs for the first time, you might need to customize the Mvn URL handler settings, as follows:

The Mvn URL handler resolves a reference to a local Maven repository and maintains a list of remote Maven repositories. When resolving an Mvn URL, the handler searches first the local repository and then the remote repositories in order to locate the specified Maven artifiact. If there is a problem with resolving an Mvn URL, the first thing you should do is to check the handler settings to see which local repository and remote repositories it is using to resolve URLs.

To check the Mvn URL settings, enter the following commands at the console:

karaf@root> config:edit org.ops4j.pax.url.mvn
karaf@root> config:proplist

The config:edit command switches the focus of the config utility to the properties belonging to the org.ops4j.pax.url.mvn persistent ID. The config:proplist command outputs all of the property settings for the current persistent ID. With the focus on org.ops4j.pax.url.mvn, you should see a listing similar to the following:

   org.ops4j.pax.url.mvn.localRepository = file:E:/Data/.m2/repository
   service.pid = org.ops4j.pax.url.mvn
   org.ops4j.pax.url.mvn.defaultRepositories = file:E:/Programs/FUSE/apache-serv
icemix-4.2.0-fuse-SNAPSHOT/system@snapshots
   felix.fileinstall.filename = org.ops4j.pax.url.mvn.cfg
   org.ops4j.pax.url.mvn.repositories = http://repo1.maven.org/maven2, http://re
po.fusesource.com/maven2, http://repo.fusesource.com/maven2-snapshot@snapshots@n
oreleases, http://repository.apache.org/content/groups/snapshots-group@snapshots
@noreleases, http://repository.ops4j.org/maven2, http://svn.apache.org/repos/asf
/servicemix/m2-repo, http://repository.springsource.com/maven/bundles/release, h
ttp://repository.springsource.com/maven/bundles/external

Where the localRepository setting shows the local repository location currently used by the handler and the repositories setting shows the remote repository list currently used by the handler.

To customize the property settings for the Mvn URL handler, edit the following configuration file:

InstallDir/etc/org.ops4j.pax.url.mvn.cfg

The settings in this file enable you to specify explicitly the location of the local Maven repository, remove Maven repositories, Maven proxy server settings, and more. Please see the comments in the configuration file for more details about these settings.

In particular, if your local Maven repository is in a non-default location, you might find it necessary to configure it explicitly in order to access Maven artifacts that you build locally. In your org.ops4j.pax.url.mvn.cfg configuration file, uncomment the org.ops4j.pax.url.mvn.localRepository property and set it to the location of your local Maven repository. For example:

# Path to the local maven repository which is used to avoid downloading
# artifacts when they already exist locally.
# The value of this property will be extracted from the settings.xml file
# above, or defaulted to:
#     System.getProperty( "user.home" ) + "/.m2/repository"
#
org.ops4j.pax.url.mvn.localRepository=file:E:/Data/.m2/repository

For more details about the mvn URL syntax, see the original Pax URL Mvn Protocol documentation.

PK HAgpOEBPS/UrlHandlers-War.html War URL Handler

War URL Handler

If you need to deploy a WAR file in an OSGi container, you can automatically add the requisite manifest headers to the WAR file by prefixing the WAR URL with war:, as described here.

A War URL is specified using either of the following syntaxes:

war:warURL
warref:instructionsURL

The first syntax, using the war scheme, specifies a WAR file that is converted into a bundle using the default instructions. The warURL can be any URL that locates a WAR file.

The second syntax, using the warref scheme, specifies a Bnd properties file, instructionsURL, that contains the conversion instructions (including some instructions that are specific to this handler). In this syntax, the location of the referenced WAR file does not appear explicitly in the URL. The WAR file is specified instead by the (mandatory) WAR-URL property in the properties file.

Some of the properties in the .bnd instructions file are specific to the War URL handler, as follows:

By default, the War URL handler adds manifest headers to the WAR's META-INF/Manifest.mf file as shown in Table A.2.

The following War URL locates version 1.4.7 of the wicket-examples WAR in a Maven repository and converts it to an OSGi bundle using the default instructions:

war:mvn:org.apache.wicket/wicket-examples/1.4.7/war

The following Wrap URL specifies the Web-ContextPath explicitly:

war:mvn:org.apache.wicket/wicket-examples/1.4.7/war?Web-ContextPath=wicket

The following War URL converts the WAR file referenced by the WAR-URL property in the wicket-examples-1.4.7.bnd file and then converts the WAR into an OSGi bundle using the other instructions in the .bnd file:

warref:file:E:/Data/Examples/wicket-examples-1.4.7.bnd

For more details about the war URL syntax, see the original Pax URL War Protocol documentation.

PK HAOEBPS/UrlHandlers-Wrap.html Wrap URL Handler

Wrap URL Handler

If you need to reference a JAR file that is not already packaged as a bundle, you can use the Wrap URL handler to convert it dynamically. The implementation of the Wrap URL handler is based on Peter Krien's open source Bnd utility.

A Wrap URL has the following syntax:

wrap:locationURL[,instructionsURL][$instructions]

The locationURL can be any URL that locates a JAR (where the referenced JAR is not formatted as a bundle). The optional instructionsURL references a Bnd properties file that specifies how the bundle conversion is performed. The optional instructions is an ampersand, &, delimited list of Bnd properties that specify how the bundle conversion is performed.

In most cases, the default Bnd instructions are adequate for wrapping an API JAR file. By default, Wrap adds manifest headers to the JAR's META-INF/Manifest.mf file as shown in Table A.1.

The following Wrap URL locates version 1.1 of the commons-logging JAR in a Maven repository and converts it to an OSGi bundle using the default Bnd properties:

wrap:mvn:commons-logging/commons-logging/1.1

The following Wrap URL uses the Bnd properties from the file, E:\Data\Examples\commons-logging-1.1.bnd:

wrap:mvn:commons-logging/commons-logging/1.1,file:E:/Data/Examples/commons-logging-1.1.bnd

The following Wrap URL specifies the Bundle-SymbolicName property and the Bundle-Version property explicitly:

wrap:mvn:commons-logging/commons-logging/1.1$Bundle-SymbolicName=apache-comm-log&Bundle-Version=1.1

If the preceding URL is used as a command-line argument, it might be necessary to escape the dollar sign, \$, to prevent it from being processed by the command line, as follows:

wrap:mvn:commons-logging/commons-logging/1.1\$Bundle-SymbolicName=apache-comm-log&Bundle-Version=1.1

For more details about the wrap URL handler, see the following references:

PK HAU :E  OEBPS/UrlHandlers.html Appendix A. URL Handlers

Appendix A. URL Handlers

File URL Handler
HTTP URL Handler
Mvn URL Handler
Wrap URL Handler
War URL Handler
PK HADDOEBPS/bk01-toc.html Deploying into the Container

Deploying into the Container

Table of Contents

I. The Fuse ESB Enterprise Container
1. Fuse ESB Enterprise Overview
Fuse ESB Enterprise Container Architecture
Deployment Models
Dependency Injection Frameworks
Synchronous Communication
Asynchronous Communication
Fuse Fabric
2. Dependency Injection Frameworks
Spring and Blueprint Frameworks
Hot Deployment
Using OSGi Configuration Properties
3. Building with Maven
Maven Directory Structure
Preparing to use Maven
4. Locating Dependencies
Understanding Where Fuse ESB Enterprise Bundles are Stored
Locating Maven Artifacts at Build Time
Locating Maven Artifacts at Run Time
Locating Artifacts in a Fabric
Generating a Custom Offline Repository
II. The Fuse Application Bundle Deployment Model
5. Building a FAB
Generating a FAB Project
Class Sharing
Modifying an Existing Maven Project
Configuring a FAB
6. Deploying a FAB
The FAB Deployment Model
FABs and Features
Hot Deployment
Manual Deployment
Configuring Maven for FAB
7. FAB Tutorial
Generating and Running an EIP FAB
III. WAR Deployment Model
8. Building a WAR
Modifying an Existing Maven Project
Bootstrapping a CXF Servlet in a WAR
Bootstrapping a Spring Context in a WAR
9. Deploying a WAR
Converting the WAR Using the war Scheme
Configuring the Web Container
IV. OSGi Bundle Deployment Model
10. Introduction to OSGi
Fuse ESB Enterprise
OSGi Framework
OSGi Services
OSGi Bundles
11. Building an OSGi Bundle
Generating a Bundle Project
Modifying an Existing Maven Project
Packaging a Web Service in a Bundle
Configuring the Bundle Plug-In
12. Deploying an OSGi Bundle
Hot Deployment
Manual Deployment
Lifecycle Management
Troubleshooting Dependencies
13. Deploying Features
Creating a Feature
Deploying a Feature
14. Deploying a Plain JAR
Bundle Tool (Bnd)
Converting a JAR Using Bnd
Converting a JAR Using the wrap Scheme
15. OSGi Bundle Tutorials
Generating and Running an EIP Bundle
Generating and Running a Web Services Bundle
V. OSGi Service Layer
16. OSGi Services
The Blueprint Container
Blueprint Configuration
Defining a Service Bean
Exporting a Service
Importing a Service
Publishing an OSGi Service
Accessing an OSGi Service
Integration with Apache Camel
VI. Asynchronous Communication
17. JMS Broker
Working with the Default Broker
JMS Endpoints in a Router Application
18. Inter-Bundle Communication with the NMR
Architecture of the NMR
The Apache Camel NMR Component
A. URL Handlers
File URL Handler
HTTP URL Handler
Mvn URL Handler
Wrap URL Handler
War URL Handler
B. OSGi Best Practices
OSGi Tooling
Building OSGi Bundles
Sample POM File
C. Pax-Exam Testing Framework
Introduction to Pax-Exam
Sample Pax-Exam Test Class
Index

List of Figures

1.1. Fuse ESB Enterprise Container Architecture
1.2. Installing an OSGi Bundle
1.3. Installing a FAB
1.4. Installing a WAR
4.1. How Maven Locates Artifacts at Build Time
4.2. How the Container Locates Artifacts at Run Time
4.3. How Containers Locate Artifacts in a Fabric
6.1. FAB Installed with Private Dependencies
6.2. FAB Installed with Shared Dependencies
6.3. FAB Start
6.4. Default FAB Install Behavior
10.1. Fuse ESB Architecture
16.1. Reference to Stateless Service
16.2. List of References to Stateful Services
18.1. NMR Architecture

List of Tables

1.1. Alternative Deployment Packages
16.1. Comparison of Spring bean with Blueprint bean
A.1. Default Instructions for Wrapping a JAR
A.2. Default Instructions for Wrapping a WAR File

List of Examples

2.1. Using OSGi Configuration Properties in Spring XML
2.2. Using OSGi Configuration Properties in Blueprint
3.1. Standard Maven Directory Layout
3.2. Adding the FuseSource Repositories to Maven
4.1. Initial Setting for a Container's Default Repositories
4.2. Setting a Container's Remote Repositories
4.3. Adding a Fabric Maven Proxy to a POM
5.1. Configuring FAB Manifest Headers in the POM
6.1. Changing the Local Repository
11.1. Configuration of Mandatory Import Packages
11.2. Setting a bundle's symbolic name
11.3. Setting a bundle's name
11.4. Setting a bundle's version
11.5. Including a private package in a bundle
11.6. Specifying the packages imported by a bundle
14.1. The example-jpa-osgi Feature
16.1. Sample Service Export with a Single Interface
16.2. Sample Account Classes and Interfaces
16.3. The HelloWorldSvc Interface
16.4. The HelloWorldSvcImpl Class
16.5. Blueprint File for Exporting a Service
16.6. Blueprint File for Importing a Service
16.7. The Client Class
17.1. Configuring the Default Broker's Data Directory
17.2. Deleting the Default Broker Configuration
17.3. Sample Route with JMS Endpoints
18.1. Creating the NMR Component Bean
18.2. Spring XML Defining a Route with an NMR Endpoint
B.1. Sample POM File Illustrating Best Practices
C.1. Pax-Exam and Related Maven Dependencies
C.2. FeaturesText Class
PK HAD!jjOEBPS/bundles.html OSGi Bundles

OSGi Bundles

With OSGi, you modularize applications into bundles. Each bundle is a tightly coupled, dynamically loadable collection of classes, JARs, and configuration files that explicitly declare any external dependencies. In OSGi, a bundle is the primary deployment format. Bundles are applications that are packaged in JARs, and can be installed, started, stopped, updated, and removed.

OSGi provides a dynamic, concise, and consistent programming model for developing bundles. Development and deployment are simplified by decoupling the service's specification (Java interface) from its implementation.

The OSGi bundle abstraction allows modules to share Java classes. This is a static form of reuse. The shared classes must be available when the dependent bundle is started.

A bundle is a JAR file with metadata in its OSGi manifest file. A bundle contains class files and, optionally, other resources and native libraries. You can explicitly declare which packages in the bundle are visible externally (exported packages) and which external packages a bundle requires (imported packages).

The module layer handles the packaging and sharing of Java packages between bundles and the hiding of packages from other bundles. The OSGi framework dynamically resolves dependencies among bundles. The framework performs bundle resolution to match imported and exported packages. It can also manage multiple versions of a deployed bundle.

OSGi uses a graph model for class loading rather than a tree model (as used by the JVM). Bundles can share and re-use classes in a standardized way, with no runtime class-loading conflicts.

Each bundle has its own internal classpath so that it can serve as an independent unit if required.

The benefits of class loading in OSGi include:

  • Sharing classes directly between bundles. There is no requirement to promote JARs to a parent class-loader.

  • You can deploy different versions of the same class at the same time, with no conflict.

PK HA|,,OEBPS/ch12s04.html Troubleshooting Dependencies

Troubleshooting Dependencies

The most common issue that can arise when you deploy an OSGi bundle into the Fuse ESB Enterprise container is that one or more dependencies are missing. This problem shows itself when you try to resolve the bundle in the OSGi container, usually as a side effect of starting the bundle. The bundle fails to resolve (or start) and a ClassNotFound error is logged (to view the log, use the log:display console command or look at the log file in the InstallDir/data/log directory).

There are two basic causes of a missing dependency: either a required feature or bundle is not installed in the container; or your bundle's Import-Package header is incomplete.

Evidently, all features and bundles required by your bundle must already be installed in the OSGi container, before you attempt to resolve your bundle. In particular, because Apache Camel has a modular architecture, where each component is installed as a separate feature, it is easy to forget to install one of the required components.

[Tip]Tip

Consider packaging your bundle as a feature. Using a feature, you can package your bundle together with all of its dependencies and thus ensure that they are all installed simultaneously. For details, see Deploying Features.

If all of the required features and bundles are already installed and you are still getting a ClassNotFound error, this means that the Import-Package header in your bundle's MANIFEST.MF file is incomplete. The maven-bundle-plugin (see Modifying an Existing Maven Project) is a great help when it comes to generating your bundle's Import-Package header, but you should note the following points:

  • Make sure that you include the wildcard, *, in the Import-Package element of the Maven bundle plug-in configuration. The wildcard directs the plug-in to scan your Java source code and automatically generates a list of package dependencies.

  • The Maven bundle plug-in is not able to figure out dynamic dependencies. For example, if your Java code explicitly calls a class loader to load a class dynamically, the bundle plug-in does not take this into account and the required Java package will not be listed in the generated Import-Package header.

  • If you define a Spring XML file (for example, in the META-INF/spring directory), the Maven bundle plug-in is not able to figure out dependencies arising from the Spring XML configuration. Any dependencies arising from Spring XML must be added manually to the bundle plug-in's Import-Package element.

  • If you define a blueprint XML file (for example, in the OSGI-INF/blueprint directory), any dependencies arising from the blueprint XML file are automatically resolved at run time. This is an important advantage of blueprint over Spring.

To track down missing dependencies, perform the following steps:

  1. Perform a quick check to ensure that all of the required bundles and features are actually installed in the OSGi container. You can use osgi:list to check which bundles are installed and features:list to check which features are installed.

  2. Install (but do not start) your bundle, using the osgi:install console command. For example:

    karaf@root> osgi:install MyBundleURL
  3. Use the dev:dynamic-import console command to enable dynamic imports on the bundle you just installed. For example, if the bundle ID of your bundle is 218, you would enable dynamic imports on this bundle by entering the following command:

    karaf@root> dev:dynamic-import 218

    This setting allows OSGi to resolve dependencies using any of the bundles already installed in the container, effectively bypassing the usual dependency resolution mechanism (based on the Import-Package header). This is not recommemded for normal deployment, because it bypasses version checks: you could easily pick up the wrong version of a package, causing your application to malfunction.

  4. You should now be able to resolve your bundle. For example, if your bundle ID is 218, enter the followng console command:

    karaf@root> osgi:resolve 218
  5. Assuming your bundle is now resolved (check the bundle status using osgi:list), you can get a complete list of all the packages wired to your bundle using the package:imports command. For example, if your bundle ID is 218, enter the following console command:

    karaf@root> package:imports 218

    You should see a list of dependent packages in the console window (where the package names are highlighted in this example):

    Spring Beans (67): org.springframework.beans.factory.xml; version=3.0.5.RELEASE
    Apache ServiceMix :: Specs :: JAXB API 2.2 (87): javax.xml.bind.annotation; version=2.2.1
    Apache ServiceMix :: Specs :: JAXB API 2.2 (87): javax.xml.bind; version=2.2.1
    Web Services Metadata 2.0 (104): javax.jws; version=2.0.0
    Apache ServiceMix :: Specs :: JAXWS API 2.2 (105): javax.xml.ws.handler; version=2.2.0
    Apache ServiceMix :: Specs :: JAXWS API 2.2 (105): javax.xml.ws; version=2.2.0
    Apache CXF Bundle Jar (125): org.apache.cxf.helpers; version=2.4.2.fuse-00-08
    Apache CXF Bundle Jar (125): org.apache.cxf.transport.jms.wsdl11; version=2.4.2.fuse-00-08
    ...
  6. Unpack your bundle JAR file and look at the packages listed under the Import-Package header in the META-INF/MANIFEST.MF file. Compare this list with the list of packages found in the previous step. Now, compile a list of the packages that are missing from the manifest's Import-Package header and add these package names to the Import-Package element of the Maven bundle plug-in configuration in your project's POM file.

  7. To cancel the dynamic import option, you must uninstall the old bundle from the OSGi container. For example, if your bundle ID is 218, enter the following command:

    karaf@root> osgi:uninstall 218
  8. You can now rebuild your bundle with the updated list of imported packages and test it in the OSGi container.

PK HA\n99OEBPS/content.opf _ESBOSGiGuideDeploying into the ContainerJuly 2012Copyright © 2012 FuseSource Corp. All rights reserved.FuseSourceenPK HAOOEBPS/cover.html Cover
Third Party Acknowledgements
PK HA~|deeOEBPS/framework.html OSGi Framework

OSGi Framework

The OSGi Alliance is an independent organization responsible for defining the features and capabilities of the OSGi Service Platform Release 4. The OSGi Service Platform is a set of open specifications that simplify building, deploying, and managing complex software applications.

OSGi technology is often referred to as the dynamic module system for Java. OSGi is a framework for Java that uses bundles to modularly deploy Java components and handle dependencies, versioning, classpath control, and class loading. OSGi's lifecycle management allows you to load, start, and stop bundles without shutting down the JVM.

OSGi provides the best runtime platform for Java, a superior class loading architecture, and a registry for services. Bundles can export services, run processes, and have their dependencies managed. Each bundle can have its requirements managed by the OSGi container.

Fuse ESB uses Equinox as its default OSGi implementation. Fuse ESB can also use any standard OSGi container, such as Apache Felix. The framework layers form the container where you install bundles. The framework manages the installation and updating of bundles in a dynamic, scalable manner, and manages the dependencies between bundles and services.

As shown in Figure 10.1, the OSGi framework contains the following:

  • Bundles — Logical modules that make up an application. See OSGi Bundles.

  • Service layer — Provides communication among modules and their contained components. This layer is tightly integrated with the lifecycle layer. See OSGi Services.

  • Lifecycle layer — Provides access to the underlying OSGi framework. This layer handles the lifecycle of individual bundles so you can manage your application dynamically, including starting and stopping bundles.

  • Module layer — Provides an API to manage bundle packaging, dependency resolution, and class loading.

  • Execution environment — A configuration of a JVM. This environment uses profiles that define the environment in which bundles can work.

  • Security layer — Optional layer based on Java 2 security, with additional constraints and enhancements.

Each layer in the framework depends on the layer beneath it. For example, the lifecycle layer requires the module layer. The module layer can be used without the lifecycle and service layers.

PK HAA^==OEBPS/images/cover.pngPNG  IHDRWƳ CiCCPICC ProfilexڝSwX>eVBl"#Ya@Ņ VHUĂ H(gAZU\8ܧ}zy&j9R<:OHɽH gyx~t?op.$P&W " R.TSd ly|B" I>ةآ(G$@`UR,@".Y2GvX@`B, 8C L0ҿ_pH˕͗K3w!lBa)f "#HL 8?flŢko">!N_puk[Vh]3 Z zy8@P< %b0>3o~@zq@qanvRB1n#Dž)4\,XP"MyRD!ɕ2 w ONl~Xv@~- g42y@+͗\LD*A aD@ $<B AT:18 \p` Aa!:b""aH4 Q"rBj]H#-r9\@ 2G1Qu@Ơst4]k=Kut}c1fa\E`X&cX5V5cX7va$^lGXLXC%#W 1'"O%zxb:XF&!!%^'_H$ɒN !%2I IkHH-S>iL&m O:ňL $RJ5e?2BQͩ:ZImvP/S4u%͛Cˤ-Кigih/t ݃EЗkw Hb(k{/LӗT02goUX**|:V~TUsU?y TU^V}FUP թU6RwRPQ__c FHTc!2eXBrV,kMb[Lvv/{LSCsfffqƱ9ٜJ! {--?-jf~7zھbrup@,:m:u 6Qu>cy Gm7046l18c̐ckihhI'&g5x>fob4ekVyVV׬I\,mWlPW :˶vm))Sn1 9a%m;t;|rtuvlp4éĩWggs5KvSmnz˕ҵܭm=}M.]=AXq㝧/^v^Y^O&0m[{`:>=e>>z"=#~~~;yN`k5/ >B Yroc3g,Z0&L~oL̶Gli})*2.QStqt,֬Yg񏩌;jrvgjlRlc웸xEt$ =sl3Ttcܢ˞w|/7bKGD pHYstIME # [| IDATx}yn/0b# ĒLe;blWU8*WS~?T*$[.Iv"ƒj$J@q'`͊<|C13/ɹ~U=sN/}nMpeyiգSO/'@Bl@η?>$I$I$I)%w6Fmo1|qq9!{`aXom-Y4 v?0ݻ|I$I$I4eݔm2!Ap`8dmc}GVچUb_\`3$MjnT%J; J&ʵ*UѶ7t4#_F5ϿHX i%I$I$I.`4~nx _PJ!"sn0ϱw~g#R"u甈*^:qfqeϰH$I$I4%]*J?:wK^NCDN?M8O*ڜֿSUo Rb3Q)֞{}{¼$I$I$ITn~RJ`(%:.)%֛gϟ^Y]gO0*NJ[Ɵ*R A} .ecÑ$I$I$iJ }DUz=w"<a۲R맹<@UA5jRCѹ D$I$I$IS` tUEgV/qrmaμx2gn %SCB}2/BI$I$I4Rjsfe4`m4/^?ÿz;3T'E+!W7 N5])%4pѹ$I$I$ISu ta3/}o\x+!/\fy4| söٖ5b!%Ƴ'N3:{ݏ=Bm%I$I$I )Ȥhu<ߺx-p?6P5"ƭSU"h._ax =aI$I$I~JJfDE\!%gI4 SgzC$I$I$i c/-mI#u:.\dIb2J$I$I$)\_Q7 @2*U\Yy%I$I$Iޙ~0̙&2Dڎ}%Rա kꋗ:Cԍ!I$I$I-2m.-2Tè(ӿ$"MJڕU6^z2y$I$I$")؋ܒK!R ѶR!_] $I$I$IER-DJҶ']0U] Ϝ>wضO$I$I[a B m ,䪈RhW:MAH$I$It t[QhKᇑG$J)HIKW<I$I$Inn RFT94nwᢇ I$I$I-0m4Fno2)eԸ2jͅKΝ0$I$I$IIR- _=w??szDJt'Rږ` HΞct!I$I$IMqR""WXGTUwbK ơ o:uT.fJ` %I$I$I;2Ҏta\fDE"Mm_"Rϒ$I$I$2ҎV8_gy8"UwS͔R4-m$I$I$Hilj" . 6Hx~TBJ$I$Ia %kӅ~kko-d*r_VHI$I$I \>]opvc)I$I$IމRцuG5AUz/DZT!%I$I$I;1Ҏ֔¥:>uN @P2BJ$I$Iwb -Gpy0RO]2Ua3PuTu!n$I$I$I@J;ZDR40h3)-HPچP֍$I$I$0Ҏ>J\<'T%JݐR$I$I$ Rڱ"mx}cрD*D[ZD"Qh $I$I$IA EY5D$HLBHDnɃ!-n$I$I$I?f…} ) GZ%I$I$Ifha~ӐH[ E\(2BJJ$I$Ic ڌ<ִn)PnkDn$I$I$Io@J;^DЖ` Q0*MCNX!%I$I$I2̸I$I$I~)hD-hr$ (MKNX!%I$I$I2XG\诳ю bOH%v%I$I$IzRmåAQMRsRJDɴk딑$I$I$Io@J3#A+>DҖK"BA6$I$I$mHi55WJ.$n5̐J J7։zyU$I$I$)͔(2"%@ִ}JӸ$I$I$)͔dV\ A-*e0t%I$I$Iz R) lu\_LF`I$I$IB-,g=mΊJgS9W $I$I$IzVHiVHoj3*yh>I$I$IފR)qRQWh7(,I$I$I[0Ҍ JWIM"ACN﻽$I$I$)xiRDyyZk' S6 $I$I$Iz+ΐy -( eT$I$I$vxSETLaxTHDi76n$I$I$Iob @)SZ,xAD!oЮɒ$I$I$34S" 2kJzvuM$I$I$M nӬ$I$I$fJDK Q`uR %ȃ횁$I$I$Iof @ Qi +&RChVֈhI$I$Ic R"hsLe_I`DJԵ-I$I$Iu 4s(k6)G#yd %I$I$I 4S GDR D-mOn>I$I$Ic R"hKLg_"TF4WV@J$I$IMR)Pe)AJQF +ْܺ$I$I$MHi2.jpDVHI$I$ItU-, Dw۪tG*܌[9CJ$I$IL)%hL)$T^)UD[h)ufK$I$I4a @ua\4rCBB lI$I$I& 4SJuDS#LBْ$I$I$MHi(4!WIEʪe8Y[m$I$I$IR)QhJ&&Җ_@"mY^!$I$I$ 4cJMd $R%Him $I$I$I 4cKKlOu̙fe<$I$I$]@DД(g`n5JWfeܷBJ$I$I$BJ3f\!iJDzJԡ]]#opI$I$IBJ3&"ȹЖ̐)%ЮѮo$I$I$afL\hJ!H䚂 A o$I$Ig R"sKSZ" iA$ʨR}I$I$Id 3-MRLc_bbL>$I$I$iHiDM4v zfeM$I$I$<)͜: u 20)P2e'$I$Ig ӖB[r.)&RQ 0KREh׬$I$I$@J3D0-y3fyTRȃ-$I$I$I@J3(aL*CTшvmM$I$I$4)͜misfOm~zCu5$I$I$6)͌qK~Pv-6nQCN|I$I$IL3̈GE:gHD)<}bJ$I$I@J3iyBaMseŶ}$I$If sCC&ibgiW׈b %I$I$I]]@hдmr]z4鶷QꬪA#5+$I$I$I3@J3iش9fTH[)5& ږvmR$I$Ie>ͤaB!Ui{nL؀RtI$I$I2L̠y*QrLZn$I$I$ifHi&5%3l[R:8m%"2:1$I$I$.)ͤa\ HLm_J BSM$I$I$,)ͤ~ M^SJB@J$I$I4 4-ǕL!UD@ȣ.I$I$IYRIuΌ64 V[E4 ?X%%I$I$IQR9hԶ4mJCn|I$I$IL2~[CL?~U CtI$I$IL2An!b G 9m'I$I$I]R))] L$9CJk>I$I$Il2L몡mz=Z 5}1_PF#1$I$I$&)ͬa۲69L*m.&XRVHI$I$Iff֠m7M[J ׍-$I$I$I3@J3ə~SS*HD &NhZn$I$I$i&Hif ۆA=͓jR1*i@J$I$I4 4(l-u!b\$Uh[HI$I$IffV33DlËa3 Jΐ$I$I$()ͬ6ښm4"9iRhZ-$I$I$I3@J3)~Ҕؖ}(m!6gUI$I$I4c 4"a0l[خH*%RBJ$I$I4 4m07(4H*D"rX!%I$I$IYRien(i%" $I$I$$)͜jdV뚲aQD$I$I$iFHi59:vw y$I$I$iFu͚[55Sn۷yA3$I$I$I )ʹ\ 6vM"P$I$IYd #XorlF)J%*H$I$I$Iw5ӚYȹ@}UR)*$I$I$I@J3-G0-!D_Ӑ"ĵ ,I$I$IffZ`-d3n'I$I$I rʹAi&Tܴ/" $I$I$I3w5Jf[2L\ӓ:$I$I$iffZDЯkF%S6y:]RK$I$Iff0 y{nz=)I$I$I2̫K4m; w+AvI-I$I$IIRyj9bVO4#u $I$I$I@J3DьstGHM+ܜR$I$Ie ٞD^Թ!mEL7{T=gHI$I$IfkfE\֛aP\Mߟ,݀kxӥH$I$Id5RHiJ/ u*{vәw%I$I$I3@JAӒK&u Ue ^J L|I$I$If-$ AT7ݲƁTT%^Nݏ?SϹ$I$Ia %\3 M.P-e\Zu"*Ͽ)6S~!:KKn$I$I$i&CLF0h3Md* mu*)RUѮoq7~K9$I$I` %aض@li"%<Oep/I$I$I R0-LZ#SXWKt {_y͍$I$I$) ̠i# MelA^%Ҭ$I$I@J3/b L]G@ h2 ϾH$I$Iv<)ib`[BLVvme7^$I$IHIei b[O\J}$I$I` ҵh3!~('J $I$I$I;41-n LlcE$I$I$I?. 40hfM$ھh*%(%9GI$I$Iv<)ib~ QDJ$I$IHI2h7~s"*c%I$I$I - \_o,nja$I$IpTUŁ9|p/]ZZdiqyv/-PU/vg"/M{rY\gT\kԔAnEa3j=M[D]9RJn$I$I$iG3&wy9rx?GЁ<{n癟0caGs}.]Y{>{;>LoGS7^Y 'sNx(.AД\"N ͋J%zTxI$I$IҎg 5E9ow=O<нG5߃^znw~|G)kad@I>G__܋'Y[xPo)aےs|'M>FAga]n$I$I$i3]O}sz{=BgRr!J# ǡћoRyOm .<\^y]x#<|G7_ayu{ m(4QHm,ӼAJDzٵDw}#* IDAT^7^$I$IHmu>O_=ž9RUANʵ*bCEA"qx?ss|Orw@m&b3Hm ,v;Y+B1*y^/%۴Up%I$I$I;^Zg'[g!90N#6DxpYo)%vZөGCyUvH9+6D[Hy|=ʰ¥~Em)̨m^H b|tOo>7^$I$IHݢ^|)/| Jzh8XTMHW?M RUցTUUؿ!sk+WA/Ut:ո:c JiOWoNR"<̉R öɅV&i2?osPzn$I$I$i3n >SOAT\)T"Ey2h3QTU< 6C>/ y q#uA3=r&H)mK$%2wzl'I$I$I R//{`}pm698d7<:U0߃ia0πb*0GzHd8/|g"ss]z.=O<yaQu3j[^oOo7z&gmK9Lx&UJxK$I$IfMZG8o7 ̦IK4߃n?՗Nq9Νȥ˫ Rw9>C͡C!%R;Ro3C`yuՍW_sç>4?ɧy=LfLh[:U'x?~U^;uރȥ0lE!D`A7\$I$I4 n:uߝдĨ :r)\87g+x㯜 #"`~}ǎ'']Q T0G۹7ռ^x ~8g]ڧ#Th3Bڽ3O?ʗ}@:M چE)^;p17\$I$I4 nc'>3\"_B۴ _=Ëϟ}~Eor*K o[!uNȯ?W{H䁴-=|y>}Ń(ui(Qvtz,ή]n$I$I$ifTnKUػ@+ 4MK0jfK/;2+0#U t:-?WN3"_q!Դs!%  mܲ/uXש/_q%I$I$I3@&wNR Tp 7̟rM":B0?ߣLqzu>p*l K:LfR"MA3㫪s'_¿}5F=s$I$I$I1` uNt;q2[/^_Οq^7etvO07ץ77\*v[ϠVVYY 7 ^ P%ٿo3q˾Q)L3J0Jq$ɔѐSQ4WX?2/G?>NUY(I$I$IH݄y*AnY^Y絓͖_[ AanGӡiV G QC 8oսJ`mR(7OgqNMCuWֈR#$I$I$f u3TF)[ 0"-{tՖ)D+Ì\={fzJ%ҸizG49 v?}Ӭ~ԗREU͓7Xw}YZp$I$I$I-Dĵ"%r 꺥-2 ^9.ʫs.^N5 D'UVHm1v| EQ˞>yOr_dx E:K}6YᅦjJ3$I$I$Ia3 M9㰧n= F # 17caa^uSJ޵Ȟ=tP?"6gJ)0бrY6ǘ?z]KOP--rPjG*R$I$I$I)0M;BSki{wt s^Z`#t*#۳ r\WΐFQӜT U]wݽmm<7c%I$I$I1|&<}QV7*AӲ8g>ܿsA/}{<OĻ9p`ZcSO<-?槞x_?ű{:ոB*%vk}^;yW^{ (nx.97[$I$I43lwFu /c@ dRág9 oo+?Qv--s+g kr.RDhs<0#6؇_{?3o_xG_ s7?L"U^¥wbsִ⹔ JRtuڧ?ƞC`8%"S_|/yM v} p-.-1w0KO$I$I4;|W&=I>?9Huć>8Kޣ?q݇y9zx?>=Zd{&L׵Ku=K|cO?1~?y4mvzn>yy#wf\Y5W5=7I\,QUjiÇH=+$I$I$I@&#~_O^h3D] }<`]y'4߃%<.uc*3 _y`^'µ}[Y!Uzt즳{3$I$I$iH݂g/Ox n?$^YVD] |_<)Z}g< IU.I;IEAR cSEDDDDDDDDDdMQ J_"ཏ܋&-(<p|nyPD=zی1Kx \zZ~NQs㍳ZceϾ$>55?o 6@T 4UdYsH݆6 -zFƇ˽9y9rf^B:ʰ'tڼt$O~Y^fZ ›t.c,[uYDDDDDDDDDDR9KOr'8\9J$^Le([B/2]R,uM:sfx_S\4{(C` j DDDDDDDDDDdQ &(;?xOg?~>Xi dEwiϨU˻k[ osYz_3|G/r9|Z[*qռPYTՊ,""""""""""k7I=.\z/޷ŝ7359kTq~B^e@z8.>:s>o^9|3.33}T!`,$VYDDDDDDDDDDRo6/tسsmd F'iЬU*$qD,Ql6CYN't3iZ_Li϶tq3.s<ϱ9z<^^(@kzNf1(ı,""""""""""kHQx9á#g7ftxӓl8Ԇ1&'bQVPᔵP4E2ffv6s-f2K9{g/23.7nK`]o"L=+3-6cpb9K,^sQ=y^g>BB9ٯ{uB rM1յ aUEDDDDDDDDDdQ s b1K*캢 "EDDDDDDDDDDkQ*wU\YsH,4Jq)DTeoT *9 D1"0{g k$M):YDDDDDDDDDD!Z<(4n5 ۲K { R1XAn*9 duO0:ܤR֒e9g8v<֛!SUعmwfQh;\̹˜8}3箐iT-%j é )6̬,""""""""""k7IZa߽îS 6cGk+o??=WޔϬV^>e1.]ç3_`߁̶gȚ22ZdƔGwQX-sաS{Ȼ8q_ۓzuc#Y+WX!s>`p2:> {~y^3#سk4øFc|68b-7Y ZG{'xpIs;g4@OS\=wuuIȚ0>:~/2{C'%do"LνwmgS^x(YP^KxL Z@c-6ظc#cXki-v joKXr0V%k0JDDDDDDDDDD*E㳟|⷟`ϻBkY!` e7L7z=7v3ج곫Isx`)2Ȃ1cgSxO褄F_ >1-~P#(ŕ0|QY?={FzK V!ܱ/.kAo&`, jf Q*xUN7e,̷!vPO"Îa#|?:1 10q{e卡y;TdYs4oF{ ITvFG !& !8 ^|Nѳ'/37ϟom:7M}{vLynYݔ}ٍ!/0c|by)g!s 7XVOxxhFSUdYsH§?^Ff:0΂5>zg}>|g.r܇ٺcckfcXm/k8xv}s-zp #l4IҬ{\]>fs.ws34 ۆF pP* cz?[q⊈ȚcUٵ}{ESvK1vg8rۋ]~a 1r@^dϮM>s*æx~v :nD7_5$#C$&q~@""""""""""&)X:7M2>1  "`+CO]kQx|;?xcCذa;woY}:0ˋγ@ lH֯#HDDDDDDDDDD,+ij Fc 6rI9z4 ڝ-;Q|`-0}`px[!땴,Wm|X5 KB'T7MaUWDDDDDDDDDD,+0ap|P*\2KNre/\a#y9> B^n|8srgKU `U*aWDDDDDDDDDD.R+0>6`;9nqyfc'Γ9qE`'R>D:JV\{Xxf1Bie5jT7Ī] V`QZK&".Ͱ 4i `%cij^RiQpHiq!sfdl@JDDDDDDDDDD0R+շTMCݷ5{ɺ9Y’gK:<r?[ MYx\B<4k4TTH IDATYH~)aہc^b(>ho4aE]Q21q}"""""""""")Z,/ȋpmDۧ9j IyrYo=n|>ǖ5eWz 724ODDDDDDDDDDdR vݠf~ 4U6#ee Y^ꐦ n$/n2x K%v:(""""""""""k[ZSFNlY?1銙=Dqq^\f N+dy+fBO09@<4"Ț@j.\c~v|o|SQ0>d刼]ۧx]8gyM -Μmks8,QI44Ț@jN 3Px1*+lg4o,CB߿> [65Ss9 + DQNl.""""""""""E*;s2O^3@^-;w [S{7.p•7:u*nJVԫ6!rc c<{:)!Hkqe;W uCbnk JljUQDDDDDDDDDD<R+Pxϡ#yioY/*)sjB$""{G!zPe ;._3:s5F1$a0{{UvQ\{@G:㣃>| ϽcM M3@پ+ٳcػȣ04gYa>6q?K0*<RN9/_= r`9ZB{lbMPDDDDDDDDDDR+vSwQF0 .ヒݹoy^xg]}mн;_e{;v'1;bImYϙsc:&PI|,4PrA{u8ki1֚[{C`)@Ԋ-:C|{'CmNXX9f͛&a>ũtyv(ذn_{̧>My\VKV2,(*,62sޗaukCN8"8v$?:rZz}͖`Tq o1~%""""""""""ң@jN}[ص;ى"(@@ٝ`bq>>?.p%]W6mv242 mJFeQv_-v9t >`nפRj`b-Dyg]_J*s UjXcRf[sDت)P *v~ik;f-wlxWjrE7*2nc|oԟ0yE{u{S7EnA5!림W&Nb:z#/`QL44)RI&.r?8n9B6*qL`΃G@(zǾvrWGe>^gT>71,BjH*8k ߤ׭1 DDDDDDDDDDD( Ͽ$~c Z#Qn!VpΖL!,%nӒ|,U5ro`nf}G_kO>lK w Q5`y0xs^[y(""""""""""@Mp}>]^+ey5Y9sO `5"/x闞SuQxF1[ %U5ODDDDDDDDDDOԛI_ Sx=wع}#LJ \=TkeEe7kʚQEAs|$?t߫8u(P+ЌcUj PxqC؊)zS^z$> r[ٵM 10Ԥ٨ĎY^qWå@/QT\(rɊN'elg8q/:ٷŹE\ U "><5 ng2L䈆˽DDDDDDDDDDDP ( 'է:[׳s;l`M4UՄP$ؕN@s4' n,vR:ͷpi/rY;cg9uA!Ԫ,5X`WcczIbAs*HX>vc'OsJ%bxp:zjPUHɲne9vS;]Z.ssmfhw乧¿h9y}. &ӍQfB a"R"""""""""""} ~xp)KE9 z#zzUB9ڽBk=(ق U*cHP^x"jvt|a3\R" eTk*:DDDDDDDDDDDQ u P~¯io\3gO;C=;6A=J@X;{H"lk4vQ14`tdًi̧);y -غmƎ1v 5H0I≈,@j8v+x{wmfl!+*/Ƙ,b߅s|`XAlY^` xq6ITHeH¶K|cæIHs~Z7K*/Ⱦ(80ϙv v;|b64pC9 4GG-))Zfw~qÐ{l{91RwH-ŋ80p㛷3^oR0 TEDDDDDDDDDDcU45} h@7tivGEzE3.>*/] 8G<2B2>\G 5ٸax֒9vH mN1`dpxx[p"""""""""""R+d9 F4 1\,d]ihR!#VDDDDDDDDDDDn@R+TxO`LyˤY F+5bXlM[x4PvI4$DC* Cjڋ]fZe1@ sZ]«@ C*:ZwmvuS &Uʆu?JDDDDDDDDDD&HЕN  XgcFg!1WL6 U*{j&M6pbU * (ZgxՓt[TupZ #ıFA!5h1 ޵iK1>Neb$* hkq8OQ]RFEVQ);݆*UF{:yF7/[P:M4DDDDDDDDDDDnF*8}? DF5TwZzCP*xEWQ߾[Q)""""""""""r3 V9p X5jl6/}!VJF#BFj[6c+'""""""""""r3 Vޏ^czbGTk~'> J"J "^(U3&ωT6n$Y7qNE 7:<ijU>pՄ{vm24XcًG( B20Uoލc| s pi瘝kM3݌,In9ifY^픯^{Sjݸ[mZ^e5* (Z.?;wOhޓ&PJ%X"KԬh[7;^YM3|Qu34et:)YMs:ݔSiN{ˇNů|/?rY-u,Pcb@䗎48B1NoR %""""""""""r V^ҬiWCNr;}5o5l0\??pE#+fc"^w c XR"""""""""""X@Zy!ޭ%eBy@^h4(yt .-igH]EU/Zm|7U1EDDDDDDDDDDP jIk}IE\ {:g䡛( ,rY}@f!|(<,yQ馴e7N۝2 eV!/ v6_;yEr)1^Gڙ9f6}@SR"""""""""""@jU$}eع6pZμUB,/;65Ly FqC*@o `f']Xȱ??pԅsRM Wʵ1NO3RDDDDDDDDDDRR$ܹ{ As-(!H(Zk-jq  HQ Hzٔ0X箽[@?`CPR>6}`%9cAԪtӌ#'17bc-uRvpInr1f|`ttf5f3h-Qv~``aʖ׏EDDDDDDDDDDR^syظqM M", |oT>ެuҐdE[>a_Sq'"""""""""" nۡ#g8t j8-LQTvH9 ;z5VFB\FJ#zj5Y*juk zA6u$A(Z04Mpig.c|? YvSK!*.b}cJd,Y1ܩ7Q2p2q9@MIYKC\`c0˚m1[yf{?ǽ4jU&&صm> }6 ![(8p8?~,Tc(ME \!u&1XMpaPzv ֝ jXQ3ʗ!U26{f3}D=DDDDDDDDDDDnDkb'O$w߱ h7ȻSٗ8}5֢j1RP,aQ!ϱILmf?(ͽGyjX#Ξ'YrAwN"B9*5I  ENTܻOE26R+%"""""""""""K)e 6==ɇwFuק' תq'c w7G4JDDDDDDDDDD)ZCΜӗOdMs;=Wb**bl:/Yi}DDDDDDDDDDDVHjwk l8 jdMקE4*[v}BDddx|L_$R EAyooX@ƖI7oP8a,fkQN2:Q}"""""""""""ks9!@(ٰntMvH7r&  bX_$R kjT*I cljkP ,*+O<S>yAai|s nfT"j#O/4D:&քKB9vl}wnghB 3?tg.}1eouܶ?0bޭIytRsmNďws/^ wFGؼqǩRtɋ4+󢼟( O=! pO5$y$~^>]dbY9zvwͮi%Et~H4Պ"""""""""""@j7)]yÿ& DQ=?Ac+J,N PVN7fZ]`ӥ b7HӜ}wmc)F liT_١U^Ib./oi]-JF1t n(07Dj)ZF0Z:*pGI#JD-:"-6{4G(mf^wfU&U 22T~ EjcAzm8^<fA~X{9}aSR<~*DDDDDDDDDDDB5Ҍ4`K֒zYpQ^c avn}1>1pH/'/\{93Kx2ƪBJDDDDDDDDDDdH]IΝ'"+ZAƾ7־㌌Nyc7w# IEYh,5y/_gbCSP˲=^"""""""""""2/ Q-yk ?;ve4٧"!b:ڛsC|Sse.o7sps*3,7f駮P}T9e| z3oy-ƴke@/_VRX+DDDDDDDDDDDd^H3/!nڽ '?^=00Uyhl3c 5X,O|]zVk\bE~|'/ s7/_R %g<5xxL`L#8K3(fxtc'x7yOTW(>%ǟSxW %"""""""""" 9FMpi? x-X ) >yB@{!R0 (BŐbP,P) zHb x#N*UF&40™KJj-ֆ]C))x2.߇0 EDDDDDDDDDDd^H]gsLUjLUj:k Z|#=E/3D)R k"Y$)jѱP  ~Hc-ޮϨeȼC@=1^e8"""""""""""2vYPʾoL>yKDc!]"""""""""""2o dY59GsaM>?JȂ(eͷApYG9FMDDDDDDDDDDDd|-3ᇙc~,0bp.p;DDDDDDDDDDDdAHCFʥa!\ )byLTjiJfqdɩ**H 8Ogi. """""""""""2 >bXtv+XŐ0) (XU#,#Kq0U2U19Uetl1r=W9) _3L)xf6of ټ]t`6[Cy6S u6_ŧO+՝Pʃ,$Ln6xJ|F2sfLM0 ڭkZHR.p//z9ȸ6eh)3`,8ȲLsDDDDDDDDDDDHuk:<]l޾BONUgoC'~w}0P~<'25+i▻v[xKs={X~UOIIʛ8y7swٗ1` (r&zؼ}ݴ^|Q,}2P(P} ff%GDei}""""""""""" @j4}7?/}7a[j)\. fZ-"3]q\};㾛ؽu-]J<;LLV^GCR}"UPeEDDDDDDDDDDdH-"k ;Ǹ]%<$Pr7<h,GXɟ?ǟ"˲e_hCB/s8WNc^@JDDDDDDDDDDdH-'r|n2R=܈/z)e֚h-A@Sb~Wd8M )yQ <ϲ}~;vWE} 6xf.w:bLc;oFG8t,os8I;5"ggdIB$#%"""""""""" AG[3_- }Z 7y˾(f>wʹj7ffΔ"h(qvcxdc;5ZJE,,GF ]jdQ4.5S lXAZ[R . $cf^3ZYY_!sB ś,ꯛ9⼜Z_/=+oY1W"mA?YBJDDDDDDDDDDdH-N>~6l䃿9=(GELNT`xtJ4p8ƳZg }Zhi.㗋P,g!N` ^Y˺?|G{޵B:e0,.EQ>{KDDDDDDDDDDDEmͽw",!NnWzP!N^ KC L0>1$Q%ik XL1tv[psN@{[& s.?3q [ְgHd1c -"a63>Fڕ䳭^D ]mlmȫ0P8wE9#4#Ee'R ՝P1YDc0^ʟ[0j̱I-<Ě.L+Wi*. }TJڋ lv-**iBZ4CJDDDDDDDDDDdެ`֬ <滲952^Y. ͫ5ߵ}are\l%khikbݚX5:eڋEB)~h^!䁔fH̟XJKk olyicg^б9>~9sB^ys@ĪmXk~mUB\.cԪL-j87R HCCq󙸣g8cRW{#?48tgt/CZfRli.n`\bUH,(B/dkU#er+9ZsY']5sGXX-B뱦=AVAR"""""""""""k Q?7pU#GWrYqq`j5kfC).óB!f eXbec Mf!2("흈R@j<+ޫBʀsdiJ%dٯsPdYRy`3{]KOnlbe9@bR"""""""""""} 9pOT@R qSu:ڛ_MA5U]moW2,sDQLKrϢ,:DR#sLW,9GǸTR"""""""""""@j*Ո(NLs|NR]Q(,77/2H$K֢TKSNs|dV4Pp,q!%""""""""""2o `|B1=!wܼV}Xnܹwmtss냢(ft|jI웮x85ۗ.rijonJ7E1)dj'""""""""""2 `pxəw /I };7'dֵ9ھ}A6n>V|af&*\4L%w976kq3S"ƀq,N\-M`d*\k !_a؃jHƝ7i{ B?yQ;F'8q":>:ȩa&6),RR"""""""""""k l?}}8cjW李\?}N204絮[l+ᅰƸz5Ղ3(R0\\3J#*F85Vs+9\v0ODDDDDDDDDDD>TEFhhg sHSLjٺkW3oZ"(!+r<>B@X\*qJ>vNyu;~sn:;0Qo{s"}l˾΍qfl-s^8t(e4[f DDDDDDDDDDDC;#g7C3R]C!3VL>Nqi*hܐdžM2 t#K\R"""""""""""rH-xwM`s%9R;6нu" JJ5"NrR#(ʥ~S2asB@*j-mUV[ a^{lp¹1r1=5Yh<)Zx}cg&qq[a3se>M !MMehϜ`:IS$Ź<&^~?Z?)D) dl;>sppTϿCG{ލF}Vc-d)0D*/fVK0Q<7@! VQc&prjS0:T-JykRT 1&* @- N1W \=3@3U_koZiʥ)+Rf[+^afeDDDDDDDDDDDH-KΩgL7~{P,r<<*x&N0 'O¿<.Jc8L",%@PY IDATeu DDDDDDDDDDDKu2<2/Q>~.v†jkR{yڑe!ATcւo4$%E\0s=˛oͽwGAusjLFi(xH欽b0 DDDDDDDDDDDCuE >;O«mض5;(w4S()>{kL>h:*VdiFDIB5JUTǧb0GcS$:Eڔ+8瘊#&4Qapy`=-<(:vC=Mvn]MlZ=+X&ʥ$M4Iɩ*CcK=A r\?Cciq2Di1˞s2k0V%""""""""""2 >bQs". k Àb!\*R*h(h,)1ZLQLUTSJ(N(NQ>$˘",]Mx>6ղODDDDDDDDDDdH dcRcRay\(W#$)Iޢ0\qDs).X{wDPHr.0EDiR< CLZ̋]=iL.[,b )yQ %T(s9\ĄIDDDDDDDDDDdH4'ZlU %""""""""""2o DZ]_7+ƭ̗) KYzy olxIDDDDDDDDDDdTD44i,)A>9 Si)R,:[Aȼ)ukYv%׮`mw=;hDZ$G={3ga4B~HsdY9`cUL(""""""""""2_ ~غ{ŭ7me˦nVwa~Cp1ΜБ^?8z}ja?229l1$hi/RF5ܺg _'͆M= %p $ܘG{tsJns=Y ϼ|MFF'pRpᕊ-M!%"""""""""" ~M46/?o}~nce|cL?97]A1xa@|~e;7ݲq'xs14b٥5l!on+/Jk@* a@G{3Me OfLLV=OvʌVv/|m %E%,}7si{467k&:ۛimmyg_z){2],Ŗ ZJE)yS U>͍ezVwyj6m\ʮ6JŐ$IWIm|[yvōNtT=߇` 2\-Vw0ac|$I^OK9, ye)^Dڂ-YR@g>mQW.}Ƙ jcc g8 hn$lo-@j㺕|7/=4P$xݷmw'?T_,ݵ|~LsJ%sy8e-<}>s-sA-R{q?T9a.,?uѽ]]li N]^f ^s3AG%DDDDDDDDDDDhYR6w [0(4<2wܴO?= #>vsS/YkO$.sPgW"+j1Vni+7'䚏],~Vͬ^j@}Ā1_~=zVuތq fvݰwl๗̭[B1|uui Bq2Fgla %C,.ַwo[s+b 8cZya/?}eSFY7nA^5,ɳ~?'ts_'OBL,WIe` kVp-}oIfvudMS4!13文9pIry+GeHm\ўR!{酽~Ə~u;MWk:̍BϾ_<6c >ޡcg<˹s 07{$=6T^{^*X̴|+҄ZqC,eH`ֵ_ a^\޲Fw^6wh15uS7׬dd*c 0#GӧޠptQ99U}yNLA0KcXd:ZsX{o  As.;eP.M]D2:wE|)kضe +WCż8O=2~6֬z6f5-y U$cϾQ;8< pl%I^N`iy=`3@kD,jb6oɨ*DDDDDDDDDDDò gt7Cyghd? W?*7^sl ~Lbրqy^w}z$Iy\0zUXުP.Rq[H9㧙f  1Zw Z6TScU+Zi,!fbҔ1 {_~}>gUƮޱ=]9Yƫo权ړ$tE_"T˯i5_XETXR{>}}샾ɀÒLNOjzYeHyDKKa-U#8amO=tt`_eUغ-'@^3"nbt7:S}~iqq`*Bj+:[)% 9 g?gI)K,вrlU^^T~vQ_,ܾukWbEHY39p e &' N0Y!ӁXߧ0chCA@`7}0@ZLN]BDDDDDDDDDDdMTSCb!cjqBضrN㟿̾HlQ_.vGQE=x3.]ubr:sp1G8ZRջ-@XCx2('H3. rw*<ϲg;\!Igks$e``dbr]!SzYy0og e?xx#qI90Y-".!""""""""""@rPYl}vn:r̓! )SU'/lofǶt|-թ*{/r9*=pWjYz=c(p{ϐ233% Y]BDDDDDDDDDDd첹ҹ9Ael!cfY-{ܨlN14[gfx89}'36>uݯ\;v Yϳ}j*gs қ!Zx`l(!RF""""""""""" l*s=x'C5X_ 39q3\{N,Va$i|Y||OJeU9GFG&x _k޸~{.֮[}H30}JC` _s` )Yeղ9'y}Q]@(fM-j"<(&I3,ùfZ{6u?'V9wYe lܾbܠɘ<ΝWp9$ny}|-6}@s|?o;Ρý 1xcҵP>[vԅa{i?/{B1*ΒYI {\=cSOVbF:VF{k#53m*9Iw?*(n׸ij{/?M{6A yeXyDI$g};{Zg1BDDDDDDDDDDdxGOok׭by(cå)&B&Z:Z`c7$ .JI,; ~|D 6}ˋ\8}g_zW:MMeWs:k7|6nغLu< C<ۼؒg|cOk1x"""""""""""2o2?}nFss]4"lj1JA *U\W 6qLY(执fR! E<ʬ^+-}vHܘ0=*<^z%ϖ<2ã>UH,\/|pxS*~[Y6- ƹOOe9po pM|fVhgu'd%{B%oΡcg>SRd5yj'"""""""""""m pՇ˘(բø.1W`yUUC?pO>Jf>96_ŗ?[z>c$óQX)ٗal|jI1>2˒M9p/_7YeYxC8xYf Q qsl˷epg1%D3W[9Wk:VCA5$4|>~iƖΆQ+>>ʷXӻ-j-ahdq>lCYo:ȇGa0` q2><[o;??y):~^϶mx~3c󫒔OW/ˢUe;!;էGM/$Aw [[(Z ?0osdqB[c2T߯<<v^}oBn_ Ɗ18k+ 07R01Ys8}}3 IDATr"-\QFLVj'xi97K#{8w~Us ˖u>q29Qep`sDQOc7uF0AC!""""""""""2O #NCra1`%jA>~'x}ܲj bZ-fhdY06ZFΑ C*DDDDDDDDDDDK,j1Zs?ww~9WW^^R"""""""""""@규s >LG vBJ|yZYs8U^W?}"""""""""""7)Ym0rn~H DDDDDDDDDDDK,Xsd k!EDDDDDDDDDDI,X󰾏=3Y10bǨBJDDDDDDDDDDdHɂrB 9L֑ϘNN-.Npi@Kc<G-~~89w~ MSL>Onra @.P4 P뻈sV"""""""""""rR7Qwg+kV-al߲%X=5S*(s\pY9,^څg?{uFTu_7/=5 Mq w7ē8ُ$IH`iSIC./efƣHejI+U3R7A>tq'ܿG7n~:9 i+NT 6r` ,[u+xkRzƗ(ݫBQLӾܺe5nYCGqb_(:Ja2ҁAqRSQtrh`dd?"""""""""""s@j w_|+wB@- SP% xSߓDp+*0P=:HҔ3/& &u!MBg.L-ZYLS-䍷#Dq)"8&YD~f8^M望xըc5hn_DDDDDDDDDDdHA>{:>']1YW\nݞs`< uJ5WcyAa}9Iqd <BZEI/웘_O|A> hU+cZVع60Y;?(!ǫ{rs v8&cPZɣ';] uMM-.Y -u}Zs{vڛP+0`9 ?C8qK#OThn*dq'nYÎmkYb3b!G_?,bRK]ȉ!~+ཷGm^v/  %NR c rcBmk0SsRv7/@Z;H=ݝ*.\n8u1#K1 R"""""""""""s@jl徻äYba {8~.s{seIu+غU]mj5*lob ظ\%5И,IRć%h\!_ BσgGwGϜ8}k^4?4X\ ⇷kT!~ykQ&&Z {:eRue)QML~SUX7c~֌@ι 9 }DDDDDDDDDDD@,wETk9cgON$3._}'xO>7a^x=d,g./N eئ*)._Jڂ |YuIc$ćYX|==W &>Ͻn{$G:6a@.wsZ-'! Y<V.@ʹ˕Oi~ ʑYDՁ%u0d| (hch+UұqI}DDDDDDDDDDDfI,4Q*=HSFط8ڜ2c00ɇMd<6Iyl$JWd?bf)W̐\O~sS=flaMG# ̒Y(rrpa ]Vu*J 0O>9G-E +Pނ[9wU eRMMsWSp%)GA%R~6kiF eeRcttc*J0  EJaT*{}A[+~e#5uURW(\0s$IJdJZ\ֲ/߄ )c |H.+Z^-@ bX^~p̊)c iBk-Q]Hyac|p)SOժ$THH‰pa40Ajimk᱇wނs k?/ _Ħu+Y q a^V\<{nom6sێ4kzy p9Z#|/b~:)6G˸4BDDDDDDDDDDA f܅N'*OgU3QB)rM|;iom3!l)c {+vR˦+mzۛ|;0=Y2O^ e_0>8[6rʁbr)FZY8r<e\c֮V~18T/~<=uB!~F) }׭I֭]#hnls?~Z7|1ޱ}vra@.{# vϜsiz@^fyƘ`kSRj'""""""""""(Rti^x=n_,ws+q>޹GKÜdxd$47im)tI'nYc"_C,vn_QN'OKsuko|, $ y7^5H%Irz>&063S æ ẐY:p,=| ѳ$ L'eؼE_q][ٽ}+vdQ+Wt֌ 񌇏kMME;{1?3<?uHWg ֯侻;n * H1;~_>}O,=Krˣ׸n\@JDDDDDDDDDDQ f)y? -= p `e?y=?@E:s5T\σ$B-Wg 8KSJ<߹%;xsyˌMP*lofْ.VZªKY|BLC.dr`SQ,ruf>DŽ!w%j04H0i֯_#&l.D5 ~/ Xz)+v{NHAljio.YaSU8S0.R[ײnrG09Q9(s6hm.Rh*B^Ÿb Y%W!Oy G/plbB2|3]!5E 4HIk{}B>&E1 & Yr1K,NL-)$fQS6ԙ J {\@nJn,WMV{Tٽ c_ ||AT=,&tb 4H<|QEZ|䶬2e-8d*0L87jq^ogσB|K|{O߾9٣v} }ƮeiJZi ܀yHR/Kyswҹ'T!Nqv]]Ō}cO1,QAΞ7ٗBn]Bxnz+p`0ԒVYk\NP uҞ:~O}wmeJMEBx`I짩b>TΌ XcHRKT';Ϟ̋«ql6ZeZ=nsٱa'+#%"""""""""" R7pe~q;;r[ؾy5+u &k!ٿ]RdAgyP}YՕrip/iz({3LLTISc ˁqPj1fH%QDDDDDDDDDD nLidtWnT*/h \jHHɂ>MMMxou4ke $&j'""""""""""ROXf EsV}BJDDDDDDDDDDaෛr\>3u$IJIc>S(016*18ZEDDDDDDDDDD@\vݺMVtIb$N<ϑc8uc>]B qUe@jPʹ\_֖nYβ%]47㔾!;DžKøPuc/zh7ߵ WJ#}sDQLe(gN_`~;Jy|cS*Y!j6vC 6T]"""""""""""r[VsMlu-KtQj* F8xϾyJmNTsێ ޗwi Ls)ұrŎgS-ܶkO={Cޔ`7T@䜻 )ilLcMZ4MDDDDDDDDDD(IJvPϭş|/~nh.B*,vsO0+ݰ;wmdӆa>9*v/܌u^ְQ &4:?ꊕٗ"""""""""""? n? bJV4#0E>N.gߑY>?zOߕ]w#&FP Yj ?ÒExӇغ,g|OIſo )Ejx ρ2\Zef"""""""""""7zS;lڴ |$Z\jqf1ࠧzlm5]iK]6ècc19\Bc?Osy|+ma50 sa+҉ iTmٍ%3YNHT!5O_y[woReECdꡔ( x{:/=N7^k[9ct^QWo)rtOI8! |Nc$i P(rUTZb+l= [/ [@JQ 5B>sO־-N:gnG$T5*cQE=qZ [}6FkQ83"tqUI˕RYuIVZ׾mM?{w?N_0{T*(W͐J'*܌`p9NDDDDDDDDDDD@j>qV{M=Pܾ7P39T7oֻ*E1_l:jmR>,[كdL0 5JZ n+I IDAT<sJ-z9 "m^77+Ty޵)GGH+里Q$""""""""""@j |]غ&XrBu8xo}I~?u(f vl]ã" Z")ZN_WOpY:ZXV}zV`W//`|08_AI3x%I$ڧR2g,+S?R 5MMܵ&642<7:w~cs1GM /?$ri~׮ >R# }1{NHsA>-RZPT(hkkX,N?fxL:>IƛL}1=%""""""""""OK0{%nݲB> v#w-Tx[پ}M-%@U1ti_kh͞s'Serx z>Wٺ+!Ie8cdFV8:_砣5ˁq GR"""""""""""7@jZ,n' 㷦l<ÅaFFu[z÷t"ALW`Qλs{k2>^M/aT*P*CUkk+W^{Ce-Ō,W*υGHcfpź1bAASxӌ7 KDDDDDDDDDDc(N.P*1 €uT*5jQ7KcXO?r;n^ UVA@cCc\\$V7Kx8q$G??G\.~CVuRKT.|<.c<9-""""""""""R')ZY \MW{ˬT/6Rhm8ɞ0Y%Dy_<.]Y%$IJ#[۩V|>G}0 bƍ\,Zǒq. ~⤩yS&j٧8JDDDDDDDDDDFHR1:63:6_ɚUKfu=c ;zW,pfj'O18TX yAdJF$55\1;j?0aNj*֬Ysy׻^PP(ԷQ9s>dV4v}3x DDDDDDDDDDD@j&*Rm `)^m;gRvn]׿wܶ\.UOFyC?t(XxQ;+z{7y㌍O^q~G{3޾C<.;[!PzэS.־#g;m˯y$iĉShߌA֭[y)W=ʢE(T*V\\.392;qZRSf_ݔX<04@ ރܺc=֦]C6lX7q߲؉'HӔf6_C R{^|?|7>K#֖>wϮGHUjqGʿ9;;w^ *F[[Z9^38瘘`dds &rݔ{ٌ/!E}c<һ|s{I'3`]V=S1|S|swqK$e׫\31ٌ8w~Z#÷wI!  r͛7cǎ!MMM000p@ Zz(.0O͵/i9x{0zSjm-~<|ȲUKXz1+qSG9Ν3֖u6mZ_62ow)sömغu߬A@XT*ݰ)MS.ٳ<G?@jj[Yq93nR3 S>/a 6ܲŽK0Q,,J-fT"S*OTxK< mͬZC'=Jzn2vȝ6lRH\P={ ׾~S|gӦMYaH.n 5s&h!l[;f>WYC!R06^G?v2!IGc:}[6[ slFՒ.ۡd 4{=Z+o䉧 MGA}v-Zts|'R3gRER)^\V(5l7& ))GDŽϟ|1W-jtԇ}(^_szښر{#;Fma x`gs@.>%O~/wݱ|G &j(F6\e%~n/S<7KT+ZO6 !0L$&. 4X3D>>v7bJ UGiJ$ Rqj3> 5zZy>>"""""""""""_&+5^x=^s\Pȇ y\j%<1IqPUԵ篒˅t4~(: xYg_yqoZa|CǧiJ6^izn80BrQDDDDDDDDDDDnHԯH'qBRcWcU~ ySweu>ZpS'/޻x<|߀Q3J%VXA`kmC&6% YWoch/wkNYe<PBJDDDDDDDDDD!oQ~8vVг0Uc˜:s'(MF477cL4mx5ĥO07L x*DDDDDDDDDDD@jxi?|s WH:m|TfP~> |DDDDDDDDDDDi HӔ8ssM81dQai.5$IB ȪK\i~HHo c +粯Q*/1G4JHZBRi͟yp+06DDDDDDDDDDDA nbz0Fk0~<Q wj> g]6CTW %""""""""""0 ™ukrmXv=]xVIRsJ5RGjQ`Ԣ4•j9k-:Ո8Mq6;Z~(&uXTkź(:'/2 &I5|uK%劈4Jݻ7ᑇnc͊t648V0)("^SEq:HU&$IHqBRHUkD2>Q%MSR눓 ֺ8!PkRR?0ʥQ8]gg-= #oe MrȦG9Դ9w͙z U(i90/~/~! ]P@gh6xd?;.of=]4 YR}tqE^r*f*bᕙL8U}eW]b;G?6II& H5Hcۺs ́ BfRs$)eZ |H5dFcrH2K9,ƒ[f֒,qIQKҒF=ݭfiKc{ `0yjm 0F7hV[-iZ(R/"~s7Z*,!.q#NCCp ~wT(KnXUsb4iY^n<!lt 1PAO~??,33=</eda󐚛 Ot;:'*CRxJ$I$It n[[- ,+/9v0>^r?/`9/PikC BdVX?F`r@J$I$Ie ;lum=K]X?GOy?g/ʏܾ;zaѩ/B,6HS#E^/pcVx@Jx&gR k/e7G:$ߙ; IDAT*LA:,'W_a#*c* ϐZRNĪ:|rvp *$I$I$I]`˾|Sw< udVM[?zy^^\~$2iE;)\l!^%dZ5UH'OPT%I$I$I.HBa޻O_> ݊\77*Ҥ%~nWVڢiuSm%s.ݫR[unYHz,Ȑ!%塃^^$I$Id˾]8znژU&u#x_|/8xpF y,kE5͌30gf\gEE[;:13ץs"I$I$I_oC|  ko㉟=w~N_ضw<3ɄIxRS Mu"-yJO^>cy_~gI&m4Exq^yo}-3p!q?VRL?ufԥꚵX!tVףw@J$I$I濲߄!ԣ3:% }qo~3 @NG&FIM4p*5LxL]7FƓɤa4r"3>'<{s?wG SNdjduyg_|W~sxrkZI[޾Ycf"k?5Z9?\%mٶW;%Yr0:rP$I$I$$Vc%;:2q~|o{q߯}"ӫ*[\9 P]qzuS:3DNӡ5I$I$In P դiIq'9 >'My]6)v2ӬD2=fJ\VBۮixW/A9s5] 9J΁@nK6uUZ7!o~I$I$In v+ffzӊ )U9)CĪ`cp`Mji7KsIzx0 W/I<=^l|66*"yWc~4MkD idѐzLU4ycS}C^_$I$I]0A!@SAQv.UEV$ MICnmJǁKأszibկ?xTU D";]f5aSsqxȠ%\=x 1B޼,#%I$I$I%6¤nz(e,rk#2wUQsփ+6=Ϥ2! E]ȿwWԴcfwg:,GΏ5CFfWEљ7$I$I$i nŅ~?BubFcmY^^Ṇy.}m!)N1Ƴ?_޸V?1ru;r50Zə*\iƢHu$I$I$If u~ܫr>˯k+EtaO}f,'}㶿^JmwIE6^9?5_|oWYa8Oekk4MM(' r $I$I$i n*_Əϟ)ϟcyes/sx7x;rۡ("1F"R@ ,1EQPH8 3')ɤ:14,G,\XO<÷$?xW\\X}ʼn{+nߨ9B+u9Q:H5$I$I$i v̹Μ[g/,_6G<0àߥS ]zN̠KSut˒L^CUTH*SNR3L&5k1g/Ko^>MJrn=fTV'm[m7 g֨S޺[~L'!9rAorI$I$I%Hhw#VynTFVlLB @c[5UUSUY0ə*(@j8:bye k1фx;Fm\ω ;Ʃ &M^/%9HQ$I$I$-}|ӏwq |?|=09jƈIus͙J r^9>`oV$5\6Ȅֻw< 1l %ǝ%I$I$I1:2O{3?3<׳2muBlCʲUL!¸&g&C'cP@%]^J t bH$I$IK3}9t|.!_Mmy2#Nm}ʰ&gV#V1uNk\͜(A:)z]\$I$I=` LjXZgx;\}&e8qt0eG#C !҆ZW9%BU9q$I$I$I+RR=pn&7 Ed~w;"395 ^!\)dx$yQo!A=qȒ$I$I$)p! s2fg.ҾL"+K{}bz+QJ,G沆}!srn W$I$I$iHno)o -B ;tk%]_%ZjrfqLuR$I$I$!)NUM+j25R1OBB۶hTΛGC !)Qй -I$I$I22R@;7,BMR%-e|O[9\%Z-~>č+MNA'u$I$I$iٗ (ˢm׷[hN4urʧ@Uu7fHW=]ja8d*v@&Mw9B1W$I$I=fPUe[Y. 32RVʙ*Fv{TڷZ:3IQu::J$I$IRE+`{K uPŁ̠C*o;s/DeE:mud¤IE^>LQ\TI$I$ITTeI qsvU49 ~ˎA>GqΞ׿_zNEݸ@anDYTr{s&LQ:G ѢAI$I$ITXQ0 n[Z!=/'Hk?K+9ԵeKV*:CjXOXkƌSC!tﺃj*I$I$I[m_Ѳ/r&&ZxpG?ػ J!RQPkWHMRb4@ΙL} *I$I$I[@TfHy{'y{(x M;GYH]Or,"eVH]ͨiXLR|1%Bw.YU$I$I>1R1Fؖg=ꦡ~*ym$O88;޻O03yw^W)#t*TΙ3z¸i6s&c$:Nu@K$I$I$<+6+6 B yߝqbRژ_u8~GpNj RT!RŸъjFQ=C Rfr"W_^\ri%I$I$Iz H@UŶB 6H*e&dCsAzꦏw?|Qꨍg^ӻZ2@Wv(5tC"Y}5&.$I$I$mE %heTk.x}w){>o3 ,,0MyNUǿϗ `8㆔!d>w?Ͻ:?yyuy}6 Hİi˛YzZ#LNZK$I$I4ؐTI >?#ﺇ?=^zM^?usYY:dR7I9~pPא6RKO-jg? }_y5:mfo7]5IL:6+ݶ~nJ^X^X OjBD$I$IxKd0!4!4CBUp;8y]09{nY^hv ʪ41@YЛN%%'smB[5O:O%oPp 3Mj+^LȐF#U)I$I$Ivt N;O'4mt#BKEnhcUIlOvz>WNrmUDw*o8{nwZ9Qĥ6TOh# $I$I$Rt &ޓ WtN|KKӐkR*O=w#߭#L44\k= HIMLH$I$IKVHazS/7 cv1+Lm2֖+@sn6bLw?|^Ciw}/BqJur>!M"7/$I$I$Id 5r毾uӰƧ{Rh*B;i-eS>ۉ}|eH{\=k=W9y4WNBRaH9(&gr΄K*m掙WC$I$I]3ڢi_O/O= s3}:N("Lס,6*"nʂn"H n"-F GlyKJrmmM> ;R$I$I$햁nk6 iTʙ:ˢ-;(^PR$I$I2{93Ԍ@*4UM d# -I$I$I.H685 zG-R ̜SĪr%I$I$I%6ԆI@0 RM _u%%I$I$I^BJ9gu$evGe As%I$I$IRuj5)}&mQR@1;X$I$I=` V 5jjFdg\6?*V[m<rn5$I$I$i/H鶖Rfu2a@rNd %, )I$I$In[!Xkhחrŭ{(fE$I$I$iHrnCitYe\m3uT`@l'I$I$I^(]~$,is'sPm/? 'T~=$I$I$I n/9Hu, iDQ#(6v1i]PGuJ$I$I$횁n;S0\S.;{b((z}BCv$I$I$i/H#>ΑqjX5>_ B(ڈj=xEGϣ$I$I$I;b n^Dș0ZG!kTH5#V\$I$I=bL&dG:L~ٿjmt IDATC*gH(+jH$I$IWWw2mSzAgX^^&JU(!I$I$I^e38J@9}Ν;G4;zMԥBhGEGI$I$IW y&ޝ'8#,,,pEr;cJbzO&e)I$I$It o9Nts{!c^}Q\UG,W6 ͡ $I$I$%]X42y2:4ǁG=eo믿uIUSĪRf !bg$I$I$I;RoF9Su98GpiN:uC1Rt*bUA|T@$I$Id@F522;906{79} 1RIJ$@ gu}Cm%I$I$IҵHiʩ!@q1eWVV8uϟ} Um˷>vT̉TOO$I$I$펁9gR3!5ݻ|w?L1m%MRUOCd[I4&C$I$I=b }$Lg85IM޻9s*ooA]XpTݹY^XhkB{)V䱁$I$I$I{@JC@?O~6M) /p̙GC~請|( > *̐jKi4H$I$IG  ʙ?)t|xg9w܎vsn+#UO97Gv̐@$5ze4$I$I$I)R!:*%ш}~cW / 7unG~o D:$ I$I$IJ@T&'tOp{ʨv̙3gxY\\xZ !?F}`T2i4^[#5TH$I$I]BJTN r<0?g?I'/*ye_ۥw(塃$zTriWIH$I$I=` [*Lrw>py9|iӎeYR9LHaGrYY!'^ I$I$Inx?{ēw^w/ӟpxS !PΉct!n^\&K$I$I$]njnFEAly >!w V!gBrӸ$I$I$풁n )%~iy],KbU9vrnP39CJJO\|I$I$Iv@J^Ι_~z^{m7Po̎jhF4+ I$I$I.Hi߫_@L>(b9%dL'9ʊ@$I$I]2ҾƷm^}1RUUUmy\뚜}}@$I$I]*]gu] /ӧO7ת(}R9\'ș LΉfyz@J$I$IݲBJڅ ;yվʲ,9!Wڲq44K^I$I$Iv@J믿߰ pӳv[iUΰe!FpDDk/$I$I$I` }k8}{ ](RV9@ Ƃ41^Z$I$I$킁_|ԩSӻQж[Vi^!u!F#%pJ$I$Ivg }?w7]\emGmy G44+kD$I$Id }'/=z=oYt:¶+Hɍ$I$I$I7@JNΙ~g?*omTJjLȐGc&/ #I$I$IM2Ҿ+|^xfeI#ƭ}۟ G !3 #I$I$IM*]'ϟ[?яX^^v_ 1cوBnj/^$VHI$I$ItҾ\pavHbQ@mU#ȋ#I$I$IM2ҾP%gϞ{Ҫo]ۥo{-@( BY7MgHdq4=I$I$It tK(wW6۫v}p@eΐ LvnIԋK4+9R$I$I$ )0Fbk|_?kUӹr Ul.yHkCUd$I$I$&H*U/|;Foݬ^`0ZXUp!HuCD`$I$I$݄%Эȏ~#x y`i/mG׻B UI BȐӖtT0YXY[Cj,za$I$I$&Ht:9r^QVz+ Pl/|R//ӬHI$I$It3![( .EQeT~Ns1RD4+˫^0I$I$InRBoiJ'Ar:C*ޮ/@ PҬڋ&I$I$I 2-s&4 :T!{m [%Cy4&'/$I$I$I7@JTJpHJ-;z`@۽~Pu QTKi<&Hk#/$I$I$I7@Jd2aiidVI]e{]BUr!5"OfU/$I$I$I7@Jh4ܹs4ZoW/z=B"QmE۲/g5U/$I$I$I7@Jh4ٳ-fffET(hB ɤ!͊$I$I$I7t t+?{ywUlv.K-{ly9g'E$kA^ 9 `3|,V_$jgEd7MR#Sdaܽ{UVWWy?FcJ7&J!IJ )T>$I$I$IO )X;lnn2y:ʸt Y|3}I$I$I tnNHmmm1Lu4Q˞}IlF=8=9,HOJ%ZgHI$I$I tiM&@*f=u:0叇S@ix)I$I$I: 666f u[SFΐ$I$I$)n.XYYyu:g]ҵ4 6n$I$I$IO )]Z\zփ)u:#8޴/rgHI$I$ITҥ(}$$eѬP͕$I$I$)X!KxғRI{~u6_Y,+$#5q%I$I$IzR677eP"ꤨ-+gHI$I$I4 tdޏ\-fݠ}A:jVi7dI$I$ItDm۲錃p.)e d 5M7X$I$Id.v}kkk]obG{PZ8lwXnHI$I$I tDlooa U9q`%X(*MKi$I$I$I[҉ڢmć=wDQU&,I$I$ISBJ6[[[_n'{0mV"]٢E+I$I$IS2ҥG_x666~g{}f߀Li$[%viخO$I$I߅._@W?#tJ&wh/HJ$I$I;0ҥK?rMw{>(-Q ˡQ$h䕗i7 $I$I$I]HEׯȵ=~swaq9T"`5U7Y$I$I߁. ]d29~o;?1pXG-u`1~+[W$I$I$I .mf{{xz0eg?.i=԰&e2f4kn$I$I$I#)]*mrvvvFݟ߹ín~N GUO( CO{շ^9%ܒ$I$I$IOu tt]W\y^{~!?'( }u=u>'sLƌ_|k*$I$I$]d2ᥗ^bm{?aDMâQ_(JlѬKl~;tΏ$I$I$?.^u}d:DFPl{lL^{eԹ$I$I$G0җ^"XL& C[ >hPј7µ?!U͕$I$I$2`mm_~D Wݽc؛TJ^bu(I$I$I!)]*[[[\~i{?gg+:9!+QVu6w#%I$I$Iz tic_իW)ўߺ>`ؽGͩ&@˽$I$I$Y2ҥʵk9O>e~&t @q_ L$I$I$Iz tilnn /ytfn|B{2RXDPy_Ct4n$I$I$Iϐ.^yԧtFdĩqTiO$I$I$n tiK'g7ChVBi⟅$I$I$IϒXߟ?;qwwa8NNZTMkp$I$I$Iϒ.??Mlp0%3UHΔFn$I$I$IϘ.qT@J$I$Ig@J)G0mKc忛n$I$I$IXpӝ~ ^F+i_u,[AD!un$I$I$IϘ2QSDpcs}[D@)@=ERA)c[I$I$IHLցgwwOBo@e(q!`f񈲲FJ$I$IHR9 u??{۷i&&ip$f2q%I$I$IzƊ[$3tA?e/%ý}(Ai&Y+^}@(㱛(I$I$I3f KgJ;@dn2L!(% "Zɘ2@I$I$I1)]:χ~QWf7>}2ab*e$4++č$I$I$90ҥu`?)r6g rY(ABY[Fn$I$I$Iρ.p:zo(jViƝ&I$I$Is` KV0oަh5+$I$I$IzN tide ;o!=44kkDg$I$I$Iσ.y&Sr߽C{64k )I$I$I)]ZsY&;d@@De~hWW)mI$I$I .!w$I$I$Iz twaњX~Մ {3c7M$I$I@JpGDݵ IDATѭ)wGsE˾`(2F#&JJ$I$It hX0^ΐ*rTUQ_NJ$I$It w}E(xdFG3QkWwM$I$I$ 8CJփsfrs繁ƥpZӾI)%!rTfkknSM$I$I$ HŠL&QlZ">0pkȀ6ŜM"hQɲ:jeBw ݕMidI$I$I΀.hx_9jͷ[ց &⡾baP@e9;j ڄfeb %I$I$I1҅uW m^r{jRe(I4t8 Ʉnsf}O(x%I$I$I: ~" 륶َۣz;r$h FReK?XmlnRF )I$I$IΊ.tc&lDk݄2ʝ왓2*THEݲe_ իʘ2$I$I$)]8tMִTnV2ʽa`$} Gt;W6i")+ʨs%I$I$I:#RFN$yX! fB@3}JI$I$It ta%IDou]Ƿ-]vtzu @Bd5$I$I$,HJAw7Z;曋2=ٰ2XTFJ$I$I$ Hסh |wߡ!.~wy_|XۛΘ @i>I$I$Iΐ. 3集Ǭ#׮o~3u1@* ͕$I$I$ n.eR0~5~=/6668z=zCO$YTI=uL$I$I$LX! )F;WW$秵VX+gٲ/$Zyo>I$I$IΐRp"j/snc fLӣ{}ϽٜryrH$I$I$Iz t!@0z%V5G3iQuU )I$I$Iΐ-taS3Ң"j}~h@u$I$I$BJP,*~ +F4C+ter7Pk=? }y&U:BJ$I$Id '#"{7:tǝ{xٿ{޴so>deE$I$I$Ig@JaT@M}v#>{:~0̆,Sfd?BJ$I$I3 )]h9B}D $>eGR$I$I$Ig@JV9 {{d}tTD!ۖzoiV+{|q#ȡ )I$I$Iΐ.. {%cfL $ 9-$I$I$I:SRr!(CϦI[!%I$I$IY2ҹW<eRǶ;||M3q;: n$I$I$Igu t^"(%"`HbE{=u6ERIW}ГY!!UBJ$I$I3cMf.*i7)%8:CH+E"u`w6 p$I$I$0J([o"):ʤjȊRJr{v@eѳoQ-%I$I$IΌ mFׯC=v/z!"h:3ws97*GI$I$It tFW7)1J "rXχCMx%I$I$Ig sreo|2u`QulAVJH&&NʝaH"󥊩$I$I$Ig@J#=YCLq2zвhw| '@J$I$Id sh/B@e(k6ֈȍ$I$I$ HB:Pk@heg C%@*m_q%I$I$I:cRjП@tHՃ)>g~EUCt;WlI$I$IΘ]fB R[Eʨ=uSϩ hPӾ)FK$I$It t!0@SNh!ƣS+fzIBE<GEqǰ ++n$I$I$Ig@JBuQ%2eTBƧVH>Ƨdb"zp0ӏԶq%I$I$I:cR:wa'E uZT>[DieCTmPK$I$I$1) &AH-Nh?f~F{hQ˾9Xsf}߻$I$I$1)]u͐cףmiƓR>gDkaudKM!"X Nˤ0P3pI$I$IΘ]=Qcӟ˨FG Ӱ~C@ ,bV 2K$I$It t!'# qwBjM>-9D|# Acq0P $I$I$I:sR:w00fNA:hf|>!ǷdD)0 ΐ$I$I$H\e&u3WH%u4-~po"WHEYE U Z+}߻$I$I$1)@@z.T4Dl>@D$I$I$|H\e&9Tr:(sZJQ ͸L'Lo|B<8CoߕK$I$It tjgGaaS4A(݈]PSP9ʨ"Y!Uk~K$I$It tR|N)?bzu`13X hRVHI$I$It> t@R.GE/}z$XO̜$I$I$IP t:YOdIhDi[{կvRӏl+3H3)I$I$I.)E Փɖ}e2(Lo|MǗ,Oq9DER$I$I$1ҹLtFA3@?_3K KkQJK$I$Itt^*3@aٲ/!IJ7L{¢)sђ/Pj[E$I$I$Iu tTO?a ݹE`Diനi0,BJ2PO]׶-m둗$I$I$W& -BeEYs1+cQ5RĨ%B,OhۖsI$I$IΘt3r6'kOƢ_u.u:M"_5)m6-J7"fh4 MӸ$I$I$1)LlNgd r:,'2Vڍ 6&ӌFT`V+y,m:CJ$I$Is:_@p0 28:jGqq9կɕ|2} a<;CJ$I$Is` sUao RHZ":W޻L^{hZZIz3뺎hd %I$I$I90ҹa@?@>PT .¨uѪrwaoSIdI ))I$I$IΏUbNP8!$8)I(wwߡXfD.(FL&)I$I$I΁Uʰϐ,g?IAPsyO4L^L^e>mLA'HEɄF.I$I$I3ҹ~`[싣R ET,*2+^`O7_'ſ$YPa u.I$I$IU=uoJ·W&^]|+? YVvked*2Ē$I$I$Ig@J*aoh2rUHr݈+ɿ|MHثɝ3w[[[s%I$I$I:ӹʾgwNV5%PkR l_믞\I$S&TUI$I$Ia sCNgPs1 P=eu?}v?e孯?HEwf2$I$I$+tnâ<wW{>s^j>I$I$IΉRP ҵ}-Vz In79-_ښ,I$I$I90҅@B3|4F8CJ$I$Isb gh/\_>Soll8CJ$I$Is )]Г@iG4uJ ն-\rhJ$I$It ta<qu]3nMu;;;HI$I$ItNl٧%3M)#~'Wԕ+W[I$I$IΉ.@)Av?GnݹsEUf2yY[[sc%I$I$I:'RpET-n޼pph'Y]]7ޠ:7V$I$Is )]8͏cf#VVVx뭷 $I$I$I:GVHjRk._֭[{'_rW_}K$I$It^V}r,^>?)RڵkR$I$I$#)],)3x'GZ__^6x%I$I$I:/B:z?3idy}N,g&D Adi cxß΀aca0$0 xl-DrHfw-vUUٝQY ꎌ8ԛpE?\{/U$I$I$1[)Hj)ԮW?~mGw';wMQ$I$I$0^oZ Y/>#>s_Ep?]ǃ1]t$I$I$I7ȆJY\tP_!Uk嗿%og2`#8)A $I$I$I7ȆNBOlN#=OXd/:kHT*tdHI$I$It ֪ 'G_W=avW `HߐZɮ@)$I$I$HT>+{_d"Y~!S0,vP $I$I$IIRzL1& i)9 IDATK ( =T5`J$I$I$)Z",CVH^I58Ujd&+I$I$Iҍ0gLtu~YPg*I$I$I 2[g'aTW FM(Qʳ9$I$I$k?J5+5hYNFI$I$It 5DkAZ4򗁔$I$I$I7ϑ}Z )j0n&}uѽzƟ$I$I$IZ9)vAR :%I$I$IV͑}ݰxȾ! e\Z(I$I$In62vnH"6"?]W$I$I$Iҍ0농`4\B6q4}dHI$I$It ahH[RgjI$I$It A#>DBjAJ$I$Id ]ƣ!J֯6B/iV@z4 #^هQ$I$I$Hi#nn2(Rj. ,x͙5R $I$I$IARZe{k jf?KLKJvs>fZ˗$8O$I$I2#* - bهj!Tc)!fTvs>"GD\*R$I$I$ RZp՚ammx<xydߎ"v|yZ;MZ+ߖR$I$I$ )Ԡm\Ӷ-V&݅aۏﻂӑ}{,e-hisj%Y$I$I$:Hiڶa}}L6L&{g?΃tpTЗu k`L -/K kHI$I$It Rm0 iX Ce}mLDGDHUOʜ@iG!2&Y!I$I$I 1jo& 4M\]Wxwt>9}H>B a+7RU†$I$I$I7@J+ -M5+G~ywDς/r$$ǥcR+DsfS2iT? p\ {c =M^hBY}$I$I$)VDҩ&+prTԄe qH5|h'6$I$I$I)RZ<$"loo*"A) "X{W=R$I$I$)Td|$MMBI]RkFe.G"I$I$I 0J՚,,ln +R<- si  xhZD̆$I$I$I7cGU2/( `в>f~qz~-Td0ip XoZxIdz$I$I$RZR*ɜR mXi텍dR{4^j#Xo^9/!rn$I$I$Iz Rpx<+rdMڈA\jzy&Pojqe%I$I$IMrdVj8<< з`m4m]d8YVk.3Qcg$I$I$I[ɆVj8m! 3!۶Ⱦ4+Ӭg  h}Y$I$I$Vjg{ fA -Mshӆ$Y5ap+$I$I$I)RZx4dYb0hiA0ʤVah(j[$I$I$IARZuفQDж \"(z~d_LZuV\,Z=I$I$InVj4>A΢/1B#.HRr_EGwxD9>&"I$I$I 0JEq YV˦UK0 D*5Pꥷ,L2 Nx'"I$I$I 0Jmnq6rn_LtQܳ$I$I$IoVf8:@-Ɍ"!xwm<8o~ރ$I$I$ 3nop7R)t R bHGq"̤fDp_rKH$I$IHieZglq2˨{!"2| 3$I$I$IoVޝܿE;h8m/՚L&3p}} UʹrS]åt''q$I$I$Ib wwww9-#EhBuW]!I³D4z3co~J< I$I$I)̃wgR*D- ',(r\O_Ўnz2~NwpI$I$IHi%Fs6v6)eC>P胧Iy.J *rrɯ?`#HI$I$IHo&ww)5L 1^- @G?TCI~o)'K$I$I7@JS5 .wnm1h&iCjzvR5|nD_f"]R,Ccf|J9:$I$I$Iz t7U]v7&v2WmHe?RWٗ}8?daI$I$IHڵM;nև@V&9G+5J@2/H?&~龇%I$I$I` k7h[em4>D R*錣*$ U ?_⷟$I$I$Iz tƣ!wno3(At#NR¶J]f 2`@`L$I$I$]`в`S;Ⱦ:ԗBwtLHL<0I$I$IV@J׮֤toEq&G'+7$vH}5;tt$I$I$i t&}tʠoa>892-|yM_!}lĆ$I$I$If kXtO?4@*d2xrvTxT9C* @c&I$I$IҊH՚XtȾ&88wH@-:QK$I$I$IZ!)]hȝ[};|@TJa23-.e(CewHu:]I$I$IBRVр[;[ *KT9/P);j> ]xp$I$I$հmXc0h]LW CdTaU꼾BHI$I$IJRm i8Rz SJjgP $I$I$IZ))] !\e)a>/.R,Үu_6" Y+%PI$I$I/f B:tKfs6 F~t_+*t$I$I$I+e kU3Yt\f\- iQyV-PaTcbzp$I$I$U)|A)eC*Y,speuCjF^Cٯ+K,Zg5+I$I$It~NV@*YKBb,"ʋ}_L kRbCJ$I$IU!kUke>_PjX[t\-: i ^兵U_|, Ն$I$I$I+d kUKe6[Ԇ*Y~YM ~B),Ń$I$I$i tRLgG$8/B2ByE)=z$ZȒ )I$I$IV@Jת+ɌR+ː'/LN._%$u6$I$I$IZ%)]+(cҢrr@IV#ܯ]ٵrс#$I$I$IZ))]R*']>,DLG~w̠, pd$I$I$I+c k7͙,E@dҶA4 "=:Z. 2|t:/vdWL%I$I$I.@Jn>/OB}4_ȾZݼ&^$Y:r6!%I$I$I Hu]ᄮ+gm撷[rxZRyF\u9y%))Y'I$I$IҊ t拎#] Z}㩐LrrŗYK 6u/OK()$I$I$iu tJ)-:6W2 ja&BϾO-:@J$I$IU1ҵ5?b6_,Fv^&Y8~Ⱦ`D0|ndeVW(pd$I$I$I+)]#&y?/`m##Tɉ;$I$I$IZ!)]Z'O9:Rj!" FFtqf0l5iϗ XHI$I$IBRvYGO9:PڶemʼuO& jGwt>I$I$IV@J׮fSjI"mX658Z^q4GlkUR::"_}$I$I$IWc kN8<0/h-k/u 8ڽ5kѰq>ʼZ \$I$I$Hi%GOha۲.pX Ձz4l-MijPWTxI$I$I"RZ$;A-[klqC* 8kF7 [/?#dQ(G$I$I$I+b ;8ih ͍7NyVjWv3Z6?Xꢣ{GwtLul$I$I$I+a 98I$I$IV@J+spxݢP3Zgw5T.K'YدqSkl֢f~P*"$?C$I$I$i 2}CꐮL%_+l4}CjAeqkB\Ӈ?$I$I$IZ) O/d&cv7|iPtl7-[0eEMfM$I$I0ʔR9(%Gܿ`pȾy&Kq-aV;` [^ IDAT/<[ h$I$I$麹CJ+5-x٢x<]a|ff2gWnZ6}"SHon:O$I$IU0J{GLgsR dgk<<5Ӭ,^j Fg[$I$I$I+` LO1_, GܽÖz.JZ[P!5n 5 ֗#h77hF#L$I$I0Ms?9d63wwxDf@Б“x.:o##Q_m`L Ò$I$I$i rGOM@jĽ;΂g_ OJʑ}̀6╡2u@J$I$I0ʕi-ܻJ TǓZ. w2bYj4)I$I$IV@J+WkxɌ̤iܿJ.)8cGMM˝vNַf4&%I$I$I Hij&p|2J4768g^eiYk"U b<@J$I$IU0e&pt4J;;lomА$<-_Hk;G%U R_$#@J$I$I0՚atFژ{wwE)i<*{hH5C4j^Wf8 Z:H$I$I ވtCOhxȽܾEI-<. ˁTzm8 D$I$I$IZ^oDMxcڶa8p6nopX K4_?MK7Hi~$I$I$ZH?b&j]ڶx帾=\n;2 $I$I$IZ)1{<;f-ܻE6|9Rm{Z㣈뾢$I$I$IZ2ē'tnorO9G\hpN4\X>rd$I$I$I` 7foGOJdcm-w6,. Z`MKGmwY*J$I$I$ >Zh&w,8@jipA*HI$I$I Rzc<;"2 `tggi:[MC+אIڐ$I$I$i% FLFmK>丽w!?3<7m+ $I$I$iE FNOɄ&Z(ˉԈoAYEbd-p%I$I$IRzN&3~#3iG?`4x!3\N; XA\@@V'I$I$IJH:>G3ɚ vlk9OqbHdWjCJ$I$IU0u2'8>QJe0l]ó;53Z{$:0$I$I$i% F >{ǓCöeksw߹ЇNC7RV6L/,PBVGI$I$I Rz'|Ǔwac}|vSx XBhA!%I$I$I*H鍛f|g4A66 h&#*$"g_R<I$I$IV@Joܢ+O? .k}C̀mZ&%- $I$I$IZ)q&g@̯Ԕ8 <I$I$IV@JoRAp#iږ\aGM]FK$I$I$IZ^oJMPgr<&6;C6wJD|}A@@_I$I$IVo&x;no4q 4t'S',Q:;m~cgoJcچ0$I$I$i%x]h4?x%#`olC5?k&k=!_~T#$I$I$IZ^W6?{|h?9dc){J&o0Z껤mmHI$I$I" l8ly-omCwHჵmg/N`oGW ̬˧ngŠtoONd+ˣ4=eӡR^<-&3M& e)|g/NU׍fݿw>۴$) =ҋzBr}\@T{YDWk%y0Ta0p>'׋S-VkFS/%3), Z?>t}vYɲ 4=~pKٸII*䙊]R`RZE=eYҦtʲ(_?׳/]^Uh Km uؾnI27XtPC >HჹJZE=yk&>A4:~+GsɂBi->- c^? +=e3p>KZWJELArIPzr??{,䭫=v6_Iyݙ,FHჹZU(ĠHӝmm3d_?_=7<%ӡ4X7I"Wqٔ'Rp.UZUH. wT^m9SsTT$ˣ[SMJIr7aK;\}B /#sVJuH"T@J6̔V|vQI%_S6J?u@]z3%wxї+{@ ]ZUꦕ$y :&yVZ.Xd=8TygP˿\8h'@ Hu垔wwTd(n.6 )v[){c ?=P6akGP >JZFU*F)3IbdэS1Ag6/7$, R"?R(jTU,Hw{앉}/M1 _'hQU72I!GF7ؒ2IrWIRjdSrQb8uWb)bCjG @ :4{~/OjRJQ W7V>Bw,l3OQi%47ѐ\RZ}y$Yb ҳX ,B0QƏkUu#)Ġ 5zTRUKMB'n_rI6^e!@ohHu%%e!t#߇˕VM]n%7IVZ7];S2(zF ԍi8(4使o\HzNfUZJU#_jAL1g|V7U\2u 4Lf&섲F\:̔vU]՛۾<1Ȳ( 4>ZU7F)%%we 嗛Q2S6hmEHuސjkZwHE,a#)|nUUR*^ۤXD h[Rޤ&ul-_W2k )Yb@oѪQUu )wWQd*~wHYגr8jOb?35JRB*.VB[ l>Z]7Z׍E UH-Q. A&? :lx=zB`d7@ [+T)eIq2`3B>uTsrHg1(d l>Z4ȾR޺3M|6nL.EImRsRsx3te$=#Gn+,r 5̬kIˢi١F_ܑeARҒukㅚz<&@ѪQUr"WY [监tmݱ_R'Jל.U]e!\J,fHC Hᣥ䪪VmǠ"v/+3m&O.im~pKtԴ[T~~vY汯%)DYs@ R7geQyOȓK.AT彽.r]4$%ㅔo\rIG}@ 4ԅ>1FEM&o, {g#Uzxtyvs! µ4MպeRe능M\@ipoOȺjs_3,Z=:R;__nFnd_!@p-uj]rI!UR${@RwyB7IճSU.+}V~񄛋?iH;)\KS7ZjI]C)˂<ɶ:&eRO4])Fy.)RUksUu+ /wRȢBs@ 4]CJ.Remebgޞ&?D+:%^ƺ/ vOA3Ot~boRmk\fRe~ywGvBuAF_{,Jrɻd}ۤhϟ*Ս d.)MR2vH;>ǵ4mz]IJ1FwBIQ&?}M{Y jVsy/}'xh Rd}!kiۤ庖,(Ϻ}hHIpL뻣$Yi^imD kiVUk EEvRf| ;nLuJZjnJn,(C HZ救}fbTg R&"vlgԴ//]RZ٥׾;Q,#oR6%ֵ]LYTl |g?Pyk&QޤUwdq7٩e(Ze\&W2)zG kiۤuUM](;>9],;3d\+vGI)i u# ︬M2F *C HZ6ijR1(/r}t"y\jZcxGʂ͸Rਖ਼ujbw2Ⱦ #wR}m*%WAeɥᧇ.tiESjZijΖ%mWbľe! µ6*)]!(àp~ \˻]ɵ5l=Y jΖ:o~|,[2z I!FYN @4ҶVJm )&I2hû*nMQf5':_]7=_dY>zGC Ҧe (kH˓+䙦iM]Lۓ$Y՜XަRf.7WLeY"Oq-m>WAe2 &yJBёPEޔ Y@4ҦպVJ$W>42ۤ8,4PR򺽈\Li'#yJ>nE)d+@4ҶIպRJI?yryJwGSeaw{N g#}.}WG?B 1ʂq@ ҶIUu]1yT yv~BIaԦ% ܵc-T٪ t~wL&b&eQ CgRպVӶJBPY H6)k[?̺QRC"Ju<ɉ\f3. /Y|kFV&TsI~zWwGmfE];WZ}\|-}H;_yeY>n-ժRW' IDAT.zebi>퍺df6:ZhDi]\$QA.)F kkۤR$e1,]*jm;}jJu㹼ieM 1B! µ5mrVv ߷\M $dRLiYi 56͟enTwM)Ыm[-kMS<ϠLqXjkUORzBYנzu7Tsu;Ivqᒔe Y& R-%FL`=R"Sq{'&AnU8Jm1n/İ>F ksw-Wk5mRA1e^{¨;*,t^|Ă]U=9Qg4> W2I!Y?xp|ksw-V6))M {c<2Lի9^hXٲ&!bܥrHSA[d1M'03hsyn2+r~,R(nZ+m+.*B!=LF;[ &LnRiKtObppmj!#|rd(^k;udjV] w>><2I!d7@ ׷WUܥe@O臟ZP]"(^zr폚O`B 7@ Zת.bPT>;TӦc/G<|ىԴ>zTw՛Be8<n]ZlR+kH/`wكߛmSאn>iKOT-tQR7";!R6#Bv4?'wUR:oH?_ekGէK-~򸾏uA \>ǵj3i8,<ɏ> 0zBP[hXi]_{ l+ލOqmrU'ɤѠP]}yvjV'۰.+~t!% X&S Y7%:>w-W+Uug8,pOpXi^ (d>Rmc, `7%VUJ]si8(]1o4Oho, Jmz-c2uRݪzv/ʛ$m$s]*C '؊ijM#3pP*"ڙ /i<*ezԜzxcei M)(n "rjLa_d/>"7AY4Os5$Ydsp)lbb%3d<Ҡ|=ڛ[ fJ=Mݵ|x寞۴Q$RSRؚ|r&ʢnt$S"MԮjyգ#"!u%oZ @ /@* pp9ڝMtfӱ$)}wK ]y1_)W.-LRJu͡p5e岒S̢Fؾۇ3ݻ{]TARs|s Ha˵?;RX{Z몖Rd̔֍U%OIv~{|BC @ Z*=zrj4ڝ5ժR]]jVZyiw:Tj5M{Ⱦj4Y/TTzDщ<%HaV?=rU)XgmզU{,׋&r\s5G BZ!f;#:K (i?$.7Hyer'Z=|D @U)N::i[L}+3SJ;a` //ZyUsx@ [X鑖JPw+ϢB0`g$?C辮ֶ. RוV_TH)l]U5zHR@h<,reY .GM.)DSAiI$_57j+Ha6ck TX2z% AK5ZzH=!֥ٱNK;яDh8(&}w;,)}JjZGOU??Rb %w=yzӅ&~?J?B)d ˢjd&SRHճJ%@2~ض?}Ӆհ,~*,(Of]C*dQ]dwh_7+>Ts6W6rl )l]Jg/NurT]tp0dR}D @ЋMz~tB0mRJ.w납)SȺɯ,QK'H)љOvԻ2)+2&ITwcVH7'g -B7LK;uVəS5H7K,oKvH껭d/jNԞ*V[F ޜ-t|2Wjۋ6BP3"w%R.7#9H7gOj.w2u 2f9L/88@ 99LmJ2f.Y BeS.\殴X=;2)fXlzӐzD*Ġ8*$r7LiRsJ H7Mj>_k;FKEeR/MWdߟm^S&|Vs2)jtz\ o %nd߸TR~i]Y84@ Z+-%IeyT3by K/42)j5_]wvlHy{5`ZZһR~>oP(B$IV HWMjZz>d2"SJ0)phlzմIU%^TB,F)H6o7D.eЧMZn߻I̕,nHIrIqpC`hHW)%Uum] A,MJY.7MyWrܕ͔84@ JU׭RJ|HBߐRΎ]шC`+wWӴJYprLPa_xm9`!ݩ=ѐC`ЫڶrY7m)dR3T==e{Ƨ蕻Զ˔#OruQ6* WnaSqx|(#@CM˧#A!{}oR+Sy玲@hH_MQ8*}7Z{L8/z@ ^Lf"y}B+ {HI"ul2ze&dflSMu'KȔ ҖHm:R]lP*S 80z@ ^b'_QoҕLqӐ BiH$0*G,r`@ 23,ʂ)ll>S>*6W&2Be}x{YH\uvTR@lSֶu- H ,],iH){mvHJOJ)ɂIBt{i[6I/Ԝ-ú){Ser|'ώU|<* 펺ے&QszvUq`RUAYjVR%ֵT\-x2S*wތ^&K.JАRUAyܕkjUu+^X*&<䒛oj~d1ʌ } Bb!\umUU]fқyr"Syw˯DmvQ٦]TB+nl+IMZZ,Vjۤ.ˊL ̷G$Řip}lÁ)dˑ\RUӼ}LB &峡BiT6jT~rWu|^IP&)%WU:/4[R$mbo,+Mz?#L&wU; ,(E@Muj1ߌ)|,q|Pҫ )Kmr{G?B7\Z.+5M+{ n_+QD٨Pe[gR4?g\=Sx=u)Dk4BxdʻP8*[w)wW0S&n0 ѐBܽg,bא:TՍd֖K P ݨ=I2{ GvuO_~!3!UHILygKU]XlPd{+UPJ=н?os@)*yRZ ʋ\yϗ֕<ޚHmeB~ب0J]}o(N8 nzնI2Ie,rNϖZwK&ǃ.zL2ٌ*?{#3B ^5MuU*\eYHOZkerLXl$+i֦T%sl3m;/Tq0 )i[UuAYh NZ,rwٛ&))7;vIrd=Fwq(ܰd.wW9(4ӹNZ󷮑•F*w$ Ԧuk5u?z?*@;@C PRY b/Nu:_) }/@X$QEQ;wtH?%zs?_C]"θ ڶg::>S[䊃BH@^fL_4SNuGLw{Лůio6kP]|zH!fː]ȔFw'2n|" ptOv~Лۇ{{_!ft2hGW>Ͽ~6޶G]Ge;#cyR^Eb9P_׃o!=@ ެZUUoO,N'y?˯ىܥ^OL&oP8*Tޚ)}J*L?G_7|bui$uSb ڛczU_?/~D.W*@2\LR}LC?6ͥ0)FGfcMtt2ףG WB5U,MXf:Dt)&fQY.4 ;tA),wGʦCY7AVP}K?S~|H7Eu\mX:ܟ^]m۪;!e1(؛({wsM~dy)f8(T|M,tpW1v^JIuݜET.SO˼kHM"B/Lx4pPS$6,sݹ<.nWEhg!%)Q!Q毫bdo<+ Ht)53Yƥ c, .Cui4ᮆRͪV}t&Mtu%ム cp-Y=E f:dTʂ.FI]4skWaDRb-If&42wlw*? ->/tpd(NP߽hVZ3u#7_)w<;f W4u!n4yr3ݽd3I|ٙҺ7l3LfΞsOt1Rغ,ukW"Wjҥ}0t$Ԯj(*9͓*v4H; 9)l]Y}8SYjˁe;#h M#5'MJ{wA8=G t7SJr u>o0(tx0lwi㹼uI&m$ugAUo6p+xNa*ϣv4 cPݴAQ`oX|g*k"RRM]-SZZ/Oӟ|{vw5 y.OU??= P&)lՠ,txЍtdfݿ.DfvwgOdם^Xrz ҌIhdcd Ӄ8$F8LDR"1nV{UVn˽GKU.^0#)˪Jw/sN/v5sMRe+̔ۤS -[ )*ai IDAT7G?U[J 0x5<:um}E7n+'JZhuѱO۬Mjܻevk6I?/\2-(`5y}MQ쥤(g׵UݺG/MC`r3eF7oh|󆬸@jbcMTԵj(  Fe>d:y]˺y}M,~ yӑFVT/kh3R\]Q4&SLx @  ,I:]$yv-/um}YKKY45/vU?z[IKYD{7uWq:Eit}C4U-XY` RԨ,<RUQkK"3SWyv:c] _)._u X]VPm*UwW( ,dfufsOpʽ0I쒁TۚGzG߸b} %HaPuݨiZyvvgZZ+|eeTPDLf;3:I% 03ɊBf> kk*n^WvWk=7;by HaP;vv*o'IZ_[V]ݼbu0*d!SV5JZs7s74Q,y#,u,VU\P뮑o-h{~0*y\30ݙ?w}Ot5Vz. 8+,"ȳ+Iiܷ;ɂɕrURqiںl2Ru |P;Bx\bkW"* w'{9\f@QT-{Z{UH.y$.R.fHKnRNRn.uo Hx@8 exTjueթ62;07Iir@[+O{IRJ.uq:ݷ3* %. ) f<.5d&@Eu%R+\J^pg'yN!%Iq:wH0*7dsVM&]Li |)%Sײ/7h$HkVf*).@  GQYײo~S5Jr|˭{'˒~v')WL %I+woS\g'#`FeTYs7@GU])R8}>NL]y]qyIiZʙ Ha0eY( uN R6K!5K{]JC6wKVH&]϶wW"0*x,9TUI&yl;O*YYcshoy\gjoE CLrz{V/mRKd7Sϟ)m~Q.@ ->ZueN BP|GՓRr'OY(R!L %ܔUbhn) 윳ɥ,igRbO͓m媑Lꤳ{JΖ7$յ~rUh ) o׷EM6SګApNRLϟo] vڏQIWH$76ݫ}\\jyT)3M}[!j_  LQ.̔մIu*cnURtNw.,rI}%kZo+,-ivv6s  "j<u#N̔nZUuT$yW4+U=@ _t|yĥVmTmhת?-HaPe5vi5/yQj}۸/e).!dޓmJGOɯ 0"U"%U׭f{UPN;~W{eɲKdok| 7]m a ) ,FE!<ʔs֬;:)rw)ɭ2<,y<3<_e$64}o(oh?U)F ,c8ޡ}MJ)kwVik{fǞSMN8}_]5T #-[7Vv>L@Zy@ )(vqɳKgRʥ8hWyɃ RLY*U&OٕJ&w=jRa2{ߺmcyJ<|NA EPQ3~IS-ev!ߑ𡔙it놦→ocap) ( e PY)gIf:yM_:>4&j?Y@ )nԢR6 N|ZsF9ufZ=Q>R8RLY*̈́:)aT۶M&ɬ:Kj%%i=7U{VWzO>ep ) ,z:MYM*'¦£y̤}N>ί^')G۟j?fp ) * LjڤnzgMif}YI6-4o2F7i]ׯu׃Gw?}B%RL_!&5unc*)&+cL}QTr+y~;~oޕKf y,!`"( _`TխfU|f` Ep/.9@jt&몲$~cHa0EQ(ƸXU9pHaf1(D[dgɵ7Um,ّ׏TK'#YYݫo~wY}}j4mFnhQqB.fwf}~\yR_mSҬU7͡CȤ0)E)&.y+tTie}\yR-V%ɕRRUժ.:|H>#Y W:'eo9R-Z>C|W[o(k{tI|HX+@ rfH5MRx)o7UDQ) -PkIZBǝi;*äd*_trf,)  Mn4t;deTGYGAI  Hk+Z}M{)P)KfJiϔ\aRgWNYyJ 3)笺n4͉\.3ʮBl}]uU+SD[z~+J {{J{,E -MYUݨi NgPFq) R}TvIݷ]f?j.j~N 0.+\]TӴjtR$Yƅ,ک$Y^[ZUܸ!3+}63j=g,) ĕrRJE)SWQUG2,FY` >٥܇]V:?3=~[*&w0jܶ}񍪯Qn J" ܥIJ|:ȓ&nXڲRgR}u + )Uh`[׭Jkb}Uk-ءk/B,D mꪝN~L&e; AKi<} & ? ޟ-0j;eCWH&) }qQ.]k˺qmU1FI}ҡf9yfI[f[ʍcZ',D Tun`ZYj}mY1 M ]Ǹk!hRK@۷^@,S}5HW3uUH&cp)u-YbYQ{Oō:Rf{OՃjY(+@ FU(,4* Ge?}6VTL:-棜^O߾uemKu3$SꇏX(+@ .pv>w)]K9+ەcYR %L޼֭.:^]r3 M?`) fVתVf-+ A!;Y0nvkW޶RX&IYInHXu+I*d/T?d!`vw+m̔s>߁'U/Iٕvkw\RS )I*76T^8{6/4{r0ݙwR$ csVJW~`T[5ʳ|.kX\[Uy^},TupUHa0T(Rd&mR۶JM}Qz/mϔ\NMRMHSk+cbe۪?Pk J!`E_!e:q6\۶ &W,`ry7Sd㱊W+4? 3)7O R@ 9\!S3`YhoR|̩RbP|rr۪~XN !pɬ:94^77UULvBRT<Q RV^OU?yr٫FgU͂\Ry2ff^9Ĉtbe61;|.OΎr۲hW+g?LJ)j5M# :>_ʮPFK"vQ!dJZ}'j?BBnX4+@ 9+tj5|^TYuӪiӫpN}˾Bq(ZpYW!j f_}G+=}.SW1ef2{u%$Wޛ)5p%0Rz'su6) :GX#Y0+Uru- RֶOj|^~>׏f )@ ϐ:7+,4e8.0s]KaG/]eTGiyߞ?4Y4+}LrWreQyd+ l^^AVDYYt9) AY<| ȶCPLnA~rv庑Ģ\ RN_4wnԡQQuZ˳lԹV1|oV%a.ז5}C:L%o[y۲fW[Lum@ pl>Xݲrowv(54Ս2)rUHf`~fdo(߹ϬFi0.pMdH.) 1}ɕ*5wPkJ󚆬Frާ)=~_ff&Q]3ۿh3L 2 ~xTj<*ʤӘ3vݿר\7pVnS7_r)&)V=Mn>!ߗTW 3G:^7CPvzfWz)m~Rn[>CYvLV]c?\7]ԡ*SB peвNƚNFL/`ETA' )ݝS>x.Wn[ys@jl5723I>kx$++)S*2`#M&cuR2+eTNfB`CQ 0r7| >B{)~lTW%ŲPby*J[w L٭ G@ Y5F. *bTÉ!Be"z\{׭nsV/ G=Cގrt[.ѝ[ ++?͐"O0.T\Xm_rYN)I ieY@O)L}h"hهK3&㑊xB$EDCǺ+.2«3ۥڪVnKUHyJjwga&&m*׎82,FYA 8UH؅GG], !40.ULmu%R)Ku\W/ԾV[,ݼ~O&ɤ5B"Kp%H̤QY*Ƴʂ(2v^ե8*&e??xFӾf+ԵjyxTB 妖e&ewbe;8H!tQܢ,C*# 2*:_fAuR̐بP3$)gysVU6]]j77 b7 L/?ĠPHj ¥LE-I.ʪS0몣bP>vk[3MRJ9~߈L}E9;ZڽTb(b7j yۦUnZIRy{}igWKyUߟ)NJ8륅 bkgf]>fHa!*땭h]U5/rIյɓm#Mm} d,s%ťIw}g\P1Fa?, 2łB w;<L.e+ו<;nWK>Z\*L& gT:Y,l,dF Ar2y7jN{'2 )Dk;wr-M#sTv?L٦]޵'TL'KdeSmoH\RYٌbgH]¼n|-f_}_|\vвOAqeYqisX BwabhpEHasWEtdI^ \]Beօ6f:_"e'[IRj|->BxLV+./-!yX&s j)\9}Bg圏ˬ#e$򮍠˥6ɛf{[;D l;*:BQ޷!$ \R(9Q!'3yUud]Awɮj|b' &ʮ=ѪpPAgQ&}TwܑL A92y5۴p>OI/~},T sKK~KkݪB9BO&bpi5[}͕)R?=ݾ, ӉlTvQTʢs*!Ԧ|}&)ʏj!^pԡr),IөǴ*=z"3bTj;ZD3H͖Ku6Kd AR$QTRT.U*7Gxb_aO\O<\T%YDb#hH dkow| d| q ^"{cZ iD .-kW6uOB꬏co ܞ9)Mgz?A1h0=:a< }zYT|ZHB4Mm?S]mJʫ@QfvR+rϫ>&yhcj0kySwni[+wd1>߃RVi7R)\U۶ϔ#yjۤ6Q2 vR9r^mD#PuCLy٪Ϻ*.3S0_?}7vAKe,I9+W23@ UU>~T>*sߐ}fSwlrd&)ʔmoֿ纝b< 2C.LU5n9wUU錙N/̺l=}M҉@j:wQCeҝ?S}[*67QdR )g.̢nT5-rvm7Ĉeu?O~+ Ե paUie1ʺv}9gmVY&{"IJxv}9R}=}EVLuw??e챇|[;m;^bkSFH)/*f>paZu(HRJJ9LfAf{lyw_hO`*}}әfS\z# nz)77$|!|6H,ZE #զ}/*wQj)3ѣo\ '"/S7]~zw~Kqق3nR˕sMxKwBfvbb9UIRw.l}- n$3 THfr2* 欜]?_?EwM5?JW.0)no]öMeIyPZH>paZYΨZo?~et]t] Ze_moipUkj|&H,Zyʨ]mJJ)=I`:.'y(_tWThW{誸Ob<૯kFzqoufR )\Ţl^+Q6~|^nZA>r1K*P+XU@ɺR'B1෿/O^翫bkm ^~Yl2+6 3@ f:4-=+N&C%od*^kwğ,-#KUƅOycG^r(lgB` pQJ\mL)%]J'?gw&K޲:TXbzo߼0J`ܺ-f̑|6HB拺CYMGkk`pfG> byTv)Sj"Չ1I!Fm|[z7RקyS/~A+M'JS@ jhu4BXSA)v4;*ƧlAnyS>t&";g>qkC|IVDLyN`HB-ZG̥kbZJY 1 plW=-,2B)d݄KZ˧k6kWd}h_b4%?)\ux4ό:!żֽwR>RJ=%ܟ╗{T7~yhͯE)%|вiRHLRi9щy|/s!:][OtPq44+ BMX{RPuh6'sI!e|>xdsLLN%_.%;;o~H孛Rj4G 4jtfTH=C{`݇{׵Ogt_7U敯QNIڽEŦ=fHBMÙ&=1,(A,ة}WRǙ-[vok/]я~wV4G.TӴ:8iZTk>W4[! Vҹ=dTOo7voiW6E IDAT?{mXik )\/B!h0(?BJAz'\bqkC;7T޺y2yg:_rrInN k}py\m v]1Fji,~yBnvR_?lk[8]횼 -zW!Kgr5WN)ik@ nZLUB<ܥFRE+d1m.ʰ㳻h_啮I%mUy.Q-`HUu:)Rr4 >EAs[UC39VLE>9+65 ^̻Vnf.\&]@ʥ"FGU˾P' ,FYs4~<@$[[rGō+_˷5|Ua`}MwBi6?W.-p4UnE{].P{;T޹Z7)7Ɍ9RF .NUUͩ׳,R-$3c{'.">Ue*oW\/od*-)\J ɻ,}فZ)5Tbdm]Xnh\V )"…w0l^l5d*x K!ARΣVᗙV]kG#ŭ &c 1)\kgև0.3RC)SySMQB ևHL]t*򜕯qVx,N̐5)\8wDB9jɽ a>*WP-d&+⠐ =wPw>C*,rJ$A*) )#…s&gAI)ex~}˾"ʆE?ɟ& ] u|g!BQ]VYi )z#¥hVGSMg YW!e}˾d)QqTvE縺+ĨPwO?I&Oh )Z#¥pgL VN1*S_kh\ 3@ h2t6ZVPE ]Tu%/gH hp VAѝC%RmN$c9'ZJʳrӰak )\LS圎g@KfΚ!%Y0"JܚyqT*^*%:Rn጖}F K3-tx4Sݷ[2I@E*qG=_dݹx1_Lf׷sZn'fb\l"¥iۤ\YBW94*BW>NlIMpm6j8@mRE K5/$+}îB RߟS ]T1fJI} f׶&]݃&yn*}D K5ε7"J̥AYt"¥2B8&)VzRu?wd%\Š0[-èx}[>(O5쓙yH.C{f,X7G,l羦dއ=1BHY-C 7N2.o[ylZ*X\&JeRz3럂Ɋ|zQ-F͡,YW)uMpZ3)m&-*pڶt6 b E<] LVFA) dr{w"(Rݏ]ߖ@qsP̺ L XORTUjo|5zƦٻ9RT k߳^к1Tˌˊb<]֢Tno>ъ0HRJ`MHRUu#m+WW. -/.PycC] u9RRwx(Ơkh&׷-wnc\/43 _vRTuhoHuHҪ]>wK_ !H )g;<ȆM[7v4x5KsRJ XKRTujw–]/~I660*5xyG.KR\f]۾k*ohTlnm>=E`=HRUu꺕Bz[ss[jpg . `(x3(4|e>B,Vs\&G.UJIGJ)ɳk8(]8ʛ[R%uL!]/o׿XA&=(lZ"¥kvsb0]E_(QΆ77%/O"n!P{%w>'rݰqk@ =;R]x,*om)QH YIR]ͣ=}_0k׿>3II{ht?P8A KU#5OUbT5VϙrFҬV]twUpmmLW^W~EEI&Sk}TUl ¥z{ljg.0( ōͱ,m>zޟmR;9Ifj5{Z@[5_{MlU r 6`mHy\Td&ɂܤ8,GeVwz$ۤ4SV0)M5}]妽5_ J0֕*ӲFpg=;dPιkxU-OYVr%߮R۬v/JwqH__ZJ&98d.w0tV)g?.2S[ջE%Iŷi9ʕViZIٻ~J{w\ W훫]L>RӶp]BGU#|C2) nmɊ\Q/ֵˋZ%%^Uꇏq$6uE wԬɄX RuplN)+Km}5}[|]aXJ)wa 03唕rm$YޞyNiW:sj>S)(X\:u̺@* ;Z 酙mV[&ܤ4_i:Uҍk[wQj}GIf\*pe!jْ=ۤ8hpkKΆRϽ*rJ=0C 6pefJBɳN?u+]}/V%"(QluM=:RpO( _}Yy8P v6W4@ +3Wu8$Mi(.ꃩssBP(.:q*7=<5Tyl8R.*-u|HTURjMfL`fw"T筒1J1:WC5׺&;*r]#X R2mZTuF'˖MU=8TntagDͣk]QX,%U8O=)\wW]ϻLyJTiZ sO2S׭n|QR:pUU5}G% \7jj'οMnNJkܪ4?ERE ZյrE #•jۤij,yU=sSni4O=)\f5MBMєZu+7H Ӥefr3&iqO}sb.S/N"ڞBQl[yNlTײoBVj )ow6p'=Rkg'.ݧSU))R׷(fBXUIMppRJjڮ ɑNnSnGGjM+{9R mLjj'SGRNuTV;HY !d>ϙ )Z •jsV YL AÙw絬x- ivFf2{e_s d!HNt"hӌ@ Wʳ+e5LGj]P󬛹,V7i̤VWy<1iN&[ NߝȢk@ W]gWۤ/ޛȳwIYw:@{S>ծoU%݄$Snڣ<] )=Vp\'=|ú)yW4`WJZW9=G*Q\GoQ^4ص[ߝ FPR:-K p]Ÿ>d1>`moYe&Ij[!s9 O;)\3G#K^|(mPɤ`jg:{3痟YJyR;)eup>m7Y5?~bS2Iv5y㮚݉*(?>;S0)gM޼?UHVvx'MJt撢58#Z-KŨ`uu͒Z΄d4t?]yvY8'KIi:ޖ}UZ2X!Ÿӊ@ W)+5P'~GZ4m&oU{8S8pwږmg/L1*kvJ=u.Ҳm]>n[gET7:]}OJ2BPUu_CyN{"Y^U򶹾E.oZyJ'eEMݸRf )PDzdk͵o([C^-Sb9iJzu~_{@*WrS_ۚx6,3\r,MԣB WL RF9Y4Y-k~o bPnv-S'BOٕZnoQr7Sǹ%+J@ G +eF]eӉ L,R<)/5ջGrgVה=+IRʮTWmeX0(d)vS A~֛ٻן+Yɢg}?.ojYjr($W׮OeE)+ #ncq2qWH%u-)fI)4r5ʫZ]ݘQA0izRR1E죗c.q]P?vP{48yj\ )oZ6:Uqw妕RZ, JM#•1,HvsL]ԩv}h٧M멎RRS@aD #•1(c7鱖}T)\R9}̳́:]$i9+/JM^ݔQ5A +CPEP޵@ʬKܥu_X<w妑ROٕ yVYdxĆ)\ME%٩]r[d˖}m7B%)s~c/{V*)\-T$ )\cH=VjwVIR0㞙h0<[0q׍<5rnM*c!`=HJEpPxԒw3Ox: 3ws7>74mLr-t:!x$ōR@ +cf} 5XaS_}Ӻ1 ux[:9DJm~\Rv٠P=V3,q30RlvTղe07cMX R2EUbgHR um:] }4̕S~quUIu߻f=+W챖}akC}5A +S]uNT3uV dd۲f&Iy^+ͫG%>Tsp TvBr_~6Wd`mH BAQ1Bf)+WcUP/Jʋ]&ݕUln0C 6peeѠ=}(')I2yJu\r윉TYitMɕoH]Rm]OLR*6R@ +3 f]t"|rq(uN9 IDATd1Be͎gH sHLLͽZK]Yi>Y̨=cY(nnҲ6peRѰꓦH)RLVD)FI.3 ڼ<Ρz'%?wxArUiZ=ytZNkYQTB &peFRrꓨec]dS7\BT(,ڲr*-Zy~)T}P~f֠=<҃|W]BFy)Fl • J .xꭢ$3)?g"BWQ^ԧ2,;eL_B_4T}M~F| |{ۊ)\pPʟ@%AaX( UҬg rwIÇ:OR֠aղϤ 7nhX#R2@a)q ʨ8,ee\fɢ+o¥籜#咢L:{¿Uw#HqcC<%y( eɆ )\@Bdp}˾qn RaXʊ}ޥvZ=?w4.t-~WL/R?cEbg[F X#R2Pe˾U]>3Y t:dR1( \R[53Rjgw/>R[JWBQ( 6 `mHJ1j<j8=GN}M&7@JfJZTcO=t{->{kP}wijk}eC͐*"6p5-.?ӢV{0SVR8.°Ir{SyV?J4} ]{jt_HZ!¥33mo52̕T% RqkPDym:5W꣇:h[MB\ܽ/+_~'0H1ôLh͐e`HҙI[[J=^rJjrN]fR*6Z39dj߿tBIf*o|lmL!>+ *w ¥*F]Y7ɽ \M, S& Aq4P5AsW9ޥYvzrUO5{sK2 nz EXa!¥36 ߑgWj򢯐z,`صS跪k*V}_=->|rjxxͶQ\ײPasK")\&+"D>{6)ͻR:Q!"tɭrS.E]0k ouܶjC[[Ox~5JacCcO?~KWQ[*C$IٕVj9!%RY+ﮑe?yC<|sxӪ?T77OWi[emUnoak@ ,KmoUũ@J&y yue,@H̥VRu?ޟGGg:SR{t$6ǧޫ}OPL]g@ n0(5VYFm̔VLn`YRRf&wumB0GoO-csRNUGѩ4CCŭMVp2j{kCe|ص/Us+KT?c]M[] 5H.UYDmm52|2Ez{)+3ZYzG-oAǕR}{h3FRiP4*PqL X?RTeYhg{CEQH2y_!U޿P[;w1:(ZlձVUKWݕ$ 课gpz98T:G$UT)\Pٷݳ>DJ9~sl^L SyK`R 9 ,&?~C<FC7OTHjS|9S)\,g~,˲;9TeUwWfw(&) "!AC/d7m l ,4I5լ!++t{{#"3+3"2{g/Z,#$3c>w?ݿO0;ϻ̰65Y%wb ֿLx)v.Mi2%/g7b0^h'"""""""""".HkUQ߲c震8:v<Ӯ.3zz=e3#=|ƒq<"Tg-|/ڮeł8 DDDDDDDDDDd(׻,0}۽eT7-yMZBqCOh6S{v|70:6( JFDDDDDDDDDD֎)ymFÊoԗ7L FJyU4-)%QS׾)?sP79/~̡y>g{x\fsh-`EA8WI&"""""""""".Hk))s~獾BM~b}n}.?7亾pl{|DL.4hbQ""""""""""Hko}yw|˴˙ܴxZRuie$9J4SNO9?[MC3{ǴgXM{TXQDDDDDDDDDD֓\^Ѱje8"';?w}>{t3 [ޫ0{#|Σ}UnV"""""""""""kL6{loiڴ긷sf0Z9\˾|Vƙ~L}O>1{G_2IOxb)YO 䵨-6̊ryqmArre s'aR8?S98dޏ`3ԏtϠmϞݣzQ %7 6#v6+\8,5m^{B]-y5Csp ǿOxBstBͺy>SȺ( ܽֈb~żQ[zwr`Xw38=?ew? RS94o=?C*឴yDDDDDDDDDDd-)q.ۛcb*'زSxo3aKx` >dd|2Awl9u7 VD""""""""""VHɍ{{*&ăLg Ƅt'wR[ض.8Plmt6-nVV R""""""""""fHɍ{{h[tL 6>rYշsWIgUHL0 &.iԵsw@Jn\YaE{nN#gtƇ= ӫy'gd)C4١@n9esojm Y;A@npX֛ +R_lix13.gg8LUt3bYRlaEѵ0l~cyQ@""""""""""vHɍeQYT#>i$"*[՗^_﹯"kAouOrorw;Mےަł@JDDDDDDDDDD֐Zɍ+ec4$MfH#6|1 +sU&WHk=@͔[[{(o[l7 ƃ,KHVX跪wanU"#_͎oZwwWO]ԲM T%9%H:- ]_ӐfR%""""""""""yR %7jg{{o)3-%CXQEYUycxX?~jkopuQ}ułӿa6#4jQ>TDnm tj#?z/|U$T%nt휾B*LxAQ{{l~߼!Θ'GxX7\2'4'}sY7d5@Jn&wo0V)ޅ@ftÏɣ͏r8(^Nnr_d//sf ?&wRn5*Hn03G_T;;L/8ʁ4\IDDDDDDDDDD֎)1om]"RKv'spt/b#qXGe)yWM,aWl8N}18(w74~oź֝r~K)Y+r]f3VIȚ )1s{'9!t[O8<S,Цtv =_( " U4iOx-GO-yM!9qTQB- """""""""">J'x: iZ'ZF]Hs)އ[}+sз9bgK1 S>Y# lqwgB'3c>y|pBtA9Bv:=s< o3iqx@^<^s"ς DDDDDDDDDDd(W{)3ìtƃOP!efCbU+EC5 |] A%""""""""""kE\[QDnm9 -̌6%I)]i1 TŅ<92SdzdO1;$pU7BX uD}-EDDDDDDDDDdovw6pPST)O.?CK(ƃe&wU;pzpgیg'8(2,'9!66Rrm[ܾCY}dt:e䣏sQޏBʪx6 zrsݿ}o5u ݉-BU`E=KhD DDDDDDDDDDd(kE骔׻w?Қf`E$b>sfĝ v~ᕪ̬k`b }Ҁbkέ""""""""""")Mw6.p dο^v}QEF韢'jk| +#fBY4 q{wHQ %׶&)U.yL_9 l.9C~-m|+Mzz*"Gn> 2 ]@Jmo R>+c!Sq/j`EAJ,`#m~;l}I1fX»VIVFQ_}g:yw?f; DDDDDDDDDDd-)kM6F>230?{W[ԻȊH-6}d e,CJșaK4k.}2>3 IDATp' J[2)w?94غI~mm.Y; ̌ݝM7ǔe oB0RNw?dz6zaP@j%wh7f=?Mv~ e]tTVF1m,u3kg@0c0[\""""""""""H7M0nn1$eF놏Y͕ 1 "bE+QrrwwK^Ļ;<'Tf$w2G=3cK*;y^f}f V|b{KKDDDDDDDDDD֒)2 ƭMFÊM >yxtv}2vCfL]O`wG NG0sG/]xN(#7v N,H`ʁ?%o%""""""""""kK\Y [{[TU ̌3']BjN(#<Hyݐs8υO}WA9cIXtW!T{]2Ndz Q~>C6Mx%""""""""""kK\}[;TUI' FʙiH]Bj5C*RֽN'鄰S`S_gޞ2XYvwy&hxδsړYܯϽǜ6uG WUU9e̺L39~ ` UMOY<|B{|z0Bv}`[c16(pwҬ9L3 m,Y[ Ê1EqeߢINfNf,骆Mօ7yѓ+h!a0\E%fF{29fMW [Z9 >ZKDDDDDDDDDD֖)چ ƈѰ"H!GSzQ]>|˾ k2ǏX_m)c&nX ޹ϾCugfR0{!+tSK}xH{x`"""""""""""+ʂ  b0&9R`tS;3'O@,Q$7-هOhOX< ^k8d]CwhO,>"JJDDDDDDDDDD֔)(-gHfd6g2}YHfXqnTWE״ǧǤB0,qs@3 :xp1i`JV7,:sf(FSўλ^P?>9<@JaQx3sR$򼁜ytMK(7Ƅ"7X0 x~>'G&}r%fF=.3[,ׯ2¨8,pȀEKxx§̐j'O87[{PU"Rl 03) L>`j5"9:={fcwo3f +h@UAL;I ZfLuYF>>9)Y?j' pjW8xM%""""""""""kGRr ]:4iw%CUPl(6Kx?C*m纡98yvⓇow_ r{kakLiɋO,*w/*pnU@KDDDDDDDDDD֎*J .\Ù暁8(Iަ.iY| yOx/~}F|{?% UqkaXM`_FGͯ٦ɔ!3P %Wc |Y-g1&D[Eަ.Jy5)0{f?_gwx UI=&1(6MnTJ ,F7$M&ԏ@Π@JDDDDDDDDDDֈ),* h`4麕CZ&#ʹE7djylx/Gxq}PTw)ۄJaP1xM@{:yoZWSDDDDDDDDDDև[d<9aR9& d.;|˖}yu4iG?3l};=%T|Kn]oSW!k3C{ L 1gG')h&""""""""""kC}ʲ`{khнdt )sjb{ܵ*MreX淿+/ BQRmQnt/ o2f/670zf]?R)ӞLhO^|(KՠC&tXF"5m"MgT/S޽Ko]rrs@ܨܴ亅>x)3zޤ)^oLOiՆ@J.}Ux_!eE"3`ŀ*rӒuw.G7`qcr a L;ouϐzl; Id9unA;<>[R"""""""""">Hɥos{BeS mVAS0XNx\y)1y,:1vqw)iVoZN'Zw[ n"nnz߭)w03BHQ %V@QĮeݹ0&{9C YMEb@'O4ofYFu! q<)fyCywe?0Yy0mwnSBUV}զ}S kCUHZQ %v:1̞y=̼nHUİw,ԢZ*2DZ0^yY MhyV76f pgm= )Y/ Ҧlѵe>t}XDB gu-0?+r݈x@XtM>9b~k>+Uƈrom; Uq31I)XlnQI( 3%ϛFe yi XʂPXxqϾ.t3BQR9pqKf5))Y eT^ΐ^O)3׫RW߅FVXVnI{:g }ԅoI\R7[]xRy@JDDDDDDDDDDփ)2M𼌇E_'1ʂ8 Y 'k YCB6AO˙lN{:yi@foj+݇טRͭB-DDDDDDDDDDdmzre}l^s|2%_B*F!eF*/_hwsy6=y* N})Pcae*R)u^GTZwny x"""""""""" )f H)3/8:zT,#Í!<eSZ=!/jtx:{Os])Uv+ EIve h[ѶײI)椩)1{;[ ٬|̀* Ay=yvH=fxېSɴRriрhVx~NAU2V}sog/G@OV}4{#VF ִ@ҫOc͐ʋ4N\A6 q`vþ_0U %""""""""""kA\h4`48ǰW( *Ȱ*)h e`ś9j c8*XDtR#/y] ]{ .\X0՗aefWnlշʼiHә6|)K@W.]?T%aU~~#uM|~ c}U].*rhFIY7өn.޽{~ʫLʋ%G=h#<{t4g\0°Sx_ε y6s/4RRfh0,K,U,[ڧep b_i*(]{`e׺nPD̼[Ψ=98ʹ"q83BY ?S5ZWԶ Ϫ/6RRf0Te삟]Wqt}!1gg9C=W.qP0 n0*>xqk 8?b}Η<VUXU5[ ;}fWnۗvT!%""""""""""_p cPEPFR!Xp=+ݹYw~B8(mtU[9E,Ϯc IDAT r3c;'ꇏ;i+ ͟9}WH)y)3t f.:UIyJz -/RrfTUqHYv'"P1AJxJݵX ( + ,tq+s.Ŭ w/;t]W%sSDDDDDDDDDDgN,ɲν22+G@$D3ViAҴߠLh\ 0 A@3BY9{_ ӋѨ,"]vc?;"¥LRSRR"ef`ZD,'R!UGU".R5*ySw8CBUbuV>_v+!p~o(~+ӱvKHU҅~MUQ'_]iG#’JH|Z--L?*YwWJM?JrrB p{Ha)f?[t>ށfł_MJoG9Dj*L2dnzsĨ0hnf"ϕg3y:]%9wz>HW)E@ -mV wru0`گg'].Nd1^(IdMU~lRJpPz^RLu.[Ii?3}ON3_RYHn7),=O !(ՏQ0Svj{r>}:2Хh66\~g,F̀=Vuw>r'1/~O uӉ%7]ahjmU[YRz3ygB S5[LʬߓI@&)Q.ԦW iY6ƃ5zʪFC o+ԱTmVwJ?9BJ?}ԵevDL~vjuT*uWB@ rmK'^f4 46rgQPG:KUk;o*nmyV`2Cs~Tv),Ww}&3k 4(R!uTBrZәIPQ}(KThj)ܕ__R)7+_7RV?Ccp)4wJ]d2+_)gC1j8l4hs?JJR5~KK%mҬU7W:Zz/K!Dw6_$ј zRk2kv}URuRV%RcPTO[dU䳉$Ii22Ɔ00#bR`ټU.uImەPW=xTHYvRdhC5]>NK`4딺Nt4J9k?5#UꍑB3NxXd`2Sv`yi6oWZ/S]Erܥ`uOqP)M[]VEu&}ǿ]M>|"Ai2riw/~"3WQa8յ`;2yi=THn/),%笽3mldfjv@$+TUEau3,ig4,u{D~_~g{R&4#n2)9ld8[@ K{{7i )+R !,W/Qw4~6Pqc3[ygH[Ir+m (jWemn 559$}{zὕٕKzfP*aRqIn&a1t [@ K Rʺo[쬼aȯ0˥%RWG YU]G IV]WH; sKL)3K!Y9[@ K13UrZPZIRrԮdu- n/KK)+Lm4W!UŨw>Q&Ub2?*FIT$bT0C pHai)>|2fVY[`{{CKK)Rdro}l:|3)X*rV.4LWp 7wemnԶi&+ݱ3 MjRX+{!4u0^iѯg׶rm'} Z}UFV>F B:΂i2k`v5/ԥ,[=Rr]K uz>?7߸]Tv&)LR5 )\jQ!(IrZ"7HnaэT3+:y~Dڼo)4 ѐR: %&5u.m+N_rO[y}W<Z ¥LR]E*dR:*\HUvtΖoޢ*[$"#[.MM.gT(ϸ\wǺѨQ7;ݕ睼˒L~%M}nI՝m*kRIB)pn ,;+ƨyܕ;ڇ뺵Rfv"z}l3wjLΖ )zB 3SUW !rI1s[`zpGr4E f%ٹWWzR}Gx)\j1CQL_X0ݻPL~->xrҴ+}j{BPug0l PLʂ -ѹ$SH XR@*PM!-Llj4OdP~wqwS9\q]U_  ռYE`upIf.×(QLLևRy[]  )\d}73̂lo+|smNC<me^P_{]ͽrk+ӢoYU߹#p敒Kujx)\Τ`:j4gV 9VUEo|/](w)U[#U[#ŦM t?赿ߨڹsh]U=Z ¥3Bb!r+mmn0*Mo]{M&R],Ku1^h*~KwT86&4wviXRY߲o1HRιU:C]EmbnS]r*R7*,@y*O%2v|3\Q)I-U[[<ڨxXF]H$wR1FF1sYɢP)%K}u) Fg{eŏݮt;S)=z?3dzvXU>xMq( ¥Ji7>JbPS7 !(hT))]/ǕWPG&j3Yu4'f'¨kJ( < Lu]B諒\9BjՉSױXb1sY쨊+,.}q|Y]QVdWE35SG|hRZlZJݻŋzRLuSKdR3RJ9U&}˾\eUPK|T3(n5s[TQ8tB ɢB/!նcnQ]KRx52Mm+I&>VAWkP?[|^p) eT y._!]Yrtjِ3:wcyyg,]R@ 23Uu8CJgHu]dgnoC̔TB~@ IDATnfRhws?#IjPbW%Z :~:LJCX+RXP]RMm)|miw@]~R7bv5]1G5IRU>uҮR!ٹA.cPAf++yּ NڶӋjN1Y9&]+9:nYλ$yVtgoݕ&Jٹz)[ZN+e**d'mR:B*嬧4ks7jɬOn0KuTZuђh\3~O[LZ3e%z$:`HR@D}g7]Od2׍ֳZMk.+:.kާbV6_eMTLRYAtx+y<RC `xbTYm۞;C*G=]~33I1l˾`.)]wk\pK5[?:~ay'd:#:\'K))<Z!…LU !<ӹR)>^Wή`|:lHB2<%Yve7Po~] ^*4|:TQYXRP0Sy6ur?BϞӗAMX.,5:wIbbVRjCmU@q4T ;2]y!%*$ewN)OѧOŞ*fY0)]{>"S07nhg\y8ko+r8d<p .- Wή->>왪uz]hzRʭ-{hW40d꫽Ke`&)\|@T(3+s\նr~G'Ou2R/QVEygA7yN~K.j665xuYS쒠R)ѲVp! A (T9mK+>豺Zם%咬/dk-w8(/W&ɪxw[qstL~f u4 %Ӳ~p1SRf̐~qg_˽|g *H\ KG `ɵpX¨:e.ȹh3)K")\ȂfHy{ y郏KbX*}&YeⰖ OJ&)Եh(IVTI]s;Z.> fbP0;pvϐ'O_?@)gxSJ rɽ֒VzYUe. :`HBև,!1K.g/OټT6-H]dU(MTH+a]IɕtfHfQ.S!X+Rΐ*3])%)-ݽӗJ)["1BeuèQhJ" *r}Rޝ~7VRrWqɓs&)\|@RfV8eWvJ)/K'zGLf_";8:QlsL)k ]LrVO>{~jU { T*Z|HBf@ʤ]6-ծoa`?_}u%eHL*ȻtTtƺϞhK1\dz%KJ:ʳ+wiwe&s7j?VQm7HRB ȱ}t)jA˗>|)2.ioC|f Ur.Rђp/b<&| R &`}޸+L%J)W i6kWUdӠVj*:JɕWHLx;wN0FɬoXްUBȌ_Moq AUegܳ.W,MNg:̔HQ!\]0e_ıxe㑶hx=0سWVp+euPhZ .> fHI.^E4 =K}}ߊ%0h̐RI<# eU cP4u)\|@BPrW^U=}y)UM6^*J0*+.]uvv4| YSe;sEAT*٠a`޸P4S<̐ƚUQ!-Zyձ` u%)S>qQ{dgK.e?6C:f4 ٟ"…,R圵j"UUQww6;4 V}tP**$Og&5[[j0޵TjZuT<.> !񨧜r^(W7҃)}{Y$Y A%,o<FXkf윖}`PE`HB1WkAM]ꃟjɢ) R5JJTs?M{&X@,HK+EBxuԢBjM]GMrg/sdWL'B) A]Vw& vnuS_XΎD X3THB3:):BJfVR_tU'?c̐mRw)\~Uۗ{D~\rOy2IxzVN"LU<~LvIrϒ]g ky)[yWZ)uz{ǟ[GOKw֮憚w9tC T(s+!VRʚNgJy1j\]RYͮPd&<)SYR;뫝̤GJ'.~^)$W 5B HF2BXش]D]J+swyW3[?IԩKI8yWg˯jqz\g'~f>]P)4`HBfV)[+bw_][V'g5ٱ}H^ƚJqcP;$-$3el?c=?IRHOK V23Tv*^.BPB_QGGԥ6y+f[>ORO;WKVE՛U[CM<5"UGW7}L%/Sҫۯ$]>ytP.pLUGqB\}TήټtB\KRe_%YqԨ)uҼ;R/fRh[=WP 4~GjvoO>.BP%/-BkUu]d2W:Ҭw ]qP+u L&/u_2uϞ}$3Y?$4DJIfHB1SN.U ]b^|֝Ya uT:(ԵŻq)+^ Q}u>~ܶ<Z!…b<#5vII^|QRiǍ́r}UnuYJ~y KJ/<Z!¹b1}Rs?>=K>rv'y+%Z'Q͡Py:W򜯟T@\G_gVF=!OXR8pDSVb ߲/SUH *A|Ty*īa+Tm >J7[!epw'RVOSϞ_!_`R8p)X!UҳﺁTQAvv|`~LO4rd1hZʟq{!')B(_fEfrjZaZqͦtΦt\zgC ʇ\e7e0Zt0{>ӷ%+Te`}P!GҞX>cVيRM]Ν MdMz{$cU T Ǧ#B8޲ef 1H jݽC$]-T*TXiϽ1Qr= >oYy_6p.H-rr`b Zgx4X2)ˮL:J az.duϡʳN/D"D@ FpX˾,(lٔN[*, \~ (3)4BRvSIs}.)gW7e`0C ~T0-B3V-xcMJr%R/7?BSbgWEYv*pX3mNHuP#I}5Ux_UWU*KXŔK%ԪLJYrزώQ))TH?!(X_d 1݌GCcɈVdQ3bL}K9/ٟ>s=Վۊ@ cRK R[Cmojo0Û8-m~ {k*JfUo!r-2n9)8RO!ugscͱ,r@k- #o!u ] 6b7dZxb4*T&l/l/6c;P*D>q L!nOMg;kCjnkfPe{ sxQ+[J[&B\*DjB$UnpHRؕ)ضyOm˾BTՠ=Ĵ&kO2o] ^8誸w?UhMŭmΑ(5.*B؄Soٚ?eMجT:5+ɓS!83&Y!efm˽Rz-[Q&?/ VHŽy:fid!H1(re})TmЫZ A ێpvq.=I@ p60C obj);D tr%wfɚLs^Q%Ooɫ2lkKByY)ɂ)v {=tԴ+P 3@ j&%MuHgGjfDu.̫k=UEb/'м>ru.+dQ^ yWᆭ祪nOLE>ʬeNL 3LRӉ휦ìhpOR굉qPFf& \K)If uT4T`Mꨩ2l>2/Ev5 f~Ӷ7Z,:tRYJUܶ=MOk A77BZ ^܄Pmo'~& R}sS _ef!eRb|PXW6BHI͌*տ~Q_}AK8$oMd! YE 5͎(YB?z$OTJu}OC`d14R4%KC)&:[B pVHaWL$g 2I1h3+NnCϳRV!RM՗KuRd/̩syQC4ffU 87vR'@ք[fHB Myt0aAM=qRۂbŶe_]+MB#QfR'#)R WD=n\Ͽv A&X:3I!Bl*RR*6j?!%oZS*NgB"M_fD=8vRpo.V9`򲒻۳ڪ%?.N@}sS6s23Y M VdTUR|=ɓ7]OX:gc0+[uӱ YvZe_TaK7_IJ)9R3z㙲dyTȣYSem>]uѶμJM5YSJ5uiZ pFWoQ&:+4Sud!Rxlϛ,v$R8fL^i{ՆNvU+JBJT*BKGpvWo<[\ӎ}ЍM>{YfMIJI)ml3s M`U>P>gjMgHR@ rm+e4i+Uu eQ*R R*Jo/(̙zd.3gJ-nB;gmq.N{fJ{L!,HJU-6yk]n'W:ƇwTL6M鎹$)B )B ]R>ksB)vk1O) Yi>m׷]!щӛΐ"f< LKd؛e_ ש}n}.ꦥ_~$Ch8C7QЉݼi7-^wǛB'SȚ@Z^־Pζ *\R2IY|+A gKB7Wd#i+_bmUDN!eAMU !3g%YB);MKfjMAWaifF9'$)؎NMJuKْq l$ɲ&hROO3*TSeq_/Iܷ^IXuWeӶ}TF)2Wtwn*_IRM`JEE _sR4)LYR'm hɥ38 hه5,/ zBI6[y]+{~Uu/˲_-Y M ?3)H/i]ɛ@dR!\˚}!RhRh4.f7jB'ShE^C_8lT޺f5|jʨiYdoU )B>e}~&e[K6#M\M`gL%)_sq^a7;t;75x޺4ͤ6[ܵXRUҲpHaW5x\%%f<:M %o\R6Sgi( &MdMc4]^z+u)m]59pbǝUsWmgv>G\Rie_Ts)v%AOqɥm- Թ4/S`+)FT44.vTsc1k2*Jm6[Y[YLߑz4RZHTV*m- ΐ:KwI )B ='VGqM3/KfL΅ _βR=*YPM\\Ε&dZ*N?&'_DR}SQTZMڹJ3V!%)dYur]+ ht,|QRwTJ?oz )F%z2B pP!=UV ̈́Fʦ KR)wuIݫKǥŁ^%Y :2)B :v^'իJR3RSQVZYې{,QV|Os^+ʗ{Zx+SS5uY;Cꔮ'ժV3_#žʺt,MJM4qY/{yA։ZueÞϟoZyu*@.N7J)A =)iRr\L׮ɂɂZ|E)Y|3)ZG-pIN*T'l>A 7Hi8)7vԴ3u$O.Kum>3L|cS yJmu6)unq<: ̀HSc~y@mlZTJj2\`C3NOJ+Jb&<(L HG>fEf= d\χ_ls ᱐ .9v*'VWh8#Ӵ3I9FT'׃ۏO?T=x)YG 4&c6 L žyAg:ƪ6R~onKe-ˢm__QhY{8?ƃ?mW^]S=g3{wcЃ5~_}^Ȳ8cwimg?@{L##´]1˳LO4B i@_YG{Q RyklH3@ 2cZrw,_LFܗJ ~JQv*7]2۬}tKտ?3M2S l"®]X˕|˴1?ǟU&SqoUFф?3sk6ٶD$+gq3%w)iֿ??ZCգܝ xfd]J~6Fcݹ &Z)ٹO9Mwgwn};? o&<®q~@m յVF*T+TiRmv.?}+Pו4t? !RSJjw )LGO̧\PQHi"S2 N7# T'uC`sRSJXgjBx z}zcTU"a2 2o{5Vr Aߓet<;NJ:EJR]&p1IڤDj>d._:%u!rͶBTI AA^U6Jr)k?%3$E>gƞRTUӶ}Ǔʄ La8usyY'$ R޶̳v Rf&&s6'A =*J1ބ(mSY*Z/.¹yuLk*q럪mf׵|p2nRյʪj~8BFdf`zWnG/bOa=ׅzbdzzkwjo*g 73RPe*:}W/nWuofk!žVQT:1eYhRO?]Z%|'ig&}sZryU>ZL:W/+lVbTU&epd5uܢG=BT+ʯ=R.ru??R&BP+ _)Ȗ@ {;)L >PjmMܜԄ/>m\O/l{튪NGef!{8y.WE ]hOBW?]s5u^ZP>h mZ}SLrNujeE}ruM05F"G.u;{Ewn\。KJm߃#L1hpEYi'?/~Zs"RD>쩪kmL&^!%I!,StleM6j^OGJz-$gBwi|7lXL"žx\1$RMYBʺ*3MZUUDfdmNTvxjI/tW|>:i4(I&V^tBKJuשi;g6˓?lw,-*p^WtUU>|;t /GTU6FUUf2m1[m\>{4zz'`|iQ/sN&]s3@ {ZeyK&%˔R|3/\KJI@Þm_9).ku-2.0s1VY'VdW o,)l/5յ<%=vx&)/SvnQԿjI? ,)쩩,@6״_6 eL!3Ź9u^Q$Iw4)3> 0i UUu1WH5Q&4ͦ*uZU䵫RJ2vUzRҢ_k2I_3 IRSUZ](eqv|);N)+%ˤRm|pG{+Je% &UI-;eMK-s;^}.X٠jy IRh4h\UYT(RM˾~/P]^Ro+d6wPSLqؓeӣreM )RؗBjRG!RRA CE {JVkoB#d14IS4PS!ev7e2Y׮|eⷿr<_iW+M 6.`fHa_]+ {̘5EdjB94z}LiqoWլ+&w ǤTO׿7 ~O:7_Koko\^afʺGcu0Q AeY;niee]+XУ?3e!H1juTP]_zc8*ҤUF|4s]U埼w~*) ¾61(ljYh>XrթWDY7S/ %GwǪ&ܸdYPTjsKG{v4ͷ7Zl^L “m#v f*J5 wKɓu#ˣ,գBhkiQ,'Ɵ|YML+cgl\L ¾b0]Ņ<ȏ0)yRU;2:\nW!R#`2LGYQ6VȢVzK@U*+`fa\ɧܧt]1hw4蓧2 & AW.-iiq,tH,6r;KtjHKzϟS~aNTl(U IDATQӥT7Tܹjeuw^w7 Q{f:)IYSq.;`CPю'3) 0O7{eI݋Թ޵s)Tkh;#e!w-o+ 5z#= 8iRؗianN(]1F Md1([y{NL&]ŽqEIR::ٶ KR;*>}UZٻRYO $47lwXRE_~` yp DJɓh'& DXvO'IŽH^WW_juS觪V@ Ovb(TREέj}zT3NLJj4LiR\^y7@'x{mͿc+lcSC 7:\!3]ʲa_@\\X[mGY1Rh]uyU+_ʲzT\)UIP}U./+M'zoSb\jU޽F<5RS'ܧ#2}B*kg55 FV[탔NSRQ:)t2熊s=yT3xX`s4.T=ZVDo{o}Mi8Tɫ x*/ Mh5c6}9Ii\* )y[t≔qK׵w-JMnQf<R85M^AՃ?= )HTAEQUuq|I yɥ,B+3$wRYef2#:Қ/RU7^W/kdf֧N[aN S(+=|pǭ ,bE5T_SqMl*Btkf[ Xں|{z_7ޔYҤ?V􎪵u6;DHa_R\nAǃԣu& &:MΫ~ɝeգ Ln$ASn哱WHIRE-p(%Ւ҃=?O~f)Ϥ k*m-4Z)mLR0Y)d٩̎rIvVUr'߃KP!O|I+e&=V=)cG }I1nk_wc<%EY9宐E)4s< WI{'cmen3L RԽtA xSqny+jwUh흟kotfe4)cSt]J=4,(MJUk#'jOo[iL'[u$)\[;rŨދϫu ݛ1ijocA =I~Wyh%yj9eYsCY S'>]^'m"6ͦ}\Xi<9򱺗/iJv\m4[XHaOyi~N'thNiqa<Ϧ6/ 97' X4ζJ.t.ܫcvwMn7)̑t2زϓb vǚNyeN5)S SzRZ[;rT67_LmT$MT>|t93-tdAG $`v2 汔$Is~NBmw .f\.)wEj}KUU]Qvf޶JtWm?\jGZ\6R6d4Y)3 RC*:ȩDB&N(o[i m^[?vz% ^mf.)zPoQ!82)ɴ0<ƶ:W0${qA@!mcN6rBd!hzkR^=z>ITHIJ+}GC =u;2ّoӬN'poZ:sρ@  *mn ԎZN(hmW UneE\oURWrdEƧ_SN{/Tu#/yT7)=a%5l.xZR8L~OUUE3hcڙEBյ-~-V ʟ'k^WN[ t(sWc_Sqew-d*N xvR8SWi8詈q^JUWd5DRRwOW&R-qwXxC׮.;<6 )!™ʲP+-=e] wi,ܽ74,FHYQ(*}Fχ@ )KnzJˊ+eeѽvq%gyziǍþB' A]$yB se ޼y\V^Pƣ}z)+kY-˩b^OqЗ(O9\p.wWjR7C%#**Y^pNyvy-%_bCY*n"*׍x4--`"¹rjRR2QRv!uUHtis(T\ڑ #G\hxvR8i2fm1Kw2*KYѶ ~&3xiŠeY\] l3#¹r^R ^}mzBU.lԉ}Ti<5C*]&zr5Ӊ|:eH\ %,Ykn02*?+fJVHUWz}eI9Ӳ\p ):Dd-AqГEvE3&>8T܋XvUNW gF se]咽.3)AqXITE\\%WsoW,+ ^VuyGѤxf9U!Zܽ $I.Q_.h˾E݃ȩ]%FWUrM*RR} )B rw&=\DJLAW3.iZ;wfV /ɚ/&)+gZe-˂ɪض] f'{֛rC^7m )s ¹ꔔ_V};,D8ݚuq&v[^UsO g )s۲/笗3:$RQk lΐ5{Oy6S5yxm^|M~KLޞ!̨¹rj 쥾^ PF. 5KP;w&SI[3zCyGW_Q{fo_y)!¹-\HIb pN[!%M4OwǓg:`zwWy6cC ]>Q::\nû+S䩑LTt8Rg )+-BTZ^ f87KʓfJIՕ ~KV=6^>r{[gGj"KG.. p][,ߑjU.eIwΏ,h$)zS[?ugZ{u_}So5{ &ÑC6H])61{.5yԌgRv x'BYҵz?ؤ)TdRՌJ򜟩 rRΒ̔t03Y0\7(I >)XWfJ#ջX*^H9mT"m:Rj?߇{U zCHޞtz'D ZR%[ IDAT,:bIX]>Y/Tu㚊-ϼVf4bC+goӛŠf4ξÉ. 8qۚwkMP: Ñd @ H2ݑWs8J.vKJUjz6,Z( YQtUb&3)ǚ߹VXRv 5wQ^IrL6kT߻p<̔'w<5)R.zVH/i4RNegs5B 2Bm"M:H](ܔFݕ5Ii>W4)O@ e&`N䲲P藲x_Kh4/x>+Mgy>WwL xJRx2r7swYz,F ҪФP:a&2+^QhVǥ(M&&1O@ UbU$R)W&?뮔rN]H&8=3{׮Q m<3H\f^U(Ġ1<`MHfBfb<I QVo J7S<1)+ƠcQYF(2 Rvջ#4h_2u_У-`^f.+ YUɪr)I y[]vnO@ @BPU*br4.)TbïRs8^̇R+Ul m ՝țF{xbR8WA^MYVD[}]uKuKVď%8FW-熚ʭ%ҴCO<_ }[4IE s1߯TQ2[6nTT^佻:+gݶ4̤T]R;[k'f\7[+_74w9Q"¹5TQ%DP,Ի`o=]4AThzڵum}Un ۢ53e{}k? p.)(ʲbRyiCSnHe,B mDڳE7~U]rqqlwOW9p.) z*pTDLm+bs8Tu7M*7^YI>x2~K_zA_OkG>/JE\YR7{lpB芆\f|hR&)jYlϻxLY)W[5u.zu]m~3Xm A7_OzR՚ݼ36 LR8WUdI\\^){|5)YۮoHM񠫋OL Wh~Bsijc6 LR8WU!Ċ$+B mU4m{mlț<)Z$m~~g%Q'm~S(^Q4SG Mwt8bD s{77$@)FYݏ4uWi:SA&pLIJZy.i,Yj۪Q{;$Y5df@ +moeʪYEL,irPj~Pa I)+׍rʒ{kZd^<絜um~XF>Rsxf@ {ZD][>Z{޼%V] R0YGZl:̮u/^_k5V&[ yGU: @ 1wfH22oÝͻrӴo\aeebWw.o_/~O+a8$U9)Ć<49PYD*\f. R}{ooD˨8ɪg^|W^p v[9eY_ebkSq2yJR+e6 nβV_eeI(б`P(MkMojr 2WzdW aO*g~Q[0O4uxk|>z}P_I1H,q2{6R8ư2JZm&Tjv58YE U)ނ e+?y]i2}s$mHŠɊ^7-Ju\L>HLþv67TrVH&sLoV:HVO{[B|tdsVueSJ\HTN~.96ԊBV,'5^,R8@}4e(v˲hmsPӛw3Y\GVBf;?vfRh~@t-)oLhѭVR8PW,BOǭ\j,Wך=P%[G2~pqًU])j3H&yv8G*S!ZJ kٴZδ5氯WHY;iSCXf]ؓf}',kR,gf4҆.gTf}JZ[yJR[[bHR8@0BJOm *63j>3ZP7b-]~vp 9I9=m@I, J++ϛFV}bTdeB(עȺozz8P 83H!f́zU)֓DK'ZdA_*JY :++]VBJRcy}H *v7gc B[!UQ~"YUbgB4wRwK-;bPde< ˳dePkۊXroק͹z`\J$CPqiGVUlCkW(ϫ}sWS=h+t" r7]a*#bX)٥a&ydԻb' vԂpwJ#YW%y4W.)g#`(b7?jż%aOQv<%yMj#$c7**GS:ٟʪbTZp.CTuRxHQ.Z9MA*zEDk+JK]r,(zmQXۻ U7vTl9R,kl7W3h2u~8PAf&_-ȊB~NSnU,T @Rޡc ^@jeBY\i4>Ւ0Tzׯ)l𐜳fZ9uߴL"ȊSP޶Sf2׶[`.\.ogXSV?=UwԻյvԊo +ײ/kX~9mvֺ@ iRhI ZS"咙ɂb8ݚϥg2ST dn:Y"#;(j+vI!8C*k鴻E﫼zUqc(8.Ms5MZ!eRhUI튤ۯ_|X eɗO/7w˨ږ^IbUWu`@ qwMs@ }NsX|TsXIR!`ǚ}+5x0j}MnVn/Uy6[$Kqk[kaxq/xKu4I9H; ď-<ZĹBYTm~P-/[j+Nv3tIYo~[?һb1-TvTlS!x[iRZlIIN:'~ܵS^zoCPE^qJ*gwGmL九 kLE0RQ4ěZAV ʝmW/)ȨU7IMu(+(j)sZ:ږt*⦜}7ICYP&Ql> jWˢJ&W%x,)otg>ke!S>5sjʒj_n/jѝ埯(de!3Se6 Ha E˾u5d`Dؕ$w΍6HEe+YIwK/Ky6[yW5C5U\@ 0Q hu^Qq/+e7fP߲s4OϿrk(%Zn_I:ӿz9_*kWT]aruRkT[IdeTٗp$eX0)?2^uUJVqMnSVkr:JjW:j!xfn9?cq?uMoRIY*w7,'B T7m k'w2*`$kٷ )I eTN 'IJ) ޼Ͽކk&Zn&_ ,ݥu[ӇR4wK3\*v <%5))IeW U7NA&?1C*HkBeERkNޛ`y]{cnhӯ9ȳ?0k3mt?ѭ?;OwF[h1[+l77z=6 H\uݨigE[O!Q˾KC}"*X;)g)e,+bTQ9=>M={c ޸k|ȪƧVtI{23YY[O~5|:UIv76x"RxT׍R . AF_M٭{,e_ײϻ ^!+T¢)C5cy*/ ߽fZ+&[;*Kfï-}Q||)'kT YlanRJr_&.3ST]TQmAI+l.+BUb5 4Ռg=TTl+*UBu_frmDj@ hه3sPAAPRfzD?f.9>?$*6Q']ʓ~PUx\noHi2Unrwp`6,fuewn&7;Ut4+F<-pnGy#d %3I=yG7,_ ~BVsޮ6T8HBuϺQ3p/,ߊKfJәt*յ#pBbc!2.S?y\x͑rڅ,(e_UTs>lvW.hyEJʣrJY>'iM/ܚW^kE[gҠ_K+HrIQReAenqhXv5h]KU׏:u?sL߻4u/5xz^R֚ܺe&4xM ?iBKSx_*}[g/5Ͻ^ͷz?X2Q/(zϥIENDB`PK HAyXX"OEBPS/images/deploy_cxf_svc_01.gifGIF89a(1999BWo?W{6|@00==7-_$Bu'6JWg_2)Jp4?Z1I)19>JRJJZRZcRZVZ19A?JcccRZNNY_6WwP0E6TB{̕m @|oȶ&ث&̄xӺu{О˽ڳ̻k kkkkkk1ksk ms~/WNꀥ都n߼߲9U&bAMt9Vkkoss9FFS{΄΄ΔҌŐ֌֔֔ޔޜ眤ƵƵ֭֭ƽֵڱޜޭ޵ֽ,()MYH$AD *PXbE1hbc ->bTG"3v4%IW~l9L5Wޤ ̔/c'Ξ;T'ӗEB]ڒ(՟SVm*tk֮Xs=XVEj׳RᶍʢE]v9ֽWo^|7ˆ +XË'n dɑ+cϞCw͹ӠImZsG+Ɔ8lظo릝n۾^xoǍV.9ɣC\zuϯkݹw͓f)H' #WX_zҲ%C8FM Go 6F(Vhfv ( H&h%b01H685c@AHF&9E.dP"$"ViXf\ve28bH`cFS_~%` h9fg)hjhh.h>*iNji^injho*jj:ꬬ +*믾밼 ,+Ⱥ鳞B+mNkm^mn({'jBoT + F h骑FoL' 7G WLgw !({).,s4l8|9>,tDmH}IN3-uTCmu7\w`-dmhlp-72+ c6`C 5BwB $O68ƋbQW.>袗N馧ꪷN@<_|/<+W<[}o=k=~>> HL:DgxQ$I S8qSؔ<sD"WxxA V6!w> "("FL"&2N"(*RVD -r"] #2zb4cHF6k#:rcHG>걏{ $ B4hF:򑐌$'IJZ̤&7Nz (GI@lC@(@,8H&b҂$0IbL28s7&4iVf6nr 6Mrs,g:ϩv:Ny̧>~3p0?JЂUP"U сF 6B`2rJ;R0}LcJәڴ8Nsӝ@PJԡH=Rԥ:lTJթZXVխz`JֲhMZֶp\J׺xk@8=`KX><׾-a ( 6rVhA%<@( Zˑ`TU[VCnr"׸΍.t\*׺̽nuf.x+z׼.zK7}/{+_Fվ/rԿ` > 7^'K- w ްGⰚ(>S80ϸ|k_wWpilc;~쏃\8ē ABdvft|1qj x@PլEgv#sѣ=~M>Ѓ.4DяF4#I3:ђJkћtGRԡN5WmiVհ~/5w^׾+oJbNf'v1nc'>?:hߘ8Fc82( !*Xr7e{Rd6 AL`؀P:(AB{n᷶#V\1.\o99N<#=r\-es'xu~sH$>ҍ7P_ӧKT s^;س"O=,`mzyrA!? m Z#gAaSީwkq8&4Pp:,!Px}/-z?~~ Sz֣=]zQǾ_{۞=oo9G>_'RF|bص{WoOO?^kC66+ QkV>D,1PPxPwpx&Ze#x yWtKpQJ05Axfrg}u`xs6$W Ƃ+_$(/H)h;-ƃC1R&H`Bgp~AAUSXW؅VZa\HbXchg؆fjqlHrXsxw؇vz({vgVx؈8XxwvveAWwgPgcpwpQ5gPPRPo oA0q SpDO{7hw|z|HiXjWhxj|ᨍX{荻8X⸎'yBGkyX}.%*Մ Tx g ِ99 !I#i%i -)ɐ4)/)573T(D[FWxLCEPRYOiQyZ\I[]ٔX d)_ia9hYjٖcp)tpGc1|u%ъT GPYe&cx#6ZyC@ PBJa^UB_vVqȵ& Cǚٚ).h`,?qكw0Py"ؚIYHkiy)Aٞ)쉟Phɟ I: Z j*J(hV*h (6(z*j,Z./J0:2Z)ڢ4z19;=6 C*gtj'zJP8t ,08ləzJPx@h-j7z6a Ȫy֫*鈪ªhi*)$ jڡʯʝ Jkz {+گKk[۰wڅՄ%(.۲0_1{2[4{&,k:<8 =;C>G[HKB۴Gk֖vP*Rڥd8&wv f$ RP UgJPXf)`QPwIpu >MxЉn@@ ^F@z$ru #魙[q0;  ۲?AZ[jPA[%EUAŪ:0Uk灹+u*Pך:]kP q5ͻY(˿ڄL,ܝ l <N(  |lL| y !j&98|:l<\=\>@<4\9FBH|KD LJUP׭YYPk)u;y D @@Q*uګRݥ*o0P8ЩK 2Pⴻ <̈́P띎 " 0ѫZT@1Pxʞ{hͺ OJPP3Q >P+3gԩϠNڸ K3pF-@5?}خ.X uV?@RÝgƣ!u x`@H#fVaڰg$~UGTȯȆɯʫN8Y.e:xw8ݲGH*iPaU=~SHt&Egr8֧_'ȵͬ]Gvvm[wӉuq>܁I_zwݻ_{g?x??wav\bg6N{Oy S82)pk`iV18 p`.8,4J*NJoؔZ* RCG0CKpUfxU)A B 8` "X*PP @ABH4liZ;"ŹxLiNLqfsy[ g>;[gs %5A tעcd՝[usG W|%o_k8aNy\O <">S JDzGtW _1CpX D (H@\! ![w5BaJ Me'?~`)oi6f lP:r1`~:ȝeX5hYNlĊTH\z $n{1CcR(!G«`e/'ͮ} ,ߑ=Q )+[M揎 >^>Θgz؁a۾SIJ204$HINՋD^:H>,Ĥ8+FI0McpEJc\Ib,;(^DC;IDf?:3rrbFDhEgoFx&:| ^OS؁t䜔FN|FXȊGVD0E@@%\]}\I+KTIICIIIIIɛɤITJItʢʠJ,ʛ<ʡ$ʥJ\JJˮJ".b"b %f >[5`b$*++ vD [U+bc Nb6~('73,%^b2d(aM=->G6cEN3Vb..MFcOcPeJ6d5dE.eSFKF:VSdS~TeZeJeLeRZeUYeUd\e^>fce_aF`Nf,ifjSkfmmfnkfqfpqknFr6gv~xny&ngugzw\~^gr~ggo&hsvguД 0<,:e|S ,_M_C_"7Rla3َU5@5`iF*&=d Y:>8.f@vbj=@&dڧfj#>b+F&7vA.)^vVbBj=jfj,fbNbٯ^be?jVb>8M뻖*~(6ꧦ븾j7n%bd>ꬎfb)^lm&fmVk>m&mFvm:me^lߦmm6n6n^cVnm!&dԦfn>VNm&nmNooَovnobBo0ppGpFf6pd0n/OTMYNl0pW3(2#>D"R` BТߤ8UpQɓi^r6X,N(N䥆r,c-*b+r+/s3+'s-i4W &s6)3Os,r;-js;68s<@0s3',B/?/sEs7'Jrl6$*7k)tjN&QN7kV6MwTNuQuMbO'WVNuTb?nXWvNuhokMUNudigfu__b`un*&fӞlumrfww>nOvu.w|wtnx~ww47Fw~wswgNrp uMs聏00yOyǁp 66*z/D8ƕ'7<9ҟOo.<ĵWݺԳnꩢZ*ꦗzf(qyr)Ꞹyܭʪ뫯Zܰ*Zr2F 챾Rkf ->l߅˭k䚛%&/~ p ̯Z#0 [L _ /<1cq wq#<61ý)V  .܂A C͂ F RM3" `5 %du [w]B$de=6h]vj6uӭnϭf-ws|}߁CN_o.;㗇w{xꦏo.N:ۮxoy2< R=RW?ы-=bC?c{/~O>?=eOzЇ@e/>Dw?/|λ` X Q;! S PӞ"5Y@$$Hd` Xj9d`Y`jC>TD#VM"+r1T"E1~QD"%bьL$F2ыl#(Q~,hE061f#"E1N1iܢ'R">$(IIU\"qI52<*U6D%giXvq%0q)`<&1e s&_$+{YaLf5]9Mm2ܦ)]3&:N:s&J3sxgyӗԧ=YCX&/uyPvB4<3*QyV /#ЂvԞDBUyҍt"?CR"Hх=-@UKJ PyCp:t#S*UjZMU Vua*Uլ^uij:UbmkVZUBrj6 #X N0yL+8f!| cw wb0U,b /fi>1O  yFqY\$ƒ!(KOr,+U.Cf&ˌ2UVg3gYsVf5y3A΄> C#ʌƣ IY3d8ʰ4 hQg:Ҁ3-ECyPF4^iPc@ NzH2NX;H D SiK;PS}mZ{u귷]lG5v*q?n[7+|{^}?;=o{Wxm~}uq?nq-[sq<̓ss0;`w<:饝zԕK] ~~u /v{:a]*{cX0w?<+X2Oek92 k|zϧy6,[Zʪφ7gN=mo*ǞΦ>O4|Gҷ~s&~ji@>U=:72_ӟ5_?_џ)ݟ.) ş ۱Y!Z%4۴YTY[cY۷AZ-[qf\ֻ༽6 \-f!!ܽ\`Aa!Vmbul 6a[\~\ ^~FJ UΥ -!70]%%X^I\{=b}bi~%J"%Wڅ#ZX1٢ŝԅ]oy"9"bQb/#7@MX2.6$w]A4 ^2>#Y6X67z#e#9N9X8X:n9:c7#:e64^=#70Y6$c5$c?c@9#Y$UCj=Y5D]FfdGb$mY _iH$K~^$$KN^NJdaO>%QZ%__y_-)%SٚEe*`qeVr%ZeA`џYߦ5`ZWšZE`22$۲8 F U[VZ͠T- "fc]۷ %fbBd6" ^}f`&fANkjqb& ai \2ov\A\u!ȹpr"$\\pe$Bpa't6ݜi1#g=]9X"a}sqb}֧ҩy~3'|rܝ5ܕX݊q#5c47##;;(MA^^EYB&RUEFZDZ$qCzJHb䐆^]HdNM_N$QQvPiROu阚}_V*AEVeTVveX)~ѩZ)%jZe~Ze\rZ[ [= :0eFۨ dveB& Nb"k``iUTcj&a* 6\6A\=ĥnu}a^fR'5n\q!mkQ!$&bUW^'atݺ]ufrܸ""{utg!a-bɧ5b*2W(gz΢(֙mC&-V-#6,E]90,6]}7(u8(=#쏕c;h;d7R6c=>h}12V$Gb.dC-wm"irv݂dۢA)>1$Nٖ>)N񗖩"7)$iE.I_S^RZ^2Xz.jY2X6`"jFj_\Nj ۶9f#,:"bU-^f6fڛfUja6O8n[m!nfA9&k*o`C=\fte 0#,}kC+{g?xnְ|\i=x'vl9)v%j0§$z ;XpR""~z]cb.ưl]mhR#jucZ(u^#-Ycj Ֆ3RV>n7F繨1G61E^vFiH䐒Y- MZq)⊩).O)i%%/fr5%v]%UZ'`e(rj%v[**q۟,K*J}`zan[<3t7,@8Ui/3:)xwwcC#Ls!lt 43|7V#@LsyksNo&=VA}7|*73mfRqwWlo.?rr+Wu!!0`/.t9{w7ԁ<,f!bnCi1Žt:@b!{B-p>pv֧)+~0ç6qI,Kbj b b.v"P',/:h.n1ppSyuzX ӣ#Z:s1\ \h~1`G^`(Fd1c#- qmM_e2!ogKrgjv"6O2R%ǩo?&/%)'rV}Y\{Z.,G 3`ߢtc*n*1Xwcs=92/]e&6O98~cAfwTpCh$n<`9!l=-ŽRcƦky1x9Dy|? oYqϸpBŵI s9˩COgO݋α|\ fa˅}=ֱtJ'J)"0zBˍb}t9Q.9(1>S053b͝3JTGϘ.3y6(=-uZszOA2m66u\kq`qNv`+v-:bEdziK~'{mrM6:jv%O_{oK)O.+3eVD2iْl`d4!A!L"ERDpBi G*VQ2d= 1 4`GyS3:xk`ʂ?A;{NlnQnh @F 2| +gOιx 46]}z6C S1saf.ҝþ<( t{3sxٽgޝtAt?/0X=-7O?-sпmpK'PmΛ-̮xBsF QtFe;qoloUtFem٦9'1/jSL?ROцRNɔI\TJ/]u/URS'UU]sݕ[Wa{v~U5XUyUXbvdwUvZa[j=&hM 7[IvہҽVRpuW]x7w啗w׭{ 7"p#Jwl "߈h`}X, )ɡ$b#Nrd J&$(8Y3:rɥ9)l)-|R1~+)m Ì^ 1hgYf$k6 ZDpغk6;+-vmEi'8;0x*B ,F" T3֓çӂ\r>zär|SR7?ymkF*؊p'eSg oTܚ ?j ߐs|-;#;w G"o !>o;$_W"Ivd#'KMj~x4:툀%Z #(HM"3%NqSބ,iMw:PB:yD{Vȧ@ԡƔHIT⣌*"TԦnJmʉ"8PWbeI1YB㳖+]Z:cvUhYkZィXr 2ٯmRcwːW$I{M~yr[ c]_[Dv1c&d b$d -{2̬$)ɈDZƑe,Ő MD-z |PZU.ی E^߂deJ+Ԥ#5xqrcd0&_X%"B2ra- dc%dH1H$ȴKXc&1AЪ76Q $MnӞ<0U'= |5zbljKZH`(āЃaZ +oN`xX ͱf;]9AF*FB`GŪIHv8.eGRTs5)wPڠ;3:Bn]@ϦB(N#ǢI<OB^B!2+e [ (N+l~]zd-KT#a Iђ,%{D'zX¶hr hAhDBʸ]YDU}KJTx)nxjOnx,5Hg/}h6ַMGp{ow[oz g=QϤG׃ ;ґV6Q^dabO2"O+Vˍ "00 ļqkfd#.r%1F̐1͚^oUkTZm4ha瘳HhTY:B @:tI3}Ҷni,̵b5j=4gy{e5j0x[Mu1|C /J-uq\$c'n;M0C.uE|w-! ?,Hp{dZdB|>tdܸÀ+ݰ#G$JH;@ JHGBD#Bb4G䃲JPLp&KrHH KNlDHP˷ŵ~ eOTN儨+kN˹l~榨R hTzrYkV뽚Un6>1+8h,ž֥%k]Nr,2ɓ<aΔq&Pb+%$II/~g,g2bF&h*"ʲ-̩˸. ,bf[C-R 1B.iA>f!,1N*i-2)v GjD h-D!U*2%UC/@n-al'@'X-7,0bj 6#r6 `rǩ;C?"D=cDX7dwb>m(#dPDGd}dJ/-# %G,~~+BStF KK !KLPHIжJ.K"L<.ltA@(Yh :Qb V7 Pb(8NkWHź.锎Aq\3TKHL].K zqv,,^NI?k \D,NLbel"IFd,Oqdr|4/f"OfQQ:L5XOi D#;#oF/bk >4BPJ*J.Fxo(FZXTv"0| x"zԡtq@ (`>:a @ȧt'-0'T2ܤ-2G1 ă0;;x0 m25J43뵲fMȄp H$㞤 i\DHGe\7QST@eĉ:_eX Ž"6F;eIY<<(ykVfQ?.],bZi%TőU?o 6,8R. rs"#*o-'=p@1Vئ)imn!7g>.su՜#xxtՁip7~}r| }W}-o0V}bp~2$zFв(|A }zdF@31聢uP5Y }YCxd3Q+'KNڗZN\kfNj6?P\۵LLl6^^Na8i8{aVQ3Wb3b]1 eeE.As^[d1^nvfnfbeg@x6XɓT3Ģ"4ZCǜ6ȪevfƱ8f @F#DgFjRz-PT$f!b' Sc1oV Ɇj*F*2gJ5GA#"d?xW\ e-\ylYJtxc5`2'R.MVY{g5>PQw}F>;EpP~fE-h5$m}% J*K y 35N0L\R w$+[C+ uM3V D 啈 xQ<ՂUUs3_%`]hU Vx.a/V.bKW:/+W[ ߅Ls?>Nډ8_tg CÚH "Bozj} x7"YdBCQ#bJ#XaR!)6+'$)m0A`L]Cq?O;$s^҄'x2 ӴyKc^U\QT?y'R9R*Rwb1$ErXJWaWd=~nuJy!Q+DD$FF0G;$|~U?UY9k~)ȲL+LS w[c0"p _4kSIk^UWZ %˥yѼ,QTΫce:ۈSBU(;{;9e; iex;I3®ܪ-f36z6XZIA&5fŐBujȊi>O%x"#L+*+J5JChotMio/=!c4SK5>TN7ws~oO"sM ;7&sٯAv";vᲛǬƛ{VBү-~jW {MdY; "k >L,DDF KF.腚d>(xȕ #>HN78(X7SU^XtSsk%SvŨV* lXN븅r>zYc|)>qٳE˟~|='sVW?/&hN@)"AQ)/lέv=#vd=$p#ZȜɱfjcsr %mcmV#ԴT's,&, b2ϸ4{};h9k6?o<9#oӐ;RwE5ءy>4-쪙k>>wHWj5 ݝ]-Hаt_I:ȵ2}GS!<6kx^ L"޶ f`An$!AnHpbF7n1H 3Txȕ&3fS@hVL:Uۉ3lA{ʔ63g͢9_u)TQISNB}ui6OTi`͎e[oڕMԼm ޱ;⺋^+rfŚUm2ю=M:eͣ]Mzgԟa6][Z.f7hNv9qeug+h͓5g֑3!P7اO^=ϋ_~몧>TQCIDa"ERJԑJضH~DK= ExJS&H7=$1yJHa/. y,$RiXvI&.f&*7)}藘Bhm>dkʙwvj)kmz&;^J륒ɫA9[*먞6*)/YӰ ?VJWծ")I-WWʈU. d[%9ɷU[:a 1jmd]J SBC\%'NtCP_SXq[X1E`UL,dr9KXXR 30AL2̔lgL14@Z 8gYl4jy(dx ;XKwdTm^Zw8]Nɑ./9QHC H$:gJsE+]r4#nG'T(HH4$%}ڌ^;m0oE^nwvzcZĔ/Qݻ^w>|+?5e4Q\/Sբ4(AI}*x_ժW M1ȪHR,?Yz/,O "*Unk+\ 7B, mt5W55/$֤a\V%ILYź.N1/n1Y"xFFLb;X ,8 ȗ-@\VFTicȧ%f-"VIfl$؈[ITwfJMmlEP" s\RukjZhEv]zw/x~׼/}^jA-oz͋^xW}Kػ⥰u` ^uk]2./wX,o[,w+ <1 W@/*H_8F0=b3ٿ#| eS%1c/C0 gy!FW(!#|{汔 >Ɓ.serEK~ϫa8Mαt˻i^ݴGiP8}23=dXzKN3|i;:Y` 3[ג&uNjH=u[WϢf5o-DoOHID"R:<%jtGGSG~g(W}K|7SR8Sr@ h (- S"A AxATUMŁ!(#C,Wr(.nE %C.LDH{qE401ダEs1a0]211KYINo$GThUWx4DH53\Ge(I[C ĆԆҀ5!IT[Ձ\ɡȁ z15qJہy$KKA7WLzqcXMŴK9zzu8LMc9$93|!t&c7لMA>#;>(")?)(>?@H+!,!, ؀A ySS A #4bB$W%UQ.\0U11C'i.c/Հ.C7q.Y6ȃ5XWEt1㓀5!cDwUXUCDSEXE]EYhU(YYy.3T蕄t4$BTG;[ca5ioYՆkp86A[Xx 6jx\M5g[0ɰ}Wb|D YNVZ@ &y>{NR=Nb<%ur&'U>ѷ~ U~q"}iR'Ӈ&ɈhPg~G~p}ٚiާ&ٚ~}(Qe*#%))SATtxRP"+T2ސPMTUIdU*HV1CD4*JjdAM= 1%j(zUx/F0.ڢ2JQ(z8 ;l1ʢX31H3uJz3R3JJRʥV^ ]Jc36] 5kJcJɦb5uZqpʧx~ڧ*b}J5vjʨꨍʦ !iyߔ%0` 0 : Oc;Ԫlb;d#O@")%u"TR?? TS  lF1]5-!H.C&%\C);b/1-1 HEˡ $Fe9{!C = X\IlmqXrɸhZ`}%)2ڳ,=ez̳ˇN 5'@ [M`NPNn꩞^N갮ꬮ빎뻮뵾Mn~Þ^ӮȮ휞ݎ۾>.n.n._궾^?^._ĚҎn & ξV{yno䀌]3uE[ 撬橜eN ]{P,y|׮0{Z M] oj׫< =)żzˎ~ $V@8O yE[s/Ooy?O+/p?xVd(EתbѫH x-L `b,8zird >`g4S^O? nƉ'xbЭ~'_Ƶd*SZՐtlR`9\k]gl=!^A ՘G=< ͕Є'Da UBgF58cXʈF6Qd K( @&)-bvpcw+=AyFu}:h;DeubLF__929ox ;%0[b>e8$G=IF|rp-p %7lf8q<0A;ᵡ% cegb$" D/>pcLp!AZ۱qK?ć<?wg9Nsn< ̡tQ }&8~='| Oh }kB ' 2x,D Џ 1 7~oă9Pp=I!EH 1o(GS8AQP/;3.?! gE rլs9kj=CbkZկkV k6tr!5lVJuMl4s^򗉸.Y!U9,K&"Rڣ;8@ƅ76MS>ѫgy7<$܋aQ/x 4h1],DC5> 'a!C@ii`Z"7aLnC|Bф"82*b2Ai:&tp$*{R7 (G;0.&ډPHG`kE5H }0/M,BX+碅HӞF4BO! pjPa e{nvhr­Q@*4z9I$'DqB4Ró5}xx/U{8B зt=%xo. m>DHw鉄@ݰ-}p7(O"r|`8UNxs]w8B\)ϓ w3w xGSrzS0zNhW7Do16, :/ꑎ Xz0. d @{ nD9EC0}OhK>`O<w7b4RސIQb;=quWh gҢZuBb<VCb]t|]q:m~-`o-(v66= I$LF"$D|Ĝ_&q=X|mz2n /ZK 9J'bs˸# 9$H' 4+{7 X4>X.@w1y B3: &r8A&&\B"/$h|AZ',0A&@~,907wpA)B C'0(kNHA9E@L??@"8z0 zH/wBoZ/;(6AY+F3<!J4盟2) ؃ ! \˵q^=1aevKe(aaʌm1~(3zhv0q?=(@OdppӃr[9(C{&* 0y`Mk9MB zruAz_@!'S.,l/G(AU9͇AB\tDÆuX';MSL:H|ᔃ:xMG0s 8UNS* N4w%70Ex^,N!$OO%0P)0r,ք:ҜtPj/t\,Ct/4NPOCG!J(L, ?%U 3dDTvhuWvKI(H '[,@؆m\L qr@(E'RZ/ PaϲYfddB&Z_e u29t Rp^慨ne A'(d{ffPT$h%_!8@-߅X7=G2#d%P%؃"!^j7_M>>_,*ۃ}UjŃ])Rp"h#ȃXчU!<آXU8R~(\ 23 V=j`iJgHK4@ᠼa$Ja=Ih],iօ]>XRTͥϖ˒b\Nh@v@"wBHoo#|e-ol7z]' [o|'ٴU7dBSC$]&لj$ج'ڞU&5>qN' D[omfwZwt[~Kٯ8kjN'ܩqo8Z/GCO,o qf9Lp pq~ 𘽰n.9̍KSwo,O) DTuCF~pcݐӭfY(#jhs:gHLz{ii&_R8TԦԥƃTز2R_;}PE!Rq<8Љnd(8H\O%x]u%,`]aU lH"\t m,vD!`g4n͎֫uׅhs&ހvTB& 2&~_%xkx~_~?gO&0u`w؀)Є X/!~wv,8frxȄnm{X !j?|R}:u=oe'u?f'A:-HT>|ۇD>YWyfPLGDC {Jz3D+ MPppI h-\.Z,uT7=U7S/E.ЀՒW`}X)9]mYz]nтd5iNMbNbEzźYL:A#>IWV&k,mzছv,qk4ˉ!cR`!o+ӗ=Wx5{CK:_8m|BxVT+O@үL/T3ߘ7?F d p? 4-{lpLYTCR/՚<Ѕ4 q[qZ? h1n5?dlj*!2T)Vg8N@#EB@#MT1m|Ns&HAޡ86YƉjvG>"VS 9?<*UX!K$J20vJIvI,xtanCh5awȆ@ '5"v$,ap2MdLl<0jS[Mkmғ~,BQ:կNk5Ьߎoyd;՝%{.כqr檁jxcވ dN#cyY4񋻓C! f7pnfy5g>,cry V⢧vGOǃz=4{75 gX /lX w# re4fx> '0 A!+mI Uy0 Sh+hAYB-BRTMYU]EUeݎ8`Zݣ։ ^X0u=p< MemO6lA`a !)3C97@7]<86pJa7_pꒊaҘm92dA|A?L8DAT1J]EءNodcYmّE*d+"^XkDrIYd`A9 c1XA0c9-/*32#4:c4R4Zc3b4fc5n5j7r#8zc88c78c99;#g7DttV'u.ufv.uzvbvgx'ovb=y'w'vg{'zg|w|2mý'o:bI'~"|:hBb=F(UZ(jhr(z*膆(h(轅Z苢hhʨ%Dۋ&ai⋌ڨ)hN.Fi2nvvvij鋎)J5Mڋi1 ijIӈ C06YAaT`Ju. QQPbLeZ%*VjfbNW*ΪV6eڡ^%q "\\ZZ"^^ : FX^ bkebkz뷂k븒k빢ko浺k«o>g⫽+뽾kʫ,vkzo+B콪&hVo$(Ƣn(z|jv,,~ɪllʲʺl̶lb,lu͎o,l ,>AmkR-FCD3( m ؾ) 6 n@<ܖT\m* >T>mjm)M*mV_>FМ}.D!^.fDjn3|A04CdȝG$ GOPT *-©C >VV+Qk :o`:JZ+voj^koo/l+¯¾+r֯oh<'/o.58:0oZCZzp',bQy ՎebYFwp6|,l0ƲpӦ0p l^q.qXB6-Ҷ*C wq~q}1Ԧ0 -k$oZmZqժo-ξDl-#־qq[m!1"ۛ@@2";L&m'Kq![1F2r2nrܾ2.,˲22--+#FIJ@>Mв1..3뎜N3&+m)C6ThsJ]%X4,b9@.̂QMҳn/3B/=O/sn^oAAS+ZoB/BGo>KJDStEh+FwFk+F:ϻotInpM,kgoO s:K0tQcM{p/ '1,M0z+lWG #qXq Z,[uZqZ?ԢnɆ K^,wuՊ0FԢ1BӪ1%r vnLvfBrGi6 ?Mߋ?h 2 #GZ2j)2|޾)#rhpr-_-ϲ0 s/G0#w/g.6qCs67Grx.DinhJnqsMz{z1ߡa9k7LRh=sc%s3/AxD4Cs#8KCCo[tkktv8o4{K뫊tLG/vptTWpӯTۯ¦gone056]75R;lW 5 k]uõkUǵ_5Zg S1_5KڬqN1B6\_vq6gvq-҂=Ld6e#wrG2f'p-+h?fö%s:$q7)w'Z.,32#mm2vNqswz河_7y*33sss7xw4zJZn.0פsiY "9C:;}%e=x3?{;#zCS3|;|~F ƴ JHǸoMo{8.9s5N׸N׸T#Qkl y w'/V_9Λ,W9qZ; 1^U^=Ճ9S}cqc_}ZOvZ1%1b2%?̨죛z23um3Ir:e7::Wzߞ"6#2ێ$-_:w 60[n,߲5~#oC0,y#yy\{OssnGBw߳s}W 4 t@Wo4AGt78 È#2|h-Ǝ>vQ’)B24:I0Q[s"H:a-ϕ:Ai 'L-A"T0jV"zjծeBŹ5+[ʲ&:&2DΕLoXmw^jhy>Ζ,r'g.{Y`r- 4d'3՟+wd;]^d~?NܷdlVtw7WwC~xѫ~g//߷z5S/ 0b^Θ3 P= =1 A|mBcAH -f-Zɢk-PQGyG"1%d&u4rG$w [R*\K){ )ɤQI*2'lN7tJTuI I@ B%>Q8X+ݤ4GK#3F1S-? 2;ERQ%UQĴU@׌OI甔H(lN/o] W5aTUy[u^3I"iX,[,ݲn3NkܴKqd+5S?=R3E^f 7_d-h{6\i5sӅ)%kVW.bK\0d~ťb-X185-s8;{)Y_y.ːmߠFYbk5[|ь短κk{kFkn6;φof{pN|p[\o#p|r3q;sE>|y\|wy7~vEq?h@k@AN4 @ f ?:$aQB-t aCΐۨ o~#!HDdI"BĈHGR+/KRde-VQaҗ;-[x;v-}) HC.- jǿcLCɲLҒcAM`28f5 jÛҨ8 hT#4%eS28Xy`zg1nD>!&~ȣ; rf|m7MT4g9INu^stg8t^ׄw tNSBg!szș*PBHQ1g# D )b`F-j Zt$%HQQ(K=(Є5MqST0a ""pNLQRJeSC`D'bFTBx\$H{E8$b V=D/aEp'TZjR+& GHD0"9Ə%$ ٮLv$#9JMNl%5+Ũ (?yf9-ό&5.i^F3-oS_3p+Ҹy98iquX:@݉cZ1tʋ󂷼jzZw@U/2>aЀ0 iD&r)ġICz?9P~1 a5 )5Pӟrqqmd8,6bP=] cc:ܰ ax:v[ld%0^zgqAF, \#V/9BLīMD>d`H˘>D"?QDEh9#y~ Pj;)3(OBjhWb T^jWըuKb k]G0q=k^zبa`3*v M?h&1Kh}WfMh WR5ҥeg _b1Qv-KW>S^Nn\y<햎w}.T2@Ǐ3y;; wūIs xj|9Ik\'OU}C3/(=ks{=B͜4ytChM/ЛOK~u3}'rh/QeP w"19|a \{ y߾ 1^;~x+?~1BeSd9~@6T$+LWD΃~k]qR=XP|SYpmK2ً9V*E$n} J6FUs4R H%gT~[V=oXz2a%@a,ZO5!F4DYX֒)LgC2(I+b2K-d%^n27| Ѝ5n4MCki+H:҃ ߦI; ȃ =)<;×C=B.Bڃ nȩ: IZi:*A0I0rj m"$ mC NJjfJEN $φ'Ot,RF, `` ``l:o9J,Hz!, !b,>OJzΘ Dob/٬#LThO#x*B%Bb&֬"lҐo1("*/tՐ-&tbBO؂-B-R!dB2#n1V P$'$ڢʹڸ &1Е6pۺm¸3̃ߔCI75<9j~8Ip:d(7-*I6/N>Ún+#2m-?X 9N-2x )I+ $n 1"s2}|n20 zA,l @@@gj +/Th/j1oa h/s3w:;Qs t2/ ",0ʆ\o#<;H2b,>gL%1qj!MOQ!t/4$!H+f+Һ/в'܊#"o.Z#Oo#VtbT"oM0)"\R%MA#Xr*ה'_+IyJI  >>M:v0pz,rM+0B+0KT?p 㙜,RD?R՛b.,k0C0SSCH2s0.UDHN5SPN4.33d:.C5g l 6N](87^8uSAx 97qZ{,9L:il:,]:3Ȉh!>H) !(g Bl*8Bb@@% bC&)h- VO 9%/EEZmF-RXF-"1NmEWME}T@򕆴0pB2KtZ'%A2sH J?c26&MqeCK:XOmOC(M{lnNP6|i.p^.I W+rer0P 2.R3Ti1RuY/31uquvEUGjUT Wyu4 Q3_4Q5 @a`\566.7 \Zy` .1lGw|ss~uL;^>WO UQ_6!V=cͤ"x̞j,> TAiObIXdFV1AL@U0V'L&Hօi*+`CԇoDFѯVt\4h5RiFYgE*#ԓ4Hv0$ن3p L2J1Jvmiڨ%ok+bI*6nlmr܆(vm2ron5JPR<߆p rdq-R Q+SRtɉSFt5u3S1 vJW5g1nUT-3WyB74În @@`m H0@|0uŪ6@ ~l  A|7{ځXJ}Mlb6b 0z9 ;9YQUw=5J*̔j5Oam>ni>)?eOID6QBAnlБ 2dOMDDoBjc[Lԉp- رV+!E3Ԉ"jx ȘIֲ؋kkT'4onm90x( 7wIoRNK[ămC9Pi,U#A20= G;r{ ri[>"L֣Gw-Vs72e02ꆮBJ495A@U 6[vH@2l䙞44֎#,§ ΁ '}[929̙8l9 Z\wW]Ƴ^;eL.q>UZB `1OV__/ѫbv?ZX4TBJ#*TԚDGˌlDbMѶgժ!2D)<"Oh1[tv2ҰTo-%{(VKC#lIS2˜̍8Y'm}2vOO.:pT䖐;04>IުಝқCsIQ;#S[}n>0}cGu0;0vsP0]mV12?Ә_ows7AjyR:)J韠ziF覬 묥i^jں髩š2^ ʨjlr~.{+KFІ[tm4 p;дJl{PnɶKB3do[oFm+0I4B$%c@yd1FYJ+R[F+#DM.L5R\J6RFCUiZ:TP]n5]f)U[ojaVsUp5\X㵶[meW^w#1~&a8Zvnr.ezmQ(u燐)A}YxtD6mDŽmw6Q'$uֈ[5LwyKB%txHP݂ȸofG|NB'9kh>qX.f믏j5J'}_FʦfZՠתLNT@T~@ VXܕ1(Vj~`%( D!UH^0`MUBPġ eX Y*! {H@<\-% ~譍0Y:HiQ][)Čf&XiB07dd(֐lcr _ǎ1!CJ&H"iFDN(IFBrA{I=dL%Iʯ!\'qV(VeBlU%-Ia- f0RLf, 4hS.Ƅ&YYff1Ypvs4:sy٦8IpӞK/ /ZpP@3uM0:.5IB& y72u-O4\;/EC oGLPw#=Z⳴R1\ȕbȯ4Q՝հfer5uIyz 9Bݍ$!]5DŽro<ЃB]Ei7D@B4I>ӓTPik,@ҞIJFVD)iI#6> pK+\lقUzYޫ {SiۮTn f VMw,K[up kzߪ"jC;lX 5DZַ6uD bk[Q\ƣ-M¸— d!gzU򏃑:ð;E8ъW}2GUl|,BFOlbr_Z&UZĢNZaGLV1"L;c2Ho'<>;b5D{qJjL\x8.r1}ds 10}l_Y,F^F'pVKVl2@]Bm"YvS+%@o{E)x+@A4b+Eo@pBD+",tW5o@oƃAp0t+A.&\Z![qAb*'G\ۢEE/\e*J,-uE]ܕ]\rAEu\[0D{(Elv^F#` G,`222!uhJ{X_tF"C0xF`wv4AvD_(uFVubadavkWwKpH}z5'FywSqK~5xGdXLxRbByXxcLy4e\eCzYvZzaFz'ON|1f7;f8p`"֡T#eFi!u "f >bt Pek Pujѡ`S 9 C%հ =5jV3%?27Vj(̆xjYSmyW%ww'sb'im"o~@ d@EAj(ݖu3xZ.xv٪A("DZKX+k,?8|)JD0rjAqن肆Dnq`ͫr;[ޕ:^6^ YT^k`ۥbJ^yRdG-kc_5tu:0q6I[G9"Swٝ;a޹H fwvfAw/5b_ӌE5dxMԲ9Wdt]N7ezzr6K B"@LP !&S(UA)\'Y!<("}A&fBp``+$飔kqurކ>lRXno{mxX2s )˹o%?ոX#B*~T YooMN(ZZ'I՘F+Ti.Wr,&WիDU$Vrhrqs00\Eڪ1qD[^$]_`!s\_^kZ{B&S!a<"TQ#;2l&)"Յ^'Zv쵦%f O\  p mU:Yy:ellT7#x+"`_ٴy]z*p唂%Zyȁ rӧ́$@$&{6]Z +8+ zځ*tA/)[ ˬZ>q[FCj̽DՇfq$^U4[(krsX1'tܾG!/ 5H {a*Gu44 MJYgJ4!aI36 ˝]n' c/Y5Ƙc갉N$'cҋ7N88ݲCܳ:F C<:nOE,Y)ׇz?juSȃm+?w$oI$}Ș@V`*IL YڦM2#HYeDYL~g9p$dAX xA33ɴۙ CtCtZS'~TnC|ޙ*`Ѳ_)4eoؙՊE?$E57٬J|ߊ'1[OS:랾.s+GIY<`cgIMG]]ҾnJO=J_vv]Љ$ndHnIyb.ҔwKyAM,,.y"\Јy1=fd71I;^6>?LeHe:-6H6O>Iٙ K@c?"4иo@*LA <0 ;A=pD ,QO$EQqFkFsqVXG|EH"+#4rI$TIWI%&J,0(0L4TsM6tM8sN:NO@tPB 5PDUtQFuQH#tRJ%B :/MS̡ PCuTRK5TTE"UV[uUXcuVZkV\suW^{W`vXb5XdUvYfuYhBiU2q 3ݶ[p[r-w\s .EsUW^x絷^|}_w` `V`nxa#x+b/8c1x;ydKdQ69eWvY哭8`ǵ(TfyU硃hFLv觃:ꦋFjhNZz멗벽lfmmǎ~;onoWu‰"0 #`qw|o%<)|r-=Cs7OM/?Wug]vo_w=ip7xW>ywy蟗>z꧷zמvӾ 9iϧ7?}gׯ}~OP`!~s@P~ ' F0$ = ^CXB"WpB+qmx#06`(CoІ16jx9qC QG,b8'2qA4"D(bQUT"h,NWF/j1w:]"_0>nݑY>1d GC&,$#HA>d%#yCbR$$3MZ e'99STe+IT’ G (*D)Q&.yLc.L&3fFT4Ll^3f5or̦8Nrvf5p8Tsg;9O{S=~ 8|1y5:U;bRjVի~UckYzְիjZVƵs%+[ Ww+_jW5`zX&jRB`UZ" [8nA hCZЦ-hU{Zִ}lQ;[ʶ%moS[mhW w .syƖ%no[Vƭ@ "}oK^N7ut˛Wu-{k|r׿e_WMPQGXp-|a gXp=aX4\׾ZhB. Jjc851uc BL Y>f\d('Rvrd,/T<,\&sl/yh.cl`e0k)kv 8\M.z`?7o,׳n+F6pyhL7Ї! .XյUӇ.p hsס&L\כk=k fC6-jc-mp[;wmq67ѽnx;V2^A]lK~.Kk"| g^< +pg\8-qo\Kr*G]r_\ k򛿼 wrgPsv wPhx/a MB}_[}җoom͆=Y?{~cB]l{Z.3ATo;}:hv뾽-yVuyO!/xuxyh:&Cwn>˞m|KXͧpyxDyX6P\DoHJtX6[ňIlRYlEJC'ʢCɣ4JTJ\AJ:c5c2c3㩸Q lۧ.}_5=Xd!eT ]RJ}'~BW  pG^"BK=T\0 8TTR xYT.%d\.\e]e^e_f`fa.fb>6\pm+\75`]6UdFNP~R&]N66e`V.Rr^Z)-es UEC"^B.RPD'P^ev)8)pf.hJAnEYu]RU=R.R!Cҕ^O5wV#e]veffgfijecQvf=Eov]9kiyX9 @4k%H=,Wq]mW$l_LPmx-u#mW%!VVIקl!^:xqVva>g-"jv-JX}0y~X!hu_ނ!0" nnn.>nnn~nnnnnnno&onbn[HoHEjsq?oeȍ]L&kE.T%݈GUCTȀE<(RڅRp>ppGq? pY#jP*k؂,j&qoov |A u''A+p!(ܘ^O!9d܀)zdOV d-$sThWh$g8]$HC.,3/e74s4Wsv)dE 9(RD o'+hOqqqpVllD^_puWMinVKWUT;#Uv# v ~8{X4p?e(ll9rhW$Pk0lfwv:xl(lu?loUWehwvxqoXhu"Ad_bhewW(o?o7oyyzzz/p/d.?v?ؕZ?4TRdh&,EWׯM^%Pe9]7)hMs]p{{| ?o|w7:5_jȂ|ħqzO]{.MEUf+_xT44w^}^"PEw.^%d%s:aqF NA*Hf˦H+0^"5I ` ލ{3h/-o -(C#PBt(FJQ^MFAQ~=)IQjҔt. KGӒ´2)MoӜ~4yq+?ɛD؅%@ y5UG !hh2P MGm#Vσu]@. @5eBA&4QFkD2թϋW!aGp FC JV]Y҈ DX.DŽ)TҟTlu"5lTQpV5B킋H @.aaX-4LQ20 C 8E61IIP\|#X49ȡ" ŊB(_1%JHasѫ#"%ЋxHf^fDC,=+Y ɜqDwFJhD-ރ)x *CI !]p0򶷈|dnn3,79t\=z3,h?:ЅEъv4-HSҖ y$j񎊼{zԡY:NW](DS  ]` t-%K:ejXc -8C9xūjLA~5ls{6-p{ d 6 Tv6vEgVOzu] BE)6A1.z"n%r'!NuSy.i=Hk Oð-n` Ző8THг2tSn0!dS._;!d~k5Efxtc$qX k!fbJ"Et@.H3ؚ4:Iv$8 ߋVD%,;3cUₙ({D2iՄ $r4GſBlLʄ 0t-b{CwPcҘ~Cү>}s?߾{6@wϻ ,Tm4l  =`y\BZJh@U`fZR`Vr`pt {ϱIV)SWP64uJjȲyAsȪBB !ByyvJEU=W eQŴ~F`KaY P!=Dp>A. h` K1{`|۽ @$ 1&vDyX.Ȓ!]&^'`P*BH<|A )JT@1ŘD[ .h"]%[t+dS_b-*5ي@9 9cc:^m=i` >E, >J@Yiډ@5@Z$ dC>$dS>>DFB*d>.dDF>GzC䚅DEJDdG$H"$?QI^KdL$KbdMBM$KJ%CPfdQL %FI.؍Dñ]༅ ؁ dy+tJp†vr,p+ġXnzՕ``% f er[ ~\A2`l&gnXUm`]-YeZͥhpȉ ]aO\6 ]h`_U[Bnͦ` z_e\qH[P fhdfgg&h a8EBe-y/12$C~|gD(|y||62҂aDC6((zgBh\(zfY2(1gMD(4H !!H-h CeM 60Byԍ?Gt%yh~H^Wj:iFBn)"irv)͘^2^Ɨ)ҍ&)n))i*ji2*:B**ji饎iJi飂j)z)r* jMzf]VmCRX绰 h8^1yֲ>+`],E^U`e&uj+kUnPnfk̂8A뼶 "+%k1kp*\ O6la lact.']*l],Œ+U\:\kF8r]8 HA{8cΌ},)|,1Βj(}͂("*֬Ӈ16p l-r`ˊ;+؆*ۮFҭm-mmF&nn* .NV:"2.b.mB.f^.n.կ.Bϔ,|x@fI /DI.R\w)oR/"TfX/\*%ϔlo/ϕx//~Iooo‘^yfhDoX.f(Op|&JpCk({hg+p| c4`C5`4C4J/8+.#q^&1.1?1GG1W1Ogk1oqcg1q1{qkq/>ɯڥ+xPahA`M+ %2 #H?#I$2$lȴ4'G2&2%r&r%)O'oA\2)"̲$Dz'P.gl 2!2"{2,۲,2+/r.24?s,H22/{+O33/2#4Gs(W4[3r)24F2;_~~}>˾>濾S:3;{;ۻ {{{{{?kôO?S;OD2iȤES,[2e &K-@i ESȰBѲ!DaA -*XbÓApȎ2?^i›:s>'M8,hRJ.u*P?j*ӫZ>k԰_b5,Xbؐa["$hP  6"BKdȷėV&qp⊐ȰcY$c7g.Ԩ7Nm1qdЕB\2͋-ܿ; }8cn{3k0j˜[S{';kYzɇ6/O幥^; 6ݮN?[LA |3еc,̰=J= 0@=lCpC1oB4O4N4( 2h7S2#I'rI)tK' 2)+ 1D&d01L-8մM7ls=S hʫ"0 EuE#}TRH-SJ5K7&>ʹSRA=TG]TVQuUVe}uXi\aݵV^qUNEua%" VY`]YdmhE[e[kp7o\r]]vmwM^w덷B _.x^ ~Xa#a%x1-XcCcE.yQ^M~YeceeyqmYgg.z褑^覍~Ziizꬱj=>^~垛ޛ ?_-5ߜ=EM\N_]emN=l}?!]襟ꭇߞw>?_/域ϟ7@ Tȸ6)X=Ђ9AIXBq!D YBЄ* iXC~2yCPy:G!P".xD8(w* `D+"mObX'v1pD"܈E0>J85T|`?nZ"VF#bqM4otx"xGvT$YDI$d(G&+0"&8?^ozb# Tш|)G`l /?`xౌ`\QKK֒me˱yR,")GY0&-KI6m1+c3cGvn =91dztB7ɦ!rc1Mk͛d4X0N`?::B_;FHvRb>YDM)u&#ŶPbG(RPaBiD)JVi9|4EXӼ]g#A&`-e!HZɶJeJ~T A^T?L LARVDdKB9&DM_X$=Tnvu_x>esk\Wsf5J:6NUڛږlVbT^ !NIZ8ԣq'B.֋t@OG D\XZAaP?9ےzRÿ@1`k@ ݸz3-bWf[b%Rm묛]XhE)ڮ"mw7}Z]bG#hk22K-Sl rf:Uٮ8pq_6"mN*P0z@uPDQf70iu)_eV pcy_w:`. ZzVXb)vcYHPpӌF9@unFjHxևr%mJie*+Se:U'L+zoѧ_mvZ9r-EKwLL1oFn_C2*ڑ(d. X3Dik0̶mߛv}/U*.F=.HK9ӛ[j\λ14$1y Q xGb oér"!)$UlyCfvYRT{6b)7Ҵ4ro}o+uڶ:vb2.|@$*xΥ&Vyyϓ.RT:Rq^yFTfy'TXLHDшVY  6փ&h zs'O\|w۳&i/op:uvۣ~Ϛ1=t"PGꮈ `wml pJr`4~/ށ_0ЧZ LĊ Kh  FHįmTL҆/& n_OO!:Pnǐ oGHsN, 5l."^Ѐifɶ" !*, MnLfͮ0ZN* +o>Bif f,/׊+*p sQOg(hi. h8)~ɾJ .nP  Wk iFQtFqlJ_􁘆O eپɏ*i/#KgK$/l.J`kG@0( &)/qQnnI Αz&1|3##R* &udJ*.1R`o"`\2#.=g]pb+lN1NQ`^H-*Oc-.P'_m~ɦ220'Iq<~0* 2cVRki7{ss3 L-/2ϰ/+LS}STab`` R4{O푺qpⰟ3 39)* 0J,i. *7A8a*ɾL 5q-/0^ C7n lQ^ > a2'qn L oo,919sRE)p2-6KI ,DATL&BԈ..?A8FZЩ~钒1&pR(밙BiFf9-,OB $nj(0$4!O ;SECO1 PmP0Ti/ɏ J˩ԴtLkVLMOգfTdRzWS.YU$)>YmdFЫsbYFf vu=U6IZqތ?Z)l҈2Њ6KZZ5҈UYEoa6m6R65kP) 3s Pɿ&6V 1pF+ kz,F o3Ao3ƞj%7k~eU_p ]E! O )ۈFd->;bl nгlF 'nFl&m% n VoVoƖo5>VpBlׄ0<qor'wprr7A-sH`?Wt!sG/gMWu1tWu_vucvkvgvoWwwwW'w{xWx/wxyxyyfyWzz &z{xW{{m{W|wt×|}p''}}w}G}~7~{~W| uN 8X؁㉁X'"/]Ȃ3;X6؃CX)G؄OJWG[c}Wk؆ӓi/Us ߦܴ pP@SiR֢XnX^- TZ؃0(a%XȮv)h ՍȎAkr`AGH4 謆钞(Bf(Ul69jg͚JBXS90(>wn<0m)dmZe! Rp"TrKACG9m$9Lmim,Vys%t0sAum&&`V Fy}qyLToA8y PCm ?+kT6i pLKZӬIK)\d*u%]ը6" xߒpLjN z܏ 0-zƺi V4\ <PZJ5?ZES̝%ꧡ^X! z idiWsK(8G6ٸ0b14k@.{3 L5Tha{A۲9y `:9*CEEi&[ \{;з2L@:;d(2Y fЭB%e9.J{8Y5 $լn !)/ <\ lT{)\OZWM{/hf` nH <ӿҜJ<<˶ u hkz ! R+<@\Gv \ ;Ύ|N@ G#P}0X%s~dȤUp f ]m+4}AٹZG,J}o (űƢ`< S]%Y P!>隁u]}J4pe9Ű|u]G2kQ` vw Iɠ\ٛ[O>X }5 Tv13~Aٜ_2y:ʿBޯy >~jŞZ~l'gPli?xRi ` JlCNF3끥/ΏU2 ZPߘ䤎jHV, fEIA'6riIΈoƤY?,wubf=nld*A0Թ_OKp= F <0… :|1ĉ+Z1ƍ;z2ȑ$K<2ʕ,[| S  4`G̝<{ 4СD=4ҥL:E8͜OZ5֭\z 6رĩڵlۺ} 7ܹt4;5ݽ| 8E[8Ō;~ 9rT%[9͜;{GYѤK>:jW~ ;ٴ;ݼ{Vyċ?:8̛;ԫ[=ڻ{>|u˛?>iۻ?>]ۿ?Q`'`}&`>8MgUa^o}zDPxHI~bA@a@O!(~?hģ Hb"a1&yc?*XY(I=X42dfr{9s[{,:rcH%f㾷Kn<CHl=.}::@%8'DdlYzpߏk3빢tpTAz6-` "؊tw4)]+M*zU &nl D|"\ѯ"bR#  Lp jM#OAYj*h;>YtPaKTSi XFы`#V8NWfSh" BE\d˟#9pO+ "/KlȔ79zbEPl].~Sz&c K27j@ :` ;=S6l#:!l.iժ?,/L-UP CeMKUsJ, S|oa%WiK<+33*?rTeO|,o9rT|況9ow:}D/z\n+}[A:ӟGnկ8=\7}dWHˎjoۡ}@;w=|; ۀpx&$W<x'|'oc~;ϋ'5_zԟo]>O}Woҟ{/P-b&\)[_v|T&/>|3_Ώc~O}g_'Ï~ߠ[_ S$;a8h"q|W (Ab))gx0q)t)_p4 SUY(*h1,8;6"_lc? #4'5g%ƃVhX2υ4Q>#&؁ `6W((C(4U(L{B40.4t*dWp,Z :O![QGQY4~0Ӆ~B:6Itp20*z8Xn![8V&L(TG!S%`=NS: tJWFp9gOBޤM}/(];9tǸ>xLt`&ڴbT;x #G]#kq ָfeUCPC'%XfT#>菢_>%8.SxhbbDIF`,fF#?RnQS0[P#AErpf,hm#Ѝ+o;(,MhV#8rptH+F'V`Db0WҥFc%;#H BZ&HSXX*X#!\$7)ru0jIMKU؁.iɈI#P-YM]HԒ"9" -W愭HccT">X6[BJ9i `+sy&I#˙M,ȩ(IRV9UjҊ/y)"GXIOrHx|#8R<b:I8&}R :y#9(! p  9ɝ+iLCMC,PtXمK@f}H&CJA;2;9k+Y% q@ࠅp+' IBUHGSy%hH:0K\,ʧ=dd|U0b`3lf+NWQr61FvdiT-^I]x)}Ц/R ϸ""$y3%(i Ӱ <0tmk`k Vsfs0Ӎ: K]9co'9Y%~}֯t،1 Qͭ5"GAJvg}.Y3Ohq| c020 ^Ĩ JB#։=]Ս(dz2!`M>wX=`2=J[x|Y#\@$u QnߺY36m#6rTIc+xX?bܾO~]gÀ[y(= A7qӬpvӋ.:3Mrp.L5|,&>ӄhнC]y˞O+'c^t?V宎n˲>;dC1Iel, (<{V"m2bWr5IU"XO2iޗωY"!-R 0%?=-!C`b*WWnmaJ}}N+}E*ڇE aPVFHoRQuM1:eϢEÁqu/tPo_xO_o{_OLmQ?opkQqG,Ql8]/1T?\cCXޞT?ڏɟ],/A ?n- a^9$%7_#? $h >1̓QFri)ZXH q`Sr9}TPEETRM>ʄQ"$hP = \ox[o"e )XsT<{ӨlX4H0۹u%@؇.e% @Lr`'5^%渕-Ms.^o6/e1ڹߖu**mؚM'ASzZө+^,S6뷈$Ӎ8cǯl0< лk/14㬠|X Z#-DϬS5UH`3(ȳVdQHQ13DH>n uQ7T]]uZt1:V˥aYRStURu1Xi 8΃ sR?՞] XXݵ !6*ddOF9eWfH J "#w-V"Lȗ栈]:82H%r@ {4+~Sr&U@q)5&'jj9i_ #:l B:nr?!2ZlKܠBۙi+\n&//"sm{Ggg~v(gG?&ugۿ}ǤN6m֎jWs}!EQ#Cʞ*t|G?}gfdfħhJ upC";Di\@qix|\/rq5//_@T|I+gV_8@8nX A1ЂSX8 " =51,C!`vk1ADr1yB@2"^ܨ=2&ČXS>ҐDd"Ȃ/fVٔ ${EG9?04 cQj {* |.H \BIEkI4IG`6w$5ڲ#tͽlÜ gb iBRrҴ1u:%tζ DXFV-UJ3S :!]8?KƯ/d  G 0gEɑ0 a;Nq[/qL\[&Vc~XU@nA<KIcVWrޠW~O$2f$5eTIQ&'ks޹$^ʚg ,34{Ͳяtf>4 iNoӝENKԧQjV>L!?ַƵQk^|4H,=`F!lf7م,FX?TmnwNOݐhF7BvnvƴF NA ߽o~'ix]ہwX"!+MX,pW<$۶x5p< Na3Ӧ@2)H Q9s 0w7?֝s\o+_rX.K|Y| 'UN}u_{K$8KZ絽xGh0λ\*sCr= {M __URvs~NH=]$[ǂ?ccGC+zą|S= j8+47ב|(ZjoTP`[HÙƼ/6SF"7Ťia1ʈ@Fʏ2{" bT{hz4G< f`Q}qM-0͛1&ɡpa={a5%b8&}R&"=UѕyOriKw& (gͤфgJ j wk)A ["y;"J}'f'hrEOI;L*Wt="=sR+I{j I}-(D%je|eW1Vb弑1hDbYTSVR0)낫}ܔR+F0a-İ*L+Z+zZBZ2Ls+*Z q,J >TR?˂Zͺ 2z:)ݬ&p-؊*Zڮj2•xbZ!Zb?@ܸ(\>zŝ ʭ ̭>bz”NJ/;ҟU^2HDz;1& ">!cE K]1s<ӿIKM}EWk2?T۰u 8^ 1E_&Sk^Z{&e/>̶)5.7kγemF LްalR(}>B"Q &bOs"F!VbM &b<`d%+6-f)n032;+vF3VcFz5vcD$$7+675}($;)=V9 F-KZCT Z6, BWHd&=8:E 'b@ƒ8"iQ^ OeGkX哹@cSI q\ NUl udI e fb6Z<qF>A>@M c܍{Ѣ$γ輼R'g$ !#G,m Ўi vFwVN0PUrAq[`Ծ⋝ ')RhEF#2~N=(Y9RR3&5gF|t V ] h,0"Ydz!: 2\U[̌(j-uNJƺk8)dFbJR֋aF{&hD3fJQJQY.(Vl缾3 /u. ]%. hK-{턴}I>gEݺ]& ۶oVZn`*nr }]U$ ΈpVf>þ ^5=~~a97?dcvpՖpi 7qG p?ER wqq_h @CDUCOWU(Eܴ•KPX}cR#Vqvg4)jw xG&גq/+:s&rJ˫̎M PҞwDs4rsiϺ);4AOl 1zOYDFw77u=r. .\k4S^01-S}Y| Nul;`:lѦfu'u5YukVZvb ;6v#QZU.u]Ӫ!Zno7T2^uUjh__MC`}/:wu+`9nx16 GP|f$%5G7(OyGbr x*Wc ^y—'z zq[l?s֜L_a! e?7a8(v,98=Odyn .K cۻLmtZ͕:\AϺk_F_ptą %$ˡ|fr}yL¯S΢\o#We"";& < wEw=Hv|ٓl $h{G}pǕūZw,tG>?XJ ;B(q"Ŋ/b̨q#ǎ? )r$ɒ&OL$[)s&͚6o̩s'Ϟ>OTiBD *q1`Ft9Pz?.(μfϢMv-۶=@v.ݺvͫwK&=Ԣ=m7 &,y2ʖ=25|y3Ξ?,W(QHZcz_Î-{~iέ{7ﻚƏ#Oj˟C.xqMX}:޿ ~<:?y]8Ï/?>."`n_v6Q!d)XUr![p1S!%I+GWXlژ;H"W!IU)dτe⁏%I ȣWd [reZD@ T$b@k#UE$C τhE@dc16Ң8x碊BjirJT_vh]pi'[=d$RB>X0ztH@ !@Q`:zIV=R>gQ*,(Z Zn8QcY}BD͑ЮDEC(1#~;Vb.=+QcCb\caR/S$>8ammDRT? CԯSP<}jq lr??FBF*??ͯCG'% kmY"KjgM, .~`,6;o-ha+UIYf۟.裓.=f:Ctl*&6y?A cD' ǽ3;B8p DTO0! M&Hu!!g. 2 "1e%L"Cw?MdH+Ά)b_ŶbL%qjF2>q#\*+1\"XQPi "gL!i6:2#ꢘ*IbBx$'J1Qad'KB2,YO2ˁ,kʕ,ܥn6_0&&1b"s6g⅖М2uAWʍڜ/#&9;sr7\!6uwNF:qQI7ϴ󚡔? s44Y8Н]h>xψ8sK +яfӞAjR *$iFʕT)M9Ћv:H?w.%GДդ7W2TxF5]*vDA&X]iP+ЭNSE+=QMRǪHѭlEVѮZ]߉ԾӬ $*`U>TD\Kͺ:֠|5#\ kcYYnv ?k՜M<'6M$&tMmŴۂt[ WM.2{ /uНsmvJ2}&qrn -NSmngaǢg7o)ͻWV;ij{:ؑ/r#FZؔ~}3{ ,~CLEX%qSE 8lcnjE)f6JU,)z,ulOBΈyLEG9{IYfLMˠG}fI>m\S}EBڇKceEεQkz)b`MV"Y{!`ϮͰ N~dwܢ?Z;ƎvM `v /{u-+Ҳ ^'n.KƱ gG^|SwAH0/glp[6gwΣ_4ЇRZG%_P/u>zk*ֿ=-w@OʥN.UgמS;Nw;J{ιpgo;>|myʏg옟d7#{^y}gsW_wĻ~@'GO{M^ٷ'!w ~OP#ȏN |\3Oؗ_ɃcCO?7}9C{r_F v)`_A`0%REY`tz =`V1q ` 0}V`^t` `h Z g`9 a_^:!e`Rj!h`O!z`f@aɡ9a!8u_FF Z|a!!"Y"fI"]S #HRb4ݡ]"_&ބ"zN4b(])bF&*bNH`,("H-T Yb/D'cIp0-cFa2"%2#D=c"4/ZcH c6 R7"/L8c5Lyc#Mlc:b;3c0F<~]>D9I9?^8H`Aj c1*H8.C$=R$H$E>j$JݣEv$GD$8 aHV$F~$G:dK~DF^Hr@¤F"7:M M$HP$J4Q&LR0>JRJR" ^VndJ$WCʣS>$MfcIRNb6XBCB5Z~%ST[#LW4Z_e|e;X3NbW_Z\d\*$fdd2ZRfY4VjffhJfQ*ea¥Azc_di^g&kfWfjefJV1Nfhoo"g5f:r?0&r&p&fU6idttn&o^pgpmR%xx'yRw#wy'kqu.gvf~gHg=.V'§RhG<-g|xb`u6F.h~PN(&Q>cnEgk~O'e3(thT"g⁺hKjQ"2Wd(Rhj2#}c(ޤF)s6W>9h:)Guiri%6'Ƣ.&#Χ防($f4UhZiCJ$)(fr&&bΩPnR&%䡖.&*.)6^zj*)⥭$#N2jK aV*j*泦Rk+$$&f饦v)&>jb2+,2,l,l*2JlRlVZlbBv,Ndž,^ǚȞlɢʪlˊ˒llά,ެ,,l2m6m:mBV^-.-nZmfm؂~mrv,hXL-۾mR-ҭm.m."n2:BFnRnNJnVj.nrvnznnf誮n뎮.nʮnnn 2/NQB/M'p@C8O0*s>67|3=6Vtj˯Rr+LtytwttGrvx3c#g5T}o5TC~~S~}}WC7΂C˷5Q:0.B.kxoxkxgxg8.LFx<,0+lxxl |&/#y+CgEDSSy[c r9NSo9y37gyhy/Z{eUy+P d:L"z3zHHT[zckzs{zzzzzzzzz {{#+{3;{CK{S[{O $GhA;XAXA{{{;ϻ{[{;|#+3|;|7?O~Scks~{~w>~蓾髾~~>~Ӿ~~>#߽C=G?w8+5P5D4PGoR4C/2{#CB1 ?@C&@TB !>D1^ԘFA~H%QTJ-aL5qԙN=ʿbB֫X\I6eBD *m9_+m٪eMoJKMrM7[}^ >/ŀnX0ɖ+KΜ˚=o4ЧMj׭a=ٶkƽ[woԯofwʼn?7o\8֫KϞڽo<ͧ﮾zᓗ?*+L2eɢ+/ J+ KIkq+-bKC/) @QPO=3CQDcR>IO!4D(mG3SE/m4TIITPSUR[E/[qZ7U_ut[e]EvY_mWh=vK6Yb5vUOeVgY\e]v\uEXUe|Yyi_{w`}6`o Mx[ V8݇-׉Ř+yG>YQ~yܕevb a`8{ߌ>3bS9jИ ,iЭ PF fDS0lm6n>sżNn`[p.<_o)wp~;&0\s19Yt?E5ꍍ)tc<Αu4P \lFHA$K1MmT#IbTtc&/E>氋b 3H!D DG҉<-+iKL1{$ {Pv0&~#db)g򊾼%5kh-b(M1FT$9) fFR@dg9M-V Q곐D1Id%jkb (!| mYK4X:`bi֔FS=햗X6a>Oͣgy%r/+XY3,Sպ*3-Mz͆2uc^#׿t:lVɌt-gZwlj[.2/Xyv䃡 CUH Å6@%-5dXcHXԤ,ظZ.NTK7n+?49膹mEŋgsC9yns+2`O P>D/ mj[m\H~.n'nqTNGgrjQiwqwQ~Q'}nQ'!G1qq'q xQDZ1!Q!!a!r!#!'2#ۑ!9F#7;r$ (mИSj<:}0; m>3?i¬!OF*D΂B `.X -EdDEdTFaDbFF IhEntGSGcGFHuG/|HII4GkHJTGI4KTI4LLKTKIL4JTMtKM4M״NMݔNTNOTOPMNTPPuOQTQ˔Q'QRP/5P#PS3Q rtMڄb8ONdBd'akBn R*T,X p@V*J?5N7QARqGQ-X1P5Z5ZZ 5T[Eu[JSRu\U[[[\;I[\UZ]X^O˵]\YXR`ZT]]5`Za VbPJ% ~