Understanding how Eclipse plug-ins work with OSGi

Eclipse and OSGi from A to Z, or in this case, plugin.xml to manifest.mf

The core of the Eclipse integrated development environment (IDE) and Eclipse Rich Client Platform (RCP) applications is driven by an implementation of the Open Services Gateway Initiative (OSGi) specification. This article illustrates Eclipse's relationship with OSGi by describing what a plug-in is in terms of the Eclipse platform and traces the evolution of plug-ins from Eclipse V2.1 through today's OSGi-based implementation. It also explains the OSGi manifest.mf file options, along with the additions provided through Eclipse.

Most Java™ programming language developers are introduced to Eclipse through its function as an IDE. The Eclipse IDE actually consists of a collection of interacting components called plug-ins. These plug-ins, which make up the base of the IDE, can also be used to create other desktop applications. The minimal set of plug-ins needed to create an Eclipse-based application is referred to as the Eclipse Rich Client Platform (RCP). Plug-ins don't just start themselves, however. They require an environment in which to start and operate. Eclipse provides this environment with an implementation of the OSGi R4 specification.

Because Eclipse is at its core driven by OSGi, it's important to understand how the concept of an Eclipse plug-in relates to the OSGi framework. In this article, I will explain this relationship in detail by describing what a plug-in is in terms of the Eclipse platform. Then I'll describe the evolution of plug-ins in the Eclipse V2.1 platform through today's OSGi-based implementation. Finally, the OSGi-provided manifest.mf options that apply to Eclipse plug-ins will be covered in detail.

What is a plug-in?

The Eclipse online help defines a plug-in as follows:

"Plug-ins are structured bundles of code and/or data that contribute function to the system. Function can be contributed in the form of code libraries (Java classes with public [application program interfaces] APIs), platform extensions, or even documentation. Plug-ins can define extension points, well-defined places where other plug-ins can add functionality."

The key point to focus on is that plug-ins contribute function in a structured manner. They may provide a service such as logging or piece functionality available in the user interface (UI), such as an editor. Regardless of their function, all plug-ins are defined in the same structured way.

The evolution to OSGi

As mentioned, Eclipse uses OSGi as the basis for its plug-in system. This wasn't always the case, however. Early versions of Eclipse were also designed as a collection of plug-ins, and Eclipse included its own propriety plug-in system to manage the interaction. However, as the requirements of the Eclipse IDE grew, it became apparent that a more robust solution was required. Basic requirements of this new system included the ability to dynamically handle the addition of new plug-ins and stopping existing plug-ins. After considerable research, the Eclipse creators decided to replace the proprietary plug-in framework by implementing the OSGi framework specification.

OSGi is a specification of a service platform. Eclipse provides one of many available implementations of this specification and serves as the reference implementation of the latest OSGi R4 specification. OSGi is a Java-based framework targeted for use by systems that require long running times, dynamic updates, and minimal disruptions to the running environment. Initially, OSGi was targeted at home automation and residential gateway devices. More recently, it has found use in everything from mobile phones to cars.

At its core, OSGi is a component and service model, as illustrated in Figure 1. The OSGi specification defines a unit of modularization called a bundle. (Unless explicitly noted during the rest of this article, the Eclipse term plug-in and the OSGi term bundle are used interchangeably because all Eclipse plug-ins are now OSGi bundles.) OSGi also provides a Java Virtual Machine (JVM)-level service registry that bundles can use to publish, discover, and bind to services.

Figure 1. The interaction of the layers in the host operating system, Java, and OSGi
The OSGi specification defines an infrastructure for a bundle's life cycle and how bundles interact. These rules are enforced through the use of special Java class loaders. In an average Java application, all classes in the CLASSPATH are visible to all other classes. In contrast, the OSGi class loaders restrict class interaction among bundles based on the OSGi specification and the options specified (covered in detail later in this article) in the manifest.mf file for each bundle.

The Eclipse IDE uses a subset of OSGi centered around modularization and bundle life cycle. However, it makes minimal use of the service support OSGi provides. Instead, Eclipse provides its own extension point system to enable bundle interaction. Bundles expose functionality as contributions to other extensions. Bundles also define their own extension points, to which other bundles may contribute. An example of using extension points in Eclipse is the Preferences window. A core Eclipse plug-in provides the central window and exposes an extension point to allow the contribution of additional preference pages. As new plug-ins are added to Eclipse, they can contribute their own pages. The model of extension points in Eclipse is different from basic OSGi services. Bundle extension points are owned by the defining bundle; other bundles simply contribute to them. In comparison, any bundle can implement and use an OSGi service.

Implementing Eclipse using OSGi

In versions of Eclipse before 3.1, you defined plug-in dependencies, as well as extensions and extension points, in each plug-in's plugin.xml file. In the newer versions of Eclipse that use OSGi, dependency information has been broken out into the manifest.mf file, leaving the plugin.xml file containing only XML definitions of extensions and extension points. It is useful to look at a live, working example of this evolution. Listing 1 shows an excerpt from the org.eclipse.pde.ui plug-in from Eclipse V3.0.

Listing 1. Excerpt from the org.eclipse.pde plug-in

































#### The declaration exposes all packages in the plug-in for use in other plug-ins. The plug-in dependency imports section lists the prerequisite plug-ins the org.eclipse.pde.ui plug-in requires.

The next two sections define the extension points org.eclipse.pde.ui makes available to other plug-ins, as well as the contributions it makes to them. In this case, you can see the definition of a custom Eclipse Plug-in Development Environment (PDE) perspective.

Let's look at the same plug-in definition in Eclipse V3.1. Listing 2 shows the plugin.xml file.

Listing 2. Plugin.xml

#### Notice that the export and import information is gone. This information now resides in the manifest.mf file shown in Listing 3. *Listing 3. Manifest.mf* #### Manifest-Version: 1.0 Bundle-Name: %name Bundle-SymbolicName: org.eclipse.pde.ui; singleton:=true Bundle-Version: 3.1.0 Bundle-ClassPath: org.eclipse.pde.ui_3.1.0.jar Bundle-Activator: org.eclipse.pde.internal.ui.PDEPlugin Bundle-Vendor: %provider-name Bundle-Localization: plugin Require-Bundle: org.eclipse.core.runtime, org.eclipse.ui.ide, org.eclipse.ui.views, org.eclipse.jface.text, org.eclipse.ui.workbench.texteditor, org.eclipse.ui.editors, org.eclipse.ant.core, org.eclipse.core.resources, org.eclipse.debug.core, org.eclipse.debug.ui, org.eclipse.jdt.core, org.eclipse.jdt.debug.ui, org.eclipse.jdt.launching, org.eclipse.jdt.ui, org.eclipse.pde, org.eclipse.pde.build, org.eclipse.search, org.eclipse.team.core, org.eclipse.ui, org.eclipse.update.core, org.eclipse.ui.forms, org.eclipse.ant.ui, org.eclipse.jdt.junit, org.eclipse.ui.intro, org.eclipse.ui.cheatsheets, org.eclipse.update.configurator, org.eclipse.help.base Bundle-ManifestVersion: 2 Eclipse-AutoStart: true Export-Package: org.eclipse.pde.internal.ui;x-internal:=true, org.eclipse.pde.internal.ui.build;x-internal:=true,

. . .

org.eclipse.pde.ui,
org.eclipse.pde.ui.internal.samples;x-internal:=true,
org.eclipse.pde.ui.templates

The various plug-in imports are now specified as required bundles, and the * package export has been replaced with a list of explicitly exported packages.

The move away from plug-in-level dependencies to dependencies that required the explicit exporting and importing of packages generated a lot of commotion when Eclipse announced the news. The primary complaint was the lack of an equivalent of , which had existed in earlier versions of Eclipse. There are many reasons for this omission, however. The most important reason is the speed gains from having explicit import and exports. Previous versions of Eclipse had to open and scan each plug-in jar file to determine which classes it contained. Not including a * export also provides a level of protection against plug-ins exposing unwanted classes. Plug-in developers must make a conscious choice to make functionality in a plug-in available for outside use. This restriction allows internal packages to stay internal.

OSGi manifest options

The current draft specification for the OSGi R4 framework core is almost 300 pages in PDF form. Covering every portion of this specification is outside the scope of this article, but I do discuss the OSGi manifest.mf options of particular interest to Eclipse plug-in developers:

Bundle-Activator

This class is used to start and stop the bundle. In the example plug-in above, the org.eclipse.pde.internal.ui.PDEPlugin class is specified. This class extends org.eclipse.core.runtime.Plugin, which implements the BundleActivator interface.

Bundle-ClassPath

This property specifies the CLASSPATH to use for the bundle. The property may contain references to directories or jar files inside the bundle jar file. You can use the period to indicate the bundle's root. In the case of the example Eclipse PDE bundle, org.eclipse.pde.ui_3.1.0.jar in the bundle jar file is specified. If you import the source version of the plug-in into your workspace, the import process changes the bundle CLASSPATH to appear as Bundle-ClassPath:, which allows the development version of the plug-in to pick up the compiled bundle classes.

Bundle-Version

This property specifies the version number of the bundle. Package imports and required bundle specifications may include a bundle version number.

Export-Package

This property specifies all the packages to publicly expose to other plug-ins.

Import-Package

This property specifies all the packages to explicitly import from required plug-ins. By default, all packages must be resolved for a bundle to start. You can also specify package imports as optional to support cases in which a package may not exist. Explicitly imported classes are resolved before packages from Require-Bundle plug-ins.

Require-Bundle

This property specifies which bundles and their exported packages to import for use in the given bundle. Specified bundles are evaluated after explicit package imports.

Additional manifest options provided by Eclipse

The manifest.mf configuration options that the OSGi specification includes don't provide all the functionality that the Eclipse platform requires. As a result, the Eclipse creators have added several extensions (and also proposed them for inclusion in future versions of the OSGi specification):

Export-Package Header Extensions
Eclipse has two OSGi resolver methods -- default and strict -- that the osgi.resolver property can specify. Eclipse also includes two extensions to the Export-Package property -- x-internal and x-friends -- both of which are enforced when you enable Strict mode.

x-internal
The default value for this property is false. When internal packages are specified as true using this option, the Eclipse PDE discourages their use.

x-friends
This option is similar to x-internal, but allows certain bundles to use the exported packages that have this option. Others bundles are discouraged. The x-internal option takes precedence over x-friends.

Eclipse-AutoStart
By default, Eclipse loads bundles on demand. Therefore, bundles are loaded when the first class they contain is required by a bundle that imports it. Specifying this value as ?? causes Eclipse to load the bundle at startup. You can also specify a list of exceptions, which are classes, and resources, and which may be loaded without starting their containing bundle.

Eclipse-PlatformFilter
This property allows you to specify conditions that must evaluate to true for a bundle to start. You can include the following information in the expression you specify:

    osgi.nl for language
    osgi.os for operating system
    osgi.arch for architecture
    osgi.ws for windowing system

An example of how to use this property is to verify whether the operating system is not Mac OS X before starting a plug-in that uses the SWT_AWT bridge. (The Mac OS X implementation of the Standard Widget Toolkit (SWT) doesn't currently support this feature.)

Eclipse-BuddyPolicy
This option specifies the class loading policy of the bundle. Typically, bundles only have visibility in their internal classes and those imported from dependent bundles. The popular example that has been used in the Eclipse newsgroups to explain buddy class loading is Hibernate. The Hibernate framework must see classes and resources that are user-created and not part of Hibernate itself. One such case is when you use a project to dynamically fill a class from a Hibernate Query Language (HQL) query. By default, Hibernate won't be able to see classes outside the plug-in containing the Hibernate jar files, and requiring modification of the Hibernate plug-in for the creation of each plug-in containing classes that Hibernate maps is not acceptable. Fortunately, you can solve this using the buddy class loader options explained in the Buddy class loader options section.

Buddy class loader options

Begin by creating a plug-in for Hibernate. Then create a plug-in containing the domain-specific classes with a dependency on Hibernate. Add the following line to the Hibernate plug-in manifest: Eclipse-BuddyPolicy: registered.

Add the following manifest property to the manifest of the plug-in containing the domain-specific classes or resources: Eclipse-RegisterBuddy: hibernate.

This line allows plug-ins to declaratively expose themselves to the Hibernate plug-in without it knowing about them beforehand. Now the Hibernate plug-in can see the needed classes even though it did not specifically import them.

Future directions of Eclipse and OSGi

Eclipse has benefited greatly in its use of OSGi, gaining a robust system managing the life cycle of components in a dynamic manner. New uses, such as dynamic Web Archive (WAR) files on the server tier featuring servlets, JavaServer Pages, and other HTTP resources in Eclipse-style plug-ins are being explored every day.

The Eclipse Foundation has positioned itself to play a key role in driving the OSGi specification forward, both for its own uses and for those of other parties leveraging OSGi. During the transition from the propriety Eclipse plug-in framework to OSGi, many additions were made to the OSGi specification that became part of the OSGi R4 specification release. The Eclipse Equinox project has, as a result, become the OSGi reference implementation moving forward. This involvement, as well as the creation of Java Specification Request (JSR) 291 to manage the evolution OSGi, guarantees that the Eclipse/OSGi partnership will continue to be successful in the years ahead.

[Understanding how Eclipse plug-ins work with OSGi][1]
[1]: http://www.ibm.com/developerworks/library/os-ecl-osgi/index.html

Message-driven vs. Web service Integration Architectures

Background

Integration schemes employed by modern enterprise-class service oriented architectures can generally be divided into two primary categories, Web Services and Message Driven Architecture (MDA). This document attempts a brief description of these schemes, a concise analysis of their respective strengths and weaknesses, and provides some basic guidelines for implementing each scheme in a scalable manner suitable for the enterprise.
Web Services are an implementation of a synchronous, request-response pattern leveraging standard web protocols (HTTP/HTTPS). Typical web service implementations are based on either SOAP, an XML-based encoding scheme which uses a specific XML envelope format to direct requests to specific operational endpoints, or REST, which leverages standard web URL addressing schemes and multiple HTTP operation types together with a variety of encodings (frequently JSON) to define service semantics.
Message Driven Architecture, in contrast, eschews the use of HTTP-based point-to-point service schemes in favor of service integration through a shared (broker-based) message bus infrastructure. Services are exposed through specific, named message broker endpoints, and a variety of message encodings can be used (including XML, JSON, or efficient binary encodings such as Google Protobuf or Swift). A variety of opens source and commercial messaging technologies can be used to wire together services in a MDA, including ActiveMQ, IBM MQ, RabbitMQ, QPid, Amazon SQS, Kafka, and ZeroMQ. Communication patterns in MDA are fundamentally asynchronous and non-blocking, although they can be used to emulate synchronous request/response behavior when appropriate, as described below.

Synchronous Semantics in MDA

Message Driven Architecture can provide synchronous request/response semantics similar to web services through the use of callback queues. In this pattern, the client instance creates or is bound to a specific queue used to receive responses. Requests are submitted with a header identifying this queue as well as a unique correlation or request ID. Service implementations publish responses to the identified callback queue and include the correlation ID header. Meanwhile, the client can block the requesting thread until a response is received on the callback queue with matching correlation ID. This pattern is illustrated below:
aaaa.png

While this pattern may appear somewhat complex, in reality it is fairly easy to implement, and, in some cases message framework providers have baked direct support for the pattern into their client APIs (e.g. RabbitMQ and IBM MQ), making implementation trivial. Note that this pattern works best when the messaging technology provides an API that allows clients to create and manage callback queues with randomized ids as needed at runtime (this are known as anonymous callback queues). The ability for clients to manage their own anonymous callback queues at runtime simplifies scaling by allowing client instances to be added or removed as needed without additional explicit message endpoint configuration.
Note that this callback queue pattern can be extended to the server side in order to efficiently implement fully stateful services when necessary.
As we shall see, using this MDA approach, even for simple blocking request/response calls has several significant advantages over more “traditional” web service based implementations in spite of the perceived increase in complexity.

Web Services versus MDA

Here we provide a brief summary of the respective advantages and disadvantages of the Web Service and MDA pattern

Web Services

Advantages:

  • Simple and well understood pattern for synchronous request/response
  • Abundant and mature developer tooling available for a variety of platforms
    - Easy for developers to implement, debug, and understand.
    - Synchronous blocking request/response patterns are easy to implement.
    Disadvantages:
  • Numerous point-to-point integrations can be difficult to manage at enterprise scale.
    - Potential firewall and DNS configuration issues can cause disruptions.
    - No single point to manage access security. Every service instance must be secured and monitored individually.
    - Service discovery can be difficult/complex
    - Encourages use of synchronous/blocking communication patterns, which can cause scalability issues at high volume.
    - Requires additional deployment of load balancing infrastructure for horizontal scaling.
    - Only scales well when services are nearly or completely stateless.
    - Managing test environments, which may require access to multiple versions of the same service, is challenging
    - DNS or port-assignment schemes typically used to manage services in an enterprise test & staging environment are complex.
    - High availability features can be challenging to implement
    - Need to explicitly manage retries, failover etc. at the client application level.
    - Connectionless architecture, coupled with the cost of setting up SSL connections, means that secure services can encounter scalability issues at high request volumes.
    - SSL resumption ameliorates this problem but can be difficult to configure (particularly cross-platform).

中老年人喜欢的歌曲和戏曲

现代医学研究表明,唱歌不仅能让人们心情愉快,而且对身体健康也有好处。唱歌能增强身体的免疫能力,是保持身心健康的一剂“天然良药”。唱歌对人的心理健康有益,这是人们能直接感受到的,它能释放悲伤,让人情绪变好,能让老年人减少吃药和看病的次数,唱歌所采用的横膈膜呼吸法,还能起到缓解压力的作用。
人到老年,退休之后,在家闲来无事,不如听上几首小曲,陶冶情操。最适合老年人听的歌曲有哪些,老人一般都听那类歌,老年人喜欢的歌曲、戏曲有哪些呢,为老年人下载一些什么呀的歌曲比较好呢?这里把我给父母下载的歌曲和戏曲发给大家,以供大家参考。
经典老歌(都是经典抒情类的歌曲,加红的是必须拷贝的歌曲。像国歌、没有共产党就没有新中国、东方红等革命歌曲就不再推荐了。2.找歌以原唱为主,除非翻唱确实比原唱好。都按老年人的口味经过深入的比较):敖包相会(电影原声)、马铃儿响来玉鸟儿唱(胡松华)、边疆的泉水清又纯(李谷一)、长城长(董文华)、常回家看看(陈红)、春天的故事(董文华)、大海啊故乡(朱明瑛)、弹起我心爱的土琵琶(李双江)、蝴蝶泉边(电影原声)、夫妻双双把家还(电影原声)、花儿为什么这样红(胡松华)、九九艳阳天(宋祖英、吕继宏)、军港之夜(苏小明)、妹妹找哥泪花流(李谷一)、母亲(阎维文)、年轻的朋友来相会(佟铁鑫)、乡恋(李谷一)、三笑(倪雅丰)、少年壮志不言愁(刘欢)、哨所的喇叭花(郁钧剑)、十五的月亮(董文华)、说句心里话(阎维文)、天涯歌女(周璇)、弯弯的月亮(刘欢)、望星空(董文华)、我爱你中国(电影原声)、我生命中最重要的两个人(潘长江)、纤夫的爱(于文华、尹相杰)、想家的时候(阎维文)、小白杨(阎维文)、血染的风采(董文华)、一朵鲜花鲜又鲜(电影原声)、一条大河波浪宽(郭兰英)、英雄赞歌(电影原声)、有一个美丽的传说(蒋大为)、月亮走我也走(董文华)、在那桃花盛开的地方(蒋大为)、在那遥远的地方(胡松华)、在希望的田野上(彭丽媛)、阿拉木汗(胡松华)、白发亲娘(吕继宏)、半个月亮爬上来(西域情歌)、北国之春(蒋大为)、草原上升起不落的太阳(吴雁泽)、草原之夜(蒋大为)、船工号子(李双江)、打靶归来(贾世骏)、大阪城的姑娘(蒋大为)、红星照我去战斗(李双江)、洪湖水浪打浪(孙莹迎)、化蝶(郑绪岚)、家和万事兴(郁钧剑、张也)、军港的晚霞(吕继宏)、骏马奔驰保边疆(蒋大为)、马儿呀你慢些走(马玉涛)、美丽草原我的家(德德玛)、牡丹之歌(蒋大为)、牧羊曲(郑绪岚)、跑马溜溜的山上(蒋大为)、牵手(苏芮)、塞北的雪(彭丽媛)、山丹丹花开红艳艳(阿宝。这个反复比较觉得还是阿宝的好,个人意见仅作参考)、十送红军(彭丽媛)、谁不说俺家乡好(彭丽媛)、说句心里话(阎维文)、桃花依旧笑春风(群星)、吐鲁番的葡萄熟了(关牧村)、驼铃(蒋大为)、我爱五指山我爱万泉河(李双江)、我爱这蓝色的海洋(吕继宏)、乌苏里船歌(蒋大为)、掀起你的盖头来(王洛宾)、乡间小路(张清芳)、再见吧妈妈(李双江)、咱老百姓(吕继宏)、祝酒歌(蒋大为)。
河南地方戏(家是河南的,以下都是最经典的河南戏。加红的是十大名剧,加下划线的是父母指定要的):诸葛亮吊孝(申凤梅)、泪洒相思地(张晓凤)、寻儿记(张宝英)、唐知县审诰命(轩玉亭)、秦香莲(崔兰田)、倒霉大叔的婚事(任宏恩)、小寡妇上坟(夏金婷)、五世请缨(陈小霞)、三哭殿(唐喜成)、三上轿(陈素珍)、花为媒(孙映雪)、墙头记(李文革)、七品芝麻官(牛得草)、三子争父(曲剧。郑庆恩)、诸葛亮祭灯(张枝茂)、打金枝(刘忠河)、李豁子离婚(曲剧。胡希华)、卷席筒(海连池)、卷席筒续(海连池)、胡二姐开店(曲剧。孔素红)、五女拜寿(邯郸东风豫剧团)、抬花轿(宋桂玲)、陈世美喊冤(李斌)、穆桂英挂帅(常香玉)、铡美案(李斯忠)、孟姜女(张新芳)、八贤王说媒(洪先礼)、朝阳沟(魏云)、人欢马叫(任宏恩)、屠夫状元(金不换)、老子儿子弦子(张海龙)、杨八姐游春(马金凤)、鞭打芦花(李树建)、包龙图坐监(李斯忠)、白蛇传(常香玉)、盘夫索夫(阎立品)、姐妹易嫁(朱秀珍)、姐妹告状(阎立品)、花枪缘(马金凤)、春风扇(马兰)、拷红(常香玉)、王金斗借粮(王秀兰)、窦娥冤(马金凤)、王三姐招亲(索海燕)、桃花庵(崔兰田)、山猫嘴说媒(张月荣)、陈三两(崔兰田)、对花枪(马金凤)、寇准背靴(马祺)、抬花轿(王清芬)、孙成打酒(李金枝)、情断状元楼(张艳萍)、十五贯(唐喜成)、刘墉下江南(唐玉成)、对花枪(马金凤)、大祭桩(常香玉)、包公审鬼(张珏东)、花木兰(常香玉)、秦雪梅(阎立品)、风雪配(王秀兰)、西厢记(阎立品)、反徐州(唐玉成)、辕门斩子(唐喜成)、下陈州(李斯忠)、十八扯(牛得草)。
豫剧代表人物介绍:
陈素真、常香玉、崔兰田、马金凤、阎立品、桑振君并称“豫剧六大名旦”,代表六大风格旦角流派。其余名家有张岫云、宋桂玲、王秀兰、安金凤、赵义庭、王素君、王希玲、唐玉成、唐喜成、刘忠河、刘新民、、李树建、李斯忠、牛得草、高洁、马琳、魏云、王善朴、柳兰芳、张宝英、王清芬、虎美玲、牛淑贤、李喜华、菅爱梅、朱巧云、李金枝、陈淑敏、马莉、胡小凤、章兰等。
曲剧代表人物介绍:
海连池、牛长鑫、、陈素菊、郭秋芳、方素珍、刘青、朱万明、杨帅学、胡希华、马骐、王秀玲、张新芳等。
注意事项:歌曲在下载时要尽量找原唱,经典歌曲乌七八糟翻唱的太多,特别是超女、快男之流,唱的跟鬼叫似的,老年人很讨厌的,听了容易血压升高!戏曲相对好一些,名家互相之间翻唱的很多,水平也都很高,只要能找到的基本都可以用。

Talend Open Studio for ESB

Talend Open Studio for ESB

splash.jpg

Copyright (C) 2006-2016 Talend Inc. - www.talend.com

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

   http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.